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 }