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  }