github.com/undoio/delve@v1.9.0/pkg/proc/linutil/regs_arm64_arch.go (about)

     1  package linutil
     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  )
    10  
    11  // ARM64Registers is a wrapper for sys.PtraceRegs.
    12  type ARM64Registers struct {
    13  	Regs      *ARM64PtraceRegs //general-purpose registers
    14  	iscgo     bool
    15  	tpidr_el0 uint64
    16  	Fpregs    []proc.Register //Formatted floating point registers
    17  	Fpregset  []byte          //holding all floating point register values
    18  
    19  	loadFpRegs func(*ARM64Registers) error
    20  }
    21  
    22  func NewARM64Registers(regs *ARM64PtraceRegs, iscgo bool, tpidr_el0 uint64, loadFpRegs func(*ARM64Registers) error) *ARM64Registers {
    23  	return &ARM64Registers{Regs: regs, iscgo: iscgo, tpidr_el0: tpidr_el0, loadFpRegs: loadFpRegs}
    24  }
    25  
    26  // ARM64PtraceRegs is the struct used by the linux kernel to return the
    27  // general purpose registers for ARM64 CPUs.
    28  // copy from sys/unix/ztypes_linux_arm64.go:735
    29  type ARM64PtraceRegs struct {
    30  	Regs   [31]uint64
    31  	Sp     uint64
    32  	Pc     uint64
    33  	Pstate uint64
    34  }
    35  
    36  // Slice returns the registers as a list of (name, value) pairs.
    37  func (r *ARM64Registers) Slice(floatingPoint bool) ([]proc.Register, error) {
    38  	var regs64 = []struct {
    39  		k string
    40  		v uint64
    41  	}{
    42  		{"X0", r.Regs.Regs[0]},
    43  		{"X1", r.Regs.Regs[1]},
    44  		{"X2", r.Regs.Regs[2]},
    45  		{"X3", r.Regs.Regs[3]},
    46  		{"X4", r.Regs.Regs[4]},
    47  		{"X5", r.Regs.Regs[5]},
    48  		{"X6", r.Regs.Regs[6]},
    49  		{"X7", r.Regs.Regs[7]},
    50  		{"X8", r.Regs.Regs[8]},
    51  		{"X9", r.Regs.Regs[9]},
    52  		{"X10", r.Regs.Regs[10]},
    53  		{"X11", r.Regs.Regs[11]},
    54  		{"X12", r.Regs.Regs[12]},
    55  		{"X13", r.Regs.Regs[13]},
    56  		{"X14", r.Regs.Regs[14]},
    57  		{"X15", r.Regs.Regs[15]},
    58  		{"X16", r.Regs.Regs[16]},
    59  		{"X17", r.Regs.Regs[17]},
    60  		{"X18", r.Regs.Regs[18]},
    61  		{"X19", r.Regs.Regs[19]},
    62  		{"X20", r.Regs.Regs[20]},
    63  		{"X21", r.Regs.Regs[21]},
    64  		{"X22", r.Regs.Regs[22]},
    65  		{"X23", r.Regs.Regs[23]},
    66  		{"X24", r.Regs.Regs[24]},
    67  		{"X25", r.Regs.Regs[25]},
    68  		{"X26", r.Regs.Regs[26]},
    69  		{"X27", r.Regs.Regs[27]},
    70  		{"X28", r.Regs.Regs[28]},
    71  		{"X29", r.Regs.Regs[29]},
    72  		{"X30", r.Regs.Regs[30]},
    73  		{"SP", r.Regs.Sp},
    74  		{"PC", r.Regs.Pc},
    75  		{"PSTATE", r.Regs.Pstate},
    76  	}
    77  	out := make([]proc.Register, 0, len(regs64)+len(r.Fpregs))
    78  	for _, reg := range regs64 {
    79  		out = proc.AppendUint64Register(out, reg.k, reg.v)
    80  	}
    81  	var floatLoadError error
    82  	if floatingPoint {
    83  		if r.loadFpRegs != nil {
    84  			floatLoadError = r.loadFpRegs(r)
    85  			r.loadFpRegs = nil
    86  		}
    87  		out = append(out, r.Fpregs...)
    88  	}
    89  	return out, floatLoadError
    90  }
    91  
    92  // PC returns the value of RIP register.
    93  func (r *ARM64Registers) PC() uint64 {
    94  	return r.Regs.Pc
    95  }
    96  
    97  // SP returns the value of RSP register.
    98  func (r *ARM64Registers) SP() uint64 {
    99  	return r.Regs.Sp
   100  }
   101  
   102  func (r *ARM64Registers) BP() uint64 {
   103  	return r.Regs.Regs[29]
   104  }
   105  
   106  // TLS returns the address of the thread local storage memory segment.
   107  func (r *ARM64Registers) TLS() uint64 {
   108  	if !r.iscgo {
   109  		return 0
   110  	}
   111  	return r.tpidr_el0
   112  }
   113  
   114  // GAddr returns the address of the G variable if it is known, 0 and false
   115  // otherwise.
   116  func (r *ARM64Registers) GAddr() (uint64, bool) {
   117  	return r.Regs.Regs[28], !r.iscgo
   118  }
   119  
   120  // LR returns the link register.
   121  func (r *ARM64Registers) LR() uint64 {
   122  	return r.Regs.Regs[30]
   123  }
   124  
   125  // Copy returns a copy of these registers that is guaranteed not to change.
   126  func (r *ARM64Registers) Copy() (proc.Registers, error) {
   127  	if r.loadFpRegs != nil {
   128  		err := r.loadFpRegs(r)
   129  		r.loadFpRegs = nil
   130  		if err != nil {
   131  			return nil, err
   132  		}
   133  	}
   134  	var rr ARM64Registers
   135  	rr.Regs = &ARM64PtraceRegs{}
   136  	*(rr.Regs) = *(r.Regs)
   137  	if r.Fpregs != nil {
   138  		rr.Fpregs = make([]proc.Register, len(r.Fpregs))
   139  		copy(rr.Fpregs, r.Fpregs)
   140  	}
   141  	if r.Fpregset != nil {
   142  		rr.Fpregset = make([]byte, len(r.Fpregset))
   143  		copy(rr.Fpregset, r.Fpregset)
   144  	}
   145  	return &rr, nil
   146  }
   147  
   148  func (r *ARM64Registers) SetReg(regNum uint64, reg *op.DwarfRegister) (fpchanged bool, err error) {
   149  	switch regNum {
   150  	case regnum.ARM64_PC:
   151  		r.Regs.Pc = reg.Uint64Val
   152  		return false, nil
   153  	case regnum.ARM64_SP:
   154  		r.Regs.Sp = reg.Uint64Val
   155  		return false, nil
   156  	default:
   157  		switch {
   158  		case regNum >= regnum.ARM64_X0 && regNum <= regnum.ARM64_X0+30:
   159  			r.Regs.Regs[regNum-regnum.ARM64_X0] = reg.Uint64Val
   160  			return false, nil
   161  
   162  		case regNum >= regnum.ARM64_V0 && regNum <= regnum.ARM64_V0+30:
   163  			if r.loadFpRegs != nil {
   164  				err := r.loadFpRegs(r)
   165  				r.loadFpRegs = nil
   166  				if err != nil {
   167  					return false, err
   168  				}
   169  			}
   170  
   171  			i := regNum - regnum.ARM64_V0
   172  			reg.FillBytes()
   173  			copy(r.Fpregset[16*i:], reg.Bytes)
   174  			return true, nil
   175  
   176  		default:
   177  			return false, fmt.Errorf("changing register %d not implemented", regNum)
   178  		}
   179  	}
   180  }
   181  
   182  type ARM64PtraceFpRegs struct {
   183  	Vregs []byte
   184  	Fpsr  uint32
   185  	Fpcr  uint32
   186  }
   187  
   188  const _ARM_FP_REGS_LENGTH = 512
   189  
   190  func (fpregs *ARM64PtraceFpRegs) Decode() (regs []proc.Register) {
   191  	for i := 0; i < len(fpregs.Vregs); i += 16 {
   192  		regs = proc.AppendBytesRegister(regs, fmt.Sprintf("V%d", i/16), fpregs.Vregs[i:i+16])
   193  	}
   194  	return
   195  }
   196  
   197  func (fpregs *ARM64PtraceFpRegs) Byte() []byte {
   198  	fpregs.Vregs = make([]byte, _ARM_FP_REGS_LENGTH)
   199  	return fpregs.Vregs[:]
   200  }