mirror of
https://github.com/go-delve/delve.git
synced 2025-10-28 04:35:19 +08:00
proc: only format registers value when it's necessary (#1860)
A significant amount of time is spent generating the string representation for the proc.Registers object of each thread, since this field is rarely used (only when the Registers API is called) it should be generated on demand. Also by changing the internal representation of proc.Register to be closer to that of op.DwarfRegister it will help us implement #1838 (when Delve will need to be able to display the registers of an internal frame, which we currently represent using op.DwarfRegister objects). Benchmark before: BenchmarkConditionalBreakpoints-4 1 22292554301 ns/op Benchmark after: BenchmarkConditionalBreakpoints-4 1 17326345671 ns/op Reduces conditional breakpoint latency from 2.2ms to 1.7ms. Updates #1549, #1838
This commit is contained in:
committed by
GitHub
parent
abb57ff017
commit
b9d0ddd82c
@ -1,12 +1,15 @@
|
||||
package proc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/go-delve/delve/pkg/dwarf/frame"
|
||||
"github.com/go-delve/delve/pkg/dwarf/op"
|
||||
"golang.org/x/arch/x86/x86asm"
|
||||
)
|
||||
|
||||
// AMD64 represents the AMD64 CPU architecture.
|
||||
@ -300,24 +303,24 @@ func (a *AMD64) RegSize(regnum uint64) int {
|
||||
// figure 3.36
|
||||
// https://www.uclibc.org/docs/psABI-x86_64.pdf
|
||||
|
||||
var amd64DwarfToHardware = map[int]x86asm.Reg{
|
||||
0: x86asm.RAX,
|
||||
1: x86asm.RDX,
|
||||
2: x86asm.RCX,
|
||||
3: x86asm.RBX,
|
||||
4: x86asm.RSI,
|
||||
5: x86asm.RDI,
|
||||
8: x86asm.R8,
|
||||
9: x86asm.R9,
|
||||
10: x86asm.R10,
|
||||
11: x86asm.R11,
|
||||
12: x86asm.R12,
|
||||
13: x86asm.R13,
|
||||
14: x86asm.R14,
|
||||
15: x86asm.R15,
|
||||
}
|
||||
|
||||
var amd64DwarfToName = map[int]string{
|
||||
0: "Rax",
|
||||
1: "Rdx",
|
||||
2: "Rcx",
|
||||
3: "Rbx",
|
||||
4: "Rsi",
|
||||
5: "Rdi",
|
||||
6: "Rbp",
|
||||
7: "Rsp",
|
||||
8: "R8",
|
||||
9: "R9",
|
||||
10: "R10",
|
||||
11: "R11",
|
||||
12: "R12",
|
||||
13: "R13",
|
||||
14: "R14",
|
||||
15: "R15",
|
||||
16: "Rip",
|
||||
17: "XMM0",
|
||||
18: "XMM1",
|
||||
19: "XMM2",
|
||||
@ -356,13 +359,25 @@ var amd64DwarfToName = map[int]string{
|
||||
66: "SW",
|
||||
}
|
||||
|
||||
var amd64NameToDwarf = func() map[string]int {
|
||||
r := make(map[string]int)
|
||||
for regNum, regName := range amd64DwarfToName {
|
||||
r[strings.ToLower(regName)] = regNum
|
||||
}
|
||||
r["eflags"] = 49
|
||||
r["st0"] = 33
|
||||
r["st1"] = 34
|
||||
r["st2"] = 35
|
||||
r["st3"] = 36
|
||||
r["st4"] = 37
|
||||
r["st5"] = 38
|
||||
r["st6"] = 39
|
||||
r["st7"] = 40
|
||||
return r
|
||||
}()
|
||||
|
||||
func maxAmd64DwarfRegister() int {
|
||||
max := int(amd64DwarfIPRegNum)
|
||||
for i := range amd64DwarfToHardware {
|
||||
if i > max {
|
||||
max = i
|
||||
}
|
||||
}
|
||||
for i := range amd64DwarfToName {
|
||||
if i > max {
|
||||
max = i
|
||||
@ -376,22 +391,9 @@ func maxAmd64DwarfRegister() int {
|
||||
func (a *AMD64) RegistersToDwarfRegisters(staticBase uint64, regs Registers) op.DwarfRegisters {
|
||||
dregs := make([]*op.DwarfRegister, maxAmd64DwarfRegister()+1)
|
||||
|
||||
dregs[amd64DwarfIPRegNum] = op.DwarfRegisterFromUint64(regs.PC())
|
||||
dregs[amd64DwarfSPRegNum] = op.DwarfRegisterFromUint64(regs.SP())
|
||||
dregs[amd64DwarfBPRegNum] = op.DwarfRegisterFromUint64(regs.BP())
|
||||
|
||||
for dwarfReg, asmReg := range amd64DwarfToHardware {
|
||||
v, err := regs.Get(int(asmReg))
|
||||
if err == nil {
|
||||
dregs[dwarfReg] = op.DwarfRegisterFromUint64(v)
|
||||
}
|
||||
}
|
||||
|
||||
for _, reg := range regs.Slice(true) {
|
||||
for dwarfReg, regName := range amd64DwarfToName {
|
||||
if regName == reg.Name {
|
||||
dregs[dwarfReg] = op.DwarfRegisterFromBytes(reg.Bytes)
|
||||
}
|
||||
if dwarfReg, ok := amd64NameToDwarf[strings.ToLower(reg.Name)]; ok {
|
||||
dregs[dwarfReg] = reg.Reg
|
||||
}
|
||||
}
|
||||
|
||||
@ -422,3 +424,132 @@ func (a *AMD64) AddrAndStackRegsToDwarfRegisters(staticBase, pc, sp, bp, lr uint
|
||||
BPRegNum: amd64DwarfBPRegNum,
|
||||
}
|
||||
}
|
||||
|
||||
func (a *AMD64) DwarfRegisterToString(name string, reg *op.DwarfRegister) string {
|
||||
name = strings.ToLower(name)
|
||||
switch name {
|
||||
case "rflags":
|
||||
return eflagsDescription.Describe(reg.Uint64Val, 64)
|
||||
|
||||
case "cw", "sw", "tw", "fop":
|
||||
return fmt.Sprintf("%#04x", reg.Uint64Val)
|
||||
|
||||
case "mxcsr_mask":
|
||||
return fmt.Sprintf("%#08x", reg.Uint64Val)
|
||||
|
||||
case "mxcsr":
|
||||
return mxcsrDescription.Describe(reg.Uint64Val, 32)
|
||||
|
||||
default:
|
||||
if reg.Bytes != nil && strings.HasPrefix(name, "xmm") {
|
||||
return formatSSEReg(reg.Bytes)
|
||||
} else if reg.Bytes != nil && strings.HasPrefix(name, "st(") {
|
||||
return formatX87Reg(reg.Bytes)
|
||||
} else if reg.Bytes == nil || (reg.Bytes != nil && len(reg.Bytes) <= 8) {
|
||||
return fmt.Sprintf("%#016x", reg.Uint64Val)
|
||||
} else {
|
||||
return fmt.Sprintf("%#x", reg.Bytes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func formatSSEReg(xmm []byte) string {
|
||||
buf := bytes.NewReader(xmm)
|
||||
|
||||
var out bytes.Buffer
|
||||
var vi [16]uint8
|
||||
for i := range vi {
|
||||
binary.Read(buf, binary.LittleEndian, &vi[i])
|
||||
}
|
||||
|
||||
fmt.Fprintf(&out, "0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", vi[15], vi[14], vi[13], vi[12], vi[11], vi[10], vi[9], vi[8], vi[7], vi[6], vi[5], vi[4], vi[3], vi[2], vi[1], vi[0])
|
||||
|
||||
fmt.Fprintf(&out, "\tv2_int={ %02x%02x%02x%02x%02x%02x%02x%02x %02x%02x%02x%02x%02x%02x%02x%02x }", vi[7], vi[6], vi[5], vi[4], vi[3], vi[2], vi[1], vi[0], vi[15], vi[14], vi[13], vi[12], vi[11], vi[10], vi[9], vi[8])
|
||||
|
||||
fmt.Fprintf(&out, "\tv4_int={ %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x }", vi[3], vi[2], vi[1], vi[0], vi[7], vi[6], vi[5], vi[4], vi[11], vi[10], vi[9], vi[8], vi[15], vi[14], vi[13], vi[12])
|
||||
|
||||
fmt.Fprintf(&out, "\tv8_int={ %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x }", vi[1], vi[0], vi[3], vi[2], vi[5], vi[4], vi[7], vi[6], vi[9], vi[8], vi[11], vi[10], vi[13], vi[12], vi[15], vi[14])
|
||||
|
||||
fmt.Fprintf(&out, "\tv16_int={ %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x }", vi[0], vi[1], vi[2], vi[3], vi[4], vi[5], vi[6], vi[7], vi[8], vi[9], vi[10], vi[11], vi[12], vi[13], vi[14], vi[15])
|
||||
|
||||
buf.Seek(0, os.SEEK_SET)
|
||||
var v2 [2]float64
|
||||
for i := range v2 {
|
||||
binary.Read(buf, binary.LittleEndian, &v2[i])
|
||||
}
|
||||
fmt.Fprintf(&out, "\tv2_float={ %g %g }", v2[0], v2[1])
|
||||
|
||||
buf.Seek(0, os.SEEK_SET)
|
||||
var v4 [4]float32
|
||||
for i := range v4 {
|
||||
binary.Read(buf, binary.LittleEndian, &v4[i])
|
||||
}
|
||||
fmt.Fprintf(&out, "\tv4_float={ %g %g %g %g }", v4[0], v4[1], v4[2], v4[3])
|
||||
|
||||
return out.String()
|
||||
}
|
||||
|
||||
func formatX87Reg(b []byte) string {
|
||||
if len(b) < 10 {
|
||||
return fmt.Sprintf("%#x", b)
|
||||
}
|
||||
mantissa := binary.LittleEndian.Uint64(b[:8])
|
||||
exponent := uint16(binary.LittleEndian.Uint16(b[8:]))
|
||||
|
||||
var f float64
|
||||
fset := false
|
||||
|
||||
const (
|
||||
_SIGNBIT = 1 << 15
|
||||
_EXP_BIAS = (1 << 14) - 1 // 2^(n-1) - 1 = 16383
|
||||
_SPECIALEXP = (1 << 15) - 1 // all bits set
|
||||
_HIGHBIT = 1 << 63
|
||||
_QUIETBIT = 1 << 62
|
||||
)
|
||||
|
||||
sign := 1.0
|
||||
if exponent&_SIGNBIT != 0 {
|
||||
sign = -1.0
|
||||
}
|
||||
exponent &= ^uint16(_SIGNBIT)
|
||||
|
||||
NaN := math.NaN()
|
||||
Inf := math.Inf(+1)
|
||||
|
||||
switch exponent {
|
||||
case 0:
|
||||
switch {
|
||||
case mantissa == 0:
|
||||
f = sign * 0.0
|
||||
fset = true
|
||||
case mantissa&_HIGHBIT != 0:
|
||||
f = NaN
|
||||
fset = true
|
||||
}
|
||||
case _SPECIALEXP:
|
||||
switch {
|
||||
case mantissa&_HIGHBIT == 0:
|
||||
f = sign * Inf
|
||||
fset = true
|
||||
default:
|
||||
f = NaN // signaling NaN
|
||||
fset = true
|
||||
}
|
||||
default:
|
||||
if mantissa&_HIGHBIT == 0 {
|
||||
f = NaN
|
||||
fset = true
|
||||
}
|
||||
}
|
||||
|
||||
if !fset {
|
||||
significand := float64(mantissa) / (1 << 63)
|
||||
f = sign * math.Ldexp(significand, int(exponent-_EXP_BIAS))
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
binary.Write(&buf, binary.LittleEndian, exponent)
|
||||
binary.Write(&buf, binary.LittleEndian, mantissa)
|
||||
|
||||
return fmt.Sprintf("%#04x%016x\t%g", exponent, mantissa, f)
|
||||
}
|
||||
|
||||
@ -21,6 +21,7 @@ type Arch interface {
|
||||
RegSize(uint64) int
|
||||
RegistersToDwarfRegisters(uint64, Registers) op.DwarfRegisters
|
||||
AddrAndStackRegsToDwarfRegisters(uint64, uint64, uint64, uint64, uint64) op.DwarfRegisters
|
||||
DwarfRegisterToString(string, *op.DwarfRegister) string
|
||||
}
|
||||
|
||||
const (
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
package proc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/go-delve/delve/pkg/dwarf/frame"
|
||||
@ -406,3 +409,44 @@ func (a *ARM64) AddrAndStackRegsToDwarfRegisters(staticBase, pc, sp, bp, lr uint
|
||||
LRRegNum: arm64DwarfLRRegNum,
|
||||
}
|
||||
}
|
||||
|
||||
func (a *ARM64) DwarfRegisterToString(name string, reg *op.DwarfRegister) string {
|
||||
if reg.Bytes != nil && (name[0] == 'v' || name[0] == 'V') {
|
||||
buf := bytes.NewReader(reg.Bytes)
|
||||
|
||||
var out bytes.Buffer
|
||||
var vi [16]uint8
|
||||
for i := range vi {
|
||||
binary.Read(buf, binary.LittleEndian, &vi[i])
|
||||
}
|
||||
|
||||
fmt.Fprintf(&out, "0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", vi[15], vi[14], vi[13], vi[12], vi[11], vi[10], vi[9], vi[8], vi[7], vi[6], vi[5], vi[4], vi[3], vi[2], vi[1], vi[0])
|
||||
|
||||
fmt.Fprintf(&out, "\tv2_int={ %02x%02x%02x%02x%02x%02x%02x%02x %02x%02x%02x%02x%02x%02x%02x%02x }", vi[7], vi[6], vi[5], vi[4], vi[3], vi[2], vi[1], vi[0], vi[15], vi[14], vi[13], vi[12], vi[11], vi[10], vi[9], vi[8])
|
||||
|
||||
fmt.Fprintf(&out, "\tv4_int={ %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x }", vi[3], vi[2], vi[1], vi[0], vi[7], vi[6], vi[5], vi[4], vi[11], vi[10], vi[9], vi[8], vi[15], vi[14], vi[13], vi[12])
|
||||
|
||||
fmt.Fprintf(&out, "\tv8_int={ %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x }", vi[1], vi[0], vi[3], vi[2], vi[5], vi[4], vi[7], vi[6], vi[9], vi[8], vi[11], vi[10], vi[13], vi[12], vi[15], vi[14])
|
||||
|
||||
fmt.Fprintf(&out, "\tv16_int={ %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x }", vi[0], vi[1], vi[2], vi[3], vi[4], vi[5], vi[6], vi[7], vi[8], vi[9], vi[10], vi[11], vi[12], vi[13], vi[14], vi[15])
|
||||
|
||||
buf.Seek(0, os.SEEK_SET)
|
||||
var v2 [2]float64
|
||||
for i := range v2 {
|
||||
binary.Read(buf, binary.LittleEndian, &v2[i])
|
||||
}
|
||||
fmt.Fprintf(&out, "\tv2_float={ %g %g }", v2[0], v2[1])
|
||||
|
||||
buf.Seek(0, os.SEEK_SET)
|
||||
var v4 [4]float32
|
||||
for i := range v4 {
|
||||
binary.Read(buf, binary.LittleEndian, &v4[i])
|
||||
}
|
||||
fmt.Fprintf(&out, "\tv4_float={ %g %g %g %g }", v4[0], v4[1], v4[2], v4[3])
|
||||
|
||||
return out.String()
|
||||
} else if reg.Bytes == nil || (reg.Bytes != nil && len(reg.Bytes) < 16) {
|
||||
return fmt.Sprintf("%#016x", reg.Uint64Val)
|
||||
}
|
||||
return fmt.Sprintf("%#x", reg.Bytes)
|
||||
}
|
||||
|
||||
@ -244,8 +244,9 @@ func TestCore(t *testing.T) {
|
||||
t.Fatalf("Couldn't get current thread registers: %v", err)
|
||||
}
|
||||
regslice := regs.Slice(true)
|
||||
arch := p.BinInfo().Arch
|
||||
for _, reg := range regslice {
|
||||
t.Logf("%s = %s", reg.Name, reg.Value)
|
||||
t.Logf("%s = %s", reg.Name, arch.DwarfRegisterToString(reg.Name, reg.Reg))
|
||||
}
|
||||
}
|
||||
|
||||
@ -312,8 +313,9 @@ func TestCoreFpRegisters(t *testing.T) {
|
||||
{"XMM8", "0x4059999a404ccccd4059999a404ccccd"},
|
||||
}
|
||||
|
||||
arch := p.BinInfo().Arch
|
||||
for _, reg := range regs.Slice(true) {
|
||||
t.Logf("%s = %s", reg.Name, reg.Value)
|
||||
t.Logf("%s = %s", reg.Name, arch.DwarfRegisterToString(reg.Name, reg.Reg))
|
||||
}
|
||||
|
||||
for _, regtest := range regtests {
|
||||
@ -321,8 +323,9 @@ func TestCoreFpRegisters(t *testing.T) {
|
||||
for _, reg := range regs.Slice(true) {
|
||||
if reg.Name == regtest.name {
|
||||
found = true
|
||||
if !strings.HasPrefix(reg.Value, regtest.value) {
|
||||
t.Fatalf("register %s expected %q got %q", reg.Name, regtest.value, reg.Value)
|
||||
regval := arch.DwarfRegisterToString(reg.Name, reg.Reg)
|
||||
if !strings.HasPrefix(regval, regtest.value) {
|
||||
t.Fatalf("register %s expected %q got %q", reg.Name, regtest.value, regval)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -101,17 +101,17 @@ func (r *AMD64Registers) Slice(floatingPoint bool) []proc.Register {
|
||||
// FreeBSD defines the registers as signed, but Linux defines
|
||||
// them as unsigned. Of course, a register doesn't really have
|
||||
// a concept of signedness. Cast to what Delve expects.
|
||||
out = proc.AppendQwordReg(out, reg.k, uint64(reg.v))
|
||||
out = proc.AppendUint64Register(out, reg.k, uint64(reg.v))
|
||||
}
|
||||
for _, reg := range regs32 {
|
||||
out = proc.AppendDwordReg(out, reg.k, reg.v)
|
||||
out = proc.AppendUint64Register(out, reg.k, uint64(reg.v))
|
||||
}
|
||||
for _, reg := range regs16 {
|
||||
out = proc.AppendWordReg(out, reg.k, reg.v)
|
||||
out = proc.AppendUint64Register(out, reg.k, uint64(reg.v))
|
||||
}
|
||||
// x86 called this register "Eflags". amd64 extended it and renamed it
|
||||
// "Rflags", but Linux still uses the old name.
|
||||
out = proc.AppendEflagReg(out, "Rflags", uint64(r.Regs.Rflags))
|
||||
out = proc.AppendUint64Register(out, "Rflags", uint64(r.Regs.Rflags))
|
||||
if floatingPoint {
|
||||
out = append(out, r.Fpregs...)
|
||||
}
|
||||
|
||||
@ -1903,15 +1903,15 @@ func (regs *gdbRegisters) Slice(floatingPoint bool) []proc.Register {
|
||||
}
|
||||
switch {
|
||||
case reginfo.Name == "eflags":
|
||||
r = proc.AppendEflagReg(r, reginfo.Name, uint64(binary.LittleEndian.Uint32(regs.regs[reginfo.Name].value)))
|
||||
r = proc.AppendBytesRegister(r, "Rflags", regs.regs[reginfo.Name].value)
|
||||
case reginfo.Name == "mxcsr":
|
||||
r = proc.AppendMxcsrReg(r, reginfo.Name, uint64(binary.LittleEndian.Uint32(regs.regs[reginfo.Name].value)))
|
||||
r = proc.AppendBytesRegister(r, reginfo.Name, regs.regs[reginfo.Name].value)
|
||||
case reginfo.Bitsize == 16:
|
||||
r = proc.AppendWordReg(r, reginfo.Name, binary.LittleEndian.Uint16(regs.regs[reginfo.Name].value))
|
||||
r = proc.AppendBytesRegister(r, reginfo.Name, regs.regs[reginfo.Name].value)
|
||||
case reginfo.Bitsize == 32:
|
||||
r = proc.AppendDwordReg(r, reginfo.Name, binary.LittleEndian.Uint32(regs.regs[reginfo.Name].value))
|
||||
r = proc.AppendBytesRegister(r, reginfo.Name, regs.regs[reginfo.Name].value)
|
||||
case reginfo.Bitsize == 64:
|
||||
r = proc.AppendQwordReg(r, reginfo.Name, binary.LittleEndian.Uint64(regs.regs[reginfo.Name].value))
|
||||
r = proc.AppendBytesRegister(r, reginfo.Name, regs.regs[reginfo.Name].value)
|
||||
case reginfo.Bitsize == 80:
|
||||
if !floatingPoint {
|
||||
continue
|
||||
@ -1923,12 +1923,11 @@ func (regs *gdbRegisters) Slice(floatingPoint bool) []proc.Register {
|
||||
break
|
||||
}
|
||||
}
|
||||
value := regs.regs[reginfo.Name].value
|
||||
r = proc.AppendX87Reg(r, idx, binary.LittleEndian.Uint16(value[8:]), binary.LittleEndian.Uint64(value[:8]))
|
||||
r = proc.AppendBytesRegister(r, fmt.Sprintf("ST(%d)", idx), regs.regs[reginfo.Name].value)
|
||||
|
||||
case reginfo.Bitsize == 128:
|
||||
if floatingPoint {
|
||||
r = proc.AppendSSEReg(r, strings.ToUpper(reginfo.Name), regs.regs[reginfo.Name].value)
|
||||
r = proc.AppendBytesRegister(r, strings.ToUpper(reginfo.Name), regs.regs[reginfo.Name].value)
|
||||
}
|
||||
|
||||
case reginfo.Bitsize == 256:
|
||||
@ -1938,8 +1937,8 @@ func (regs *gdbRegisters) Slice(floatingPoint bool) []proc.Register {
|
||||
|
||||
value := regs.regs[reginfo.Name].value
|
||||
xmmName := "x" + reginfo.Name[1:]
|
||||
r = proc.AppendSSEReg(r, strings.ToUpper(xmmName), value[:16])
|
||||
r = proc.AppendSSEReg(r, strings.ToUpper(reginfo.Name), value[16:])
|
||||
r = proc.AppendBytesRegister(r, strings.ToUpper(xmmName), value[:16])
|
||||
r = proc.AppendBytesRegister(r, strings.ToUpper(reginfo.Name), value[16:])
|
||||
}
|
||||
}
|
||||
return r
|
||||
|
||||
@ -75,7 +75,7 @@ func (r *AMD64Registers) Slice(floatingPoint bool) []proc.Register {
|
||||
{"R15", r.Regs.R15},
|
||||
{"Orig_rax", r.Regs.Orig_rax},
|
||||
{"Cs", r.Regs.Cs},
|
||||
{"Eflags", r.Regs.Eflags},
|
||||
{"Rflags", r.Regs.Eflags},
|
||||
{"Ss", r.Regs.Ss},
|
||||
{"Fs_base", r.Regs.Fs_base},
|
||||
{"Gs_base", r.Regs.Gs_base},
|
||||
@ -86,11 +86,7 @@ func (r *AMD64Registers) Slice(floatingPoint bool) []proc.Register {
|
||||
}
|
||||
out := make([]proc.Register, 0, len(regs)+len(r.Fpregs))
|
||||
for _, reg := range regs {
|
||||
if reg.k == "Eflags" {
|
||||
out = proc.AppendEflagReg(out, reg.k, reg.v)
|
||||
} else {
|
||||
out = proc.AppendQwordReg(out, reg.k, reg.v)
|
||||
}
|
||||
out = proc.AppendUint64Register(out, reg.k, reg.v)
|
||||
}
|
||||
if floatingPoint {
|
||||
out = append(out, r.Fpregs...)
|
||||
@ -325,25 +321,28 @@ type AMD64Xstate struct {
|
||||
// Decode decodes an XSAVE area to a list of name/value pairs of registers.
|
||||
func (xsave *AMD64Xstate) Decode() (regs []proc.Register) {
|
||||
// x87 registers
|
||||
regs = proc.AppendWordReg(regs, "CW", xsave.Cwd)
|
||||
regs = proc.AppendWordReg(regs, "SW", xsave.Swd)
|
||||
regs = proc.AppendWordReg(regs, "TW", xsave.Ftw)
|
||||
regs = proc.AppendWordReg(regs, "FOP", xsave.Fop)
|
||||
regs = proc.AppendQwordReg(regs, "FIP", xsave.Rip)
|
||||
regs = proc.AppendQwordReg(regs, "FDP", xsave.Rdp)
|
||||
regs = proc.AppendUint64Register(regs, "CW", uint64(xsave.Cwd))
|
||||
regs = proc.AppendUint64Register(regs, "SW", uint64(xsave.Swd))
|
||||
regs = proc.AppendUint64Register(regs, "TW", uint64(xsave.Ftw))
|
||||
regs = proc.AppendUint64Register(regs, "FOP", uint64(xsave.Fop))
|
||||
regs = proc.AppendUint64Register(regs, "FIP", xsave.Rip)
|
||||
regs = proc.AppendUint64Register(regs, "FDP", xsave.Rdp)
|
||||
|
||||
for i := 0; i < len(xsave.StSpace); i += 4 {
|
||||
regs = proc.AppendX87Reg(regs, i/4, uint16(xsave.StSpace[i+2]), uint64(xsave.StSpace[i+1])<<32|uint64(xsave.StSpace[i]))
|
||||
var buf bytes.Buffer
|
||||
binary.Write(&buf, binary.LittleEndian, uint64(xsave.StSpace[i+1])<<32|uint64(xsave.StSpace[i]))
|
||||
binary.Write(&buf, binary.LittleEndian, uint16(xsave.StSpace[i+2]))
|
||||
regs = proc.AppendBytesRegister(regs, fmt.Sprintf("ST(%d)", i/4), buf.Bytes())
|
||||
}
|
||||
|
||||
// SSE registers
|
||||
regs = proc.AppendMxcsrReg(regs, "MXCSR", uint64(xsave.Mxcsr))
|
||||
regs = proc.AppendDwordReg(regs, "MXCSR_MASK", xsave.MxcrMask)
|
||||
regs = proc.AppendUint64Register(regs, "MXCSR", uint64(xsave.Mxcsr))
|
||||
regs = proc.AppendUint64Register(regs, "MXCSR_MASK", uint64(xsave.MxcrMask))
|
||||
|
||||
for i := 0; i < len(xsave.XmmSpace); i += 16 {
|
||||
regs = proc.AppendSSEReg(regs, fmt.Sprintf("XMM%d", i/16), xsave.XmmSpace[i:i+16])
|
||||
regs = proc.AppendBytesRegister(regs, fmt.Sprintf("XMM%d", i/16), xsave.XmmSpace[i:i+16])
|
||||
if xsave.AvxState {
|
||||
regs = proc.AppendSSEReg(regs, fmt.Sprintf("YMM%d", i/16), xsave.YmmSpace[i:i+16])
|
||||
regs = proc.AppendBytesRegister(regs, fmt.Sprintf("YMM%d", i/16), xsave.YmmSpace[i:i+16])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -67,7 +67,7 @@ func (r *ARM64Registers) Slice(floatingPoint bool) []proc.Register {
|
||||
}
|
||||
out := make([]proc.Register, 0, len(regs64)+len(r.Fpregs))
|
||||
for _, reg := range regs64 {
|
||||
out = proc.AppendQwordReg(out, reg.k, reg.v)
|
||||
out = proc.AppendUint64Register(out, reg.k, reg.v)
|
||||
}
|
||||
out = append(out, r.Fpregs...)
|
||||
return out
|
||||
@ -128,7 +128,7 @@ func (r *ARM64Registers) Copy() proc.Registers {
|
||||
// Decode decodes an XSAVE area to a list of name/value pairs of registers.
|
||||
func Decode(fpregs []byte) (regs []proc.Register) {
|
||||
for i := 0; i < len(fpregs); i += 16 {
|
||||
regs = proc.AppendFPReg(regs, fmt.Sprintf("V%d", i/16), fpregs[i:i+16])
|
||||
regs = proc.AppendBytesRegister(regs, fmt.Sprintf("V%d", i/16), fpregs[i:i+16])
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -5,7 +5,6 @@ package native
|
||||
// #include "threads_darwin.h"
|
||||
import "C"
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"unsafe"
|
||||
@ -73,9 +72,9 @@ func (r *Regs) Slice(floatingPoint bool) []proc.Register {
|
||||
out := make([]proc.Register, 0, len(regs)+len(r.fpregs))
|
||||
for _, reg := range regs {
|
||||
if reg.k == "Rflags" {
|
||||
out = proc.AppendEflagReg(out, reg.k, reg.v)
|
||||
out = proc.AppendUint64Register(out, reg.k, reg.v)
|
||||
} else {
|
||||
out = proc.AppendQwordReg(out, reg.k, reg.v)
|
||||
out = proc.AppendUint64Register(out, reg.k, reg.v)
|
||||
}
|
||||
}
|
||||
if floatingPoint {
|
||||
@ -342,25 +341,23 @@ func registers(thread *Thread, floatingPoint bool) (proc.Registers, error) {
|
||||
return nil, fmt.Errorf("could not get floating point registers")
|
||||
}
|
||||
|
||||
regs.fpregs = proc.AppendWordReg(regs.fpregs, "CW", *((*uint16)(unsafe.Pointer(&fpstate.__fpu_fcw))))
|
||||
regs.fpregs = proc.AppendWordReg(regs.fpregs, "SW", *((*uint16)(unsafe.Pointer(&fpstate.__fpu_fsw))))
|
||||
regs.fpregs = proc.AppendWordReg(regs.fpregs, "TW", uint16(fpstate.__fpu_ftw))
|
||||
regs.fpregs = proc.AppendWordReg(regs.fpregs, "FOP", uint16(fpstate.__fpu_fop))
|
||||
regs.fpregs = proc.AppendQwordReg(regs.fpregs, "FIP", uint64(fpstate.__fpu_cs)<<32|uint64(fpstate.__fpu_ip))
|
||||
regs.fpregs = proc.AppendQwordReg(regs.fpregs, "FDP", uint64(fpstate.__fpu_ds)<<32|uint64(fpstate.__fpu_dp))
|
||||
regs.fpregs = proc.AppendUint64Register(regs.fpregs, "CW", uint64(*((*uint16)(unsafe.Pointer(&fpstate.__fpu_fcw)))))
|
||||
regs.fpregs = proc.AppendUint64Register(regs.fpregs, "SW", uint64(*((*uint16)(unsafe.Pointer(&fpstate.__fpu_fsw)))))
|
||||
regs.fpregs = proc.AppendUint64Register(regs.fpregs, "TW", uint64(fpstate.__fpu_ftw))
|
||||
regs.fpregs = proc.AppendUint64Register(regs.fpregs, "FOP", uint64(fpstate.__fpu_fop))
|
||||
regs.fpregs = proc.AppendUint64Register(regs.fpregs, "FIP", uint64(fpstate.__fpu_cs)<<32|uint64(fpstate.__fpu_ip))
|
||||
regs.fpregs = proc.AppendUint64Register(regs.fpregs, "FDP", uint64(fpstate.__fpu_ds)<<32|uint64(fpstate.__fpu_dp))
|
||||
|
||||
for i, st := range []*C.char{&fpstate.__fpu_stmm0.__mmst_reg[0], &fpstate.__fpu_stmm1.__mmst_reg[0], &fpstate.__fpu_stmm2.__mmst_reg[0], &fpstate.__fpu_stmm3.__mmst_reg[0], &fpstate.__fpu_stmm4.__mmst_reg[0], &fpstate.__fpu_stmm5.__mmst_reg[0], &fpstate.__fpu_stmm6.__mmst_reg[0], &fpstate.__fpu_stmm7.__mmst_reg[0]} {
|
||||
stb := C.GoBytes(unsafe.Pointer(st), 10)
|
||||
mantissa := binary.LittleEndian.Uint64(stb[:8])
|
||||
exponent := binary.LittleEndian.Uint16(stb[8:])
|
||||
regs.fpregs = proc.AppendX87Reg(regs.fpregs, i, exponent, mantissa)
|
||||
regs.fpregs = proc.AppendBytesRegister(regs.fpregs, fmt.Sprintf("ST(%d)", i), stb)
|
||||
}
|
||||
|
||||
regs.fpregs = proc.AppendMxcsrReg(regs.fpregs, "MXCSR", uint64(fpstate.__fpu_mxcsr))
|
||||
regs.fpregs = proc.AppendDwordReg(regs.fpregs, "MXCSR_MASK", uint32(fpstate.__fpu_mxcsrmask))
|
||||
regs.fpregs = proc.AppendUint64Register(regs.fpregs, "MXCSR", uint64(fpstate.__fpu_mxcsr))
|
||||
regs.fpregs = proc.AppendUint64Register(regs.fpregs, "MXCSR_MASK", uint64(fpstate.__fpu_mxcsrmask))
|
||||
|
||||
for i, xmm := range []*C.char{&fpstate.__fpu_xmm0.__xmm_reg[0], &fpstate.__fpu_xmm1.__xmm_reg[0], &fpstate.__fpu_xmm2.__xmm_reg[0], &fpstate.__fpu_xmm3.__xmm_reg[0], &fpstate.__fpu_xmm4.__xmm_reg[0], &fpstate.__fpu_xmm5.__xmm_reg[0], &fpstate.__fpu_xmm6.__xmm_reg[0], &fpstate.__fpu_xmm7.__xmm_reg[0], &fpstate.__fpu_xmm8.__xmm_reg[0], &fpstate.__fpu_xmm9.__xmm_reg[0], &fpstate.__fpu_xmm10.__xmm_reg[0], &fpstate.__fpu_xmm11.__xmm_reg[0], &fpstate.__fpu_xmm12.__xmm_reg[0], &fpstate.__fpu_xmm13.__xmm_reg[0], &fpstate.__fpu_xmm14.__xmm_reg[0], &fpstate.__fpu_xmm15.__xmm_reg[0]} {
|
||||
regs.fpregs = proc.AppendSSEReg(regs.fpregs, fmt.Sprintf("XMM%d", i), C.GoBytes(unsafe.Pointer(xmm), 16))
|
||||
regs.fpregs = proc.AppendBytesRegister(regs.fpregs, fmt.Sprintf("XMM%d", i), C.GoBytes(unsafe.Pointer(xmm), 16))
|
||||
}
|
||||
}
|
||||
return regs, nil
|
||||
|
||||
@ -1,13 +1,12 @@
|
||||
package proc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/go-delve/delve/pkg/dwarf/op"
|
||||
)
|
||||
|
||||
// Registers is an interface for a generic register type. The
|
||||
@ -30,180 +29,16 @@ type Registers interface {
|
||||
|
||||
// Register represents a CPU register.
|
||||
type Register struct {
|
||||
Name string
|
||||
Bytes []byte
|
||||
Value string
|
||||
Name string
|
||||
Reg *op.DwarfRegister
|
||||
}
|
||||
|
||||
// AppendWordReg appends a word (16 bit) register to regs.
|
||||
func AppendWordReg(regs []Register, name string, value uint16) []Register {
|
||||
var buf bytes.Buffer
|
||||
binary.Write(&buf, binary.LittleEndian, value)
|
||||
return append(regs, Register{name, buf.Bytes(), fmt.Sprintf("%#04x", value)})
|
||||
func AppendUint64Register(regs []Register, name string, value uint64) []Register {
|
||||
return append(regs, Register{name, op.DwarfRegisterFromUint64(value)})
|
||||
}
|
||||
|
||||
// AppendDwordReg appends a double word (32 bit) register to regs.
|
||||
func AppendDwordReg(regs []Register, name string, value uint32) []Register {
|
||||
var buf bytes.Buffer
|
||||
binary.Write(&buf, binary.LittleEndian, value)
|
||||
return append(regs, Register{name, buf.Bytes(), fmt.Sprintf("%#08x", value)})
|
||||
}
|
||||
|
||||
// AppendQwordReg appends a quad word (64 bit) register to regs.
|
||||
func AppendQwordReg(regs []Register, name string, value uint64) []Register {
|
||||
var buf bytes.Buffer
|
||||
binary.Write(&buf, binary.LittleEndian, value)
|
||||
return append(regs, Register{name, buf.Bytes(), fmt.Sprintf("%#016x", value)})
|
||||
}
|
||||
|
||||
func appendFlagReg(regs []Register, name string, value uint64, descr flagRegisterDescr, size int) []Register {
|
||||
var buf bytes.Buffer
|
||||
binary.Write(&buf, binary.LittleEndian, value)
|
||||
return append(regs, Register{name, buf.Bytes()[:size], descr.Describe(value, size)})
|
||||
}
|
||||
|
||||
// AppendEflagReg appends EFLAG register to regs.
|
||||
func AppendEflagReg(regs []Register, name string, value uint64) []Register {
|
||||
return appendFlagReg(regs, name, value, eflagsDescription, 64)
|
||||
}
|
||||
|
||||
// AppendMxcsrReg appends MXCSR register to regs.
|
||||
func AppendMxcsrReg(regs []Register, name string, value uint64) []Register {
|
||||
return appendFlagReg(regs, name, value, mxcsrDescription, 32)
|
||||
}
|
||||
|
||||
// AppendX87Reg appends a 80 bit float register to regs.
|
||||
func AppendX87Reg(regs []Register, index int, exponent uint16, mantissa uint64) []Register {
|
||||
var f float64
|
||||
fset := false
|
||||
|
||||
const (
|
||||
_SIGNBIT = 1 << 15
|
||||
_EXP_BIAS = (1 << 14) - 1 // 2^(n-1) - 1 = 16383
|
||||
_SPECIALEXP = (1 << 15) - 1 // all bits set
|
||||
_HIGHBIT = 1 << 63
|
||||
_QUIETBIT = 1 << 62
|
||||
)
|
||||
|
||||
sign := 1.0
|
||||
if exponent&_SIGNBIT != 0 {
|
||||
sign = -1.0
|
||||
}
|
||||
exponent &= ^uint16(_SIGNBIT)
|
||||
|
||||
NaN := math.NaN()
|
||||
Inf := math.Inf(+1)
|
||||
|
||||
switch exponent {
|
||||
case 0:
|
||||
switch {
|
||||
case mantissa == 0:
|
||||
f = sign * 0.0
|
||||
fset = true
|
||||
case mantissa&_HIGHBIT != 0:
|
||||
f = NaN
|
||||
fset = true
|
||||
}
|
||||
case _SPECIALEXP:
|
||||
switch {
|
||||
case mantissa&_HIGHBIT == 0:
|
||||
f = sign * Inf
|
||||
fset = true
|
||||
default:
|
||||
f = NaN // signaling NaN
|
||||
fset = true
|
||||
}
|
||||
default:
|
||||
if mantissa&_HIGHBIT == 0 {
|
||||
f = NaN
|
||||
fset = true
|
||||
}
|
||||
}
|
||||
|
||||
if !fset {
|
||||
significand := float64(mantissa) / (1 << 63)
|
||||
f = sign * math.Ldexp(significand, int(exponent-_EXP_BIAS))
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
binary.Write(&buf, binary.LittleEndian, exponent)
|
||||
binary.Write(&buf, binary.LittleEndian, mantissa)
|
||||
|
||||
return append(regs, Register{fmt.Sprintf("ST(%d)", index), buf.Bytes(), fmt.Sprintf("%#04x%016x\t%g", exponent, mantissa, f)})
|
||||
}
|
||||
|
||||
// AppendSSEReg appends a 256 bit SSE register to regs.
|
||||
func AppendSSEReg(regs []Register, name string, xmm []byte) []Register {
|
||||
buf := bytes.NewReader(xmm)
|
||||
|
||||
var out bytes.Buffer
|
||||
var vi [16]uint8
|
||||
for i := range vi {
|
||||
binary.Read(buf, binary.LittleEndian, &vi[i])
|
||||
}
|
||||
|
||||
fmt.Fprintf(&out, "0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", vi[15], vi[14], vi[13], vi[12], vi[11], vi[10], vi[9], vi[8], vi[7], vi[6], vi[5], vi[4], vi[3], vi[2], vi[1], vi[0])
|
||||
|
||||
fmt.Fprintf(&out, "\tv2_int={ %02x%02x%02x%02x%02x%02x%02x%02x %02x%02x%02x%02x%02x%02x%02x%02x }", vi[7], vi[6], vi[5], vi[4], vi[3], vi[2], vi[1], vi[0], vi[15], vi[14], vi[13], vi[12], vi[11], vi[10], vi[9], vi[8])
|
||||
|
||||
fmt.Fprintf(&out, "\tv4_int={ %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x }", vi[3], vi[2], vi[1], vi[0], vi[7], vi[6], vi[5], vi[4], vi[11], vi[10], vi[9], vi[8], vi[15], vi[14], vi[13], vi[12])
|
||||
|
||||
fmt.Fprintf(&out, "\tv8_int={ %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x }", vi[1], vi[0], vi[3], vi[2], vi[5], vi[4], vi[7], vi[6], vi[9], vi[8], vi[11], vi[10], vi[13], vi[12], vi[15], vi[14])
|
||||
|
||||
fmt.Fprintf(&out, "\tv16_int={ %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x }", vi[0], vi[1], vi[2], vi[3], vi[4], vi[5], vi[6], vi[7], vi[8], vi[9], vi[10], vi[11], vi[12], vi[13], vi[14], vi[15])
|
||||
|
||||
buf.Seek(0, os.SEEK_SET)
|
||||
var v2 [2]float64
|
||||
for i := range v2 {
|
||||
binary.Read(buf, binary.LittleEndian, &v2[i])
|
||||
}
|
||||
fmt.Fprintf(&out, "\tv2_float={ %g %g }", v2[0], v2[1])
|
||||
|
||||
buf.Seek(0, os.SEEK_SET)
|
||||
var v4 [4]float32
|
||||
for i := range v4 {
|
||||
binary.Read(buf, binary.LittleEndian, &v4[i])
|
||||
}
|
||||
fmt.Fprintf(&out, "\tv4_float={ %g %g %g %g }", v4[0], v4[1], v4[2], v4[3])
|
||||
|
||||
return append(regs, Register{name, xmm, out.String()})
|
||||
}
|
||||
|
||||
// AppendFPReg appends a 128 bit FP register to regs.
|
||||
func AppendFPReg(regs []Register, name string, reg_value []byte) []Register {
|
||||
buf := bytes.NewReader(reg_value)
|
||||
|
||||
var out bytes.Buffer
|
||||
var vi [16]uint8
|
||||
for i := range vi {
|
||||
binary.Read(buf, binary.LittleEndian, &vi[i])
|
||||
}
|
||||
|
||||
fmt.Fprintf(&out, "0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", vi[15], vi[14], vi[13], vi[12], vi[11], vi[10], vi[9], vi[8], vi[7], vi[6], vi[5], vi[4], vi[3], vi[2], vi[1], vi[0])
|
||||
|
||||
fmt.Fprintf(&out, "\tv2_int={ %02x%02x%02x%02x%02x%02x%02x%02x %02x%02x%02x%02x%02x%02x%02x%02x }", vi[7], vi[6], vi[5], vi[4], vi[3], vi[2], vi[1], vi[0], vi[15], vi[14], vi[13], vi[12], vi[11], vi[10], vi[9], vi[8])
|
||||
|
||||
fmt.Fprintf(&out, "\tv4_int={ %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x }", vi[3], vi[2], vi[1], vi[0], vi[7], vi[6], vi[5], vi[4], vi[11], vi[10], vi[9], vi[8], vi[15], vi[14], vi[13], vi[12])
|
||||
|
||||
fmt.Fprintf(&out, "\tv8_int={ %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x }", vi[1], vi[0], vi[3], vi[2], vi[5], vi[4], vi[7], vi[6], vi[9], vi[8], vi[11], vi[10], vi[13], vi[12], vi[15], vi[14])
|
||||
|
||||
fmt.Fprintf(&out, "\tv16_int={ %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x }", vi[0], vi[1], vi[2], vi[3], vi[4], vi[5], vi[6], vi[7], vi[8], vi[9], vi[10], vi[11], vi[12], vi[13], vi[14], vi[15])
|
||||
|
||||
buf.Seek(0, os.SEEK_SET)
|
||||
var v2 [2]float64
|
||||
for i := range v2 {
|
||||
binary.Read(buf, binary.LittleEndian, &v2[i])
|
||||
}
|
||||
fmt.Fprintf(&out, "\tv2_float={ %g %g }", v2[0], v2[1])
|
||||
|
||||
buf.Seek(0, os.SEEK_SET)
|
||||
var v4 [4]float32
|
||||
for i := range v4 {
|
||||
binary.Read(buf, binary.LittleEndian, &v4[i])
|
||||
}
|
||||
fmt.Fprintf(&out, "\tv4_float={ %g %g %g %g }", v4[0], v4[1], v4[2], v4[3])
|
||||
|
||||
return append(regs, Register{name, reg_value, out.String()})
|
||||
func AppendBytesRegister(regs []Register, name string, value []byte) []Register {
|
||||
return append(regs, Register{name, op.DwarfRegisterFromBytes(value)})
|
||||
}
|
||||
|
||||
// ErrUnknownRegister is returned when the value of an unknown
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
package winutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"unsafe"
|
||||
|
||||
@ -96,7 +98,7 @@ func (r *AMD64Registers) Slice(floatingPoint bool) []proc.Register {
|
||||
{"R13", r.r13},
|
||||
{"R14", r.r14},
|
||||
{"R15", r.r15},
|
||||
{"Eflags", r.eflags},
|
||||
{"Rflags", r.eflags},
|
||||
{"Cs", r.cs},
|
||||
{"Fs", r.fs},
|
||||
{"Gs", r.gs},
|
||||
@ -108,29 +110,28 @@ func (r *AMD64Registers) Slice(floatingPoint bool) []proc.Register {
|
||||
}
|
||||
out := make([]proc.Register, 0, outlen)
|
||||
for _, reg := range regs {
|
||||
if reg.k == "Eflags" {
|
||||
out = proc.AppendEflagReg(out, reg.k, reg.v)
|
||||
} else {
|
||||
out = proc.AppendQwordReg(out, reg.k, reg.v)
|
||||
}
|
||||
out = proc.AppendUint64Register(out, reg.k, reg.v)
|
||||
}
|
||||
if r.fltSave != nil && floatingPoint {
|
||||
out = proc.AppendWordReg(out, "CW", r.fltSave.ControlWord)
|
||||
out = proc.AppendWordReg(out, "SW", r.fltSave.StatusWord)
|
||||
out = proc.AppendWordReg(out, "TW", uint16(r.fltSave.TagWord))
|
||||
out = proc.AppendWordReg(out, "FOP", r.fltSave.ErrorOpcode)
|
||||
out = proc.AppendQwordReg(out, "FIP", uint64(r.fltSave.ErrorSelector)<<32|uint64(r.fltSave.ErrorOffset))
|
||||
out = proc.AppendQwordReg(out, "FDP", uint64(r.fltSave.DataSelector)<<32|uint64(r.fltSave.DataOffset))
|
||||
out = proc.AppendUint64Register(out, "CW", uint64(r.fltSave.ControlWord))
|
||||
out = proc.AppendUint64Register(out, "SW", uint64(r.fltSave.StatusWord))
|
||||
out = proc.AppendUint64Register(out, "TW", uint64(uint16(r.fltSave.TagWord)))
|
||||
out = proc.AppendUint64Register(out, "FOP", uint64(r.fltSave.ErrorOpcode))
|
||||
out = proc.AppendUint64Register(out, "FIP", uint64(r.fltSave.ErrorSelector)<<32|uint64(r.fltSave.ErrorOffset))
|
||||
out = proc.AppendUint64Register(out, "FDP", uint64(r.fltSave.DataSelector)<<32|uint64(r.fltSave.DataOffset))
|
||||
|
||||
for i := range r.fltSave.FloatRegisters {
|
||||
out = proc.AppendX87Reg(out, i, uint16(r.fltSave.FloatRegisters[i].High), r.fltSave.FloatRegisters[i].Low)
|
||||
var buf bytes.Buffer
|
||||
binary.Write(&buf, binary.LittleEndian, r.fltSave.FloatRegisters[i].Low)
|
||||
binary.Write(&buf, binary.LittleEndian, r.fltSave.FloatRegisters[i].High)
|
||||
out = proc.AppendBytesRegister(out, fmt.Sprintf("ST(%d)", i), buf.Bytes())
|
||||
}
|
||||
|
||||
out = proc.AppendMxcsrReg(out, "MXCSR", uint64(r.fltSave.MxCsr))
|
||||
out = proc.AppendDwordReg(out, "MXCSR_MASK", r.fltSave.MxCsr_Mask)
|
||||
out = proc.AppendUint64Register(out, "MXCSR", uint64(r.fltSave.MxCsr))
|
||||
out = proc.AppendUint64Register(out, "MXCSR_MASK", uint64(r.fltSave.MxCsr_Mask))
|
||||
|
||||
for i := 0; i < len(r.fltSave.XmmRegisters); i += 16 {
|
||||
out = proc.AppendSSEReg(out, fmt.Sprintf("XMM%d", i/16), r.fltSave.XmmRegisters[i:i+16])
|
||||
out = proc.AppendBytesRegister(out, fmt.Sprintf("XMM%d", i/16), r.fltSave.XmmRegisters[i:i+16])
|
||||
}
|
||||
}
|
||||
return out
|
||||
|
||||
@ -328,10 +328,10 @@ func LoadConfigFromProc(cfg *proc.LoadConfig) *LoadConfig {
|
||||
}
|
||||
|
||||
// ConvertRegisters converts proc.Register to api.Register for a slice.
|
||||
func ConvertRegisters(in []proc.Register) (out []Register) {
|
||||
func ConvertRegisters(in []proc.Register, arch proc.Arch) (out []Register) {
|
||||
out = make([]Register, len(in))
|
||||
for i := range in {
|
||||
out[i] = Register{in[i].Name, in[i].Value}
|
||||
out[i] = Register{in[i].Name, arch.DwarfRegisterToString(in[i].Name, in[i].Reg)}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -961,7 +961,7 @@ func (d *Debugger) Registers(threadID int, floatingPoint bool) (api.Registers, e
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return api.ConvertRegisters(regs.Slice(floatingPoint)), err
|
||||
return api.ConvertRegisters(regs.Slice(floatingPoint), d.target.BinInfo().Arch), err
|
||||
}
|
||||
|
||||
func convertVars(pv []*proc.Variable) []api.Variable {
|
||||
|
||||
Reference in New Issue
Block a user