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  }