proc: remove duplicate Registers.Get implementations (#2415)

Moves the implementation of Registers.Get out of the backends and into
proc where it can be implemented only once per architecture.
This commit is contained in:
Alessandro Arzilli
2021-04-28 19:00:26 +02:00
committed by GitHub
parent 7bf5482b32
commit 35d4f05c4e
26 changed files with 242 additions and 1206 deletions

View File

@ -16,7 +16,7 @@ const (
ARM64_SP = 31
ARM64_PC = 32
ARM64_V0 = 64 // V1 through V31 follow
_ARM64_MaxRegNum = ARM64_V0 + 31
)
func ARM64ToName(num uint64) string {
@ -33,3 +33,24 @@ func ARM64ToName(num uint64) string {
return fmt.Sprintf("unknown%d", num)
}
}
func ARM64MaxRegNum() uint64 {
return _ARM64_MaxRegNum
}
var ARM64NameToDwarf = func() map[string]int {
r := make(map[string]int)
for i := 0; i <= 32; i++ {
r[fmt.Sprintf("x%d", i)] = ARM64_X0 + i
}
r["fp"] = 29
r["lr"] = 30
r["sp"] = 31
r["pc"] = 32
for i := 0; i <= 31; i++ {
r[fmt.Sprintf("v%d", i)] = ARM64_V0 + i
}
return r
}()

View File

@ -38,6 +38,7 @@ func AMD64Arch(goos string) *Arch {
SPRegNum: regnum.AMD64_Rsp,
BPRegNum: regnum.AMD64_Rbp,
ContextRegNum: regnum.AMD64_Rdx,
asmRegisters: amd64AsmRegisters,
}
}
@ -255,11 +256,11 @@ func amd64RegSize(rn uint64) int {
return 8
}
func amd64RegistersToDwarfRegisters(staticBase uint64, regs Registers) op.DwarfRegisters {
func amd64RegistersToDwarfRegisters(staticBase uint64, regs Registers) *op.DwarfRegisters {
dregs := initDwarfRegistersFromSlice(int(regnum.AMD64MaxRegNum()), regs, regnum.AMD64NameToDwarf)
dr := op.NewDwarfRegisters(staticBase, dregs, binary.LittleEndian, regnum.AMD64_Rip, regnum.AMD64_Rsp, regnum.AMD64_Rbp, 0)
dr.SetLoadMoreCallback(loadMoreDwarfRegistersFromSliceFunc(dr, regs, regnum.AMD64NameToDwarf))
return *dr
return dr
}
func initDwarfRegistersFromSlice(maxRegs int, regs Registers, nameToDwarf map[string]int) []*op.DwarfRegister {

View File

@ -5,10 +5,13 @@
package proc
import (
"github.com/go-delve/delve/pkg/dwarf/op"
"github.com/go-delve/delve/pkg/dwarf/regnum"
"golang.org/x/arch/x86/x86asm"
)
func amd64AsmDecode(asmInst *AsmInstruction, mem []byte, regs Registers, memrw MemoryReadWriter, bi *BinaryInfo) error {
func amd64AsmDecode(asmInst *AsmInstruction, mem []byte, regs *op.DwarfRegisters, memrw MemoryReadWriter, bi *BinaryInfo) error {
return x86AsmDecode(asmInst, mem, regs, memrw, bi, 64)
}
@ -36,3 +39,81 @@ func init() {
}
}
}
var amd64AsmRegisters = map[int]asmRegister{
// 8-bit
int(x86asm.AL): asmRegister{regnum.AMD64_Rax, 0, mask8},
int(x86asm.CL): asmRegister{regnum.AMD64_Rcx, 0, mask8},
int(x86asm.DL): asmRegister{regnum.AMD64_Rdx, 0, mask8},
int(x86asm.BL): asmRegister{regnum.AMD64_Rbx, 0, mask8},
int(x86asm.AH): asmRegister{regnum.AMD64_Rax, 8, mask8},
int(x86asm.CH): asmRegister{regnum.AMD64_Rcx, 8, mask8},
int(x86asm.DH): asmRegister{regnum.AMD64_Rdx, 8, mask8},
int(x86asm.BH): asmRegister{regnum.AMD64_Rbx, 8, mask8},
int(x86asm.SPB): asmRegister{regnum.AMD64_Rsp, 0, mask8},
int(x86asm.BPB): asmRegister{regnum.AMD64_Rbp, 0, mask8},
int(x86asm.SIB): asmRegister{regnum.AMD64_Rsi, 0, mask8},
int(x86asm.DIB): asmRegister{regnum.AMD64_Rdi, 0, mask8},
int(x86asm.R8B): asmRegister{regnum.AMD64_R8, 0, mask8},
int(x86asm.R9B): asmRegister{regnum.AMD64_R9, 0, mask8},
int(x86asm.R10B): asmRegister{regnum.AMD64_R10, 0, mask8},
int(x86asm.R11B): asmRegister{regnum.AMD64_R11, 0, mask8},
int(x86asm.R12B): asmRegister{regnum.AMD64_R12, 0, mask8},
int(x86asm.R13B): asmRegister{regnum.AMD64_R13, 0, mask8},
int(x86asm.R14B): asmRegister{regnum.AMD64_R14, 0, mask8},
int(x86asm.R15B): asmRegister{regnum.AMD64_R15, 0, mask8},
// 16-bit
int(x86asm.AX): asmRegister{regnum.AMD64_Rax, 0, mask16},
int(x86asm.CX): asmRegister{regnum.AMD64_Rcx, 0, mask16},
int(x86asm.DX): asmRegister{regnum.AMD64_Rdx, 0, mask16},
int(x86asm.BX): asmRegister{regnum.AMD64_Rbx, 0, mask16},
int(x86asm.SP): asmRegister{regnum.AMD64_Rsp, 0, mask16},
int(x86asm.BP): asmRegister{regnum.AMD64_Rbp, 0, mask16},
int(x86asm.SI): asmRegister{regnum.AMD64_Rsi, 0, mask16},
int(x86asm.DI): asmRegister{regnum.AMD64_Rdi, 0, mask16},
int(x86asm.R8W): asmRegister{regnum.AMD64_R8, 0, mask16},
int(x86asm.R9W): asmRegister{regnum.AMD64_R9, 0, mask16},
int(x86asm.R10W): asmRegister{regnum.AMD64_R10, 0, mask16},
int(x86asm.R11W): asmRegister{regnum.AMD64_R11, 0, mask16},
int(x86asm.R12W): asmRegister{regnum.AMD64_R12, 0, mask16},
int(x86asm.R13W): asmRegister{regnum.AMD64_R13, 0, mask16},
int(x86asm.R14W): asmRegister{regnum.AMD64_R14, 0, mask16},
int(x86asm.R15W): asmRegister{regnum.AMD64_R15, 0, mask16},
// 32-bit
int(x86asm.EAX): asmRegister{regnum.AMD64_Rax, 0, mask32},
int(x86asm.ECX): asmRegister{regnum.AMD64_Rcx, 0, mask32},
int(x86asm.EDX): asmRegister{regnum.AMD64_Rdx, 0, mask32},
int(x86asm.EBX): asmRegister{regnum.AMD64_Rbx, 0, mask32},
int(x86asm.ESP): asmRegister{regnum.AMD64_Rsp, 0, mask32},
int(x86asm.EBP): asmRegister{regnum.AMD64_Rbp, 0, mask32},
int(x86asm.ESI): asmRegister{regnum.AMD64_Rsi, 0, mask32},
int(x86asm.EDI): asmRegister{regnum.AMD64_Rdi, 0, mask32},
int(x86asm.R8L): asmRegister{regnum.AMD64_R8, 0, mask32},
int(x86asm.R9L): asmRegister{regnum.AMD64_R9, 0, mask32},
int(x86asm.R10L): asmRegister{regnum.AMD64_R10, 0, mask32},
int(x86asm.R11L): asmRegister{regnum.AMD64_R11, 0, mask32},
int(x86asm.R12L): asmRegister{regnum.AMD64_R12, 0, mask32},
int(x86asm.R13L): asmRegister{regnum.AMD64_R13, 0, mask32},
int(x86asm.R14L): asmRegister{regnum.AMD64_R14, 0, mask32},
int(x86asm.R15L): asmRegister{regnum.AMD64_R15, 0, mask32},
// 64-bit
int(x86asm.RAX): asmRegister{regnum.AMD64_Rax, 0, 0},
int(x86asm.RCX): asmRegister{regnum.AMD64_Rcx, 0, 0},
int(x86asm.RDX): asmRegister{regnum.AMD64_Rdx, 0, 0},
int(x86asm.RBX): asmRegister{regnum.AMD64_Rbx, 0, 0},
int(x86asm.RSP): asmRegister{regnum.AMD64_Rsp, 0, 0},
int(x86asm.RBP): asmRegister{regnum.AMD64_Rbp, 0, 0},
int(x86asm.RSI): asmRegister{regnum.AMD64_Rsi, 0, 0},
int(x86asm.RDI): asmRegister{regnum.AMD64_Rdi, 0, 0},
int(x86asm.R8): asmRegister{regnum.AMD64_R8, 0, 0},
int(x86asm.R9): asmRegister{regnum.AMD64_R9, 0, 0},
int(x86asm.R10): asmRegister{regnum.AMD64_R10, 0, 0},
int(x86asm.R11): asmRegister{regnum.AMD64_R11, 0, 0},
int(x86asm.R12): asmRegister{regnum.AMD64_R12, 0, 0},
int(x86asm.R13): asmRegister{regnum.AMD64_R13, 0, 0},
int(x86asm.R14): asmRegister{regnum.AMD64_R14, 0, 0},
int(x86asm.R15): asmRegister{regnum.AMD64_R15, 0, 0},
}

View File

@ -1,6 +1,8 @@
package proc
import (
"fmt"
"github.com/go-delve/delve/pkg/dwarf/frame"
"github.com/go-delve/delve/pkg/dwarf/op"
)
@ -24,7 +26,7 @@ type Arch struct {
// asmDecode decodes the assembly instruction starting at mem[0:] into asmInst.
// It assumes that the Loc and AtPC fields of asmInst have already been filled.
asmDecode func(asmInst *AsmInstruction, mem []byte, regs Registers, memrw MemoryReadWriter, bi *BinaryInfo) error
asmDecode func(asmInst *AsmInstruction, mem []byte, regs *op.DwarfRegisters, memrw MemoryReadWriter, bi *BinaryInfo) error
// fixFrameUnwindContext applies architecture specific rules for unwinding a stack frame
// on the given arch.
fixFrameUnwindContext func(*frame.FrameContext, uint64, *BinaryInfo) *frame.FrameContext
@ -34,7 +36,7 @@ type Arch struct {
// regSize returns the size (in bytes) of register regnum.
regSize func(uint64) int
// RegistersToDwarfRegisters maps hardware registers to DWARF registers.
RegistersToDwarfRegisters func(uint64, Registers) op.DwarfRegisters
RegistersToDwarfRegisters func(uint64, Registers) *op.DwarfRegisters
// addrAndStackRegsToDwarfRegisters returns DWARF registers from the passed in
// PC, SP, and BP registers in the format used by the DWARF expression interpreter.
addrAndStackRegsToDwarfRegisters func(uint64, uint64, uint64, uint64, uint64) op.DwarfRegisters
@ -45,6 +47,9 @@ type Arch struct {
// inhibitStepInto returns whether StepBreakpoint can be set at pc.
inhibitStepInto func(bi *BinaryInfo, pc uint64) bool
// asmRegisters maps assembly register numbers to dwarf registers.
asmRegisters map[int]asmRegister
// crosscall2fn is the DIE of crosscall2, a function used by the go runtime
// to call C functions. This function in go 1.9 (and previous versions) had
// a bad frame descriptor which needs to be fixed to generate good stack
@ -57,6 +62,18 @@ type Arch struct {
sigreturnfn *Function
}
type asmRegister struct {
dwarfNum uint64
offset uint
mask uint64
}
const (
mask8 = 0x000000ff
mask16 = 0x0000ffff
mask32 = 0xffffffff
)
// PtrSize returns the size of a pointer for the architecture.
func (a *Arch) PtrSize() int {
return a.ptrSize
@ -95,6 +112,25 @@ func (a *Arch) DerefTLS() bool {
return a.derefTLS
}
// getAsmRegister returns the value of the asm register asmreg using the asmRegisters table of arch.
// The interpretation of asmreg is architecture specific and defined by the disassembler.
// A mask value of 0 inside asmRegisters is equivalent to ^uint64(0).
func (arch *Arch) getAsmRegister(regs *op.DwarfRegisters, asmreg int) (uint64, error) {
hwreg, ok := arch.asmRegisters[asmreg]
if !ok {
return 0, ErrUnknownRegister
}
reg := regs.Reg(hwreg.dwarfNum)
if reg == nil {
return 0, fmt.Errorf("register %#x not found", asmreg)
}
n := (reg.Uint64Val >> hwreg.offset)
if hwreg.mask != 0 {
n = n & hwreg.mask
}
return n, nil
}
// crosscall2 is defined in $GOROOT/src/runtime/cgo/asm_amd64.s.
const (
crosscall2SPOffsetBad = 0x8

View File

@ -9,7 +9,6 @@ import (
"github.com/go-delve/delve/pkg/dwarf/frame"
"github.com/go-delve/delve/pkg/dwarf/op"
"github.com/go-delve/delve/pkg/dwarf/regnum"
"golang.org/x/arch/arm64/arm64asm"
)
var arm64BreakInstruction = []byte{0x0, 0x0, 0x20, 0xd4}
@ -36,6 +35,7 @@ func ARM64Arch(goos string) *Arch {
usesLR: true,
PCRegNum: regnum.ARM64_PC,
SPRegNum: regnum.ARM64_SP,
asmRegisters: arm64AsmRegisters,
}
}
@ -235,78 +235,6 @@ func arm64RegSize(regnum uint64) int {
return 8 // general registers
}
// The mapping between hardware registers and DWARF registers is specified
// in the DWARF for the ARM® Architecture page 7,
// Table 1
// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0040b/IHI0040B_aadwarf.pdf
var arm64DwarfToHardware = map[int]arm64asm.Reg{
0: arm64asm.X0,
1: arm64asm.X1,
2: arm64asm.X2,
3: arm64asm.X3,
4: arm64asm.X4,
5: arm64asm.X5,
6: arm64asm.X6,
7: arm64asm.X7,
8: arm64asm.X8,
9: arm64asm.X9,
10: arm64asm.X10,
11: arm64asm.X11,
12: arm64asm.X12,
13: arm64asm.X13,
14: arm64asm.X14,
15: arm64asm.X15,
16: arm64asm.X16,
17: arm64asm.X17,
18: arm64asm.X18,
19: arm64asm.X19,
20: arm64asm.X20,
21: arm64asm.X21,
22: arm64asm.X22,
23: arm64asm.X23,
24: arm64asm.X24,
25: arm64asm.X25,
26: arm64asm.X26,
27: arm64asm.X27,
28: arm64asm.X28,
29: arm64asm.X29,
30: arm64asm.X30,
31: arm64asm.SP,
64: arm64asm.V0,
65: arm64asm.V1,
66: arm64asm.V2,
67: arm64asm.V3,
68: arm64asm.V4,
69: arm64asm.V5,
70: arm64asm.V6,
71: arm64asm.V7,
72: arm64asm.V8,
73: arm64asm.V9,
74: arm64asm.V10,
75: arm64asm.V11,
76: arm64asm.V12,
77: arm64asm.V13,
78: arm64asm.V14,
79: arm64asm.V15,
80: arm64asm.V16,
81: arm64asm.V17,
82: arm64asm.V18,
83: arm64asm.V19,
84: arm64asm.V20,
85: arm64asm.V21,
86: arm64asm.V22,
87: arm64asm.V23,
88: arm64asm.V24,
89: arm64asm.V25,
90: arm64asm.V26,
91: arm64asm.V27,
92: arm64asm.V28,
93: arm64asm.V29,
94: arm64asm.V30,
95: arm64asm.V31,
}
var arm64NameToDwarf = func() map[string]int {
r := make(map[string]int)
for i := 0; i <= 30; i++ {
@ -321,36 +249,11 @@ var arm64NameToDwarf = func() map[string]int {
return r
}()
func maxArm64DwarfRegister() int {
max := int(regnum.ARM64_PC)
for i := range arm64DwarfToHardware {
if i > max {
max = i
}
}
return max
}
func arm64RegistersToDwarfRegisters(staticBase uint64, regs Registers) op.DwarfRegisters {
dregs := make([]*op.DwarfRegister, maxArm64DwarfRegister()+1)
dregs[regnum.ARM64_PC] = op.DwarfRegisterFromUint64(regs.PC())
dregs[regnum.ARM64_SP] = op.DwarfRegisterFromUint64(regs.SP())
dregs[regnum.ARM64_BP] = op.DwarfRegisterFromUint64(regs.BP())
if lr, err := regs.Get(int(arm64asm.X30)); err != nil {
dregs[regnum.ARM64_LR] = op.DwarfRegisterFromUint64(lr)
}
for dwarfReg, asmReg := range arm64DwarfToHardware {
v, err := regs.Get(int(asmReg))
if err == nil {
dregs[dwarfReg] = op.DwarfRegisterFromUint64(v)
}
}
func arm64RegistersToDwarfRegisters(staticBase uint64, regs Registers) *op.DwarfRegisters {
dregs := initDwarfRegistersFromSlice(int(regnum.ARM64MaxRegNum()), regs, regnum.ARM64NameToDwarf)
dr := op.NewDwarfRegisters(staticBase, dregs, binary.LittleEndian, regnum.ARM64_PC, regnum.ARM64_SP, regnum.ARM64_BP, regnum.ARM64_LR)
dr.SetLoadMoreCallback(loadMoreDwarfRegistersFromSliceFunc(dr, regs, arm64NameToDwarf))
return *dr
return dr
}
func arm64AddrAndStackRegsToDwarfRegisters(staticBase, pc, sp, bp, lr uint64) op.DwarfRegisters {

View File

@ -5,10 +5,13 @@
package proc
import (
"github.com/go-delve/delve/pkg/dwarf/op"
"github.com/go-delve/delve/pkg/dwarf/regnum"
"golang.org/x/arch/arm64/arm64asm"
)
func arm64AsmDecode(asmInst *AsmInstruction, mem []byte, regs Registers, memrw MemoryReadWriter, bi *BinaryInfo) error {
func arm64AsmDecode(asmInst *AsmInstruction, mem []byte, regs *op.DwarfRegisters, memrw MemoryReadWriter, bi *BinaryInfo) error {
asmInst.Size = 4
asmInst.Bytes = mem[:asmInst.Size]
@ -37,7 +40,7 @@ func arm64AsmDecode(asmInst *AsmInstruction, mem []byte, regs Registers, memrw M
return nil
}
func resolveCallArgARM64(inst *arm64asm.Inst, instAddr uint64, currentGoroutine bool, regs Registers, mem MemoryReadWriter, bininfo *BinaryInfo) *Location {
func resolveCallArgARM64(inst *arm64asm.Inst, instAddr uint64, currentGoroutine bool, regs *op.DwarfRegisters, mem MemoryReadWriter, bininfo *BinaryInfo) *Location {
switch inst.Op {
case arm64asm.BL, arm64asm.BLR, arm64asm.B, arm64asm.BR:
//ok
@ -55,7 +58,7 @@ func resolveCallArgARM64(inst *arm64asm.Inst, instAddr uint64, currentGoroutine
if !currentGoroutine || regs == nil {
return nil
}
pc, err = regs.Get(int(arg))
pc, err = bininfo.Arch.getAsmRegister(regs, int(arg))
if err != nil {
return nil
}
@ -118,3 +121,11 @@ func (inst *arm64ArchInst) OpcodeEquals(op uint64) bool {
}
return uint64(inst.Op) == op
}
var arm64AsmRegisters = func() map[int]asmRegister {
r := make(map[int]asmRegister)
for i := arm64asm.X0; i <= arm64asm.X30; i++ {
r[int(i)] = asmRegister{regnum.ARM64_X0 + uint64(i-arm64asm.X0), 0, 0}
}
return r
}()

View File

@ -3,7 +3,6 @@ package core
import (
"bytes"
"encoding/binary"
"errors"
"fmt"
"strconv"
"strings"
@ -156,10 +155,6 @@ func (regs *delveRegisters) Copy() (proc.Registers, error) {
return regs, nil
}
func (regs *delveRegisters) Get(int) (uint64, error) {
return 0, errors.New("not supported")
}
func (regs *delveRegisters) Slice(bool) ([]proc.Register, error) {
return regs.slice, nil
}

View File

@ -1,6 +1,10 @@
package proc
import "fmt"
import (
"fmt"
"github.com/go-delve/delve/pkg/dwarf/op"
)
// AsmInstruction represents one assembly instruction.
type AsmInstruction struct {
@ -124,6 +128,11 @@ func Disassemble(mem MemoryReadWriter, regs Registers, breakpoints *BreakpointMa
}
func disassemble(memrw MemoryReadWriter, regs Registers, breakpoints *BreakpointMap, bi *BinaryInfo, startAddr, endAddr uint64, singleInstr bool) ([]AsmInstruction, error) {
var dregs *op.DwarfRegisters
if regs != nil {
dregs = bi.Arch.RegistersToDwarfRegisters(0, regs)
}
mem := make([]byte, int(endAddr-startAddr))
_, err := memrw.ReadMemory(mem, startAddr)
if err != nil {
@ -153,7 +162,7 @@ func disassemble(memrw MemoryReadWriter, regs Registers, breakpoints *Breakpoint
inst.Breakpoint = atbp
inst.AtPC = (regs != nil) && (curpc == pc)
bi.Arch.asmDecode(&inst, mem, regs, memrw, bi)
bi.Arch.asmDecode(&inst, mem, dregs, memrw, bi)
r = append(r, inst)

View File

@ -17,5 +17,5 @@ func NewCompositeMemory(p *Target, pieces []op.Piece) (*compositeMemory, error)
dwarfregs := arch.RegistersToDwarfRegisters(0, regs)
dwarfregs.ChangeFunc = p.CurrentThread().SetReg
return newCompositeMemory(p.Memory(), arch, dwarfregs, pieces)
return newCompositeMemory(p.Memory(), arch, *dwarfregs, pieces)
}

View File

@ -102,8 +102,8 @@ func uintExprCheck(t *testing.T, scope *proc.EvalScope, expr string, tgt uint64)
}
}
func fakeScope(mem proc.MemoryReadWriter, regs op.DwarfRegisters, bi *proc.BinaryInfo, fn *proc.Function) *proc.EvalScope {
return &proc.EvalScope{Location: proc.Location{PC: 0x40100, Fn: fn}, Regs: regs, Mem: mem, BinInfo: bi}
func fakeScope(mem proc.MemoryReadWriter, regs *op.DwarfRegisters, bi *proc.BinaryInfo, fn *proc.Function) *proc.EvalScope {
return &proc.EvalScope{Location: proc.Location{PC: 0x40100, Fn: fn}, Regs: *regs, Mem: mem, BinInfo: bi}
}
func dwarfExprCheck(t *testing.T, scope *proc.EvalScope, testCases map[string]uint16) {
@ -112,7 +112,7 @@ func dwarfExprCheck(t *testing.T, scope *proc.EvalScope, testCases map[string]ui
}
}
func dwarfRegisters(bi *proc.BinaryInfo, regs *linutil.AMD64Registers) op.DwarfRegisters {
func dwarfRegisters(bi *proc.BinaryInfo, regs *linutil.AMD64Registers) *op.DwarfRegisters {
a := proc.AMD64Arch("linux")
so := bi.PCToImage(regs.PC())
dwarfRegs := a.RegistersToDwarfRegisters(so.StaticBase, regs)
@ -271,7 +271,7 @@ func TestDwarfExprLoclist(t *testing.T) {
const PC = 0x40100
regs := linutil.AMD64Registers{Regs: &linutil.AMD64PtraceRegs{Rip: PC}}
scope := &proc.EvalScope{Location: proc.Location{PC: PC, Fn: mainfn}, Regs: dwarfRegisters(bi, &regs), Mem: mem, BinInfo: bi}
scope := &proc.EvalScope{Location: proc.Location{PC: PC, Fn: mainfn}, Regs: *dwarfRegisters(bi, &regs), Mem: mem, BinInfo: bi}
uintExprCheck(t, scope, "a", before)
scope.PC = 0x40800

View File

@ -1,8 +1,6 @@
package fbsdutil
import (
"golang.org/x/arch/x86/x86asm"
"github.com/go-delve/delve/pkg/proc"
"github.com/go-delve/delve/pkg/proc/amd64util"
)
@ -154,164 +152,6 @@ func (r *AMD64Registers) GAddr() (uint64, bool) {
return 0, false
}
// Get returns the value of the n-th register (in x86asm order).
func (r *AMD64Registers) Get(n int) (uint64, error) {
reg := x86asm.Reg(n)
const (
mask8 = 0x000000ff
mask16 = 0x0000ffff
mask32 = 0xffffffff
)
switch reg {
// 8-bit
case x86asm.AL:
return uint64(r.Regs.Rax) & mask8, nil
case x86asm.CL:
return uint64(r.Regs.Rcx) & mask8, nil
case x86asm.DL:
return uint64(r.Regs.Rdx) & mask8, nil
case x86asm.BL:
return uint64(r.Regs.Rbx) & mask8, nil
case x86asm.AH:
return (uint64(r.Regs.Rax) >> 8) & mask8, nil
case x86asm.CH:
return (uint64(r.Regs.Rcx) >> 8) & mask8, nil
case x86asm.DH:
return (uint64(r.Regs.Rdx) >> 8) & mask8, nil
case x86asm.BH:
return (uint64(r.Regs.Rbx) >> 8) & mask8, nil
case x86asm.SPB:
return uint64(r.Regs.Rsp) & mask8, nil
case x86asm.BPB:
return uint64(r.Regs.Rbp) & mask8, nil
case x86asm.SIB:
return uint64(r.Regs.Rsi) & mask8, nil
case x86asm.DIB:
return uint64(r.Regs.Rdi) & mask8, nil
case x86asm.R8B:
return uint64(r.Regs.R8) & mask8, nil
case x86asm.R9B:
return uint64(r.Regs.R9) & mask8, nil
case x86asm.R10B:
return uint64(r.Regs.R10) & mask8, nil
case x86asm.R11B:
return uint64(r.Regs.R11) & mask8, nil
case x86asm.R12B:
return uint64(r.Regs.R12) & mask8, nil
case x86asm.R13B:
return uint64(r.Regs.R13) & mask8, nil
case x86asm.R14B:
return uint64(r.Regs.R14) & mask8, nil
case x86asm.R15B:
return uint64(r.Regs.R15) & mask8, nil
// 16-bit
case x86asm.AX:
return uint64(r.Regs.Rax) & mask16, nil
case x86asm.CX:
return uint64(r.Regs.Rcx) & mask16, nil
case x86asm.DX:
return uint64(r.Regs.Rdx) & mask16, nil
case x86asm.BX:
return uint64(r.Regs.Rbx) & mask16, nil
case x86asm.SP:
return uint64(r.Regs.Rsp) & mask16, nil
case x86asm.BP:
return uint64(r.Regs.Rbp) & mask16, nil
case x86asm.SI:
return uint64(r.Regs.Rsi) & mask16, nil
case x86asm.DI:
return uint64(r.Regs.Rdi) & mask16, nil
case x86asm.R8W:
return uint64(r.Regs.R8) & mask16, nil
case x86asm.R9W:
return uint64(r.Regs.R9) & mask16, nil
case x86asm.R10W:
return uint64(r.Regs.R10) & mask16, nil
case x86asm.R11W:
return uint64(r.Regs.R11) & mask16, nil
case x86asm.R12W:
return uint64(r.Regs.R12) & mask16, nil
case x86asm.R13W:
return uint64(r.Regs.R13) & mask16, nil
case x86asm.R14W:
return uint64(r.Regs.R14) & mask16, nil
case x86asm.R15W:
return uint64(r.Regs.R15) & mask16, nil
// 32-bit
case x86asm.EAX:
return uint64(r.Regs.Rax) & mask32, nil
case x86asm.ECX:
return uint64(r.Regs.Rcx) & mask32, nil
case x86asm.EDX:
return uint64(r.Regs.Rdx) & mask32, nil
case x86asm.EBX:
return uint64(r.Regs.Rbx) & mask32, nil
case x86asm.ESP:
return uint64(r.Regs.Rsp) & mask32, nil
case x86asm.EBP:
return uint64(r.Regs.Rbp) & mask32, nil
case x86asm.ESI:
return uint64(r.Regs.Rsi) & mask32, nil
case x86asm.EDI:
return uint64(r.Regs.Rdi) & mask32, nil
case x86asm.R8L:
return uint64(r.Regs.R8) & mask32, nil
case x86asm.R9L:
return uint64(r.Regs.R9) & mask32, nil
case x86asm.R10L:
return uint64(r.Regs.R10) & mask32, nil
case x86asm.R11L:
return uint64(r.Regs.R11) & mask32, nil
case x86asm.R12L:
return uint64(r.Regs.R12) & mask32, nil
case x86asm.R13L:
return uint64(r.Regs.R13) & mask32, nil
case x86asm.R14L:
return uint64(r.Regs.R14) & mask32, nil
case x86asm.R15L:
return uint64(r.Regs.R15) & mask32, nil
// 64-bit
case x86asm.RAX:
return uint64(r.Regs.Rax), nil
case x86asm.RCX:
return uint64(r.Regs.Rcx), nil
case x86asm.RDX:
return uint64(r.Regs.Rdx), nil
case x86asm.RBX:
return uint64(r.Regs.Rbx), nil
case x86asm.RSP:
return uint64(r.Regs.Rsp), nil
case x86asm.RBP:
return uint64(r.Regs.Rbp), nil
case x86asm.RSI:
return uint64(r.Regs.Rsi), nil
case x86asm.RDI:
return uint64(r.Regs.Rdi), nil
case x86asm.R8:
return uint64(r.Regs.R8), nil
case x86asm.R9:
return uint64(r.Regs.R9), nil
case x86asm.R10:
return uint64(r.Regs.R10), nil
case x86asm.R11:
return uint64(r.Regs.R11), nil
case x86asm.R12:
return uint64(r.Regs.R12), nil
case x86asm.R13:
return uint64(r.Regs.R13), nil
case x86asm.R14:
return uint64(r.Regs.R14), nil
case x86asm.R15:
return uint64(r.Regs.R15), nil
}
return 0, proc.ErrUnknownRegister
}
// Copy returns a copy of these registers that is guaranteed not to change.
func (r *AMD64Registers) Copy() (proc.Registers, error) {
if r.loadFpRegs != nil {

View File

@ -1,60 +0,0 @@
package fbsdutil
import (
"testing"
"golang.org/x/arch/x86/x86asm"
)
func TestAMD64Get(t *testing.T) {
val := int64(0x7fffffffdeadbeef)
regs := AMD64Registers{
Regs: &AMD64PtraceRegs{
Rax: val,
},
}
// Test AL, low 8 bits of RAX
al, err := regs.Get(int(x86asm.AL))
if err != nil {
t.Fatal(err)
}
if al != 0xef {
t.Fatalf("expected %#v, got %#v\n", 0xef, al)
}
// Test AH, high 8 bits of RAX
ah, err := regs.Get(int(x86asm.AH))
if err != nil {
t.Fatal(err)
}
if ah != 0xBE {
t.Fatalf("expected %#v, got %#v\n", 0xbe, ah)
}
// Test AX, lower 16 bits of RAX
ax, err := regs.Get(int(x86asm.AX))
if err != nil {
t.Fatal(err)
}
if ax != 0xBEEF {
t.Fatalf("expected %#v, got %#v\n", 0xbeef, ax)
}
// Test EAX, lower 32 bits of RAX
eax, err := regs.Get(int(x86asm.EAX))
if err != nil {
t.Fatal(err)
}
if eax != 0xDEADBEEF {
t.Fatalf("expected %#v, got %#v\n", uint64(0xdeadbeef), eax)
}
// Test RAX, full 64 bits of register
rax, err := regs.Get(int(x86asm.RAX))
if err != nil {
t.Fatal(err)
}
if rax != uint64(val) {
t.Fatalf("expected %#v, got %#v\n", val, rax)
}
}

View File

@ -16,9 +16,9 @@ import (
"github.com/go-delve/delve/pkg/dwarf/godwarf"
"github.com/go-delve/delve/pkg/dwarf/op"
"github.com/go-delve/delve/pkg/dwarf/reader"
"github.com/go-delve/delve/pkg/dwarf/regnum"
"github.com/go-delve/delve/pkg/goversion"
"github.com/go-delve/delve/pkg/logflags"
"golang.org/x/arch/x86/x86asm"
)
// This file implements the function call injection introduced in go1.11.
@ -289,8 +289,7 @@ func evalFunctionCall(scope *EvalScope, node *ast.CallExpr) (*Variable, error) {
if regs.SP()-256 <= stacklo {
return nil, errNotEnoughStack
}
_, err = regs.Get(int(x86asm.RAX))
if err != nil {
if bi.Arch.RegistersToDwarfRegisters(0, regs).Reg(regnum.AMD64_Rax) == nil { //TODO(aarzilli): make this generic when call injection is supported on other architectures
return nil, errFuncCallUnsupportedBackend
}
@ -705,7 +704,7 @@ func funcCallStep(callScope *EvalScope, fncall *functionCallState, thread Thread
return true
}
rax, _ := regs.Get(int(x86asm.RAX))
rax := bi.Arch.RegistersToDwarfRegisters(0, regs).Uint64Val(regnum.AMD64_Rax) //TODO(aarzilli): make this generic when call injection is supported on other architectures
if logflags.FnCall() {
loc, _ := thread.Location()

View File

@ -77,9 +77,6 @@ import (
"sync"
"time"
"golang.org/x/arch/arm64/arm64asm"
"golang.org/x/arch/x86/x86asm"
"github.com/go-delve/delve/pkg/dwarf/op"
"github.com/go-delve/delve/pkg/elfwriter"
"github.com/go-delve/delve/pkg/logflags"
@ -1835,375 +1832,6 @@ func (regs *gdbRegisters) byName(name string) uint64 {
return binary.LittleEndian.Uint64(reg.value)
}
func (regs *gdbRegisters) Get(n int) (uint64, error) {
const (
mask8 = 0xff
mask16 = 0xffff
mask32 = 0xffffffff
)
if regs.arch.Name == "arm64" {
reg := arm64asm.Reg(n)
switch reg {
// 64-bit
case arm64asm.X0:
return regs.byName("x0"), nil
case arm64asm.X1:
return regs.byName("x1"), nil
case arm64asm.X2:
return regs.byName("x2"), nil
case arm64asm.X3:
return regs.byName("x3"), nil
case arm64asm.X4:
return regs.byName("x4"), nil
case arm64asm.X5:
return regs.byName("x5"), nil
case arm64asm.X6:
return regs.byName("x6"), nil
case arm64asm.X7:
return regs.byName("x7"), nil
case arm64asm.X8:
return regs.byName("x8"), nil
case arm64asm.X9:
return regs.byName("x9"), nil
case arm64asm.X10:
return regs.byName("x10"), nil
case arm64asm.X11:
return regs.byName("x11"), nil
case arm64asm.X12:
return regs.byName("x12"), nil
case arm64asm.X13:
return regs.byName("x13"), nil
case arm64asm.X14:
return regs.byName("x14"), nil
case arm64asm.X15:
return regs.byName("x15"), nil
case arm64asm.X16:
return regs.byName("x16"), nil
case arm64asm.X17:
return regs.byName("x17"), nil
case arm64asm.X18:
return regs.byName("x18"), nil
case arm64asm.X19:
return regs.byName("x19"), nil
case arm64asm.X20:
return regs.byName("x20"), nil
case arm64asm.X21:
return regs.byName("x21"), nil
case arm64asm.X22:
return regs.byName("x22"), nil
case arm64asm.X23:
return regs.byName("x23"), nil
case arm64asm.X24:
return regs.byName("x24"), nil
case arm64asm.X25:
return regs.byName("x25"), nil
case arm64asm.X26:
return regs.byName("x26"), nil
case arm64asm.X27:
return regs.byName("x27"), nil
case arm64asm.X28:
return regs.byName("x28"), nil
case arm64asm.X29:
return regs.byName("fp"), nil
case arm64asm.X30:
return regs.byName("lr"), nil
case arm64asm.SP:
return regs.byName("sp"), nil
}
// 64-bit
switch reg {
case arm64asm.W0:
return regs.byName("w0"), nil
case arm64asm.W1:
return regs.byName("w1"), nil
case arm64asm.W2:
return regs.byName("w2"), nil
case arm64asm.W3:
return regs.byName("w3"), nil
case arm64asm.W4:
return regs.byName("w4"), nil
case arm64asm.W5:
return regs.byName("w5"), nil
case arm64asm.W6:
return regs.byName("w6"), nil
case arm64asm.W7:
return regs.byName("w7"), nil
case arm64asm.W8:
return regs.byName("w8"), nil
case arm64asm.W9:
return regs.byName("w9"), nil
case arm64asm.W10:
return regs.byName("w10"), nil
case arm64asm.W11:
return regs.byName("w11"), nil
case arm64asm.W12:
return regs.byName("w12"), nil
case arm64asm.W13:
return regs.byName("w13"), nil
case arm64asm.W14:
return regs.byName("w14"), nil
case arm64asm.W15:
return regs.byName("w15"), nil
case arm64asm.W16:
return regs.byName("w16"), nil
case arm64asm.W17:
return regs.byName("w17"), nil
case arm64asm.W18:
return regs.byName("w18"), nil
case arm64asm.W19:
return regs.byName("w19"), nil
case arm64asm.W20:
return regs.byName("w20"), nil
case arm64asm.W21:
return regs.byName("w21"), nil
case arm64asm.W22:
return regs.byName("w22"), nil
case arm64asm.W23:
return regs.byName("w23"), nil
case arm64asm.W24:
return regs.byName("w24"), nil
case arm64asm.W25:
return regs.byName("w25"), nil
case arm64asm.W26:
return regs.byName("w26"), nil
case arm64asm.W27:
return regs.byName("w27"), nil
case arm64asm.W28:
return regs.byName("w28"), nil
// TODO: not sure about these ones, they are not returned by debugserver
// probably need to take the x-register and bitmask them
/*case arm64asm.W29:
return regs.byName("w29"), nil
case arm64asm.W30:
return regs.byName("w30"), nil
/*case arm64asm.WSP:
return regs.byName("wsp"), nil*/
}
// vector registers
// 64-bit
switch reg {
case arm64asm.V0:
return regs.byName("v0"), nil
case arm64asm.V1:
return regs.byName("v1"), nil
case arm64asm.V2:
return regs.byName("v2"), nil
case arm64asm.V3:
return regs.byName("v3"), nil
case arm64asm.V4:
return regs.byName("v4"), nil
case arm64asm.V5:
return regs.byName("v5"), nil
case arm64asm.V6:
return regs.byName("v6"), nil
case arm64asm.V7:
return regs.byName("v7"), nil
case arm64asm.V8:
return regs.byName("v8"), nil
case arm64asm.V9:
return regs.byName("v9"), nil
case arm64asm.V10:
return regs.byName("v10"), nil
case arm64asm.V11:
return regs.byName("v11"), nil
case arm64asm.V12:
return regs.byName("v12"), nil
case arm64asm.V13:
return regs.byName("v13"), nil
case arm64asm.V14:
return regs.byName("v14"), nil
case arm64asm.V15:
return regs.byName("v15"), nil
case arm64asm.V16:
return regs.byName("v16"), nil
case arm64asm.V17:
return regs.byName("v17"), nil
case arm64asm.V18:
return regs.byName("v18"), nil
case arm64asm.V19:
return regs.byName("v19"), nil
case arm64asm.V20:
return regs.byName("v20"), nil
case arm64asm.V21:
return regs.byName("v21"), nil
case arm64asm.V22:
return regs.byName("v22"), nil
case arm64asm.V23:
return regs.byName("v23"), nil
case arm64asm.V24:
return regs.byName("v24"), nil
case arm64asm.V25:
return regs.byName("v25"), nil
case arm64asm.V26:
return regs.byName("v26"), nil
case arm64asm.V27:
return regs.byName("v27"), nil
case arm64asm.V28:
return regs.byName("v28"), nil
case arm64asm.V29:
return regs.byName("v29"), nil
case arm64asm.V30:
return regs.byName("v30"), nil
case arm64asm.V31:
return regs.byName("v31"), nil
}
} else {
reg := x86asm.Reg(n)
switch reg {
// 8-bit
case x86asm.AL:
return regs.byName("rax") & mask8, nil
case x86asm.CL:
return regs.byName("rcx") & mask8, nil
case x86asm.DL:
return regs.byName("rdx") & mask8, nil
case x86asm.BL:
return regs.byName("rbx") & mask8, nil
case x86asm.AH:
return (regs.byName("rax") >> 8) & mask8, nil
case x86asm.CH:
return (regs.byName("rcx") >> 8) & mask8, nil
case x86asm.DH:
return (regs.byName("rdx") >> 8) & mask8, nil
case x86asm.BH:
return (regs.byName("rbx") >> 8) & mask8, nil
case x86asm.SPB:
return regs.byName("rsp") & mask8, nil
case x86asm.BPB:
return regs.byName("rbp") & mask8, nil
case x86asm.SIB:
return regs.byName("rsi") & mask8, nil
case x86asm.DIB:
return regs.byName("rdi") & mask8, nil
case x86asm.R8B:
return regs.byName("r8") & mask8, nil
case x86asm.R9B:
return regs.byName("r9") & mask8, nil
case x86asm.R10B:
return regs.byName("r10") & mask8, nil
case x86asm.R11B:
return regs.byName("r11") & mask8, nil
case x86asm.R12B:
return regs.byName("r12") & mask8, nil
case x86asm.R13B:
return regs.byName("r13") & mask8, nil
case x86asm.R14B:
return regs.byName("r14") & mask8, nil
case x86asm.R15B:
return regs.byName("r15") & mask8, nil
// 16-bit
case x86asm.AX:
return regs.byName("rax") & mask16, nil
case x86asm.CX:
return regs.byName("rcx") & mask16, nil
case x86asm.DX:
return regs.byName("rdx") & mask16, nil
case x86asm.BX:
return regs.byName("rbx") & mask16, nil
case x86asm.SP:
return regs.byName("rsp") & mask16, nil
case x86asm.BP:
return regs.byName("rbp") & mask16, nil
case x86asm.SI:
return regs.byName("rsi") & mask16, nil
case x86asm.DI:
return regs.byName("rdi") & mask16, nil
case x86asm.R8W:
return regs.byName("r8") & mask16, nil
case x86asm.R9W:
return regs.byName("r9") & mask16, nil
case x86asm.R10W:
return regs.byName("r10") & mask16, nil
case x86asm.R11W:
return regs.byName("r11") & mask16, nil
case x86asm.R12W:
return regs.byName("r12") & mask16, nil
case x86asm.R13W:
return regs.byName("r13") & mask16, nil
case x86asm.R14W:
return regs.byName("r14") & mask16, nil
case x86asm.R15W:
return regs.byName("r15") & mask16, nil
// 32-bit
case x86asm.EAX:
return regs.byName("rax") & mask32, nil
case x86asm.ECX:
return regs.byName("rcx") & mask32, nil
case x86asm.EDX:
return regs.byName("rdx") & mask32, nil
case x86asm.EBX:
return regs.byName("rbx") & mask32, nil
case x86asm.ESP:
return regs.byName("rsp") & mask32, nil
case x86asm.EBP:
return regs.byName("rbp") & mask32, nil
case x86asm.ESI:
return regs.byName("rsi") & mask32, nil
case x86asm.EDI:
return regs.byName("rdi") & mask32, nil
case x86asm.R8L:
return regs.byName("r8") & mask32, nil
case x86asm.R9L:
return regs.byName("r9") & mask32, nil
case x86asm.R10L:
return regs.byName("r10") & mask32, nil
case x86asm.R11L:
return regs.byName("r11") & mask32, nil
case x86asm.R12L:
return regs.byName("r12") & mask32, nil
case x86asm.R13L:
return regs.byName("r13") & mask32, nil
case x86asm.R14L:
return regs.byName("r14") & mask32, nil
case x86asm.R15L:
return regs.byName("r15") & mask32, nil
// 64-bit
case x86asm.RAX:
return regs.byName("rax"), nil
case x86asm.RCX:
return regs.byName("rcx"), nil
case x86asm.RDX:
return regs.byName("rdx"), nil
case x86asm.RBX:
return regs.byName("rbx"), nil
case x86asm.RSP:
return regs.byName("rsp"), nil
case x86asm.RBP:
return regs.byName("rbp"), nil
case x86asm.RSI:
return regs.byName("rsi"), nil
case x86asm.RDI:
return regs.byName("rdi"), nil
case x86asm.R8:
return regs.byName("r8"), nil
case x86asm.R9:
return regs.byName("r9"), nil
case x86asm.R10:
return regs.byName("r10"), nil
case x86asm.R11:
return regs.byName("r11"), nil
case x86asm.R12:
return regs.byName("r12"), nil
case x86asm.R13:
return regs.byName("r13"), nil
case x86asm.R14:
return regs.byName("r14"), nil
case x86asm.R15:
return regs.byName("r15"), nil
}
}
return 0, proc.ErrUnknownRegister
}
func (r *gdbRegisters) FloatLoadError() error {
return nil
}

View File

@ -34,6 +34,7 @@ func I386Arch(goos string) *Arch {
asmDecode: i386AsmDecode,
PCRegNum: regnum.I386_Eip,
SPRegNum: regnum.I386_Esp,
asmRegisters: i386AsmRegisters,
}
}
@ -184,12 +185,12 @@ func i386RegSize(regnum uint64) int {
return 4
}
func i386RegistersToDwarfRegisters(staticBase uint64, regs Registers) op.DwarfRegisters {
func i386RegistersToDwarfRegisters(staticBase uint64, regs Registers) *op.DwarfRegisters {
dregs := initDwarfRegistersFromSlice(regnum.I386MaxRegNum(), regs, regnum.I386NameToDwarf)
dr := op.NewDwarfRegisters(staticBase, dregs, binary.LittleEndian, regnum.I386_Eip, regnum.I386_Esp, regnum.I386_Ebp, 0)
dr.SetLoadMoreCallback(loadMoreDwarfRegistersFromSliceFunc(dr, regs, regnum.I386NameToDwarf))
return *dr
return dr
}
func i386AddrAndStackRegsToDwarfRegisters(staticBase, pc, sp, bp, lr uint64) op.DwarfRegisters {

View File

@ -5,10 +5,13 @@
package proc
import (
"github.com/go-delve/delve/pkg/dwarf/op"
"github.com/go-delve/delve/pkg/dwarf/regnum"
"golang.org/x/arch/x86/x86asm"
)
func i386AsmDecode(asmInst *AsmInstruction, mem []byte, regs Registers, memrw MemoryReadWriter, bi *BinaryInfo) error {
func i386AsmDecode(asmInst *AsmInstruction, mem []byte, regs *op.DwarfRegisters, memrw MemoryReadWriter, bi *BinaryInfo) error {
return x86AsmDecode(asmInst, mem, regs, memrw, bi, 32)
}
@ -37,3 +40,39 @@ func init() {
}
}
}
var i386AsmRegisters = map[int]asmRegister{
// 8-bit
int(x86asm.AL): asmRegister{regnum.I386_Eax, 0, mask8},
int(x86asm.CL): asmRegister{regnum.I386_Ecx, 0, mask8},
int(x86asm.DL): asmRegister{regnum.I386_Edx, 0, mask8},
int(x86asm.BL): asmRegister{regnum.I386_Ebx, 0, mask8},
int(x86asm.AH): asmRegister{regnum.I386_Eax, 8, mask8},
int(x86asm.CH): asmRegister{regnum.I386_Ecx, 8, mask8},
int(x86asm.DH): asmRegister{regnum.I386_Edx, 8, mask8},
int(x86asm.BH): asmRegister{regnum.I386_Ebx, 8, mask8},
int(x86asm.SPB): asmRegister{regnum.I386_Esp, 0, mask8},
int(x86asm.BPB): asmRegister{regnum.I386_Ebp, 0, mask8},
int(x86asm.SIB): asmRegister{regnum.I386_Esi, 0, mask8},
int(x86asm.DIB): asmRegister{regnum.I386_Edi, 0, mask8},
// 16-bit
int(x86asm.AX): asmRegister{regnum.I386_Eax, 0, mask16},
int(x86asm.CX): asmRegister{regnum.I386_Ecx, 0, mask16},
int(x86asm.DX): asmRegister{regnum.I386_Edx, 0, mask16},
int(x86asm.BX): asmRegister{regnum.I386_Ebx, 0, mask16},
int(x86asm.SP): asmRegister{regnum.I386_Esp, 0, mask16},
int(x86asm.BP): asmRegister{regnum.I386_Ebp, 0, mask16},
int(x86asm.SI): asmRegister{regnum.I386_Esi, 0, mask16},
int(x86asm.DI): asmRegister{regnum.I386_Edi, 0, mask16},
// 32-bit
int(x86asm.EAX): asmRegister{regnum.I386_Eax, 0, mask32},
int(x86asm.ECX): asmRegister{regnum.I386_Ecx, 0, mask32},
int(x86asm.EDX): asmRegister{regnum.I386_Edx, 0, mask32},
int(x86asm.EBX): asmRegister{regnum.I386_Ebx, 0, mask32},
int(x86asm.ESP): asmRegister{regnum.I386_Esp, 0, mask32},
int(x86asm.EBP): asmRegister{regnum.I386_Ebp, 0, mask32},
int(x86asm.ESI): asmRegister{regnum.I386_Esi, 0, mask32},
int(x86asm.EDI): asmRegister{regnum.I386_Edi, 0, mask32},
}

View File

@ -3,8 +3,6 @@ package linutil
import (
"fmt"
"golang.org/x/arch/x86/x86asm"
"github.com/go-delve/delve/pkg/dwarf/op"
"github.com/go-delve/delve/pkg/dwarf/regnum"
"github.com/go-delve/delve/pkg/proc"
@ -131,164 +129,6 @@ func (r *AMD64Registers) GAddr() (uint64, bool) {
return 0, false
}
// Get returns the value of the n-th register (in x86asm order).
func (r *AMD64Registers) Get(n int) (uint64, error) {
reg := x86asm.Reg(n)
const (
mask8 = 0x000000ff
mask16 = 0x0000ffff
mask32 = 0xffffffff
)
switch reg {
// 8-bit
case x86asm.AL:
return r.Regs.Rax & mask8, nil
case x86asm.CL:
return r.Regs.Rcx & mask8, nil
case x86asm.DL:
return r.Regs.Rdx & mask8, nil
case x86asm.BL:
return r.Regs.Rbx & mask8, nil
case x86asm.AH:
return (r.Regs.Rax >> 8) & mask8, nil
case x86asm.CH:
return (r.Regs.Rcx >> 8) & mask8, nil
case x86asm.DH:
return (r.Regs.Rdx >> 8) & mask8, nil
case x86asm.BH:
return (r.Regs.Rbx >> 8) & mask8, nil
case x86asm.SPB:
return r.Regs.Rsp & mask8, nil
case x86asm.BPB:
return r.Regs.Rbp & mask8, nil
case x86asm.SIB:
return r.Regs.Rsi & mask8, nil
case x86asm.DIB:
return r.Regs.Rdi & mask8, nil
case x86asm.R8B:
return r.Regs.R8 & mask8, nil
case x86asm.R9B:
return r.Regs.R9 & mask8, nil
case x86asm.R10B:
return r.Regs.R10 & mask8, nil
case x86asm.R11B:
return r.Regs.R11 & mask8, nil
case x86asm.R12B:
return r.Regs.R12 & mask8, nil
case x86asm.R13B:
return r.Regs.R13 & mask8, nil
case x86asm.R14B:
return r.Regs.R14 & mask8, nil
case x86asm.R15B:
return r.Regs.R15 & mask8, nil
// 16-bit
case x86asm.AX:
return r.Regs.Rax & mask16, nil
case x86asm.CX:
return r.Regs.Rcx & mask16, nil
case x86asm.DX:
return r.Regs.Rdx & mask16, nil
case x86asm.BX:
return r.Regs.Rbx & mask16, nil
case x86asm.SP:
return r.Regs.Rsp & mask16, nil
case x86asm.BP:
return r.Regs.Rbp & mask16, nil
case x86asm.SI:
return r.Regs.Rsi & mask16, nil
case x86asm.DI:
return r.Regs.Rdi & mask16, nil
case x86asm.R8W:
return r.Regs.R8 & mask16, nil
case x86asm.R9W:
return r.Regs.R9 & mask16, nil
case x86asm.R10W:
return r.Regs.R10 & mask16, nil
case x86asm.R11W:
return r.Regs.R11 & mask16, nil
case x86asm.R12W:
return r.Regs.R12 & mask16, nil
case x86asm.R13W:
return r.Regs.R13 & mask16, nil
case x86asm.R14W:
return r.Regs.R14 & mask16, nil
case x86asm.R15W:
return r.Regs.R15 & mask16, nil
// 32-bit
case x86asm.EAX:
return r.Regs.Rax & mask32, nil
case x86asm.ECX:
return r.Regs.Rcx & mask32, nil
case x86asm.EDX:
return r.Regs.Rdx & mask32, nil
case x86asm.EBX:
return r.Regs.Rbx & mask32, nil
case x86asm.ESP:
return r.Regs.Rsp & mask32, nil
case x86asm.EBP:
return r.Regs.Rbp & mask32, nil
case x86asm.ESI:
return r.Regs.Rsi & mask32, nil
case x86asm.EDI:
return r.Regs.Rdi & mask32, nil
case x86asm.R8L:
return r.Regs.R8 & mask32, nil
case x86asm.R9L:
return r.Regs.R9 & mask32, nil
case x86asm.R10L:
return r.Regs.R10 & mask32, nil
case x86asm.R11L:
return r.Regs.R11 & mask32, nil
case x86asm.R12L:
return r.Regs.R12 & mask32, nil
case x86asm.R13L:
return r.Regs.R13 & mask32, nil
case x86asm.R14L:
return r.Regs.R14 & mask32, nil
case x86asm.R15L:
return r.Regs.R15 & mask32, nil
// 64-bit
case x86asm.RAX:
return r.Regs.Rax, nil
case x86asm.RCX:
return r.Regs.Rcx, nil
case x86asm.RDX:
return r.Regs.Rdx, nil
case x86asm.RBX:
return r.Regs.Rbx, nil
case x86asm.RSP:
return r.Regs.Rsp, nil
case x86asm.RBP:
return r.Regs.Rbp, nil
case x86asm.RSI:
return r.Regs.Rsi, nil
case x86asm.RDI:
return r.Regs.Rdi, nil
case x86asm.R8:
return r.Regs.R8, nil
case x86asm.R9:
return r.Regs.R9, nil
case x86asm.R10:
return r.Regs.R10, nil
case x86asm.R11:
return r.Regs.R11, nil
case x86asm.R12:
return r.Regs.R12, nil
case x86asm.R13:
return r.Regs.R13, nil
case x86asm.R14:
return r.Regs.R14, nil
case x86asm.R15:
return r.Regs.R15, nil
}
return 0, proc.ErrUnknownRegister
}
// Copy returns a copy of these registers that is guaranteed not to change.
func (r *AMD64Registers) Copy() (proc.Registers, error) {
if r.loadFpRegs != nil {

View File

@ -2,7 +2,6 @@ package linutil
import (
"fmt"
"golang.org/x/arch/arm64/arm64asm"
"github.com/go-delve/delve/pkg/proc"
)
@ -116,17 +115,6 @@ func (r *ARM64Registers) GAddr() (uint64, bool) {
return r.Regs.Regs[28], !r.iscgo
}
// Get returns the value of the n-th register (in arm64asm order).
func (r *ARM64Registers) Get(n int) (uint64, error) {
reg := arm64asm.Reg(n)
if reg >= arm64asm.X0 && reg <= arm64asm.X30 {
return r.Regs.Regs[reg-arm64asm.X0], nil
}
return 0, proc.ErrUnknownRegister
}
// Copy returns a copy of these registers that is guaranteed not to change.
func (r *ARM64Registers) Copy() (proc.Registers, error) {
if r.loadFpRegs != nil {

View File

@ -1,8 +1,6 @@
package linutil
import (
"golang.org/x/arch/x86/x86asm"
"github.com/go-delve/delve/pkg/proc"
"github.com/go-delve/delve/pkg/proc/amd64util"
)
@ -113,80 +111,6 @@ func (r *I386Registers) GAddr() (uint64, bool) {
return 0, false
}
// Get returns the value of the n-th register (in x86asm order).
func (r *I386Registers) Get(n int) (uint64, error) {
reg := x86asm.Reg(n)
const (
mask8 = 0x000000ff
mask16 = 0x0000ffff
)
switch reg {
// 8-bit
case x86asm.AL:
return uint64(r.Regs.Eax) & mask8, nil
case x86asm.CL:
return uint64(r.Regs.Ecx) & mask8, nil
case x86asm.DL:
return uint64(r.Regs.Edx) & mask8, nil
case x86asm.BL:
return uint64(r.Regs.Ebx) & mask8, nil
case x86asm.AH:
return (uint64(r.Regs.Eax) >> 8) & mask8, nil
case x86asm.CH:
return (uint64(r.Regs.Ecx) >> 8) & mask8, nil
case x86asm.DH:
return (uint64(r.Regs.Edx) >> 8) & mask8, nil
case x86asm.BH:
return (uint64(r.Regs.Ebx) >> 8) & mask8, nil
case x86asm.SPB:
return uint64(r.Regs.Esp) & mask8, nil
case x86asm.BPB:
return uint64(r.Regs.Ebp) & mask8, nil
case x86asm.SIB:
return uint64(r.Regs.Esi) & mask8, nil
case x86asm.DIB:
return uint64(r.Regs.Edi) & mask8, nil
// 16-bit
case x86asm.AX:
return uint64(r.Regs.Eax) & mask16, nil
case x86asm.CX:
return uint64(r.Regs.Ecx) & mask16, nil
case x86asm.DX:
return uint64(r.Regs.Edx) & mask16, nil
case x86asm.BX:
return uint64(r.Regs.Ebx) & mask16, nil
case x86asm.SP:
return uint64(r.Regs.Esp) & mask16, nil
case x86asm.BP:
return uint64(r.Regs.Ebp) & mask16, nil
case x86asm.SI:
return uint64(r.Regs.Esi) & mask16, nil
case x86asm.DI:
return uint64(r.Regs.Edi) & mask16, nil
// 32-bit
case x86asm.EAX:
return uint64(uint32(r.Regs.Eax)), nil
case x86asm.ECX:
return uint64(uint32(r.Regs.Ecx)), nil
case x86asm.EDX:
return uint64(uint32(r.Regs.Edx)), nil
case x86asm.EBX:
return uint64(uint32(r.Regs.Ebx)), nil
case x86asm.ESP:
return uint64(uint32(r.Regs.Esp)), nil
case x86asm.EBP:
return uint64(uint32(r.Regs.Ebp)), nil
case x86asm.ESI:
return uint64(uint32(r.Regs.Esi)), nil
case x86asm.EDI:
return uint64(uint32(r.Regs.Edi)), nil
}
return 0, proc.ErrUnknownRegister
}
// Copy returns a copy of these registers that is guaranteed not to change.
func (r *I386Registers) Copy() (proc.Registers, error) {
if r.loadFpRegs != nil {

View File

@ -1,60 +0,0 @@
package linutil
import (
"testing"
"golang.org/x/arch/x86/x86asm"
)
func TestAMD64Get(t *testing.T) {
val := uint64(0xffffffffdeadbeef)
regs := AMD64Registers{
Regs: &AMD64PtraceRegs{
Rax: val,
},
}
// Test AL, low 8 bits of RAX
al, err := regs.Get(int(x86asm.AL))
if err != nil {
t.Fatal(err)
}
if al != 0xef {
t.Fatalf("expected %#v, got %#v\n", 0xef, al)
}
// Test AH, high 8 bits of RAX
ah, err := regs.Get(int(x86asm.AH))
if err != nil {
t.Fatal(err)
}
if ah != 0xBE {
t.Fatalf("expected %#v, got %#v\n", 0xbe, ah)
}
// Test AX, lower 16 bits of RAX
ax, err := regs.Get(int(x86asm.AX))
if err != nil {
t.Fatal(err)
}
if ax != 0xBEEF {
t.Fatalf("expected %#v, got %#v\n", 0xbeef, ax)
}
// Test EAX, lower 32 bits of RAX
eax, err := regs.Get(int(x86asm.EAX))
if err != nil {
t.Fatal(err)
}
if eax != 0xDEADBEEF {
t.Fatalf("expected %#v, got %#v\n", uint64(0xdeadbeef), eax)
}
// Test RAX, full 64 bits of register
rax, err := regs.Get(int(x86asm.RAX))
if err != nil {
t.Fatal(err)
}
if rax != val {
t.Fatalf("expected %#v, got %#v\n", val, rax)
}
}

View File

@ -4994,7 +4994,7 @@ func TestDump(t *testing.T) {
assertNoError(err, t, fmt.Sprintf("Thread registers %d", thread.ThreadID()))
arch := thread.BinInfo().Arch
dregs := arch.RegistersToDwarfRegisters(0, regs)
return fmt.Sprintf("%08d %s", thread.ThreadID(), convertRegisters(arch, dregs))
return fmt.Sprintf("%08d %s", thread.ThreadID(), convertRegisters(arch, *dregs))
}
convertThreads := func(threads []proc.Thread) []string {

View File

@ -20,7 +20,6 @@ type Registers interface {
TLS() uint64
// GAddr returns the address of the G variable if it is known, 0 and false otherwise
GAddr() (uint64, bool)
Get(int) (uint64, error)
Slice(floatingPoint bool) ([]Register, error)
// Copy returns a copy of the registers that is guaranteed not to change
// when the registers of the associated thread change.

View File

@ -100,7 +100,7 @@ func ThreadStacktrace(thread Thread, depth int) ([]Stackframe, error) {
return nil, err
}
so := thread.BinInfo().PCToImage(regs.PC())
dwarfRegs := thread.BinInfo().Arch.RegistersToDwarfRegisters(so.StaticBase, regs)
dwarfRegs := *(thread.BinInfo().Arch.RegistersToDwarfRegisters(so.StaticBase, regs))
dwarfRegs.ChangeFunc = thread.SetReg
it := newStackIterator(thread.BinInfo(), thread.ProcessMemory(), dwarfRegs, 0, nil, -1, nil, 0)
return it.stacktrace(depth)
@ -121,7 +121,7 @@ func (g *G) stackIterator(opts StacktraceOptions) (*stackIterator, error) {
return nil, err
}
so := bi.PCToImage(regs.PC())
dwarfRegs := bi.Arch.RegistersToDwarfRegisters(so.StaticBase, regs)
dwarfRegs := *(bi.Arch.RegistersToDwarfRegisters(so.StaticBase, regs))
dwarfRegs.ChangeFunc = g.Thread.SetReg
return newStackIterator(
bi, g.variable.mem,

View File

@ -6,8 +6,6 @@ import (
"fmt"
"unsafe"
"golang.org/x/arch/x86/x86asm"
"github.com/go-delve/delve/pkg/proc"
)
@ -164,164 +162,6 @@ func (r *AMD64Registers) GAddr() (uint64, bool) {
return 0, false
}
// Get returns the value of the n-th register (in x86asm order).
func (r *AMD64Registers) Get(n int) (uint64, error) {
reg := x86asm.Reg(n)
const (
mask8 = 0x000f
mask16 = 0x00ff
mask32 = 0xffff
)
switch reg {
// 8-bit
case x86asm.AL:
return r.rax & mask8, nil
case x86asm.CL:
return r.rcx & mask8, nil
case x86asm.DL:
return r.rdx & mask8, nil
case x86asm.BL:
return r.rbx & mask8, nil
case x86asm.AH:
return (r.rax >> 8) & mask8, nil
case x86asm.CH:
return (r.rcx >> 8) & mask8, nil
case x86asm.DH:
return (r.rdx >> 8) & mask8, nil
case x86asm.BH:
return (r.rbx >> 8) & mask8, nil
case x86asm.SPB:
return r.rsp & mask8, nil
case x86asm.BPB:
return r.rbp & mask8, nil
case x86asm.SIB:
return r.rsi & mask8, nil
case x86asm.DIB:
return r.rdi & mask8, nil
case x86asm.R8B:
return r.r8 & mask8, nil
case x86asm.R9B:
return r.r9 & mask8, nil
case x86asm.R10B:
return r.r10 & mask8, nil
case x86asm.R11B:
return r.r11 & mask8, nil
case x86asm.R12B:
return r.r12 & mask8, nil
case x86asm.R13B:
return r.r13 & mask8, nil
case x86asm.R14B:
return r.r14 & mask8, nil
case x86asm.R15B:
return r.r15 & mask8, nil
// 16-bit
case x86asm.AX:
return r.rax & mask16, nil
case x86asm.CX:
return r.rcx & mask16, nil
case x86asm.DX:
return r.rdx & mask16, nil
case x86asm.BX:
return r.rbx & mask16, nil
case x86asm.SP:
return r.rsp & mask16, nil
case x86asm.BP:
return r.rbp & mask16, nil
case x86asm.SI:
return r.rsi & mask16, nil
case x86asm.DI:
return r.rdi & mask16, nil
case x86asm.R8W:
return r.r8 & mask16, nil
case x86asm.R9W:
return r.r9 & mask16, nil
case x86asm.R10W:
return r.r10 & mask16, nil
case x86asm.R11W:
return r.r11 & mask16, nil
case x86asm.R12W:
return r.r12 & mask16, nil
case x86asm.R13W:
return r.r13 & mask16, nil
case x86asm.R14W:
return r.r14 & mask16, nil
case x86asm.R15W:
return r.r15 & mask16, nil
// 32-bit
case x86asm.EAX:
return r.rax & mask32, nil
case x86asm.ECX:
return r.rcx & mask32, nil
case x86asm.EDX:
return r.rdx & mask32, nil
case x86asm.EBX:
return r.rbx & mask32, nil
case x86asm.ESP:
return r.rsp & mask32, nil
case x86asm.EBP:
return r.rbp & mask32, nil
case x86asm.ESI:
return r.rsi & mask32, nil
case x86asm.EDI:
return r.rdi & mask32, nil
case x86asm.R8L:
return r.r8 & mask32, nil
case x86asm.R9L:
return r.r9 & mask32, nil
case x86asm.R10L:
return r.r10 & mask32, nil
case x86asm.R11L:
return r.r11 & mask32, nil
case x86asm.R12L:
return r.r12 & mask32, nil
case x86asm.R13L:
return r.r13 & mask32, nil
case x86asm.R14L:
return r.r14 & mask32, nil
case x86asm.R15L:
return r.r15 & mask32, nil
// 64-bit
case x86asm.RAX:
return r.rax, nil
case x86asm.RCX:
return r.rcx, nil
case x86asm.RDX:
return r.rdx, nil
case x86asm.RBX:
return r.rbx, nil
case x86asm.RSP:
return r.rsp, nil
case x86asm.RBP:
return r.rbp, nil
case x86asm.RSI:
return r.rsi, nil
case x86asm.RDI:
return r.rdi, nil
case x86asm.R8:
return r.r8, nil
case x86asm.R9:
return r.r9, nil
case x86asm.R10:
return r.r10, nil
case x86asm.R11:
return r.r11, nil
case x86asm.R12:
return r.r12, nil
case x86asm.R13:
return r.r13, nil
case x86asm.R14:
return r.r14, nil
case x86asm.R15:
return r.r15, nil
}
return 0, proc.ErrUnknownRegister
}
// Copy returns a copy of these registers that is guaranteed not to change.
func (r *AMD64Registers) Copy() (proc.Registers, error) {
var rr AMD64Registers

View File

@ -1,6 +1,8 @@
package proc
import (
"github.com/go-delve/delve/pkg/dwarf/op"
"golang.org/x/arch/x86/x86asm"
)
@ -8,7 +10,7 @@ type x86Inst x86asm.Inst
// AsmDecode decodes the assembly instruction starting at mem[0:] into asmInst.
// It assumes that the Loc and AtPC fields of asmInst have already been filled.
func x86AsmDecode(asmInst *AsmInstruction, mem []byte, regs Registers, memrw MemoryReadWriter, bi *BinaryInfo, bit int) error {
func x86AsmDecode(asmInst *AsmInstruction, mem []byte, regs *op.DwarfRegisters, memrw MemoryReadWriter, bi *BinaryInfo, bit int) error {
inst, err := x86asm.Decode(mem, bit)
if err != nil {
asmInst.Inst = (*x86Inst)(nil)
@ -76,7 +78,7 @@ func (inst *x86Inst) OpcodeEquals(op uint64) bool {
return uint64(inst.Op) == op
}
func resolveCallArgX86(inst *x86asm.Inst, instAddr uint64, currentGoroutine bool, regs Registers, mem MemoryReadWriter, bininfo *BinaryInfo) *Location {
func resolveCallArgX86(inst *x86asm.Inst, instAddr uint64, currentGoroutine bool, regs *op.DwarfRegisters, mem MemoryReadWriter, bininfo *BinaryInfo) *Location {
switch inst.Op {
case x86asm.CALL, x86asm.LCALL, x86asm.JMP, x86asm.LJMP:
// ok
@ -94,7 +96,7 @@ func resolveCallArgX86(inst *x86asm.Inst, instAddr uint64, currentGoroutine bool
if !currentGoroutine || regs == nil {
return nil
}
pc, err = regs.Get(int(arg))
pc, err = bininfo.Arch.getAsmRegister(regs, int(arg))
if err != nil {
return nil
}
@ -105,8 +107,8 @@ func resolveCallArgX86(inst *x86asm.Inst, instAddr uint64, currentGoroutine bool
if arg.Segment != 0 {
return nil
}
base, err1 := regs.Get(int(arg.Base))
index, err2 := regs.Get(int(arg.Index))
base, err1 := bininfo.Arch.getAsmRegister(regs, int(arg.Base))
index, err2 := bininfo.Arch.getAsmRegister(regs, int(arg.Index))
if err1 != nil || err2 != nil {
return nil
}

View File

@ -1313,8 +1313,7 @@ func (d *Debugger) ThreadRegisters(threadID int, floatingPoint bool) (*op.DwarfR
if err != nil {
return nil, err
}
dregs := d.target.BinInfo().Arch.RegistersToDwarfRegisters(0, regs)
return &dregs, nil
return d.target.BinInfo().Arch.RegistersToDwarfRegisters(0, regs), nil
}
// ScopeRegisters returns registers for the specified scope.