github.com/cnboonhan/delve@v0.0.0-20230908061759-363f2388c2fb/pkg/proc/winutil/regs_amd64_arch.go (about) 1 package winutil 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "fmt" 7 "unsafe" 8 9 "github.com/go-delve/delve/pkg/dwarf/op" 10 "github.com/go-delve/delve/pkg/dwarf/regnum" 11 "github.com/go-delve/delve/pkg/proc" 12 ) 13 14 // AMD64Registers represents CPU registers on an AMD64 processor. 15 type AMD64Registers struct { 16 rax uint64 17 rbx uint64 18 rcx uint64 19 rdx uint64 20 rdi uint64 21 rsi uint64 22 rbp uint64 23 rsp uint64 24 r8 uint64 25 r9 uint64 26 r10 uint64 27 r11 uint64 28 r12 uint64 29 r13 uint64 30 r14 uint64 31 r15 uint64 32 rip uint64 33 eflags uint64 34 cs uint64 35 fs uint64 36 gs uint64 37 tls uint64 38 Context *AMD64CONTEXT 39 fltSave *XMM_SAVE_AREA32 40 } 41 42 // NewAMD64Registers creates a new AMD64Registers struct from a CONTEXT 43 // struct and the TEB base address of the thread. 44 func NewAMD64Registers(context *AMD64CONTEXT, TebBaseAddress uint64) *AMD64Registers { 45 regs := &AMD64Registers{ 46 rax: uint64(context.Rax), 47 rbx: uint64(context.Rbx), 48 rcx: uint64(context.Rcx), 49 rdx: uint64(context.Rdx), 50 rdi: uint64(context.Rdi), 51 rsi: uint64(context.Rsi), 52 rbp: uint64(context.Rbp), 53 rsp: uint64(context.Rsp), 54 r8: uint64(context.R8), 55 r9: uint64(context.R9), 56 r10: uint64(context.R10), 57 r11: uint64(context.R11), 58 r12: uint64(context.R12), 59 r13: uint64(context.R13), 60 r14: uint64(context.R14), 61 r15: uint64(context.R15), 62 rip: uint64(context.Rip), 63 eflags: uint64(context.EFlags), 64 cs: uint64(context.SegCs), 65 fs: uint64(context.SegFs), 66 gs: uint64(context.SegGs), 67 tls: TebBaseAddress, 68 } 69 70 regs.fltSave = &context.FltSave 71 regs.Context = context 72 73 return regs 74 } 75 76 // Slice returns the registers as a list of (name, value) pairs. 77 func (r *AMD64Registers) Slice(floatingPoint bool) ([]proc.Register, error) { 78 var regs = []struct { 79 k string 80 v uint64 81 }{ 82 {"Rip", r.rip}, 83 {"Rsp", r.rsp}, 84 {"Rax", r.rax}, 85 {"Rbx", r.rbx}, 86 {"Rcx", r.rcx}, 87 {"Rdx", r.rdx}, 88 {"Rdi", r.rdi}, 89 {"Rsi", r.rsi}, 90 {"Rbp", r.rbp}, 91 {"R8", r.r8}, 92 {"R9", r.r9}, 93 {"R10", r.r10}, 94 {"R11", r.r11}, 95 {"R12", r.r12}, 96 {"R13", r.r13}, 97 {"R14", r.r14}, 98 {"R15", r.r15}, 99 {"Rflags", r.eflags}, 100 {"Cs", r.cs}, 101 {"Fs", r.fs}, 102 {"Gs", r.gs}, 103 {"TLS", r.tls}, 104 } 105 outlen := len(regs) 106 if r.fltSave != nil && floatingPoint { 107 outlen += 6 + 8 + 2 + 16 108 } 109 out := make([]proc.Register, 0, outlen) 110 for _, reg := range regs { 111 out = proc.AppendUint64Register(out, reg.k, reg.v) 112 } 113 if r.fltSave != nil && floatingPoint { 114 out = proc.AppendUint64Register(out, "CW", uint64(r.fltSave.ControlWord)) 115 out = proc.AppendUint64Register(out, "SW", uint64(r.fltSave.StatusWord)) 116 out = proc.AppendUint64Register(out, "TW", uint64(uint16(r.fltSave.TagWord))) 117 out = proc.AppendUint64Register(out, "FOP", uint64(r.fltSave.ErrorOpcode)) 118 out = proc.AppendUint64Register(out, "FIP", uint64(r.fltSave.ErrorSelector)<<32|uint64(r.fltSave.ErrorOffset)) 119 out = proc.AppendUint64Register(out, "FDP", uint64(r.fltSave.DataSelector)<<32|uint64(r.fltSave.DataOffset)) 120 121 for i := range r.fltSave.FloatRegisters { 122 var buf bytes.Buffer 123 binary.Write(&buf, binary.LittleEndian, r.fltSave.FloatRegisters[i].Low) 124 binary.Write(&buf, binary.LittleEndian, r.fltSave.FloatRegisters[i].High) 125 out = proc.AppendBytesRegister(out, fmt.Sprintf("ST(%d)", i), buf.Bytes()) 126 } 127 128 out = proc.AppendUint64Register(out, "MXCSR", uint64(r.fltSave.MxCsr)) 129 out = proc.AppendUint64Register(out, "MXCSR_MASK", uint64(r.fltSave.MxCsr_Mask)) 130 131 for i := 0; i < len(r.fltSave.XmmRegisters); i += 16 { 132 out = proc.AppendBytesRegister(out, fmt.Sprintf("XMM%d", i/16), r.fltSave.XmmRegisters[i:i+16]) 133 } 134 } 135 return out, nil 136 } 137 138 // PC returns the current program counter 139 // i.e. the RIP CPU register. 140 func (r *AMD64Registers) PC() uint64 { 141 return r.rip 142 } 143 144 // SP returns the stack pointer location, 145 // i.e. the RSP register. 146 func (r *AMD64Registers) SP() uint64 { 147 return r.rsp 148 } 149 150 func (r *AMD64Registers) BP() uint64 { 151 return r.rbp 152 } 153 154 // LR returns the link register. 155 func (r *AMD64Registers) LR() uint64 { 156 return 0 157 } 158 159 // TLS returns the value of the register 160 // that contains the location of the thread 161 // local storage segment. 162 func (r *AMD64Registers) TLS() uint64 { 163 return r.tls 164 } 165 166 // GAddr returns the address of the G variable if it is known, 0 and false 167 // otherwise. 168 func (r *AMD64Registers) GAddr() (uint64, bool) { 169 return 0, false 170 } 171 172 // Copy returns a copy of these registers that is guaranteed not to change. 173 func (r *AMD64Registers) Copy() (proc.Registers, error) { 174 var rr AMD64Registers 175 rr = *r 176 rr.Context = NewAMD64CONTEXT() 177 *(rr.Context) = *(r.Context) 178 rr.fltSave = &rr.Context.FltSave 179 return &rr, nil 180 } 181 182 // M128A tracks the _M128A windows struct. 183 type M128A struct { 184 Low uint64 185 High int64 186 } 187 188 // XMM_SAVE_AREA32 tracks the _XMM_SAVE_AREA32 windows struct. 189 type XMM_SAVE_AREA32 struct { 190 ControlWord uint16 191 StatusWord uint16 192 TagWord byte 193 Reserved1 byte 194 ErrorOpcode uint16 195 ErrorOffset uint32 196 ErrorSelector uint16 197 Reserved2 uint16 198 DataOffset uint32 199 DataSelector uint16 200 Reserved3 uint16 201 MxCsr uint32 202 MxCsr_Mask uint32 203 FloatRegisters [8]M128A 204 XmmRegisters [256]byte 205 Reserved4 [96]byte 206 } 207 208 // AMD64CONTEXT tracks the _CONTEXT of windows. 209 type AMD64CONTEXT struct { 210 P1Home uint64 211 P2Home uint64 212 P3Home uint64 213 P4Home uint64 214 P5Home uint64 215 P6Home uint64 216 217 ContextFlags uint32 218 MxCsr uint32 219 220 SegCs uint16 221 SegDs uint16 222 SegEs uint16 223 SegFs uint16 224 SegGs uint16 225 SegSs uint16 226 EFlags uint32 227 228 Dr0 uint64 229 Dr1 uint64 230 Dr2 uint64 231 Dr3 uint64 232 Dr6 uint64 233 Dr7 uint64 234 235 Rax uint64 236 Rcx uint64 237 Rdx uint64 238 Rbx uint64 239 Rsp uint64 240 Rbp uint64 241 Rsi uint64 242 Rdi uint64 243 R8 uint64 244 R9 uint64 245 R10 uint64 246 R11 uint64 247 R12 uint64 248 R13 uint64 249 R14 uint64 250 R15 uint64 251 252 Rip uint64 253 254 FltSave XMM_SAVE_AREA32 255 256 VectorRegister [26]M128A 257 VectorControl uint64 258 259 DebugControl uint64 260 LastBranchToRip uint64 261 LastBranchFromRip uint64 262 LastExceptionToRip uint64 263 LastExceptionFromRip uint64 264 } 265 266 // NewAMD64CONTEXT allocates Windows CONTEXT structure aligned to 16 bytes. 267 func NewAMD64CONTEXT() *AMD64CONTEXT { 268 var c *AMD64CONTEXT 269 buf := make([]byte, unsafe.Sizeof(*c)+15) 270 return (*AMD64CONTEXT)(unsafe.Pointer((uintptr(unsafe.Pointer(&buf[15]))) &^ 15)) 271 } 272 273 func (ctx *AMD64CONTEXT) SetFlags(flags uint32) { 274 ctx.ContextFlags = flags 275 } 276 277 func (ctx *AMD64CONTEXT) SetPC(pc uint64) { 278 ctx.Rip = pc 279 } 280 281 func (ctx *AMD64CONTEXT) SetTrap(trap bool) { 282 const v = 0x100 283 if trap { 284 ctx.EFlags |= v 285 } else { 286 ctx.EFlags &= ^uint32(v) 287 } 288 } 289 290 func (ctx *AMD64CONTEXT) SetReg(regNum uint64, reg *op.DwarfRegister) error { 291 var p *uint64 292 293 switch regNum { 294 case regnum.AMD64_Rax: 295 p = &ctx.Rax 296 case regnum.AMD64_Rbx: 297 p = &ctx.Rbx 298 case regnum.AMD64_Rcx: 299 p = &ctx.Rcx 300 case regnum.AMD64_Rdx: 301 p = &ctx.Rdx 302 case regnum.AMD64_Rsi: 303 p = &ctx.Rsi 304 case regnum.AMD64_Rdi: 305 p = &ctx.Rdi 306 case regnum.AMD64_Rbp: 307 p = &ctx.Rbp 308 case regnum.AMD64_Rsp: 309 p = &ctx.Rsp 310 case regnum.AMD64_R8: 311 p = &ctx.R8 312 case regnum.AMD64_R9: 313 p = &ctx.R9 314 case regnum.AMD64_R10: 315 p = &ctx.R10 316 case regnum.AMD64_R11: 317 p = &ctx.R11 318 case regnum.AMD64_R12: 319 p = &ctx.R12 320 case regnum.AMD64_R13: 321 p = &ctx.R13 322 case regnum.AMD64_R14: 323 p = &ctx.R14 324 case regnum.AMD64_R15: 325 p = &ctx.R15 326 case regnum.AMD64_Rip: 327 p = &ctx.Rip 328 } 329 330 if p != nil { 331 if reg.Bytes != nil && len(reg.Bytes) != 8 { 332 return fmt.Errorf("wrong number of bytes for register %s (%d)", regnum.AMD64ToName(regNum), len(reg.Bytes)) 333 } 334 *p = reg.Uint64Val 335 } else if regNum == regnum.AMD64_Rflags { 336 ctx.EFlags = uint32(reg.Uint64Val) 337 } else { 338 if regNum < regnum.AMD64_XMM0 || regNum > regnum.AMD64_XMM0+15 { 339 return fmt.Errorf("can not set register %s", regnum.AMD64ToName(regNum)) 340 } 341 reg.FillBytes() 342 if len(reg.Bytes) > 16 { 343 return fmt.Errorf("too many bytes when setting register %s", regnum.AMD64ToName(regNum)) 344 } 345 copy(ctx.FltSave.XmmRegisters[(regNum-regnum.AMD64_XMM0)*16:], reg.Bytes) 346 } 347 return nil 348 }