github.com/undoio/delve@v1.9.0/pkg/proc/fbsdutil/regs.go (about)

     1  package fbsdutil
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/undoio/delve/pkg/dwarf/op"
     7  	"github.com/undoio/delve/pkg/dwarf/regnum"
     8  	"github.com/undoio/delve/pkg/proc"
     9  	"github.com/undoio/delve/pkg/proc/amd64util"
    10  )
    11  
    12  // AMD64Registers implements the proc.Registers interface for the native/freebsd
    13  // backend and core/freebsd backends, on AMD64.
    14  type AMD64Registers struct {
    15  	Regs     *AMD64PtraceRegs
    16  	Fpregs   []proc.Register
    17  	Fpregset *amd64util.AMD64Xstate
    18  	Fsbase   uint64
    19  
    20  	loadFpRegs func(*AMD64Registers) error
    21  }
    22  
    23  func NewAMD64Registers(regs *AMD64PtraceRegs, fsbase uint64, loadFpRegs func(*AMD64Registers) error) *AMD64Registers {
    24  	return &AMD64Registers{Regs: regs, Fsbase: fsbase, loadFpRegs: loadFpRegs}
    25  }
    26  
    27  // AMD64PtraceRegs is the struct used by the freebsd kernel to return the
    28  // general purpose registers for AMD64 CPUs.
    29  // source: sys/x86/include/reg.h
    30  type AMD64PtraceRegs struct {
    31  	R15    int64
    32  	R14    int64
    33  	R13    int64
    34  	R12    int64
    35  	R11    int64
    36  	R10    int64
    37  	R9     int64
    38  	R8     int64
    39  	Rdi    int64
    40  	Rsi    int64
    41  	Rbp    int64
    42  	Rbx    int64
    43  	Rdx    int64
    44  	Rcx    int64
    45  	Rax    int64
    46  	Trapno uint32
    47  	Fs     uint16
    48  	Gs     uint16
    49  	Err    uint32
    50  	Es     uint16
    51  	Ds     uint16
    52  	Rip    int64
    53  	Cs     int64
    54  	Rflags int64
    55  	Rsp    int64
    56  	Ss     int64
    57  }
    58  
    59  // Slice returns the registers as a list of (name, value) pairs.
    60  func (r *AMD64Registers) Slice(floatingPoint bool) ([]proc.Register, error) {
    61  	var regs64 = []struct {
    62  		k string
    63  		v int64
    64  	}{
    65  		{"R15", r.Regs.R15},
    66  		{"R14", r.Regs.R14},
    67  		{"R13", r.Regs.R13},
    68  		{"R12", r.Regs.R12},
    69  		{"R11", r.Regs.R11},
    70  		{"R10", r.Regs.R10},
    71  		{"R9", r.Regs.R9},
    72  		{"R8", r.Regs.R8},
    73  		{"Rdi", r.Regs.Rdi},
    74  		{"Rsi", r.Regs.Rsi},
    75  		{"Rbp", r.Regs.Rbp},
    76  		{"Rbx", r.Regs.Rbx},
    77  		{"Rdx", r.Regs.Rdx},
    78  		{"Rcx", r.Regs.Rcx},
    79  		{"Rax", r.Regs.Rax},
    80  		{"Rip", r.Regs.Rip},
    81  		{"Cs", r.Regs.Cs},
    82  		{"Rflags", r.Regs.Rflags},
    83  		{"Rsp", r.Regs.Rsp},
    84  		{"Ss", r.Regs.Ss},
    85  	}
    86  	var regs32 = []struct {
    87  		k string
    88  		v uint32
    89  	}{
    90  		{"Trapno", r.Regs.Trapno},
    91  		{"Err", r.Regs.Err},
    92  	}
    93  	var regs16 = []struct {
    94  		k string
    95  		v uint16
    96  	}{
    97  		{"Fs", r.Regs.Fs},
    98  		{"Gs", r.Regs.Gs},
    99  		{"Es", r.Regs.Es},
   100  		{"Ds", r.Regs.Ds},
   101  	}
   102  	out := make([]proc.Register, 0,
   103  		len(regs64)+
   104  			len(regs32)+
   105  			len(regs16)+
   106  			1+ // for Rflags
   107  			len(r.Fpregs))
   108  	for _, reg := range regs64 {
   109  		// FreeBSD defines the registers as signed, but Linux defines
   110  		// them as unsigned.  Of course, a register doesn't really have
   111  		// a concept of signedness.  Cast to what Delve expects.
   112  		out = proc.AppendUint64Register(out, reg.k, uint64(reg.v))
   113  	}
   114  	for _, reg := range regs32 {
   115  		out = proc.AppendUint64Register(out, reg.k, uint64(reg.v))
   116  	}
   117  	for _, reg := range regs16 {
   118  		out = proc.AppendUint64Register(out, reg.k, uint64(reg.v))
   119  	}
   120  	// x86 called this register "Eflags".  amd64 extended it and renamed it
   121  	// "Rflags", but Linux still uses the old name.
   122  	out = proc.AppendUint64Register(out, "Rflags", uint64(r.Regs.Rflags))
   123  	var floatLoadError error
   124  	if floatingPoint {
   125  		if r.loadFpRegs != nil {
   126  			floatLoadError = r.loadFpRegs(r)
   127  			r.loadFpRegs = nil
   128  		}
   129  		out = append(out, r.Fpregs...)
   130  	}
   131  	return out, floatLoadError
   132  }
   133  
   134  // PC returns the value of RIP register.
   135  func (r *AMD64Registers) PC() uint64 {
   136  	return uint64(r.Regs.Rip)
   137  }
   138  
   139  // SP returns the value of RSP register.
   140  func (r *AMD64Registers) SP() uint64 {
   141  	return uint64(r.Regs.Rsp)
   142  }
   143  
   144  func (r *AMD64Registers) BP() uint64 {
   145  	return uint64(r.Regs.Rbp)
   146  }
   147  
   148  func (r *AMD64Registers) LR() uint64 {
   149  	return 0
   150  }
   151  
   152  // TLS returns the address of the thread local storage memory segment.
   153  func (r *AMD64Registers) TLS() uint64 {
   154  	return r.Fsbase
   155  }
   156  
   157  // GAddr returns the address of the G variable if it is known, 0 and false
   158  // otherwise.
   159  func (r *AMD64Registers) GAddr() (uint64, bool) {
   160  	return 0, false
   161  }
   162  
   163  // Copy returns a copy of these registers that is guaranteed not to change.
   164  func (r *AMD64Registers) Copy() (proc.Registers, error) {
   165  	if r.loadFpRegs != nil {
   166  		err := r.loadFpRegs(r)
   167  		r.loadFpRegs = nil
   168  		if err != nil {
   169  			return nil, err
   170  		}
   171  	}
   172  	var rr AMD64Registers
   173  	rr.Regs = &AMD64PtraceRegs{}
   174  	rr.Fpregset = &amd64util.AMD64Xstate{}
   175  	*(rr.Regs) = *(r.Regs)
   176  	if r.Fpregset != nil {
   177  		*(rr.Fpregset) = *(r.Fpregset)
   178  	}
   179  	if r.Fpregs != nil {
   180  		rr.Fpregs = make([]proc.Register, len(r.Fpregs))
   181  		copy(rr.Fpregs, r.Fpregs)
   182  	}
   183  	return &rr, nil
   184  }
   185  
   186  func (r *AMD64Registers) SetReg(regNum uint64, reg *op.DwarfRegister) (bool, error) {
   187  	var p *int64
   188  	switch regNum {
   189  	case regnum.AMD64_Rax:
   190  		p = &r.Regs.Rax
   191  	case regnum.AMD64_Rbx:
   192  		p = &r.Regs.Rbx
   193  	case regnum.AMD64_Rcx:
   194  		p = &r.Regs.Rcx
   195  	case regnum.AMD64_Rdx:
   196  		p = &r.Regs.Rdx
   197  	case regnum.AMD64_Rsi:
   198  		p = &r.Regs.Rsi
   199  	case regnum.AMD64_Rdi:
   200  		p = &r.Regs.Rdi
   201  	case regnum.AMD64_Rbp:
   202  		p = &r.Regs.Rbp
   203  	case regnum.AMD64_Rsp:
   204  		p = &r.Regs.Rsp
   205  	case regnum.AMD64_R8:
   206  		p = &r.Regs.R8
   207  	case regnum.AMD64_R9:
   208  		p = &r.Regs.R9
   209  	case regnum.AMD64_R10:
   210  		p = &r.Regs.R10
   211  	case regnum.AMD64_R11:
   212  		p = &r.Regs.R11
   213  	case regnum.AMD64_R12:
   214  		p = &r.Regs.R12
   215  	case regnum.AMD64_R13:
   216  		p = &r.Regs.R13
   217  	case regnum.AMD64_R14:
   218  		p = &r.Regs.R14
   219  	case regnum.AMD64_R15:
   220  		p = &r.Regs.R15
   221  	case regnum.AMD64_Rip:
   222  		p = &r.Regs.Rip
   223  	case regnum.AMD64_Rflags:
   224  		p = &r.Regs.Rflags
   225  	}
   226  
   227  	if p != nil {
   228  		if reg.Bytes != nil && len(reg.Bytes) != 8 {
   229  			return false, fmt.Errorf("wrong number of bytes for register %s (%d)", regnum.AMD64ToName(regNum), len(reg.Bytes))
   230  		}
   231  		*p = int64(reg.Uint64Val)
   232  		return false, nil
   233  	}
   234  
   235  	if r.loadFpRegs != nil {
   236  		if err := r.loadFpRegs(r); err != nil {
   237  			return false, err
   238  		}
   239  		r.loadFpRegs = nil
   240  	}
   241  
   242  	if regNum < regnum.AMD64_XMM0 || regNum > regnum.AMD64_XMM0+15 {
   243  		return false, fmt.Errorf("can not set %s", regnum.AMD64ToName(regNum))
   244  	}
   245  
   246  	reg.FillBytes()
   247  
   248  	if err := r.Fpregset.SetXmmRegister(int(regNum-regnum.AMD64_XMM0), reg.Bytes); err != nil {
   249  		return false, err
   250  	}
   251  	return true, nil
   252  }