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 }