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