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

proc: convert Arch into a struct (#1972)

Replace the interface type Arch with a struct with the same
functionality.
上级 85c34e47
...@@ -12,23 +12,6 @@ import ( ...@@ -12,23 +12,6 @@ import (
"github.com/go-delve/delve/pkg/dwarf/op" "github.com/go-delve/delve/pkg/dwarf/op"
) )
// AMD64 represents the AMD64 CPU architecture.
type AMD64 struct {
gStructOffset uint64
goos string
// 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
// traces.
crosscall2fn *Function
// sigreturnfn is the DIE of runtime.sigreturn, the return trampoline for
// the signal handler. See comment in FixFrameUnwindContext for a
// description of why this is needed.
sigreturnfn *Function
}
const ( const (
amd64DwarfIPRegNum uint64 = 16 amd64DwarfIPRegNum uint64 = 16
amd64DwarfSPRegNum uint64 = 7 amd64DwarfSPRegNum uint64 = 7
...@@ -39,51 +22,28 @@ var amd64BreakInstruction = []byte{0xCC} ...@@ -39,51 +22,28 @@ var amd64BreakInstruction = []byte{0xCC}
// AMD64Arch returns an initialized AMD64 // AMD64Arch returns an initialized AMD64
// struct. // struct.
func AMD64Arch(goos string) *AMD64 { func AMD64Arch(goos string) *Arch {
return &AMD64{ return &Arch{
goos: goos, Name: "amd64",
ptrSize: 8,
maxInstructionLength: 15,
breakpointInstruction: amd64BreakInstruction,
breakInstrMovesPC: true,
derefTLS: goos == "windows",
prologues: prologuesAMD64,
fixFrameUnwindContext: amd64FixFrameUnwindContext,
switchStack: amd64SwitchStack,
regSize: amd64RegSize,
RegistersToDwarfRegisters: amd64RegistersToDwarfRegisters,
addrAndStackRegsToDwarfRegisters: amd64AddrAndStackRegsToDwarfRegisters,
DwarfRegisterToString: amd64DwarfRegisterToString,
inhibitStepInto: func(*BinaryInfo, uint64) bool { return false },
asmDecode: amd64AsmDecode,
} }
} }
// PtrSize returns the size of a pointer func amd64FixFrameUnwindContext(fctxt *frame.FrameContext, pc uint64, bi *BinaryInfo) *frame.FrameContext {
// on this architecture. a := bi.Arch
func (a *AMD64) PtrSize() int {
return 8
}
// MaxInstructionLength returns the maximum length of an instruction.
func (a *AMD64) MaxInstructionLength() int {
return 15
}
// BreakpointInstruction returns the Breakpoint
// instruction for this architecture.
func (a *AMD64) BreakpointInstruction() []byte {
return amd64BreakInstruction
}
// BreakInstrMovesPC returns whether the
// breakpoint instruction will change the value
// of PC after being executed
func (a *AMD64) BreakInstrMovesPC() bool {
return true
}
// BreakpointSize returns the size of the
// breakpoint instruction on this architecture.
func (a *AMD64) BreakpointSize() int {
return len(amd64BreakInstruction)
}
// DerefTLS returns true if the value of regs.TLS()+GStructOffset() is a
// pointer to the G struct
func (a *AMD64) DerefTLS() bool {
return a.goos == "windows"
}
// FixFrameUnwindContext adds default architecture rules to fctxt or returns
// the default frame unwind context if fctxt is nil.
func (a *AMD64) FixFrameUnwindContext(fctxt *frame.FrameContext, pc uint64, bi *BinaryInfo) *frame.FrameContext {
if a.sigreturnfn == nil { if a.sigreturnfn == nil {
a.sigreturnfn = bi.LookupFunc["runtime.sigreturn"] a.sigreturnfn = bi.LookupFunc["runtime.sigreturn"]
} }
...@@ -138,7 +98,7 @@ func (a *AMD64) FixFrameUnwindContext(fctxt *frame.FrameContext, pc uint64, bi * ...@@ -138,7 +98,7 @@ func (a *AMD64) FixFrameUnwindContext(fctxt *frame.FrameContext, pc uint64, bi *
if a.crosscall2fn != nil && pc >= a.crosscall2fn.Entry && pc < a.crosscall2fn.End { if a.crosscall2fn != nil && pc >= a.crosscall2fn.Entry && pc < a.crosscall2fn.End {
rule := fctxt.CFA rule := fctxt.CFA
if rule.Offset == crosscall2SPOffsetBad { if rule.Offset == crosscall2SPOffsetBad {
switch a.goos { switch bi.GOOS {
case "windows": case "windows":
rule.Offset += crosscall2SPOffsetWindows rule.Offset += crosscall2SPOffsetWindows
default: default:
...@@ -168,10 +128,7 @@ func (a *AMD64) FixFrameUnwindContext(fctxt *frame.FrameContext, pc uint64, bi * ...@@ -168,10 +128,7 @@ func (a *AMD64) FixFrameUnwindContext(fctxt *frame.FrameContext, pc uint64, bi *
// switch happens. // switch happens.
const amd64cgocallSPOffsetSaveSlot = 0x28 const amd64cgocallSPOffsetSaveSlot = 0x28
// SwitchStack will use the current frame to determine if it's time to func amd64SwitchStack(it *stackIterator, _ *op.DwarfRegisters) bool {
// switch between the system stack and the goroutine stack or vice versa.
// Sets it.atend when the top of the stack is reached.
func (a *AMD64) SwitchStack(it *stackIterator, _ *op.DwarfRegisters) bool {
if it.frame.Current.Fn == nil { if it.frame.Current.Fn == nil {
return false return false
} }
...@@ -282,12 +239,12 @@ func (a *AMD64) SwitchStack(it *stackIterator, _ *op.DwarfRegisters) bool { ...@@ -282,12 +239,12 @@ func (a *AMD64) SwitchStack(it *stackIterator, _ *op.DwarfRegisters) bool {
} }
} }
// RegSize returns the size (in bytes) of register regnum. // amd64RegSize returns the size (in bytes) of register regnum.
// The mapping between hardware registers and DWARF registers is specified // The mapping between hardware registers and DWARF registers is specified
// in the System V ABI AMD64 Architecture Processor Supplement page 57, // in the System V ABI AMD64 Architecture Processor Supplement page 57,
// figure 3.36 // figure 3.36
// https://www.uclibc.org/docs/psABI-x86_64.pdf // https://www.uclibc.org/docs/psABI-x86_64.pdf
func (a *AMD64) RegSize(regnum uint64) int { func amd64RegSize(regnum uint64) int {
// XMM registers // XMM registers
if regnum > amd64DwarfIPRegNum && regnum <= 32 { if regnum > amd64DwarfIPRegNum && regnum <= 32 {
return 16 return 16
...@@ -387,9 +344,7 @@ func maxAmd64DwarfRegister() int { ...@@ -387,9 +344,7 @@ func maxAmd64DwarfRegister() int {
return max return max
} }
// RegistersToDwarfRegisters converts hardware registers to the format used func amd64RegistersToDwarfRegisters(staticBase uint64, regs Registers) op.DwarfRegisters {
// by the DWARF expression interpreter.
func (a *AMD64) RegistersToDwarfRegisters(staticBase uint64, regs Registers) op.DwarfRegisters {
dregs := make([]*op.DwarfRegister, maxAmd64DwarfRegister()+1) dregs := make([]*op.DwarfRegister, maxAmd64DwarfRegister()+1)
for _, reg := range regs.Slice(true) { for _, reg := range regs.Slice(true) {
...@@ -408,9 +363,7 @@ func (a *AMD64) RegistersToDwarfRegisters(staticBase uint64, regs Registers) op. ...@@ -408,9 +363,7 @@ func (a *AMD64) RegistersToDwarfRegisters(staticBase uint64, regs Registers) op.
} }
} }
// AddrAndStackRegsToDwarfRegisters returns DWARF registers from the passed in func amd64AddrAndStackRegsToDwarfRegisters(staticBase, pc, sp, bp, lr uint64) op.DwarfRegisters {
// PC, SP, and BP registers in the format used by the DWARF expression interpreter.
func (a *AMD64) AddrAndStackRegsToDwarfRegisters(staticBase, pc, sp, bp, lr uint64) op.DwarfRegisters {
dregs := make([]*op.DwarfRegister, amd64DwarfIPRegNum+1) dregs := make([]*op.DwarfRegister, amd64DwarfIPRegNum+1)
dregs[amd64DwarfIPRegNum] = op.DwarfRegisterFromUint64(pc) dregs[amd64DwarfIPRegNum] = op.DwarfRegisterFromUint64(pc)
dregs[amd64DwarfSPRegNum] = op.DwarfRegisterFromUint64(sp) dregs[amd64DwarfSPRegNum] = op.DwarfRegisterFromUint64(sp)
...@@ -426,8 +379,7 @@ func (a *AMD64) AddrAndStackRegsToDwarfRegisters(staticBase, pc, sp, bp, lr uint ...@@ -426,8 +379,7 @@ func (a *AMD64) AddrAndStackRegsToDwarfRegisters(staticBase, pc, sp, bp, lr uint
} }
} }
// DwarfRegisterToString returns the name and value representation of the given register. func amd64DwarfRegisterToString(i int, reg *op.DwarfRegister) (name string, floatingPoint bool, repr string) {
func (a *AMD64) DwarfRegisterToString(i int, reg *op.DwarfRegister) (name string, floatingPoint bool, repr string) {
name, ok := amd64DwarfToName[i] name, ok := amd64DwarfToName[i]
if !ok { if !ok {
name = fmt.Sprintf("unknown%d", i) name = fmt.Sprintf("unknown%d", i)
...@@ -559,9 +511,3 @@ func formatX87Reg(b []byte) string { ...@@ -559,9 +511,3 @@ func formatX87Reg(b []byte) string {
return fmt.Sprintf("%#04x%016x\t%g", exponent, mantissa, f) return fmt.Sprintf("%#04x%016x\t%g", exponent, mantissa, f)
} }
// InhibitStepInto returns whether StepBreakpoint can be set at pc.
// Always return false on amd64.
func (a *AMD64) InhibitStepInto(bi *BinaryInfo, pc uint64) bool {
return false
}
...@@ -8,16 +8,10 @@ import ( ...@@ -8,16 +8,10 @@ import (
"golang.org/x/arch/x86/x86asm" "golang.org/x/arch/x86/x86asm"
) )
// AsmDecode decodes the assembly instruction starting at mem[0:] into asmInst. func amd64AsmDecode(asmInst *AsmInstruction, mem []byte, regs Registers, memrw MemoryReadWriter, bi *BinaryInfo) error {
// It assumes that the Loc and AtPC fields of asmInst have already been filled.
func (a *AMD64) AsmDecode(asmInst *AsmInstruction, mem []byte, regs Registers, memrw MemoryReadWriter, bi *BinaryInfo) error {
return x86AsmDecode(asmInst, mem, regs, memrw, bi, 64) return x86AsmDecode(asmInst, mem, regs, memrw, bi, 64)
} }
func (a *AMD64) Prologues() []opcodeSeq {
return prologuesAMD64
}
// Possible stacksplit prologues are inserted by stacksplit in // Possible stacksplit prologues are inserted by stacksplit in
// $GOROOT/src/cmd/internal/obj/x86/obj6.go. // $GOROOT/src/cmd/internal/obj/x86/obj6.go.
// The stacksplit prologue will always begin with loading curg in CX, this // The stacksplit prologue will always begin with loading curg in CX, this
......
...@@ -5,47 +5,87 @@ import ( ...@@ -5,47 +5,87 @@ import (
"github.com/go-delve/delve/pkg/dwarf/op" "github.com/go-delve/delve/pkg/dwarf/op"
) )
// Arch defines an interface for representing a // Arch represents a CPU architecture.
// CPU architecture. type Arch struct {
type Arch interface { Name string // architecture name
// PtrSize returns the size of a pointer for the architecture.
PtrSize() int ptrSize int
// MaxInstructionLength is the maximum size in bytes of an instruction. maxInstructionLength int
MaxInstructionLength() int prologues []opcodeSeq
// AsmDecode decodes the assembly instruction starting at mem[0:] into asmInst. breakpointInstruction []byte
breakInstrMovesPC bool
derefTLS bool
// 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. // It assumes that the Loc and AtPC fields of asmInst have already been filled.
AsmDecode(asmInst *AsmInstruction, mem []byte, regs Registers, memrw MemoryReadWriter, bi *BinaryInfo) error asmDecode func(asmInst *AsmInstruction, mem []byte, regs Registers, memrw MemoryReadWriter, bi *BinaryInfo) error
// Prologues returns a list of stack split prologues // fixFrameUnwindContext applies architecture specific rules for unwinding a stack frame
// that are inserted at function entry.
Prologues() []opcodeSeq
// BreakpointInstruction is the instruction that will trigger a breakpoint trap for
// the given architecture.
BreakpointInstruction() []byte
// BreakInstrMovesPC is true if hitting the breakpoint instruction advances the
// instruction counter by the size of the breakpoint instruction.
BreakInstrMovesPC() bool
// BreakpointSize is the size of the breakpoint instruction for the given architecture.
BreakpointSize() int
// DerefTLS is true if the G struct stored in the TLS section is a pointer
// and the address must be dereferenced to find to actual G struct.
DerefTLS() bool
// FixFrameUnwindContext applies architecture specific rules for unwinding a stack frame
// on the given arch. // on the given arch.
FixFrameUnwindContext(*frame.FrameContext, uint64, *BinaryInfo) *frame.FrameContext fixFrameUnwindContext func(*frame.FrameContext, uint64, *BinaryInfo) *frame.FrameContext
// SwitchStack will use the current frame to determine if it's time to // switchStack will use the current frame to determine if it's time to
// switch between the system stack and the goroutine stack or vice versa. // switch between the system stack and the goroutine stack or vice versa.
SwitchStack(it *stackIterator, callFrameRegs *op.DwarfRegisters) bool switchStack func(it *stackIterator, callFrameRegs *op.DwarfRegisters) bool
// RegSize returns the size (in bytes) of register regnum. // regSize returns the size (in bytes) of register regnum.
RegSize(uint64) int regSize func(uint64) int
// RegistersToDwarfRegisters maps hardware registers to DWARF registers. // RegistersToDwarfRegisters maps hardware registers to DWARF registers.
RegistersToDwarfRegisters(uint64, Registers) op.DwarfRegisters RegistersToDwarfRegisters func(uint64, Registers) op.DwarfRegisters
// AddrAndStackRegsToDwarfRegisters returns DWARF registers from the passed in // addrAndStackRegsToDwarfRegisters returns DWARF registers from the passed in
// PC, SP, and BP registers in the format used by the DWARF expression interpreter. // PC, SP, and BP registers in the format used by the DWARF expression interpreter.
AddrAndStackRegsToDwarfRegisters(uint64, uint64, uint64, uint64, uint64) op.DwarfRegisters addrAndStackRegsToDwarfRegisters func(uint64, uint64, uint64, uint64, uint64) op.DwarfRegisters
// DwarfRegisterToString returns the name and value representation of the given register. // DwarfRegisterToString returns the name and value representation of the given register.
DwarfRegisterToString(int, *op.DwarfRegister) (string, bool, string) DwarfRegisterToString func(int, *op.DwarfRegister) (string, bool, string)
// InhibitStepInto returns whether StepBreakpoint can be set at pc. // inhibitStepInto returns whether StepBreakpoint can be set at pc.
InhibitStepInto(bi *BinaryInfo, pc uint64) bool inhibitStepInto func(bi *BinaryInfo, pc uint64) bool
// 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
// traces.
crosscall2fn *Function
// sigreturnfn is the DIE of runtime.sigreturn, the return trampoline for
// the signal handler. See comment in FixFrameUnwindContext for a
// description of why this is needed.
sigreturnfn *Function
}
// PtrSize returns the size of a pointer for the architecture.
func (a *Arch) PtrSize() int {
return a.ptrSize
}
// MaxInstructionLength is the maximum size in bytes of an instruction.
func (a *Arch) MaxInstructionLength() int {
return a.maxInstructionLength
}
// Prologues returns a list of stack split prologues
// that are inserted at function entry.
func (a *Arch) Prologues() []opcodeSeq {
return a.prologues
}
// BreakpointInstruction is the instruction that will trigger a breakpoint trap for
// the given architecture.
func (a *Arch) BreakpointInstruction() []byte {
return a.breakpointInstruction
}
// BreakInstrMovesPC is true if hitting the breakpoint instruction advances the
// instruction counter by the size of the breakpoint instruction.
func (a *Arch) BreakInstrMovesPC() bool {
return a.breakInstrMovesPC
}
// BreakpointSize is the size of the breakpoint instruction for the given architecture.
func (a *Arch) BreakpointSize() int {
return len(a.breakpointInstruction)
}
// DerefTLS is true if the G struct stored in the TLS section is a pointer
// and the address must be dereferenced to find to actual G struct.
func (a *Arch) DerefTLS() bool {
return a.derefTLS
} }
// crosscall2 is defined in $GOROOT/src/runtime/cgo/asm_amd64.s. // crosscall2 is defined in $GOROOT/src/runtime/cgo/asm_amd64.s.
......
...@@ -12,23 +12,6 @@ import ( ...@@ -12,23 +12,6 @@ import (
"golang.org/x/arch/arm64/arm64asm" "golang.org/x/arch/arm64/arm64asm"
) )
// ARM64 represents the ARM64 CPU architecture.
type ARM64 struct {
gStructOffset uint64
goos string
// 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
// traces.
crosscall2fn *Function
// sigreturnfn is the DIE of runtime.sigreturn, the return trampoline for
// the signal handler. See comment in FixFrameUnwindContext for a
// description of why this is needed.
sigreturnfn *Function
}
const ( const (
arm64DwarfIPRegNum uint64 = 32 arm64DwarfIPRegNum uint64 = 32
arm64DwarfSPRegNum uint64 = 31 arm64DwarfSPRegNum uint64 = 31
...@@ -40,50 +23,28 @@ var arm64BreakInstruction = []byte{0x0, 0x0, 0x20, 0xd4} ...@@ -40,50 +23,28 @@ var arm64BreakInstruction = []byte{0x0, 0x0, 0x20, 0xd4}
// ARM64Arch returns an initialized ARM64 // ARM64Arch returns an initialized ARM64
// struct. // struct.
func ARM64Arch(goos string) *ARM64 { func ARM64Arch(goos string) *Arch {
return &ARM64{ return &Arch{
goos: goos, Name: "arm64",
ptrSize: 8,
maxInstructionLength: 4,
breakpointInstruction: arm64BreakInstruction,
breakInstrMovesPC: false,
derefTLS: false,
prologues: prologuesARM64,
fixFrameUnwindContext: arm64FixFrameUnwindContext,
switchStack: arm64SwitchStack,
regSize: arm64RegSize,
RegistersToDwarfRegisters: arm64RegistersToDwarfRegisters,
addrAndStackRegsToDwarfRegisters: arm64AddrAndStackRegsToDwarfRegisters,
DwarfRegisterToString: arm64DwarfRegisterToString,
inhibitStepInto: func(*BinaryInfo, uint64) bool { return false },
asmDecode: arm64AsmDecode,
} }
} }
// PtrSize returns the size of a pointer func arm64FixFrameUnwindContext(fctxt *frame.FrameContext, pc uint64, bi *BinaryInfo) *frame.FrameContext {
// on this architecture. a := bi.Arch
func (a *ARM64) PtrSize() int {
return 8
}
// MaxInstructionLength returns the maximum length of an instruction.
func (a *ARM64) MaxInstructionLength() int {
return 4
}
// BreakpointInstruction returns the Breakpoint
// instruction for this architecture.
func (a *ARM64) BreakpointInstruction() []byte {
return arm64BreakInstruction
}
// BreakInstrMovesPC returns whether the
// breakpoint instruction will change the value
// of PC after being executed
func (a *ARM64) BreakInstrMovesPC() bool {
return false
}
// BreakpointSize returns the size of the
// breakpoint instruction on this architecture.
func (a *ARM64) BreakpointSize() int {
return len(arm64BreakInstruction)
}
// Always return false for now.
func (a *ARM64) DerefTLS() bool {
return false
}
// FixFrameUnwindContext adds default architecture rules to fctxt or returns
// the default frame unwind context if fctxt is nil.
func (a *ARM64) FixFrameUnwindContext(fctxt *frame.FrameContext, pc uint64, bi *BinaryInfo) *frame.FrameContext {
if a.sigreturnfn == nil { if a.sigreturnfn == nil {
a.sigreturnfn = bi.LookupFunc["runtime.sigreturn"] a.sigreturnfn = bi.LookupFunc["runtime.sigreturn"]
} }
...@@ -138,7 +99,7 @@ func (a *ARM64) FixFrameUnwindContext(fctxt *frame.FrameContext, pc uint64, bi * ...@@ -138,7 +99,7 @@ func (a *ARM64) FixFrameUnwindContext(fctxt *frame.FrameContext, pc uint64, bi *
if a.crosscall2fn != nil && pc >= a.crosscall2fn.Entry && pc < a.crosscall2fn.End { if a.crosscall2fn != nil && pc >= a.crosscall2fn.Entry && pc < a.crosscall2fn.End {
rule := fctxt.CFA rule := fctxt.CFA
if rule.Offset == crosscall2SPOffsetBad { if rule.Offset == crosscall2SPOffsetBad {
switch a.goos { switch bi.GOOS {
case "windows": case "windows":
rule.Offset += crosscall2SPOffsetWindows rule.Offset += crosscall2SPOffsetWindows
default: default:
...@@ -174,7 +135,7 @@ const arm64cgocallSPOffsetSaveSlot = 0x8 ...@@ -174,7 +135,7 @@ const arm64cgocallSPOffsetSaveSlot = 0x8
const prevG0schedSPOffsetSaveSlot = 0x10 const prevG0schedSPOffsetSaveSlot = 0x10
const spAlign = 16 const spAlign = 16
func (a *ARM64) SwitchStack(it *stackIterator, callFrameRegs *op.DwarfRegisters) bool { func arm64SwitchStack(it *stackIterator, callFrameRegs *op.DwarfRegisters) bool {
if it.frame.Current.Fn != nil { if it.frame.Current.Fn != nil {
switch it.frame.Current.Fn.Name { switch it.frame.Current.Fn.Name {
case "runtime.asmcgocall", "runtime.cgocallback_gofunc", "runtime.sigpanic": case "runtime.asmcgocall", "runtime.cgocallback_gofunc", "runtime.sigpanic":
...@@ -270,7 +231,7 @@ func (a *ARM64) SwitchStack(it *stackIterator, callFrameRegs *op.DwarfRegisters) ...@@ -270,7 +231,7 @@ func (a *ARM64) SwitchStack(it *stackIterator, callFrameRegs *op.DwarfRegisters)
return false return false
} }
func (a *ARM64) RegSize(regnum uint64) int { func arm64RegSize(regnum uint64) int {
// fp registers // fp registers
if regnum >= 64 && regnum <= 95 { if regnum >= 64 && regnum <= 95 {
return 16 return 16
...@@ -361,9 +322,7 @@ func maxArm64DwarfRegister() int { ...@@ -361,9 +322,7 @@ func maxArm64DwarfRegister() int {
return max return max
} }
// RegistersToDwarfRegisters converts hardware registers to the format used func arm64RegistersToDwarfRegisters(staticBase uint64, regs Registers) op.DwarfRegisters {
// by the DWARF expression interpreter.
func (a *ARM64) RegistersToDwarfRegisters(staticBase uint64, regs Registers) op.DwarfRegisters {
dregs := make([]*op.DwarfRegister, maxArm64DwarfRegister()+1) dregs := make([]*op.DwarfRegister, maxArm64DwarfRegister()+1)
dregs[arm64DwarfIPRegNum] = op.DwarfRegisterFromUint64(regs.PC()) dregs[arm64DwarfIPRegNum] = op.DwarfRegisterFromUint64(regs.PC())
...@@ -391,9 +350,7 @@ func (a *ARM64) RegistersToDwarfRegisters(staticBase uint64, regs Registers) op. ...@@ -391,9 +350,7 @@ func (a *ARM64) RegistersToDwarfRegisters(staticBase uint64, regs Registers) op.
} }
} }
// AddrAndStackRegsToDwarfRegisters returns DWARF registers from the passed in func arm64AddrAndStackRegsToDwarfRegisters(staticBase, pc, sp, bp, lr uint64) op.DwarfRegisters {
// PC, SP, and BP registers in the format used by the DWARF expression interpreter.
func (a *ARM64) AddrAndStackRegsToDwarfRegisters(staticBase, pc, sp, bp, lr uint64) op.DwarfRegisters {
dregs := make([]*op.DwarfRegister, arm64DwarfIPRegNum+1) dregs := make([]*op.DwarfRegister, arm64DwarfIPRegNum+1)
dregs[arm64DwarfIPRegNum] = op.DwarfRegisterFromUint64(pc) dregs[arm64DwarfIPRegNum] = op.DwarfRegisterFromUint64(pc)
dregs[arm64DwarfSPRegNum] = op.DwarfRegisterFromUint64(sp) dregs[arm64DwarfSPRegNum] = op.DwarfRegisterFromUint64(sp)
...@@ -411,7 +368,7 @@ func (a *ARM64) AddrAndStackRegsToDwarfRegisters(staticBase, pc, sp, bp, lr uint ...@@ -411,7 +368,7 @@ func (a *ARM64) AddrAndStackRegsToDwarfRegisters(staticBase, pc, sp, bp, lr uint
} }
} }
func (a *ARM64) DwarfRegisterToString(i int, reg *op.DwarfRegister) (name string, floatingPoint bool, repr string) { func arm64DwarfRegisterToString(i int, reg *op.DwarfRegister) (name string, floatingPoint bool, repr string) {
// see arm64DwarfToHardware table for explanation // see arm64DwarfToHardware table for explanation
switch { switch {
case i <= 30: case i <= 30:
...@@ -465,9 +422,3 @@ func (a *ARM64) DwarfRegisterToString(i int, reg *op.DwarfRegister) (name string ...@@ -465,9 +422,3 @@ func (a *ARM64) DwarfRegisterToString(i int, reg *op.DwarfRegister) (name string
} }
return name, false, fmt.Sprintf("%#x", reg.Bytes) return name, false, fmt.Sprintf("%#x", reg.Bytes)
} }
// InhibitStepInto returns whether StepBreakpoint can be set at pc.
// Always return false on arm64.
func (a *ARM64) InhibitStepInto(bi *BinaryInfo, pc uint64) bool {
return false
}
...@@ -8,9 +8,7 @@ import ( ...@@ -8,9 +8,7 @@ import (
"golang.org/x/arch/arm64/arm64asm" "golang.org/x/arch/arm64/arm64asm"
) )
// AsmDecode decodes the assembly instruction starting at mem[0:] into asmInst. func arm64AsmDecode(asmInst *AsmInstruction, mem []byte, regs Registers, memrw MemoryReadWriter, bi *BinaryInfo) error {
// It assumes that the Loc and AtPC fields of asmInst have already been filled.
func (a *ARM64) AsmDecode(asmInst *AsmInstruction, mem []byte, regs Registers, memrw MemoryReadWriter, bi *BinaryInfo) error {
asmInst.Size = 4 asmInst.Size = 4
asmInst.Bytes = mem[:asmInst.Size] asmInst.Bytes = mem[:asmInst.Size]
...@@ -35,10 +33,6 @@ func (a *ARM64) AsmDecode(asmInst *AsmInstruction, mem []byte, regs Registers, m ...@@ -35,10 +33,6 @@ func (a *ARM64) AsmDecode(asmInst *AsmInstruction, mem []byte, regs Registers, m
return nil return nil
} }
func (a *ARM64) Prologues() []opcodeSeq {
return prologuesARM64
}
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 Registers, mem MemoryReadWriter, bininfo *BinaryInfo) *Location {
if inst.Op != arm64asm.BL && inst.Op != arm64asm.BLR { if inst.Op != arm64asm.BL && inst.Op != arm64asm.BLR {
return nil return nil
......
...@@ -43,7 +43,7 @@ const ( ...@@ -43,7 +43,7 @@ const (
// includes both the executable and also any loaded libraries). // includes both the executable and also any loaded libraries).
type BinaryInfo struct { type BinaryInfo struct {
// Architecture of this binary. // Architecture of this binary.
Arch Arch Arch *Arch
// GOOS operating system this binary is executing on. // GOOS operating system this binary is executing on.
GOOS string GOOS string
......
...@@ -313,11 +313,6 @@ func (t *Thread) RestoreRegisters(proc.Registers) error { ...@@ -313,11 +313,6 @@ func (t *Thread) RestoreRegisters(proc.Registers) error {
return ErrChangeRegisterCore return ErrChangeRegisterCore
} }
// Arch returns the architecture the target is built for and executing on.
func (t *Thread) Arch() proc.Arch {
return t.p.bi.Arch
}
// BinInfo returns information about the binary. // BinInfo returns information about the binary.
func (t *Thread) BinInfo() *proc.BinaryInfo { func (t *Thread) BinInfo() *proc.BinaryInfo {
return t.p.bi return t.p.bi
......
...@@ -185,7 +185,7 @@ func withCoreFile(t *testing.T, name, args string) *proc.Target { ...@@ -185,7 +185,7 @@ func withCoreFile(t *testing.T, name, args string) *proc.Target {
return p return p
} }
func logRegisters(t *testing.T, regs proc.Registers, arch proc.Arch) { func logRegisters(t *testing.T, regs proc.Registers, arch *proc.Arch) {
dregs := arch.RegistersToDwarfRegisters(0, regs) dregs := arch.RegistersToDwarfRegisters(0, regs)
for i, reg := range dregs.Regs { for i, reg := range dregs.Regs {
if reg == nil { if reg == nil {
......
...@@ -139,7 +139,7 @@ func disassemble(memrw MemoryReadWriter, regs Registers, breakpoints *Breakpoint ...@@ -139,7 +139,7 @@ func disassemble(memrw MemoryReadWriter, regs Registers, breakpoints *Breakpoint
inst.Breakpoint = atbp inst.Breakpoint = atbp
inst.AtPC = (regs != nil) && (curpc == pc) inst.AtPC = (regs != nil) && (curpc == pc)
bi.Arch.AsmDecode(&inst, mem, regs, memrw, bi) bi.Arch.asmDecode(&inst, mem, regs, memrw, bi)
r = append(r, inst) r = append(r, inst)
......
...@@ -1303,11 +1303,6 @@ func (t *Thread) RestoreRegisters(savedRegs proc.Registers) error { ...@@ -1303,11 +1303,6 @@ func (t *Thread) RestoreRegisters(savedRegs proc.Registers) error {
return t.writeRegisters() return t.writeRegisters()
} }
// Arch will return the CPU architecture for the target.
func (t *Thread) Arch() proc.Arch {
return t.p.bi.Arch
}
// BinInfo will return information on the binary being debugged. // BinInfo will return information on the binary being debugged.
func (t *Thread) BinInfo() *proc.BinaryInfo { func (t *Thread) BinInfo() *proc.BinaryInfo {
return t.p.bi return t.p.bi
......
...@@ -8,23 +8,6 @@ import ( ...@@ -8,23 +8,6 @@ import (
"strings" "strings"
) )
// I386 represents the Intel386 CPU architecture.
type I386 struct {
gStructOffset uint64
goos string
// 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
// traces.
crosscall2fn *Function
// sigreturnfn is the DIE of runtime.sigreturn, the return trampoline for
// the signal handler. See comment in FixFrameUnwindContext for a
// description of why this is needed.
sigreturnfn *Function
}
const ( const (
i386DwarfIPRegNum uint64 = 8 i386DwarfIPRegNum uint64 = 8
i386DwarfSPRegNum uint64 = 4 i386DwarfSPRegNum uint64 = 4
...@@ -35,50 +18,28 @@ var i386BreakInstruction = []byte{0xCC} ...@@ -35,50 +18,28 @@ var i386BreakInstruction = []byte{0xCC}
// I386Arch returns an initialized I386Arch // I386Arch returns an initialized I386Arch
// struct. // struct.
func I386Arch(goos string) *I386 { func I386Arch(goos string) *Arch {
return &I386{ return &Arch{
goos: goos, Name: "386",
ptrSize: 4,
maxInstructionLength: 15,
breakpointInstruction: i386BreakInstruction,
breakInstrMovesPC: true,
derefTLS: false,
prologues: prologuesI386,
fixFrameUnwindContext: i386FixFrameUnwindContext,
switchStack: i386SwitchStack,
regSize: i386RegSize,
RegistersToDwarfRegisters: i386RegistersToDwarfRegisters,
addrAndStackRegsToDwarfRegisters: i386AddrAndStackRegsToDwarfRegisters,
DwarfRegisterToString: i386DwarfRegisterToString,
inhibitStepInto: i386InhibitStepInto,
asmDecode: i386AsmDecode,
} }
} }
// PtrSize returns the size of a pointer func i386FixFrameUnwindContext(fctxt *frame.FrameContext, pc uint64, bi *BinaryInfo) *frame.FrameContext {
// on this architecture. i := bi.Arch
func (i *I386) PtrSize() int {
return 4
}
// MaxInstructionLength returns the maximum length of an instruction.
func (i *I386) MaxInstructionLength() int {
return 15
}
// BreakpointInstruction returns the Breakpoint
// instruction for this architecture.
func (i *I386) BreakpointInstruction() []byte {
return i386BreakInstruction
}
// BreakInstrMovesPC returns whether the
// breakpoint instruction will change the value
// of PC after being executed
func (i *I386) BreakInstrMovesPC() bool {
return true
}
// BreakpointSize returns the size of the
// breakpoint instruction on this architecture.
func (i *I386) BreakpointSize() int {
return len(i386BreakInstruction)
}
// TODO, Not sure, always return false for now. Need to test on windows.
func (i *I386) DerefTLS() bool {
return false
}
// FixFrameUnwindContext adds default architecture rules to fctxt or returns
// the default frame unwind context if fctxt is nil.
func (i *I386) FixFrameUnwindContext(fctxt *frame.FrameContext, pc uint64, bi *BinaryInfo) *frame.FrameContext {
if i.sigreturnfn == nil { if i.sigreturnfn == nil {
i.sigreturnfn = bi.LookupFunc["runtime.sigreturn"] i.sigreturnfn = bi.LookupFunc["runtime.sigreturn"]
} }
...@@ -153,9 +114,7 @@ func (i *I386) FixFrameUnwindContext(fctxt *frame.FrameContext, pc uint64, bi *B ...@@ -153,9 +114,7 @@ func (i *I386) FixFrameUnwindContext(fctxt *frame.FrameContext, pc uint64, bi *B
} }
// SwitchStack will use the current frame to determine if it's time to // SwitchStack will use the current frame to determine if it's time to
// switch between the system stack and the goroutine stack or vice versa. func i386SwitchStack(it *stackIterator, _ *op.DwarfRegisters) bool {
// Sets it.atend when the top of the stack is reached.
func (i *I386) SwitchStack(it *stackIterator, _ *op.DwarfRegisters) bool {
if it.frame.Current.Fn == nil { if it.frame.Current.Fn == nil {
return false return false
} }
...@@ -214,7 +173,7 @@ func (i *I386) SwitchStack(it *stackIterator, _ *op.DwarfRegisters) bool { ...@@ -214,7 +173,7 @@ func (i *I386) SwitchStack(it *stackIterator, _ *op.DwarfRegisters) bool {
// in the System V ABI Intel386 Architecture Processor Supplement page 25, // in the System V ABI Intel386 Architecture Processor Supplement page 25,
// table 2.14 // table 2.14
// https://www.uclibc.org/docs/psABI-i386.pdf // https://www.uclibc.org/docs/psABI-i386.pdf
func (i *I386) RegSize(regnum uint64) int { func i386RegSize(regnum uint64) int {
// XMM registers // XMM registers
if regnum >= 21 && regnum <= 36 { if regnum >= 21 && regnum <= 36 {
return 16 return 16
...@@ -293,7 +252,7 @@ func maxI386DwarfRegister() int { ...@@ -293,7 +252,7 @@ func maxI386DwarfRegister() int {
return max return max
} }
func (i *I386) RegistersToDwarfRegisters(staticBase uint64, regs Registers) op.DwarfRegisters { func i386RegistersToDwarfRegisters(staticBase uint64, regs Registers) op.DwarfRegisters {
dregs := make([]*op.DwarfRegister, maxI386DwarfRegister()+1) dregs := make([]*op.DwarfRegister, maxI386DwarfRegister()+1)
for _, reg := range regs.Slice(true) { for _, reg := range regs.Slice(true) {
...@@ -312,9 +271,7 @@ func (i *I386) RegistersToDwarfRegisters(staticBase uint64, regs Registers) op.D ...@@ -312,9 +271,7 @@ func (i *I386) RegistersToDwarfRegisters(staticBase uint64, regs Registers) op.D
} }
} }
// AddrAndStackRegsToDwarfRegisters returns DWARF registers from the passed in func i386AddrAndStackRegsToDwarfRegisters(staticBase, pc, sp, bp, lr uint64) op.DwarfRegisters {
// PC, SP, and BP registers in the format used by the DWARF expression interpreter.
func (i *I386) AddrAndStackRegsToDwarfRegisters(staticBase, pc, sp, bp, lr uint64) op.DwarfRegisters {
dregs := make([]*op.DwarfRegister, i386DwarfIPRegNum+1) dregs := make([]*op.DwarfRegister, i386DwarfIPRegNum+1)
dregs[i386DwarfIPRegNum] = op.DwarfRegisterFromUint64(pc) dregs[i386DwarfIPRegNum] = op.DwarfRegisterFromUint64(pc)
dregs[i386DwarfSPRegNum] = op.DwarfRegisterFromUint64(sp) dregs[i386DwarfSPRegNum] = op.DwarfRegisterFromUint64(sp)
...@@ -330,7 +287,7 @@ func (i *I386) AddrAndStackRegsToDwarfRegisters(staticBase, pc, sp, bp, lr uint6 ...@@ -330,7 +287,7 @@ func (i *I386) AddrAndStackRegsToDwarfRegisters(staticBase, pc, sp, bp, lr uint6
} }
} }
func (i *I386) DwarfRegisterToString(j int, reg *op.DwarfRegister) (name string, floatingPoint bool, repr string) { func i386DwarfRegisterToString(j int, reg *op.DwarfRegister) (name string, floatingPoint bool, repr string) {
name, ok := i386DwarfToName[j] name, ok := i386DwarfToName[j]
if !ok { if !ok {
name = fmt.Sprintf("unknown%d", j) name = fmt.Sprintf("unknown%d", j)
...@@ -356,11 +313,11 @@ func (i *I386) DwarfRegisterToString(j int, reg *op.DwarfRegister) (name string, ...@@ -356,11 +313,11 @@ func (i *I386) DwarfRegisterToString(j int, reg *op.DwarfRegister) (name string,
} }
} }
// InhibitStepInto returns whether StepBreakpoint can be set at pc. // i386InhibitStepInto returns whether StepBreakpoint can be set at pc.
// When cgo or pie on 386 linux, compiler will insert more instructions (ex: call __x86.get_pc_thunk.). // When cgo or pie on 386 linux, compiler will insert more instructions (ex: call __x86.get_pc_thunk.).
// StepBreakpoint shouldn't be set on __x86.get_pc_thunk and skip it. // StepBreakpoint shouldn't be set on __x86.get_pc_thunk and skip it.
// See comments on stacksplit in $GOROOT/src/cmd/internal/obj/x86/obj6.go for generated instructions details. // See comments on stacksplit in $GOROOT/src/cmd/internal/obj/x86/obj6.go for generated instructions details.
func (i *I386) InhibitStepInto(bi *BinaryInfo, pc uint64) bool { func i386InhibitStepInto(bi *BinaryInfo, pc uint64) bool {
if bi.SymNames != nil && bi.SymNames[pc] != nil && if bi.SymNames != nil && bi.SymNames[pc] != nil &&
strings.HasPrefix(bi.SymNames[pc].Name, "__x86.get_pc_thunk.") { strings.HasPrefix(bi.SymNames[pc].Name, "__x86.get_pc_thunk.") {
return true return true
......
...@@ -8,18 +8,10 @@ import ( ...@@ -8,18 +8,10 @@ import (
"golang.org/x/arch/x86/x86asm" "golang.org/x/arch/x86/x86asm"
) )
// AsmDecode decodes the assembly instruction starting at mem[0:] into asmInst. func i386AsmDecode(asmInst *AsmInstruction, mem []byte, regs Registers, memrw MemoryReadWriter, bi *BinaryInfo) error {
// It assumes that the Loc and AtPC fields of asmInst have already been filled.
func (i *I386) AsmDecode(asmInst *AsmInstruction, mem []byte, regs Registers, memrw MemoryReadWriter, bi *BinaryInfo) error {
return x86AsmDecode(asmInst, mem, regs, memrw, bi, 32) return x86AsmDecode(asmInst, mem, regs, memrw, bi, 32)
} }
// Prologues returns a list of stack split prologues
// that are inserted at function entry.
func (i *I386) Prologues() []opcodeSeq {
return prologuesI386
}
// Possible stacksplit prologues are inserted by stacksplit in // Possible stacksplit prologues are inserted by stacksplit in
// $GOROOT/src/cmd/internal/obj/x86/obj6.go. // $GOROOT/src/cmd/internal/obj/x86/obj6.go.
// If 386 on linux when pie, the stacksplit prologue beigin with `call __x86.get_pc_thunk.` sometime. // If 386 on linux when pie, the stacksplit prologue beigin with `call __x86.get_pc_thunk.` sometime.
......
...@@ -94,12 +94,6 @@ func (t *Thread) Location() (*proc.Location, error) { ...@@ -94,12 +94,6 @@ func (t *Thread) Location() (*proc.Location, error) {
return &proc.Location{PC: pc, File: f, Line: l, Fn: fn}, nil return &proc.Location{PC: pc, File: f, Line: l, Fn: fn}, nil
} }
// Arch returns the architecture the binary is
// compiled for and executing on.
func (t *Thread) Arch() proc.Arch {
return t.dbp.bi.Arch
}
// BinInfo returns information on the binary. // BinInfo returns information on the binary.
func (t *Thread) BinInfo() *proc.BinaryInfo { func (t *Thread) BinInfo() *proc.BinaryInfo {
return t.dbp.bi return t.dbp.bi
...@@ -124,7 +118,7 @@ func (t *Thread) SetCurrentBreakpoint(adjustPC bool) error { ...@@ -124,7 +118,7 @@ func (t *Thread) SetCurrentBreakpoint(adjustPC bool) error {
// of PC after being executed we should look for breakpoints // of PC after being executed we should look for breakpoints
// with bp.Addr == PC and there is no need to call SetPC // with bp.Addr == PC and there is no need to call SetPC
// after finding one. // after finding one.
adjustPC = adjustPC && t.Arch().BreakInstrMovesPC() adjustPC = adjustPC && t.BinInfo().Arch.BreakInstrMovesPC()
if bp, ok := t.dbp.FindBreakpoint(pc, adjustPC); ok { if bp, ok := t.dbp.FindBreakpoint(pc, adjustPC); ok {
if adjustPC { if adjustPC {
......
...@@ -127,7 +127,7 @@ func (g *G) stackIterator(opts StacktraceOptions) (*stackIterator, error) { ...@@ -127,7 +127,7 @@ func (g *G) stackIterator(opts StacktraceOptions) (*stackIterator, error) {
so := g.variable.bi.PCToImage(g.PC) so := g.variable.bi.PCToImage(g.PC)
return newStackIterator( return newStackIterator(
bi, g.variable.mem, bi, g.variable.mem,
bi.Arch.AddrAndStackRegsToDwarfRegisters(so.StaticBase, g.PC, g.SP, g.BP, g.LR), bi.Arch.addrAndStackRegsToDwarfRegisters(so.StaticBase, g.PC, g.SP, g.BP, g.LR),
g.stackhi, stkbar, g.stkbarPos, g, opts), nil g.stackhi, stkbar, g.stkbarPos, g, opts), nil
} }
...@@ -246,7 +246,7 @@ func (it *stackIterator) Next() bool { ...@@ -246,7 +246,7 @@ func (it *stackIterator) Next() bool {
} }
if it.opts&StacktraceSimple == 0 { if it.opts&StacktraceSimple == 0 {
if it.bi.Arch.SwitchStack(it, &callFrameRegs) { if it.bi.Arch.switchStack(it, &callFrameRegs) {
return true return true
} }
} }
...@@ -268,7 +268,7 @@ func (it *stackIterator) switchToGoroutineStack() { ...@@ -268,7 +268,7 @@ func (it *stackIterator) switchToGoroutineStack() {
it.pc = it.g.PC it.pc = it.g.PC
it.regs.Reg(it.regs.SPRegNum).Uint64Val = it.g.SP it.regs.Reg(it.regs.SPRegNum).Uint64Val = it.g.SP
it.regs.AddReg(it.regs.BPRegNum, op.DwarfRegisterFromUint64(it.g.BP)) it.regs.AddReg(it.regs.BPRegNum, op.DwarfRegisterFromUint64(it.g.BP))
if _, ok := it.bi.Arch.(*ARM64); ok { if it.bi.Arch.Name == "arm64" {
it.regs.Reg(it.regs.LRRegNum).Uint64Val = it.g.LR it.regs.Reg(it.regs.LRRegNum).Uint64Val = it.g.LR
} }
} }
...@@ -414,9 +414,9 @@ func (it *stackIterator) advanceRegs() (callFrameRegs op.DwarfRegisters, ret uin ...@@ -414,9 +414,9 @@ func (it *stackIterator) advanceRegs() (callFrameRegs op.DwarfRegisters, ret uin
fde, err := it.bi.frameEntries.FDEForPC(it.pc) fde, err := it.bi.frameEntries.FDEForPC(it.pc)
var framectx *frame.FrameContext var framectx *frame.FrameContext
if _, nofde := err.(*frame.ErrNoFDEForPC); nofde { if _, nofde := err.(*frame.ErrNoFDEForPC); nofde {
framectx = it.bi.Arch.FixFrameUnwindContext(nil, it.pc, it.bi) framectx = it.bi.Arch.fixFrameUnwindContext(nil, it.pc, it.bi)
} else { } else {
framectx = it.bi.Arch.FixFrameUnwindContext(fde.EstablishFrame(it.pc), it.pc, it.bi) framectx = it.bi.Arch.fixFrameUnwindContext(fde.EstablishFrame(it.pc), it.pc, it.bi)
} }
cfareg, err := it.executeFrameRegRule(0, framectx.CFA, 0) cfareg, err := it.executeFrameRegRule(0, framectx.CFA, 0)
...@@ -455,7 +455,7 @@ func (it *stackIterator) advanceRegs() (callFrameRegs op.DwarfRegisters, ret uin ...@@ -455,7 +455,7 @@ func (it *stackIterator) advanceRegs() (callFrameRegs op.DwarfRegisters, ret uin
} }
} }
if _, ok := it.bi.Arch.(*ARM64); ok { if it.bi.Arch.Name == "arm64" {
if ret == 0 && it.regs.Regs[it.regs.LRRegNum] != nil { if ret == 0 && it.regs.Regs[it.regs.LRRegNum] != nil {
ret = it.regs.Regs[it.regs.LRRegNum].Uint64Val ret = it.regs.Regs[it.regs.LRRegNum].Uint64Val
} }
...@@ -515,7 +515,7 @@ func (it *stackIterator) executeFrameRegRule(regnum uint64, rule frame.DWRule, c ...@@ -515,7 +515,7 @@ func (it *stackIterator) executeFrameRegRule(regnum uint64, rule frame.DWRule, c
} }
func (it *stackIterator) readRegisterAt(regnum uint64, addr uint64) (*op.DwarfRegister, error) { func (it *stackIterator) readRegisterAt(regnum uint64, addr uint64) (*op.DwarfRegister, error) {
buf := make([]byte, it.bi.Arch.RegSize(regnum)) buf := make([]byte, it.bi.Arch.regSize(regnum))
_, err := it.mem.ReadMemory(buf, uintptr(addr)) _, err := it.mem.ReadMemory(buf, uintptr(addr))
if err != nil { if err != nil {
return nil, err return nil, err
......
...@@ -152,8 +152,7 @@ func (t *Target) SupportsFunctionCalls() bool { ...@@ -152,8 +152,7 @@ func (t *Target) SupportsFunctionCalls() bool {
if ok, _ := t.Process.Recorded(); ok { if ok, _ := t.Process.Recorded(); ok {
return false return false
} }
_, ok := t.Process.BinInfo().Arch.(*AMD64) return t.Process.BinInfo().Arch.Name == "amd64"
return ok
} }
// ClearAllGCache clears the internal Goroutine cache. // ClearAllGCache clears the internal Goroutine cache.
......
...@@ -770,7 +770,7 @@ func setStepIntoBreakpoint(dbp Process, text []AsmInstruction, cond ast.Expr) er ...@@ -770,7 +770,7 @@ func setStepIntoBreakpoint(dbp Process, text []AsmInstruction, cond ast.Expr) er
pc := instr.DestLoc.PC pc := instr.DestLoc.PC
// Skip InhibitStepInto functions for different arch. // Skip InhibitStepInto functions for different arch.
if dbp.BinInfo().Arch.InhibitStepInto(dbp.BinInfo(), pc) { if dbp.BinInfo().Arch.inhibitStepInto(dbp.BinInfo(), pc) {
return nil return nil
} }
......
...@@ -23,7 +23,6 @@ type Thread interface { ...@@ -23,7 +23,6 @@ type Thread interface {
// RestoreRegisters restores saved registers // RestoreRegisters restores saved registers
RestoreRegisters(Registers) error RestoreRegisters(Registers) error
Arch() Arch
BinInfo() *BinaryInfo BinInfo() *BinaryInfo
StepInstruction() error StepInstruction() error
// Blocked returns true if the thread is blocked // Blocked returns true if the thread is blocked
......
...@@ -46,7 +46,7 @@ type runtimeTypeDIE struct { ...@@ -46,7 +46,7 @@ type runtimeTypeDIE struct {
kind int64 kind int64
} }
func pointerTo(typ godwarf.Type, arch Arch) godwarf.Type { func pointerTo(typ godwarf.Type, arch *Arch) godwarf.Type {
return &godwarf.PtrType{ return &godwarf.PtrType{
CommonType: godwarf.CommonType{ CommonType: godwarf.CommonType{
ByteSize: int64(arch.PtrSize()), ByteSize: int64(arch.PtrSize()),
......
...@@ -432,7 +432,7 @@ func getGVariable(thread Thread) (*Variable, error) { ...@@ -432,7 +432,7 @@ func getGVariable(thread Thread) (*Variable, error) {
} }
} }
return newGVariable(thread, uintptr(gaddr), thread.Arch().DerefTLS()) return newGVariable(thread, uintptr(gaddr), thread.BinInfo().Arch.DerefTLS())
} }
func newGVariable(thread Thread, gaddr uintptr, deref bool) (*Variable, error) { func newGVariable(thread Thread, gaddr uintptr, deref bool) (*Variable, error) {
...@@ -446,7 +446,7 @@ func newGVariable(thread Thread, gaddr uintptr, deref bool) (*Variable, error) { ...@@ -446,7 +446,7 @@ func newGVariable(thread Thread, gaddr uintptr, deref bool) (*Variable, error) {
if deref { if deref {
typ = &godwarf.PtrType{ typ = &godwarf.PtrType{
CommonType: godwarf.CommonType{ CommonType: godwarf.CommonType{
ByteSize: int64(thread.Arch().PtrSize()), ByteSize: int64(thread.BinInfo().Arch.PtrSize()),
Name: "", Name: "",
ReflectKind: reflect.Ptr, ReflectKind: reflect.Ptr,
Offset: 0, Offset: 0,
...@@ -1305,7 +1305,7 @@ func convertToEface(srcv, dstv *Variable) error { ...@@ -1305,7 +1305,7 @@ func convertToEface(srcv, dstv *Variable) error {
return dstv.writeEmptyInterface(typeAddr, srcv) return dstv.writeEmptyInterface(typeAddr, srcv)
} }
func readStringInfo(mem MemoryReadWriter, arch Arch, addr uintptr) (uintptr, int64, error) { func readStringInfo(mem MemoryReadWriter, arch *Arch, addr uintptr) (uintptr, int64, error) {
// string data structure is always two ptrs in size. Addr, followed by len // string data structure is always two ptrs in size. Addr, followed by len
// http://research.swtch.com/godata // http://research.swtch.com/godata
......
...@@ -329,7 +329,7 @@ func LoadConfigFromProc(cfg *proc.LoadConfig) *LoadConfig { ...@@ -329,7 +329,7 @@ func LoadConfigFromProc(cfg *proc.LoadConfig) *LoadConfig {
} }
// ConvertRegisters converts proc.Register to api.Register for a slice. // ConvertRegisters converts proc.Register to api.Register for a slice.
func ConvertRegisters(in op.DwarfRegisters, arch proc.Arch, floatingPoint bool) (out []Register) { func ConvertRegisters(in op.DwarfRegisters, arch *proc.Arch, floatingPoint bool) (out []Register) {
out = make([]Register, 0, len(in.Regs)) out = make([]Register, 0, len(in.Regs))
for i := range in.Regs { for i := range in.Regs {
reg := in.Reg(uint64(i)) reg := in.Reg(uint64(i))
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册