gitlab.com/Raven-IO/raven-delve@v1.22.4/pkg/proc/native/registers_darwin_amd64.go (about) 1 //go:build darwin && macnative 2 3 package native 4 5 // #include "threads_darwin.h" 6 import "C" 7 import ( 8 "fmt" 9 "unsafe" 10 11 "golang.org/x/arch/x86/x86asm" 12 13 "gitlab.com/Raven-IO/raven-delve/pkg/dwarf/op" 14 "gitlab.com/Raven-IO/raven-delve/pkg/dwarf/regnum" 15 "gitlab.com/Raven-IO/raven-delve/pkg/proc" 16 ) 17 18 // Regs represents CPU registers on an AMD64 processor. 19 type Regs struct { 20 rax uint64 21 rbx uint64 22 rcx uint64 23 rdx uint64 24 rdi uint64 25 rsi uint64 26 rbp uint64 27 rsp uint64 28 r8 uint64 29 r9 uint64 30 r10 uint64 31 r11 uint64 32 r12 uint64 33 r13 uint64 34 r14 uint64 35 r15 uint64 36 rip uint64 37 rflags uint64 38 cs uint64 39 fs uint64 40 gs uint64 41 gsBase uint64 42 fpregs []proc.Register 43 } 44 45 func (r *Regs) Slice(floatingPoint bool) ([]proc.Register, error) { 46 var regs = []struct { 47 k string 48 v uint64 49 }{ 50 {"Rip", r.rip}, 51 {"Rsp", r.rsp}, 52 {"Rax", r.rax}, 53 {"Rbx", r.rbx}, 54 {"Rcx", r.rcx}, 55 {"Rdx", r.rdx}, 56 {"Rdi", r.rdi}, 57 {"Rsi", r.rsi}, 58 {"Rbp", r.rbp}, 59 {"R8", r.r8}, 60 {"R9", r.r9}, 61 {"R10", r.r10}, 62 {"R11", r.r11}, 63 {"R12", r.r12}, 64 {"R13", r.r13}, 65 {"R14", r.r14}, 66 {"R15", r.r15}, 67 {"Rflags", r.rflags}, 68 {"Cs", r.cs}, 69 {"Fs", r.fs}, 70 {"Gs", r.gs}, 71 {"Gs_base", r.gsBase}, 72 } 73 out := make([]proc.Register, 0, len(regs)+len(r.fpregs)) 74 for _, reg := range regs { 75 if reg.k == "Rflags" { 76 out = proc.AppendUint64Register(out, reg.k, reg.v) 77 } else { 78 out = proc.AppendUint64Register(out, reg.k, reg.v) 79 } 80 } 81 if floatingPoint { 82 out = append(out, r.fpregs...) 83 } 84 return out, nil 85 } 86 87 // PC returns the current program counter 88 // i.e. the RIP CPU register. 89 func (r *Regs) PC() uint64 { 90 return r.rip 91 } 92 93 // SP returns the stack pointer location, 94 // i.e. the RSP register. 95 func (r *Regs) SP() uint64 { 96 return r.rsp 97 } 98 99 func (r *Regs) BP() uint64 { 100 return r.rbp 101 } 102 103 func (r *Regs) LR() uint64 { 104 return 0 105 } 106 107 // TLS returns the value of the register 108 // that contains the location of the thread 109 // local storage segment. 110 func (r *Regs) TLS() uint64 { 111 return r.gsBase 112 } 113 114 func (r *Regs) GAddr() (uint64, bool) { 115 return 0, false 116 } 117 118 // SetPC sets the RIP register to the value specified by `pc`. 119 func (thread *nativeThread) setPC(pc uint64) error { 120 kret := C.set_pc(thread.os.threadAct, C.uint64_t(pc)) 121 if kret != C.KERN_SUCCESS { 122 return fmt.Errorf("could not set pc") 123 } 124 return nil 125 } 126 127 // SetReg changes the value of the specified register. 128 func (thread *nativeThread) SetReg(regNum uint64, reg *op.DwarfRegister) error { 129 if regNum != regnum.AMD64_Rip { 130 return fmt.Errorf("changing register %d not implemented", regNum) 131 } 132 return thread.setPC(reg.Uint64Val) 133 } 134 135 func (r *Regs) Get(n int) (uint64, error) { 136 reg := x86asm.Reg(n) 137 const ( 138 mask8 = 0x000f 139 mask16 = 0x00ff 140 mask32 = 0xffff 141 ) 142 143 switch reg { 144 // 8-bit 145 case x86asm.AL: 146 return r.rax & mask8, nil 147 case x86asm.CL: 148 return r.rcx & mask8, nil 149 case x86asm.DL: 150 return r.rdx & mask8, nil 151 case x86asm.BL: 152 return r.rbx & mask8, nil 153 case x86asm.AH: 154 return (r.rax >> 8) & mask8, nil 155 case x86asm.CH: 156 return (r.rcx >> 8) & mask8, nil 157 case x86asm.DH: 158 return (r.rdx >> 8) & mask8, nil 159 case x86asm.BH: 160 return (r.rbx >> 8) & mask8, nil 161 case x86asm.SPB: 162 return r.rsp & mask8, nil 163 case x86asm.BPB: 164 return r.rbp & mask8, nil 165 case x86asm.SIB: 166 return r.rsi & mask8, nil 167 case x86asm.DIB: 168 return r.rdi & mask8, nil 169 case x86asm.R8B: 170 return r.r8 & mask8, nil 171 case x86asm.R9B: 172 return r.r9 & mask8, nil 173 case x86asm.R10B: 174 return r.r10 & mask8, nil 175 case x86asm.R11B: 176 return r.r11 & mask8, nil 177 case x86asm.R12B: 178 return r.r12 & mask8, nil 179 case x86asm.R13B: 180 return r.r13 & mask8, nil 181 case x86asm.R14B: 182 return r.r14 & mask8, nil 183 case x86asm.R15B: 184 return r.r15 & mask8, nil 185 186 // 16-bit 187 case x86asm.AX: 188 return r.rax & mask16, nil 189 case x86asm.CX: 190 return r.rcx & mask16, nil 191 case x86asm.DX: 192 return r.rdx & mask16, nil 193 case x86asm.BX: 194 return r.rbx & mask16, nil 195 case x86asm.SP: 196 return r.rsp & mask16, nil 197 case x86asm.BP: 198 return r.rbp & mask16, nil 199 case x86asm.SI: 200 return r.rsi & mask16, nil 201 case x86asm.DI: 202 return r.rdi & mask16, nil 203 case x86asm.R8W: 204 return r.r8 & mask16, nil 205 case x86asm.R9W: 206 return r.r9 & mask16, nil 207 case x86asm.R10W: 208 return r.r10 & mask16, nil 209 case x86asm.R11W: 210 return r.r11 & mask16, nil 211 case x86asm.R12W: 212 return r.r12 & mask16, nil 213 case x86asm.R13W: 214 return r.r13 & mask16, nil 215 case x86asm.R14W: 216 return r.r14 & mask16, nil 217 case x86asm.R15W: 218 return r.r15 & mask16, nil 219 220 // 32-bit 221 case x86asm.EAX: 222 return r.rax & mask32, nil 223 case x86asm.ECX: 224 return r.rcx & mask32, nil 225 case x86asm.EDX: 226 return r.rdx & mask32, nil 227 case x86asm.EBX: 228 return r.rbx & mask32, nil 229 case x86asm.ESP: 230 return r.rsp & mask32, nil 231 case x86asm.EBP: 232 return r.rbp & mask32, nil 233 case x86asm.ESI: 234 return r.rsi & mask32, nil 235 case x86asm.EDI: 236 return r.rdi & mask32, nil 237 case x86asm.R8L: 238 return r.r8 & mask32, nil 239 case x86asm.R9L: 240 return r.r9 & mask32, nil 241 case x86asm.R10L: 242 return r.r10 & mask32, nil 243 case x86asm.R11L: 244 return r.r11 & mask32, nil 245 case x86asm.R12L: 246 return r.r12 & mask32, nil 247 case x86asm.R13L: 248 return r.r13 & mask32, nil 249 case x86asm.R14L: 250 return r.r14 & mask32, nil 251 case x86asm.R15L: 252 return r.r15 & mask32, nil 253 254 // 64-bit 255 case x86asm.RAX: 256 return r.rax, nil 257 case x86asm.RCX: 258 return r.rcx, nil 259 case x86asm.RDX: 260 return r.rdx, nil 261 case x86asm.RBX: 262 return r.rbx, nil 263 case x86asm.RSP: 264 return r.rsp, nil 265 case x86asm.RBP: 266 return r.rbp, nil 267 case x86asm.RSI: 268 return r.rsi, nil 269 case x86asm.RDI: 270 return r.rdi, nil 271 case x86asm.R8: 272 return r.r8, nil 273 case x86asm.R9: 274 return r.r9, nil 275 case x86asm.R10: 276 return r.r10, nil 277 case x86asm.R11: 278 return r.r11, nil 279 case x86asm.R12: 280 return r.r12, nil 281 case x86asm.R13: 282 return r.r13, nil 283 case x86asm.R14: 284 return r.r14, nil 285 case x86asm.R15: 286 return r.r15, nil 287 } 288 289 return 0, proc.ErrUnknownRegister 290 } 291 292 func registers(thread *nativeThread) (proc.Registers, error) { 293 var state C.x86_thread_state64_t 294 var identity C.thread_identifier_info_data_t 295 kret := C.get_registers(C.mach_port_name_t(thread.os.threadAct), &state) 296 if kret != C.KERN_SUCCESS { 297 return nil, fmt.Errorf("could not get registers") 298 } 299 kret = C.get_identity(C.mach_port_name_t(thread.os.threadAct), &identity) 300 if kret != C.KERN_SUCCESS { 301 return nil, fmt.Errorf("could not get thread identity information") 302 } 303 /* 304 thread_identifier_info::thread_handle contains the base of the 305 thread-specific data area, which on x86 and x86_64 is the thread’s base 306 address of the %gs segment. 10.9.2 xnu-2422.90.20/osfmk/kern/thread.c 307 thread_info_internal() gets the value from 308 machine_thread::cthread_self, which is the same value used to set the 309 %gs base in xnu-2422.90.20/osfmk/i386/pcb_native.c 310 act_machine_switch_pcb(). 311 -- 312 comment copied from chromium's crashpad 313 https://chromium.googlesource.com/crashpad/crashpad/+/master/snapshot/mac/process_reader.cc 314 */ 315 regs := &Regs{ 316 rax: uint64(state.__rax), 317 rbx: uint64(state.__rbx), 318 rcx: uint64(state.__rcx), 319 rdx: uint64(state.__rdx), 320 rdi: uint64(state.__rdi), 321 rsi: uint64(state.__rsi), 322 rbp: uint64(state.__rbp), 323 rsp: uint64(state.__rsp), 324 r8: uint64(state.__r8), 325 r9: uint64(state.__r9), 326 r10: uint64(state.__r10), 327 r11: uint64(state.__r11), 328 r12: uint64(state.__r12), 329 r13: uint64(state.__r13), 330 r14: uint64(state.__r14), 331 r15: uint64(state.__r15), 332 rip: uint64(state.__rip), 333 rflags: uint64(state.__rflags), 334 cs: uint64(state.__cs), 335 fs: uint64(state.__fs), 336 gs: uint64(state.__gs), 337 gsBase: uint64(identity.thread_handle), 338 } 339 340 // https://opensource.apple.com/source/xnu/xnu-792.13.8/osfmk/mach/i386/thread_status.h?txt 341 var fpstate C.x86_float_state64_t 342 kret = C.get_fpu_registers(C.mach_port_name_t(thread.os.threadAct), &fpstate) 343 if kret != C.KERN_SUCCESS { 344 return nil, fmt.Errorf("could not get floating point registers") 345 } 346 347 regs.fpregs = proc.AppendUint64Register(regs.fpregs, "CW", uint64(*((*uint16)(unsafe.Pointer(&fpstate.__fpu_fcw))))) 348 regs.fpregs = proc.AppendUint64Register(regs.fpregs, "SW", uint64(*((*uint16)(unsafe.Pointer(&fpstate.__fpu_fsw))))) 349 regs.fpregs = proc.AppendUint64Register(regs.fpregs, "TW", uint64(fpstate.__fpu_ftw)) 350 regs.fpregs = proc.AppendUint64Register(regs.fpregs, "FOP", uint64(fpstate.__fpu_fop)) 351 regs.fpregs = proc.AppendUint64Register(regs.fpregs, "FIP", uint64(fpstate.__fpu_cs)<<32|uint64(fpstate.__fpu_ip)) 352 regs.fpregs = proc.AppendUint64Register(regs.fpregs, "FDP", uint64(fpstate.__fpu_ds)<<32|uint64(fpstate.__fpu_dp)) 353 354 for i, st := range []*C.char{&fpstate.__fpu_stmm0.__mmst_reg[0], &fpstate.__fpu_stmm1.__mmst_reg[0], &fpstate.__fpu_stmm2.__mmst_reg[0], &fpstate.__fpu_stmm3.__mmst_reg[0], &fpstate.__fpu_stmm4.__mmst_reg[0], &fpstate.__fpu_stmm5.__mmst_reg[0], &fpstate.__fpu_stmm6.__mmst_reg[0], &fpstate.__fpu_stmm7.__mmst_reg[0]} { 355 stb := C.GoBytes(unsafe.Pointer(st), 10) 356 regs.fpregs = proc.AppendBytesRegister(regs.fpregs, fmt.Sprintf("ST(%d)", i), stb) 357 } 358 359 regs.fpregs = proc.AppendUint64Register(regs.fpregs, "MXCSR", uint64(fpstate.__fpu_mxcsr)) 360 regs.fpregs = proc.AppendUint64Register(regs.fpregs, "MXCSR_MASK", uint64(fpstate.__fpu_mxcsrmask)) 361 362 for i, xmm := range []*C.char{&fpstate.__fpu_xmm0.__xmm_reg[0], &fpstate.__fpu_xmm1.__xmm_reg[0], &fpstate.__fpu_xmm2.__xmm_reg[0], &fpstate.__fpu_xmm3.__xmm_reg[0], &fpstate.__fpu_xmm4.__xmm_reg[0], &fpstate.__fpu_xmm5.__xmm_reg[0], &fpstate.__fpu_xmm6.__xmm_reg[0], &fpstate.__fpu_xmm7.__xmm_reg[0], &fpstate.__fpu_xmm8.__xmm_reg[0], &fpstate.__fpu_xmm9.__xmm_reg[0], &fpstate.__fpu_xmm10.__xmm_reg[0], &fpstate.__fpu_xmm11.__xmm_reg[0], &fpstate.__fpu_xmm12.__xmm_reg[0], &fpstate.__fpu_xmm13.__xmm_reg[0], &fpstate.__fpu_xmm14.__xmm_reg[0], &fpstate.__fpu_xmm15.__xmm_reg[0]} { 363 regs.fpregs = proc.AppendBytesRegister(regs.fpregs, fmt.Sprintf("XMM%d", i), C.GoBytes(unsafe.Pointer(xmm), 16)) 364 } 365 366 return regs, nil 367 } 368 369 func (r *Regs) Copy() (proc.Registers, error) { 370 //TODO(aarzilli): implement this to support function calls 371 return nil, nil 372 }