未验证 提交 b9d0ddd8 编写于 作者: A Alessandro Arzilli 提交者: GitHub

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
上级 abb57ff0
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 (
......
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
......
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
}
// 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)})
}
// 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)})
Name string
Reg *op.DwarfRegister
}
// 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()})
func AppendUint64Register(regs []Register, name string, value uint64) []Register {
return append(regs, Register{name, op.DwarfRegisterFromUint64(value)})
}
// 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
......
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 {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册