
* proc: separate amd64-arch code separate amd64 code about stacktrace, so we can add arm64 stacktrace code. * proc: implemente stacktrace of arm64 * delve now can use stack, frame commands on arm64-arch debug. Co-authored-by: tykcd996 <tang.yuke@zte.com.cn> Co-authored-by: hengwu0 <wu.heng@zte.com.cn> * test: remove skip-code of stacktrace on arm64 * add LR DWARF register and remove skip-code for fixed tests * proc: fix the Continue command after the hardcoded breakpoint on arm64 Arm64 use hardware breakpoint, and it will not set PC to the next instruction like amd64. We should move PC in both runtime.breakpoints and hardcoded breakpoints(probably cgo). * proc: implement cgo stacktrace on arm64 * proc: combine amd64_stack.go and arm64_stack.go file * proc: reorganize the stacktrace code * move SwitchStack function arch-related * fix Continue command after manual stop on arm64 * add timeout flag to make.go to enable infinite timeouts Co-authored-by: aarzilli <alessandro.arzilli@gmail.com> Co-authored-by: hengwu0 <wu.heng@zte.com.cn> Co-authored-by: tykcd996 <56993522+tykcd996@users.noreply.github.com> Co-authored-by: Alessandro Arzilli <alessandro.arzilli@gmail.com>
104 lines
2.1 KiB
Go
104 lines
2.1 KiB
Go
package op
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
)
|
|
|
|
type DwarfRegisters struct {
|
|
StaticBase uint64
|
|
|
|
CFA int64
|
|
FrameBase int64
|
|
ObjBase int64
|
|
Regs []*DwarfRegister
|
|
|
|
ByteOrder binary.ByteOrder
|
|
PCRegNum uint64
|
|
SPRegNum uint64
|
|
BPRegNum uint64
|
|
LRRegNum uint64
|
|
}
|
|
|
|
type DwarfRegister struct {
|
|
Uint64Val uint64
|
|
Bytes []byte
|
|
}
|
|
|
|
// Uint64Val returns the uint64 value of register idx.
|
|
func (regs *DwarfRegisters) Uint64Val(idx uint64) uint64 {
|
|
reg := regs.Reg(idx)
|
|
if reg == nil {
|
|
return 0
|
|
}
|
|
return regs.Regs[idx].Uint64Val
|
|
}
|
|
|
|
// Bytes returns the bytes value of register idx, nil if the register is not
|
|
// defined.
|
|
func (regs *DwarfRegisters) Bytes(idx uint64) []byte {
|
|
reg := regs.Reg(idx)
|
|
if reg == nil {
|
|
return nil
|
|
}
|
|
if reg.Bytes == nil {
|
|
var buf bytes.Buffer
|
|
binary.Write(&buf, regs.ByteOrder, reg.Uint64Val)
|
|
reg.Bytes = buf.Bytes()
|
|
}
|
|
return reg.Bytes
|
|
}
|
|
|
|
// Reg returns register idx or nil if the register is not defined.
|
|
func (regs *DwarfRegisters) Reg(idx uint64) *DwarfRegister {
|
|
if idx >= uint64(len(regs.Regs)) {
|
|
return nil
|
|
}
|
|
return regs.Regs[idx]
|
|
}
|
|
|
|
func (regs *DwarfRegisters) PC() uint64 {
|
|
return regs.Uint64Val(regs.PCRegNum)
|
|
}
|
|
|
|
func (regs *DwarfRegisters) SP() uint64 {
|
|
return regs.Uint64Val(regs.SPRegNum)
|
|
}
|
|
|
|
func (regs *DwarfRegisters) BP() uint64 {
|
|
return regs.Uint64Val(regs.BPRegNum)
|
|
}
|
|
|
|
// AddReg adds register idx to regs.
|
|
func (regs *DwarfRegisters) AddReg(idx uint64, reg *DwarfRegister) {
|
|
if idx >= uint64(len(regs.Regs)) {
|
|
newRegs := make([]*DwarfRegister, idx+1)
|
|
copy(newRegs, regs.Regs)
|
|
regs.Regs = newRegs
|
|
}
|
|
regs.Regs[idx] = reg
|
|
}
|
|
|
|
func DwarfRegisterFromUint64(v uint64) *DwarfRegister {
|
|
return &DwarfRegister{Uint64Val: v}
|
|
}
|
|
|
|
func DwarfRegisterFromBytes(bytes []byte) *DwarfRegister {
|
|
var v uint64
|
|
switch len(bytes) {
|
|
case 1:
|
|
v = uint64(bytes[0])
|
|
case 2:
|
|
x := binary.LittleEndian.Uint16(bytes)
|
|
v = uint64(x)
|
|
case 4:
|
|
x := binary.LittleEndian.Uint32(bytes)
|
|
v = uint64(x)
|
|
default:
|
|
if len(bytes) >= 8 {
|
|
v = binary.LittleEndian.Uint64(bytes[:8])
|
|
}
|
|
}
|
|
return &DwarfRegister{Uint64Val: v, Bytes: bytes}
|
|
}
|