proc/*: only load floating point registers when needed (#1981)
Changes implementations of proc.Registers interface and the op.DwarfRegisters struct so that floating point registers can be loaded only when they are needed. Removes the floatingPoint parameter from proc.Thread.Registers. This accomplishes three things: 1. it simplifies the proc.Thread.Registers interface 2. it makes it impossible to accidentally create a broken set of saved registers or of op.DwarfRegisters by accidentally calling Registers(false) 3. it improves general performance of Delve by avoiding to load floating point registers as much as possible Floating point registers are loaded under two circumstances: 1. When the Slice method is called with floatingPoint == true 2. When the Copy method is called Benchmark before: BenchmarkConditionalBreakpoints-4 1 4327350142 ns/op Benchmark after: BenchmarkConditionalBreakpoints-4 1 3852642917 ns/op Updates #1549
This commit is contained in:
parent
f96663a243
commit
200994bc8f
@ -12,13 +12,16 @@ type DwarfRegisters struct {
|
|||||||
CFA int64
|
CFA int64
|
||||||
FrameBase int64
|
FrameBase int64
|
||||||
ObjBase int64
|
ObjBase int64
|
||||||
Regs []*DwarfRegister
|
regs []*DwarfRegister
|
||||||
|
|
||||||
ByteOrder binary.ByteOrder
|
ByteOrder binary.ByteOrder
|
||||||
PCRegNum uint64
|
PCRegNum uint64
|
||||||
SPRegNum uint64
|
SPRegNum uint64
|
||||||
BPRegNum uint64
|
BPRegNum uint64
|
||||||
LRRegNum uint64
|
LRRegNum uint64
|
||||||
|
|
||||||
|
FloatLoadError error // error produced when loading floating point registers
|
||||||
|
loadMoreCallback func()
|
||||||
}
|
}
|
||||||
|
|
||||||
type DwarfRegister struct {
|
type DwarfRegister struct {
|
||||||
@ -26,13 +29,38 @@ type DwarfRegister struct {
|
|||||||
Bytes []byte
|
Bytes []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewDwarfRegisters returns a new DwarfRegisters object.
|
||||||
|
func NewDwarfRegisters(staticBase uint64, regs []*DwarfRegister, byteOrder binary.ByteOrder, pcRegNum, spRegNum, bpRegNum, lrRegNum uint64) *DwarfRegisters {
|
||||||
|
return &DwarfRegisters{
|
||||||
|
StaticBase: staticBase,
|
||||||
|
regs: regs,
|
||||||
|
ByteOrder: byteOrder,
|
||||||
|
PCRegNum: pcRegNum,
|
||||||
|
SPRegNum: spRegNum,
|
||||||
|
BPRegNum: bpRegNum,
|
||||||
|
LRRegNum: lrRegNum,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLoadMoreCallback sets a callback function that will be called the
|
||||||
|
// first time the user of regs tries to access an undefined register.
|
||||||
|
func (regs *DwarfRegisters) SetLoadMoreCallback(fn func()) {
|
||||||
|
regs.loadMoreCallback = fn
|
||||||
|
}
|
||||||
|
|
||||||
|
// CurrentSize returns the current number of known registers. This number might be
|
||||||
|
// wrong if loadMoreCallback has been set.
|
||||||
|
func (regs *DwarfRegisters) CurrentSize() int {
|
||||||
|
return len(regs.regs)
|
||||||
|
}
|
||||||
|
|
||||||
// Uint64Val returns the uint64 value of register idx.
|
// Uint64Val returns the uint64 value of register idx.
|
||||||
func (regs *DwarfRegisters) Uint64Val(idx uint64) uint64 {
|
func (regs *DwarfRegisters) Uint64Val(idx uint64) uint64 {
|
||||||
reg := regs.Reg(idx)
|
reg := regs.Reg(idx)
|
||||||
if reg == nil {
|
if reg == nil {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return regs.Regs[idx].Uint64Val
|
return regs.regs[idx].Uint64Val
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bytes returns the bytes value of register idx, nil if the register is not
|
// Bytes returns the bytes value of register idx, nil if the register is not
|
||||||
@ -50,12 +78,26 @@ func (regs *DwarfRegisters) Bytes(idx uint64) []byte {
|
|||||||
return reg.Bytes
|
return reg.Bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (regs *DwarfRegisters) loadMore() {
|
||||||
|
if regs.loadMoreCallback == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
regs.loadMoreCallback()
|
||||||
|
regs.loadMoreCallback = nil
|
||||||
|
}
|
||||||
|
|
||||||
// Reg returns register idx or nil if the register is not defined.
|
// Reg returns register idx or nil if the register is not defined.
|
||||||
func (regs *DwarfRegisters) Reg(idx uint64) *DwarfRegister {
|
func (regs *DwarfRegisters) Reg(idx uint64) *DwarfRegister {
|
||||||
if idx >= uint64(len(regs.Regs)) {
|
if idx >= uint64(len(regs.regs)) {
|
||||||
return nil
|
regs.loadMore()
|
||||||
|
if idx >= uint64(len(regs.regs)) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return regs.Regs[idx]
|
if regs.regs[idx] == nil {
|
||||||
|
regs.loadMore()
|
||||||
|
}
|
||||||
|
return regs.regs[idx]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (regs *DwarfRegisters) PC() uint64 {
|
func (regs *DwarfRegisters) PC() uint64 {
|
||||||
@ -72,12 +114,20 @@ func (regs *DwarfRegisters) BP() uint64 {
|
|||||||
|
|
||||||
// AddReg adds register idx to regs.
|
// AddReg adds register idx to regs.
|
||||||
func (regs *DwarfRegisters) AddReg(idx uint64, reg *DwarfRegister) {
|
func (regs *DwarfRegisters) AddReg(idx uint64, reg *DwarfRegister) {
|
||||||
if idx >= uint64(len(regs.Regs)) {
|
if idx >= uint64(len(regs.regs)) {
|
||||||
newRegs := make([]*DwarfRegister, idx+1)
|
newRegs := make([]*DwarfRegister, idx+1)
|
||||||
copy(newRegs, regs.Regs)
|
copy(newRegs, regs.regs)
|
||||||
regs.Regs = newRegs
|
regs.regs = newRegs
|
||||||
|
}
|
||||||
|
regs.regs[idx] = reg
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearRegisters clears all registers.
|
||||||
|
func (regs *DwarfRegisters) ClearRegisters() {
|
||||||
|
regs.loadMoreCallback = nil
|
||||||
|
for regnum := range regs.regs {
|
||||||
|
regs.regs[regnum] = nil
|
||||||
}
|
}
|
||||||
regs.Regs[idx] = reg
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func DwarfRegisterFromUint64(v uint64) *DwarfRegister {
|
func DwarfRegisterFromUint64(v uint64) *DwarfRegister {
|
||||||
|
|||||||
@ -345,21 +345,32 @@ func maxAmd64DwarfRegister() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func amd64RegistersToDwarfRegisters(staticBase uint64, regs Registers) op.DwarfRegisters {
|
func amd64RegistersToDwarfRegisters(staticBase uint64, regs Registers) op.DwarfRegisters {
|
||||||
dregs := make([]*op.DwarfRegister, maxAmd64DwarfRegister()+1)
|
dregs := initDwarfRegistersFromSlice(maxAmd64DwarfRegister(), regs, amd64NameToDwarf)
|
||||||
|
dr := op.NewDwarfRegisters(staticBase, dregs, binary.LittleEndian, amd64DwarfIPRegNum, amd64DwarfSPRegNum, amd64DwarfBPRegNum, 0)
|
||||||
|
dr.SetLoadMoreCallback(loadMoreDwarfRegistersFromSliceFunc(dr, regs, amd64NameToDwarf))
|
||||||
|
return *dr
|
||||||
|
}
|
||||||
|
|
||||||
for _, reg := range regs.Slice(true) {
|
func initDwarfRegistersFromSlice(maxRegs int, regs Registers, nameToDwarf map[string]int) []*op.DwarfRegister {
|
||||||
if dwarfReg, ok := amd64NameToDwarf[strings.ToLower(reg.Name)]; ok {
|
dregs := make([]*op.DwarfRegister, maxRegs+1)
|
||||||
|
regslice, _ := regs.Slice(false)
|
||||||
|
for _, reg := range regslice {
|
||||||
|
if dwarfReg, ok := nameToDwarf[strings.ToLower(reg.Name)]; ok {
|
||||||
dregs[dwarfReg] = reg.Reg
|
dregs[dwarfReg] = reg.Reg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return dregs
|
||||||
|
}
|
||||||
|
|
||||||
return op.DwarfRegisters{
|
func loadMoreDwarfRegistersFromSliceFunc(dr *op.DwarfRegisters, regs Registers, nameToDwarf map[string]int) func() {
|
||||||
StaticBase: staticBase,
|
return func() {
|
||||||
Regs: dregs,
|
regslice, err := regs.Slice(true)
|
||||||
ByteOrder: binary.LittleEndian,
|
dr.FloatLoadError = err
|
||||||
PCRegNum: amd64DwarfIPRegNum,
|
for _, reg := range regslice {
|
||||||
SPRegNum: amd64DwarfSPRegNum,
|
if dwarfReg, ok := nameToDwarf[strings.ToLower(reg.Name)]; ok {
|
||||||
BPRegNum: amd64DwarfBPRegNum,
|
dr.AddReg(uint64(dwarfReg), reg.Reg)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -369,14 +380,7 @@ func amd64AddrAndStackRegsToDwarfRegisters(staticBase, pc, sp, bp, lr uint64) op
|
|||||||
dregs[amd64DwarfSPRegNum] = op.DwarfRegisterFromUint64(sp)
|
dregs[amd64DwarfSPRegNum] = op.DwarfRegisterFromUint64(sp)
|
||||||
dregs[amd64DwarfBPRegNum] = op.DwarfRegisterFromUint64(bp)
|
dregs[amd64DwarfBPRegNum] = op.DwarfRegisterFromUint64(bp)
|
||||||
|
|
||||||
return op.DwarfRegisters{
|
return *op.NewDwarfRegisters(staticBase, dregs, binary.LittleEndian, amd64DwarfIPRegNum, amd64DwarfSPRegNum, amd64DwarfBPRegNum, 0)
|
||||||
StaticBase: staticBase,
|
|
||||||
Regs: dregs,
|
|
||||||
ByteOrder: binary.LittleEndian,
|
|
||||||
PCRegNum: amd64DwarfIPRegNum,
|
|
||||||
SPRegNum: amd64DwarfSPRegNum,
|
|
||||||
BPRegNum: amd64DwarfBPRegNum,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func amd64DwarfRegisterToString(i int, reg *op.DwarfRegister) (name string, floatingPoint bool, repr string) {
|
func amd64DwarfRegisterToString(i int, reg *op.DwarfRegister) (name string, floatingPoint bool, repr string) {
|
||||||
|
|||||||
@ -312,6 +312,20 @@ var arm64DwarfToHardware = map[int]arm64asm.Reg{
|
|||||||
95: arm64asm.V31,
|
95: arm64asm.V31,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var arm64NameToDwarf = func() map[string]int {
|
||||||
|
r := make(map[string]int)
|
||||||
|
for i := 0; i <= 30; i++ {
|
||||||
|
r[fmt.Sprintf("x%d", i)] = i
|
||||||
|
}
|
||||||
|
r["pc"] = int(arm64DwarfIPRegNum)
|
||||||
|
r["lr"] = int(arm64DwarfLRRegNum)
|
||||||
|
r["sp"] = 31
|
||||||
|
for i := 0; i <= 31; i++ {
|
||||||
|
r[fmt.Sprintf("v%d", i)] = i + 64
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}()
|
||||||
|
|
||||||
func maxArm64DwarfRegister() int {
|
func maxArm64DwarfRegister() int {
|
||||||
max := int(arm64DwarfIPRegNum)
|
max := int(arm64DwarfIPRegNum)
|
||||||
for i := range arm64DwarfToHardware {
|
for i := range arm64DwarfToHardware {
|
||||||
@ -339,15 +353,9 @@ func arm64RegistersToDwarfRegisters(staticBase uint64, regs Registers) op.DwarfR
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return op.DwarfRegisters{
|
dr := op.NewDwarfRegisters(staticBase, dregs, binary.LittleEndian, arm64DwarfIPRegNum, arm64DwarfSPRegNum, arm64DwarfBPRegNum, arm64DwarfLRRegNum)
|
||||||
StaticBase: staticBase,
|
dr.SetLoadMoreCallback(loadMoreDwarfRegistersFromSliceFunc(dr, regs, arm64NameToDwarf))
|
||||||
Regs: dregs,
|
return *dr
|
||||||
ByteOrder: binary.LittleEndian,
|
|
||||||
PCRegNum: arm64DwarfIPRegNum,
|
|
||||||
SPRegNum: arm64DwarfSPRegNum,
|
|
||||||
BPRegNum: arm64DwarfBPRegNum,
|
|
||||||
LRRegNum: arm64DwarfLRRegNum,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func arm64AddrAndStackRegsToDwarfRegisters(staticBase, pc, sp, bp, lr uint64) op.DwarfRegisters {
|
func arm64AddrAndStackRegsToDwarfRegisters(staticBase, pc, sp, bp, lr uint64) op.DwarfRegisters {
|
||||||
@ -357,15 +365,7 @@ func arm64AddrAndStackRegsToDwarfRegisters(staticBase, pc, sp, bp, lr uint64) op
|
|||||||
dregs[arm64DwarfBPRegNum] = op.DwarfRegisterFromUint64(bp)
|
dregs[arm64DwarfBPRegNum] = op.DwarfRegisterFromUint64(bp)
|
||||||
dregs[arm64DwarfLRRegNum] = op.DwarfRegisterFromUint64(lr)
|
dregs[arm64DwarfLRRegNum] = op.DwarfRegisterFromUint64(lr)
|
||||||
|
|
||||||
return op.DwarfRegisters{
|
return *op.NewDwarfRegisters(staticBase, dregs, binary.LittleEndian, arm64DwarfIPRegNum, arm64DwarfSPRegNum, arm64DwarfBPRegNum, arm64DwarfLRRegNum)
|
||||||
StaticBase: staticBase,
|
|
||||||
Regs: dregs,
|
|
||||||
ByteOrder: binary.LittleEndian,
|
|
||||||
PCRegNum: arm64DwarfIPRegNum,
|
|
||||||
SPRegNum: arm64DwarfSPRegNum,
|
|
||||||
BPRegNum: arm64DwarfBPRegNum,
|
|
||||||
LRRegNum: arm64DwarfLRRegNum,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func arm64DwarfRegisterToString(i int, reg *op.DwarfRegister) (name string, floatingPoint bool, repr string) {
|
func arm64DwarfRegisterToString(i int, reg *op.DwarfRegister) (name string, floatingPoint bool, repr string) {
|
||||||
|
|||||||
@ -170,7 +170,7 @@ type thread struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type osThread interface {
|
type osThread interface {
|
||||||
registers(floatingPoint bool) (proc.Registers, error)
|
registers() (proc.Registers, error)
|
||||||
pid() int
|
pid() int
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,7 +281,7 @@ func (t *thread) WriteMemory(addr uintptr, data []byte) (int, error) {
|
|||||||
// Location returns the location of this thread based on
|
// Location returns the location of this thread based on
|
||||||
// the value of the instruction pointer register.
|
// the value of the instruction pointer register.
|
||||||
func (t *thread) Location() (*proc.Location, error) {
|
func (t *thread) Location() (*proc.Location, error) {
|
||||||
regs, err := t.th.registers(false)
|
regs, err := t.th.registers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -303,8 +303,8 @@ func (t *thread) ThreadID() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Registers returns the current value of the registers for this thread.
|
// Registers returns the current value of the registers for this thread.
|
||||||
func (t *thread) Registers(floatingPoint bool) (proc.Registers, error) {
|
func (t *thread) Registers() (proc.Registers, error) {
|
||||||
return t.th.registers(floatingPoint)
|
return t.th.registers()
|
||||||
}
|
}
|
||||||
|
|
||||||
// RestoreRegisters will only return an error for core files,
|
// RestoreRegisters will only return an error for core files,
|
||||||
|
|||||||
@ -187,7 +187,9 @@ func withCoreFile(t *testing.T, name, args string) *proc.Target {
|
|||||||
|
|
||||||
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 {
|
dregs.Reg(^uint64(0))
|
||||||
|
for i := 0; i < dregs.CurrentSize(); i++ {
|
||||||
|
reg := dregs.Reg(uint64(i))
|
||||||
if reg == nil {
|
if reg == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -250,7 +252,7 @@ func TestCore(t *testing.T) {
|
|||||||
t.Errorf("main.msg = %q, want %q", msg.Value, "BOOM!")
|
t.Errorf("main.msg = %q, want %q", msg.Value, "BOOM!")
|
||||||
}
|
}
|
||||||
|
|
||||||
regs, err := p.CurrentThread().Registers(true)
|
regs, err := p.CurrentThread().Registers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Couldn't get current thread registers: %v", err)
|
t.Fatalf("Couldn't get current thread registers: %v", err)
|
||||||
}
|
}
|
||||||
@ -286,7 +288,7 @@ func TestCoreFpRegisters(t *testing.T) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if frames[i].Current.Fn.Name == "main.main" {
|
if frames[i].Current.Fn.Name == "main.main" {
|
||||||
regs, err = thread.Registers(true)
|
regs, err = thread.Registers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Could not get registers for thread %x, %v", thread.ThreadID(), err)
|
t.Fatalf("Could not get registers for thread %x, %v", thread.ThreadID(), err)
|
||||||
}
|
}
|
||||||
@ -326,7 +328,9 @@ func TestCoreFpRegisters(t *testing.T) {
|
|||||||
|
|
||||||
for _, regtest := range regtests {
|
for _, regtest := range regtests {
|
||||||
found := false
|
found := false
|
||||||
for i, reg := range dregs.Regs {
|
dregs.Reg(^uint64(0))
|
||||||
|
for i := 0; i < dregs.CurrentSize(); i++ {
|
||||||
|
reg := dregs.Reg(uint64(i))
|
||||||
regname, _, regval := arch.DwarfRegisterToString(i, reg)
|
regname, _, regval := arch.DwarfRegisterToString(i, reg)
|
||||||
if reg != nil && regname == regtest.name {
|
if reg != nil && regname == regtest.name {
|
||||||
found = true
|
found = true
|
||||||
|
|||||||
@ -154,21 +154,17 @@ type linuxARM64Thread struct {
|
|||||||
t *linuxPrStatusARM64
|
t *linuxPrStatusARM64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *linuxAMD64Thread) registers(floatingPoint bool) (proc.Registers, error) {
|
func (t *linuxAMD64Thread) registers() (proc.Registers, error) {
|
||||||
var r linutil.AMD64Registers
|
var r linutil.AMD64Registers
|
||||||
r.Regs = t.regs.Regs
|
r.Regs = t.regs.Regs
|
||||||
if floatingPoint {
|
r.Fpregs = t.regs.Fpregs
|
||||||
r.Fpregs = t.regs.Fpregs
|
|
||||||
}
|
|
||||||
return &r, nil
|
return &r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *linuxARM64Thread) registers(floatingPoint bool) (proc.Registers, error) {
|
func (t *linuxARM64Thread) registers() (proc.Registers, error) {
|
||||||
var r linutil.ARM64Registers
|
var r linutil.ARM64Registers
|
||||||
r.Regs = t.regs.Regs
|
r.Regs = t.regs.Regs
|
||||||
if floatingPoint {
|
r.Fpregs = t.regs.Fpregs
|
||||||
r.Fpregs = t.regs.Fpregs
|
|
||||||
}
|
|
||||||
return &r, nil
|
return &r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -54,6 +54,6 @@ func (th *windowsAMD64Thread) pid() int {
|
|||||||
return int(th.th.ID)
|
return int(th.th.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (th *windowsAMD64Thread) registers(floatingPoint bool) (proc.Registers, error) {
|
func (th *windowsAMD64Thread) registers() (proc.Registers, error) {
|
||||||
return winutil.NewAMD64Registers(&th.th.Context, th.th.TEB, floatingPoint), nil
|
return winutil.NewAMD64Registers(&th.th.Context, th.th.TEB), nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -232,7 +232,7 @@ func TestDwarfExprLoclist(t *testing.T) {
|
|||||||
|
|
||||||
uintExprCheck(t, scope, "a", before)
|
uintExprCheck(t, scope, "a", before)
|
||||||
scope.PC = 0x40800
|
scope.PC = 0x40800
|
||||||
scope.Regs.Regs[scope.Regs.PCRegNum].Uint64Val = scope.PC
|
scope.Regs.Reg(scope.Regs.PCRegNum).Uint64Val = scope.PC
|
||||||
uintExprCheck(t, scope, "a", after)
|
uintExprCheck(t, scope, "a", after)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,6 +14,12 @@ type AMD64Registers struct {
|
|||||||
Fpregs []proc.Register
|
Fpregs []proc.Register
|
||||||
Fpregset *AMD64Xstate
|
Fpregset *AMD64Xstate
|
||||||
Fsbase uint64
|
Fsbase uint64
|
||||||
|
|
||||||
|
loadFpRegs func(*AMD64Registers) error
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAMD64Registers(regs *AMD64PtraceRegs, fsbase uint64, loadFpRegs func(*AMD64Registers) error) *AMD64Registers {
|
||||||
|
return &AMD64Registers{Regs: regs, Fsbase: fsbase, loadFpRegs: loadFpRegs}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AMD64PtraceRegs is the struct used by the freebsd kernel to return the
|
// AMD64PtraceRegs is the struct used by the freebsd kernel to return the
|
||||||
@ -49,7 +55,7 @@ type AMD64PtraceRegs struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Slice returns the registers as a list of (name, value) pairs.
|
// Slice returns the registers as a list of (name, value) pairs.
|
||||||
func (r *AMD64Registers) Slice(floatingPoint bool) []proc.Register {
|
func (r *AMD64Registers) Slice(floatingPoint bool) ([]proc.Register, error) {
|
||||||
var regs64 = []struct {
|
var regs64 = []struct {
|
||||||
k string
|
k string
|
||||||
v int64
|
v int64
|
||||||
@ -112,10 +118,15 @@ func (r *AMD64Registers) Slice(floatingPoint bool) []proc.Register {
|
|||||||
// x86 called this register "Eflags". amd64 extended it and renamed it
|
// x86 called this register "Eflags". amd64 extended it and renamed it
|
||||||
// "Rflags", but Linux still uses the old name.
|
// "Rflags", but Linux still uses the old name.
|
||||||
out = proc.AppendUint64Register(out, "Rflags", uint64(r.Regs.Rflags))
|
out = proc.AppendUint64Register(out, "Rflags", uint64(r.Regs.Rflags))
|
||||||
|
var floatLoadError error
|
||||||
if floatingPoint {
|
if floatingPoint {
|
||||||
|
if r.loadFpRegs != nil {
|
||||||
|
floatLoadError = r.loadFpRegs(r)
|
||||||
|
r.loadFpRegs = nil
|
||||||
|
}
|
||||||
out = append(out, r.Fpregs...)
|
out = append(out, r.Fpregs...)
|
||||||
}
|
}
|
||||||
return out
|
return out, floatLoadError
|
||||||
}
|
}
|
||||||
|
|
||||||
// PC returns the value of RIP register.
|
// PC returns the value of RIP register.
|
||||||
@ -302,7 +313,14 @@ func (r *AMD64Registers) Get(n int) (uint64, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Copy returns a copy of these registers that is guarenteed not to change.
|
// Copy returns a copy of these registers that is guarenteed not to change.
|
||||||
func (r *AMD64Registers) Copy() proc.Registers {
|
func (r *AMD64Registers) Copy() (proc.Registers, error) {
|
||||||
|
if r.loadFpRegs != nil {
|
||||||
|
err := r.loadFpRegs(r)
|
||||||
|
r.loadFpRegs = nil
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
var rr AMD64Registers
|
var rr AMD64Registers
|
||||||
rr.Regs = &AMD64PtraceRegs{}
|
rr.Regs = &AMD64PtraceRegs{}
|
||||||
rr.Fpregset = &AMD64Xstate{}
|
rr.Fpregset = &AMD64Xstate{}
|
||||||
@ -314,7 +332,7 @@ func (r *AMD64Registers) Copy() proc.Registers {
|
|||||||
rr.Fpregs = make([]proc.Register, len(r.Fpregs))
|
rr.Fpregs = make([]proc.Register, len(r.Fpregs))
|
||||||
copy(rr.Fpregs, r.Fpregs)
|
copy(rr.Fpregs, r.Fpregs)
|
||||||
}
|
}
|
||||||
return &rr
|
return &rr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type AMD64Xstate linutil.AMD64Xstate
|
type AMD64Xstate linutil.AMD64Xstate
|
||||||
|
|||||||
@ -252,11 +252,14 @@ func evalFunctionCall(scope *EvalScope, node *ast.CallExpr) (*Variable, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check that there are at least 256 bytes free on the stack
|
// check that there are at least 256 bytes free on the stack
|
||||||
regs, err := scope.g.Thread.Registers(true)
|
regs, err := scope.g.Thread.Registers()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
regs, err = regs.Copy()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
regs = regs.Copy()
|
|
||||||
if regs.SP()-256 <= scope.g.stack.lo {
|
if regs.SP()-256 <= scope.g.stack.lo {
|
||||||
return nil, errNotEnoughStack
|
return nil, errNotEnoughStack
|
||||||
}
|
}
|
||||||
@ -293,18 +296,13 @@ func evalFunctionCall(scope *EvalScope, node *ast.CallExpr) (*Variable, error) {
|
|||||||
scope.g = scope.callCtx.doContinue()
|
scope.g = scope.callCtx.doContinue()
|
||||||
|
|
||||||
// adjust the value of registers inside scope
|
// adjust the value of registers inside scope
|
||||||
for regnum := range scope.Regs.Regs {
|
pcreg, bpreg, spreg := scope.Regs.Reg(scope.Regs.PCRegNum), scope.Regs.Reg(scope.Regs.BPRegNum), scope.Regs.Reg(scope.Regs.SPRegNum)
|
||||||
switch uint64(regnum) {
|
scope.Regs.ClearRegisters()
|
||||||
case scope.Regs.PCRegNum, scope.Regs.SPRegNum, scope.Regs.BPRegNum:
|
scope.Regs.AddReg(scope.Regs.PCRegNum, pcreg)
|
||||||
// leave these alone
|
scope.Regs.AddReg(scope.Regs.BPRegNum, bpreg)
|
||||||
default:
|
scope.Regs.AddReg(scope.Regs.SPRegNum, spreg)
|
||||||
// every other register is dirty and unrecoverable
|
scope.Regs.Reg(scope.Regs.SPRegNum).Uint64Val = uint64(spoff + int64(scope.g.stack.hi))
|
||||||
scope.Regs.Regs[regnum] = nil
|
scope.Regs.Reg(scope.Regs.BPRegNum).Uint64Val = uint64(bpoff + int64(scope.g.stack.hi))
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
scope.Regs.Regs[scope.Regs.SPRegNum].Uint64Val = uint64(spoff + int64(scope.g.stack.hi))
|
|
||||||
scope.Regs.Regs[scope.Regs.BPRegNum].Uint64Val = uint64(bpoff + int64(scope.g.stack.hi))
|
|
||||||
scope.Regs.FrameBase = fboff + int64(scope.g.stack.hi)
|
scope.Regs.FrameBase = fboff + int64(scope.g.stack.hi)
|
||||||
scope.Regs.CFA = scope.frameOffset + int64(scope.g.stack.hi)
|
scope.Regs.CFA = scope.frameOffset + int64(scope.g.stack.hi)
|
||||||
|
|
||||||
@ -655,12 +653,16 @@ func funcCallStep(callScope *EvalScope, fncall *functionCallState) bool {
|
|||||||
bi := p.BinInfo()
|
bi := p.BinInfo()
|
||||||
|
|
||||||
thread := callScope.g.Thread
|
thread := callScope.g.Thread
|
||||||
regs, err := thread.Registers(false)
|
regs, err := thread.Registers()
|
||||||
|
if err != nil {
|
||||||
|
fncall.err = err
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
regs, err = regs.Copy()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fncall.err = err
|
fncall.err = err
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
regs = regs.Copy()
|
|
||||||
|
|
||||||
rax, _ := regs.Get(int(x86asm.RAX))
|
rax, _ := regs.Get(int(x86asm.RAX))
|
||||||
|
|
||||||
@ -823,7 +825,7 @@ func fakeFunctionEntryScope(scope *EvalScope, fn *Function, cfa int64, sp uint64
|
|||||||
scope.File, scope.Line, _ = scope.BinInfo.PCToLine(fn.Entry)
|
scope.File, scope.Line, _ = scope.BinInfo.PCToLine(fn.Entry)
|
||||||
|
|
||||||
scope.Regs.CFA = cfa
|
scope.Regs.CFA = cfa
|
||||||
scope.Regs.Regs[scope.Regs.SPRegNum].Uint64Val = sp
|
scope.Regs.Reg(scope.Regs.SPRegNum).Uint64Val = sp
|
||||||
|
|
||||||
fn.cu.image.dwarfReader.Seek(fn.offset)
|
fn.cu.image.dwarfReader.Seek(fn.offset)
|
||||||
e, err := fn.cu.image.dwarfReader.Next()
|
e, err := fn.cu.image.dwarfReader.Next()
|
||||||
|
|||||||
@ -1286,7 +1286,7 @@ func (t *gdbThread) WriteMemory(addr uintptr, data []byte) (written int, err err
|
|||||||
|
|
||||||
// Location returns the current location of this thread.
|
// Location returns the current location of this thread.
|
||||||
func (t *gdbThread) Location() (*proc.Location, error) {
|
func (t *gdbThread) Location() (*proc.Location, error) {
|
||||||
regs, err := t.Registers(false)
|
regs, err := t.Registers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -1311,7 +1311,7 @@ func (t *gdbThread) ThreadID() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Registers returns the CPU registers for this thread.
|
// Registers returns the CPU registers for this thread.
|
||||||
func (t *gdbThread) Registers(floatingPoint bool) (proc.Registers, error) {
|
func (t *gdbThread) Registers() (proc.Registers, error) {
|
||||||
if t.regs.regs == nil {
|
if t.regs.regs == nil {
|
||||||
if err := t.reloadRegisters(); err != nil {
|
if err := t.reloadRegisters(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -1358,7 +1358,7 @@ func (t *gdbThread) StepInstruction() error {
|
|||||||
|
|
||||||
// Blocked returns true if the thread is blocked in runtime or kernel code.
|
// Blocked returns true if the thread is blocked in runtime or kernel code.
|
||||||
func (t *gdbThread) Blocked() bool {
|
func (t *gdbThread) Blocked() bool {
|
||||||
regs, err := t.Registers(false)
|
regs, err := t.Registers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -1639,7 +1639,7 @@ func (t *gdbThread) SetCurrentBreakpoint(adjustPC bool) error {
|
|||||||
// adjustPC is ignored, it is the stub's responsibiility to set the PC
|
// adjustPC is ignored, it is the stub's responsibiility to set the PC
|
||||||
// address correctly after hitting a breakpoint.
|
// address correctly after hitting a breakpoint.
|
||||||
t.clearBreakpointState()
|
t.clearBreakpointState()
|
||||||
regs, err := t.Registers(false)
|
regs, err := t.Registers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -1865,6 +1865,10 @@ func (regs *gdbRegisters) Get(n int) (uint64, error) {
|
|||||||
return 0, proc.ErrUnknownRegister
|
return 0, proc.ErrUnknownRegister
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *gdbRegisters) FloatLoadError() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// SetPC will set the value of the PC register to the given value.
|
// SetPC will set the value of the PC register to the given value.
|
||||||
func (t *gdbThread) SetPC(pc uint64) error {
|
func (t *gdbThread) SetPC(pc uint64) error {
|
||||||
t.regs.setPC(pc)
|
t.regs.setPC(pc)
|
||||||
@ -1895,7 +1899,7 @@ func (t *gdbThread) SetDX(dx uint64) error {
|
|||||||
return t.p.conn.writeRegister(t.strID, reg.regnum, reg.value)
|
return t.p.conn.writeRegister(t.strID, reg.regnum, reg.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (regs *gdbRegisters) Slice(floatingPoint bool) []proc.Register {
|
func (regs *gdbRegisters) Slice(floatingPoint bool) ([]proc.Register, error) {
|
||||||
r := make([]proc.Register, 0, len(regs.regsInfo))
|
r := make([]proc.Register, 0, len(regs.regsInfo))
|
||||||
for _, reginfo := range regs.regsInfo {
|
for _, reginfo := range regs.regsInfo {
|
||||||
if reginfo.Group == "float" && !floatingPoint {
|
if reginfo.Group == "float" && !floatingPoint {
|
||||||
@ -1941,12 +1945,12 @@ func (regs *gdbRegisters) Slice(floatingPoint bool) []proc.Register {
|
|||||||
r = proc.AppendBytesRegister(r, strings.ToUpper(reginfo.Name), value[16:])
|
r = proc.AppendBytesRegister(r, strings.ToUpper(reginfo.Name), value[16:])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return r
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (regs *gdbRegisters) Copy() proc.Registers {
|
func (regs *gdbRegisters) Copy() (proc.Registers, error) {
|
||||||
savedRegs := &gdbRegisters{}
|
savedRegs := &gdbRegisters{}
|
||||||
savedRegs.init(regs.regsInfo)
|
savedRegs.init(regs.regsInfo)
|
||||||
copy(savedRegs.buf, regs.buf)
|
copy(savedRegs.buf, regs.buf)
|
||||||
return savedRegs
|
return savedRegs, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -253,22 +253,11 @@ func maxI386DwarfRegister() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func i386RegistersToDwarfRegisters(staticBase uint64, regs Registers) op.DwarfRegisters {
|
func i386RegistersToDwarfRegisters(staticBase uint64, regs Registers) op.DwarfRegisters {
|
||||||
dregs := make([]*op.DwarfRegister, maxI386DwarfRegister()+1)
|
dregs := initDwarfRegistersFromSlice(maxI386DwarfRegister(), regs, i386NameToDwarf)
|
||||||
|
dr := op.NewDwarfRegisters(staticBase, dregs, binary.LittleEndian, i386DwarfIPRegNum, i386DwarfSPRegNum, i386DwarfBPRegNum, 0)
|
||||||
|
dr.SetLoadMoreCallback(loadMoreDwarfRegistersFromSliceFunc(dr, regs, i386NameToDwarf))
|
||||||
|
|
||||||
for _, reg := range regs.Slice(true) {
|
return *dr
|
||||||
if dwarfReg, ok := i386NameToDwarf[strings.ToLower(reg.Name)]; ok {
|
|
||||||
dregs[dwarfReg] = reg.Reg
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return op.DwarfRegisters{
|
|
||||||
StaticBase: staticBase,
|
|
||||||
Regs: dregs,
|
|
||||||
ByteOrder: binary.LittleEndian,
|
|
||||||
PCRegNum: i386DwarfIPRegNum,
|
|
||||||
SPRegNum: i386DwarfSPRegNum,
|
|
||||||
BPRegNum: i386DwarfBPRegNum,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func i386AddrAndStackRegsToDwarfRegisters(staticBase, pc, sp, bp, lr uint64) op.DwarfRegisters {
|
func i386AddrAndStackRegsToDwarfRegisters(staticBase, pc, sp, bp, lr uint64) op.DwarfRegisters {
|
||||||
@ -277,14 +266,7 @@ func i386AddrAndStackRegsToDwarfRegisters(staticBase, pc, sp, bp, lr uint64) op.
|
|||||||
dregs[i386DwarfSPRegNum] = op.DwarfRegisterFromUint64(sp)
|
dregs[i386DwarfSPRegNum] = op.DwarfRegisterFromUint64(sp)
|
||||||
dregs[i386DwarfBPRegNum] = op.DwarfRegisterFromUint64(bp)
|
dregs[i386DwarfBPRegNum] = op.DwarfRegisterFromUint64(bp)
|
||||||
|
|
||||||
return op.DwarfRegisters{
|
return *op.NewDwarfRegisters(staticBase, dregs, binary.LittleEndian, i386DwarfIPRegNum, i386DwarfSPRegNum, i386DwarfBPRegNum, 0)
|
||||||
StaticBase: staticBase,
|
|
||||||
Regs: dregs,
|
|
||||||
ByteOrder: binary.LittleEndian,
|
|
||||||
PCRegNum: i386DwarfIPRegNum,
|
|
||||||
SPRegNum: i386DwarfSPRegNum,
|
|
||||||
BPRegNum: i386DwarfBPRegNum,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func i386DwarfRegisterToString(j int, reg *op.DwarfRegister) (name string, floatingPoint bool, repr string) {
|
func i386DwarfRegisterToString(j int, reg *op.DwarfRegister) (name string, floatingPoint bool, repr string) {
|
||||||
@ -301,9 +283,9 @@ func i386DwarfRegisterToString(j int, reg *op.DwarfRegister) (name string, float
|
|||||||
return name, true, fmt.Sprintf("%#04x", reg.Uint64Val)
|
return name, true, fmt.Sprintf("%#04x", reg.Uint64Val)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if reg.Bytes != nil && strings.HasPrefix(name, "xmm") {
|
if reg.Bytes != nil && strings.HasPrefix(n, "xmm") {
|
||||||
return name, true, formatSSEReg(reg.Bytes)
|
return name, true, formatSSEReg(reg.Bytes)
|
||||||
} else if reg.Bytes != nil && strings.HasPrefix(name, "st(") {
|
} else if reg.Bytes != nil && strings.HasPrefix(n, "st(") {
|
||||||
return name, true, formatX87Reg(reg.Bytes)
|
return name, true, formatX87Reg(reg.Bytes)
|
||||||
} else if reg.Bytes == nil || (reg.Bytes != nil && len(reg.Bytes) <= 8) {
|
} else if reg.Bytes == nil || (reg.Bytes != nil && len(reg.Bytes) <= 8) {
|
||||||
return name, false, fmt.Sprintf("%#016x", reg.Uint64Val)
|
return name, false, fmt.Sprintf("%#016x", reg.Uint64Val)
|
||||||
|
|||||||
@ -16,6 +16,12 @@ type AMD64Registers struct {
|
|||||||
Regs *AMD64PtraceRegs
|
Regs *AMD64PtraceRegs
|
||||||
Fpregs []proc.Register
|
Fpregs []proc.Register
|
||||||
Fpregset *AMD64Xstate
|
Fpregset *AMD64Xstate
|
||||||
|
|
||||||
|
loadFpRegs func(*AMD64Registers) error
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAMD64Registers(regs *AMD64PtraceRegs, loadFpRegs func(*AMD64Registers) error) *AMD64Registers {
|
||||||
|
return &AMD64Registers{Regs: regs, loadFpRegs: loadFpRegs}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AMD64PtraceRegs is the struct used by the linux kernel to return the
|
// AMD64PtraceRegs is the struct used by the linux kernel to return the
|
||||||
@ -51,7 +57,7 @@ type AMD64PtraceRegs struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Slice returns the registers as a list of (name, value) pairs.
|
// Slice returns the registers as a list of (name, value) pairs.
|
||||||
func (r *AMD64Registers) Slice(floatingPoint bool) []proc.Register {
|
func (r *AMD64Registers) Slice(floatingPoint bool) ([]proc.Register, error) {
|
||||||
var regs = []struct {
|
var regs = []struct {
|
||||||
k string
|
k string
|
||||||
v uint64
|
v uint64
|
||||||
@ -88,10 +94,15 @@ func (r *AMD64Registers) Slice(floatingPoint bool) []proc.Register {
|
|||||||
for _, reg := range regs {
|
for _, reg := range regs {
|
||||||
out = proc.AppendUint64Register(out, reg.k, reg.v)
|
out = proc.AppendUint64Register(out, reg.k, reg.v)
|
||||||
}
|
}
|
||||||
|
var floatLoadError error
|
||||||
if floatingPoint {
|
if floatingPoint {
|
||||||
|
if r.loadFpRegs != nil {
|
||||||
|
floatLoadError = r.loadFpRegs(r)
|
||||||
|
r.loadFpRegs = nil
|
||||||
|
}
|
||||||
out = append(out, r.Fpregs...)
|
out = append(out, r.Fpregs...)
|
||||||
}
|
}
|
||||||
return out
|
return out, floatLoadError
|
||||||
}
|
}
|
||||||
|
|
||||||
// PC returns the value of RIP register.
|
// PC returns the value of RIP register.
|
||||||
@ -278,7 +289,14 @@ func (r *AMD64Registers) Get(n int) (uint64, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Copy returns a copy of these registers that is guarenteed not to change.
|
// Copy returns a copy of these registers that is guarenteed not to change.
|
||||||
func (r *AMD64Registers) Copy() proc.Registers {
|
func (r *AMD64Registers) Copy() (proc.Registers, error) {
|
||||||
|
if r.loadFpRegs != nil {
|
||||||
|
err := r.loadFpRegs(r)
|
||||||
|
r.loadFpRegs = nil
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
var rr AMD64Registers
|
var rr AMD64Registers
|
||||||
rr.Regs = &AMD64PtraceRegs{}
|
rr.Regs = &AMD64PtraceRegs{}
|
||||||
rr.Fpregset = &AMD64Xstate{}
|
rr.Fpregset = &AMD64Xstate{}
|
||||||
@ -290,7 +308,7 @@ func (r *AMD64Registers) Copy() proc.Registers {
|
|||||||
rr.Fpregs = make([]proc.Register, len(r.Fpregs))
|
rr.Fpregs = make([]proc.Register, len(r.Fpregs))
|
||||||
copy(rr.Fpregs, r.Fpregs)
|
copy(rr.Fpregs, r.Fpregs)
|
||||||
}
|
}
|
||||||
return &rr
|
return &rr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AMD64PtraceFpRegs tracks user_fpregs_struct in /usr/include/x86_64-linux-gnu/sys/user.h
|
// AMD64PtraceFpRegs tracks user_fpregs_struct in /usr/include/x86_64-linux-gnu/sys/user.h
|
||||||
|
|||||||
@ -12,6 +12,12 @@ type ARM64Registers struct {
|
|||||||
Regs *ARM64PtraceRegs //general-purpose registers
|
Regs *ARM64PtraceRegs //general-purpose registers
|
||||||
Fpregs []proc.Register //Formatted floating point registers
|
Fpregs []proc.Register //Formatted floating point registers
|
||||||
Fpregset []byte //holding all floating point register values
|
Fpregset []byte //holding all floating point register values
|
||||||
|
|
||||||
|
loadFpRegs func(*ARM64Registers) error
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewARM64Registers(regs *ARM64PtraceRegs, loadFpRegs func(*ARM64Registers) error) *ARM64Registers {
|
||||||
|
return &ARM64Registers{Regs: regs, loadFpRegs: loadFpRegs}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ARM64PtraceRegs is the struct used by the linux kernel to return the
|
// ARM64PtraceRegs is the struct used by the linux kernel to return the
|
||||||
@ -25,7 +31,7 @@ type ARM64PtraceRegs struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Slice returns the registers as a list of (name, value) pairs.
|
// Slice returns the registers as a list of (name, value) pairs.
|
||||||
func (r *ARM64Registers) Slice(floatingPoint bool) []proc.Register {
|
func (r *ARM64Registers) Slice(floatingPoint bool) ([]proc.Register, error) {
|
||||||
var regs64 = []struct {
|
var regs64 = []struct {
|
||||||
k string
|
k string
|
||||||
v uint64
|
v uint64
|
||||||
@ -69,8 +75,15 @@ func (r *ARM64Registers) Slice(floatingPoint bool) []proc.Register {
|
|||||||
for _, reg := range regs64 {
|
for _, reg := range regs64 {
|
||||||
out = proc.AppendUint64Register(out, reg.k, reg.v)
|
out = proc.AppendUint64Register(out, reg.k, reg.v)
|
||||||
}
|
}
|
||||||
out = append(out, r.Fpregs...)
|
var floatLoadError error
|
||||||
return out
|
if floatingPoint {
|
||||||
|
if r.loadFpRegs != nil {
|
||||||
|
floatLoadError = r.loadFpRegs(r)
|
||||||
|
r.loadFpRegs = nil
|
||||||
|
}
|
||||||
|
out = append(out, r.Fpregs...)
|
||||||
|
}
|
||||||
|
return out, floatLoadError
|
||||||
}
|
}
|
||||||
|
|
||||||
// PC returns the value of RIP register.
|
// PC returns the value of RIP register.
|
||||||
@ -110,7 +123,14 @@ func (r *ARM64Registers) Get(n int) (uint64, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Copy returns a copy of these registers that is guarenteed not to change.
|
// Copy returns a copy of these registers that is guarenteed not to change.
|
||||||
func (r *ARM64Registers) Copy() proc.Registers {
|
func (r *ARM64Registers) Copy() (proc.Registers, error) {
|
||||||
|
if r.loadFpRegs != nil {
|
||||||
|
err := r.loadFpRegs(r)
|
||||||
|
r.loadFpRegs = nil
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
var rr ARM64Registers
|
var rr ARM64Registers
|
||||||
rr.Regs = &ARM64PtraceRegs{}
|
rr.Regs = &ARM64PtraceRegs{}
|
||||||
*(rr.Regs) = *(r.Regs)
|
*(rr.Regs) = *(r.Regs)
|
||||||
@ -122,7 +142,7 @@ func (r *ARM64Registers) Copy() proc.Registers {
|
|||||||
rr.Fpregset = make([]byte, len(r.Fpregset))
|
rr.Fpregset = make([]byte, len(r.Fpregset))
|
||||||
copy(rr.Fpregset, r.Fpregset)
|
copy(rr.Fpregset, r.Fpregset)
|
||||||
}
|
}
|
||||||
return &rr
|
return &rr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type ARM64PtraceFpRegs struct {
|
type ARM64PtraceFpRegs struct {
|
||||||
|
|||||||
@ -15,6 +15,12 @@ type I386Registers struct {
|
|||||||
Fpregs []proc.Register
|
Fpregs []proc.Register
|
||||||
Fpregset *I386Xstate
|
Fpregset *I386Xstate
|
||||||
Tls uint64
|
Tls uint64
|
||||||
|
|
||||||
|
loadFpRegs func(*I386Registers) error
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewI386Registers(regs *I386PtraceRegs, loadFpRegs func(*I386Registers) error) *I386Registers {
|
||||||
|
return &I386Registers{Regs: regs, Fpregs: nil, Fpregset: nil, Tls: 0, loadFpRegs: loadFpRegs}
|
||||||
}
|
}
|
||||||
|
|
||||||
// I386PtraceRegs is the struct used by the linux kernel to return the
|
// I386PtraceRegs is the struct used by the linux kernel to return the
|
||||||
@ -40,7 +46,7 @@ type I386PtraceRegs struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Slice returns the registers as a list of (name, value) pairs.
|
// Slice returns the registers as a list of (name, value) pairs.
|
||||||
func (r *I386Registers) Slice(floatingPoint bool) []proc.Register {
|
func (r *I386Registers) Slice(floatingPoint bool) ([]proc.Register, error) {
|
||||||
var regs = []struct {
|
var regs = []struct {
|
||||||
k string
|
k string
|
||||||
v int32
|
v int32
|
||||||
@ -67,10 +73,15 @@ func (r *I386Registers) Slice(floatingPoint bool) []proc.Register {
|
|||||||
for _, reg := range regs {
|
for _, reg := range regs {
|
||||||
out = proc.AppendUint64Register(out, reg.k, uint64(uint32(reg.v)))
|
out = proc.AppendUint64Register(out, reg.k, uint64(uint32(reg.v)))
|
||||||
}
|
}
|
||||||
|
var floatLoadError error
|
||||||
if floatingPoint {
|
if floatingPoint {
|
||||||
|
if r.loadFpRegs != nil {
|
||||||
|
floatLoadError = r.loadFpRegs(r)
|
||||||
|
r.loadFpRegs = nil
|
||||||
|
}
|
||||||
out = append(out, r.Fpregs...)
|
out = append(out, r.Fpregs...)
|
||||||
}
|
}
|
||||||
return out
|
return out, floatLoadError
|
||||||
}
|
}
|
||||||
|
|
||||||
// PC returns the value of EIP register.
|
// PC returns the value of EIP register.
|
||||||
@ -178,7 +189,14 @@ func (r *I386Registers) Get(n int) (uint64, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Copy returns a copy of these registers that is guarenteed not to change.
|
// Copy returns a copy of these registers that is guarenteed not to change.
|
||||||
func (r *I386Registers) Copy() proc.Registers {
|
func (r *I386Registers) Copy() (proc.Registers, error) {
|
||||||
|
if r.loadFpRegs != nil {
|
||||||
|
err := r.loadFpRegs(r)
|
||||||
|
r.loadFpRegs = nil
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
var rr I386Registers
|
var rr I386Registers
|
||||||
rr.Regs = &I386PtraceRegs{}
|
rr.Regs = &I386PtraceRegs{}
|
||||||
rr.Fpregset = &I386Xstate{}
|
rr.Fpregset = &I386Xstate{}
|
||||||
@ -190,7 +208,7 @@ func (r *I386Registers) Copy() proc.Registers {
|
|||||||
rr.Fpregs = make([]proc.Register, len(r.Fpregs))
|
rr.Fpregs = make([]proc.Register, len(r.Fpregs))
|
||||||
copy(rr.Fpregs, r.Fpregs)
|
copy(rr.Fpregs, r.Fpregs)
|
||||||
}
|
}
|
||||||
return &rr
|
return &rr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// I386PtraceFpRegs tracks user_fpregs_struct in /usr/include/x86_64-linux-gnu/sys/user.h
|
// I386PtraceFpRegs tracks user_fpregs_struct in /usr/include/x86_64-linux-gnu/sys/user.h
|
||||||
|
|||||||
@ -104,6 +104,9 @@ func newCompositeMemory(mem MemoryReadWriter, regs op.DwarfRegisters, pieces []o
|
|||||||
sz = len(reg)
|
sz = len(reg)
|
||||||
}
|
}
|
||||||
if sz > len(reg) {
|
if sz > len(reg) {
|
||||||
|
if regs.FloatLoadError != nil {
|
||||||
|
return nil, fmt.Errorf("could not read %d bytes from register %d (size: %d), also error loading floating point registers: %v", sz, piece.RegNum, len(reg), regs.FloatLoadError)
|
||||||
|
}
|
||||||
return nil, fmt.Errorf("could not read %d bytes from register %d (size: %d)", sz, piece.RegNum, len(reg))
|
return nil, fmt.Errorf("could not read %d bytes from register %d (size: %d)", sz, piece.RegNum, len(reg))
|
||||||
}
|
}
|
||||||
cmem.data = append(cmem.data, reg[:sz]...)
|
cmem.data = append(cmem.data, reg[:sz]...)
|
||||||
|
|||||||
@ -39,7 +39,7 @@ func killProcess(pid int) error {
|
|||||||
panic(ErrNativeBackendDisabled)
|
panic(ErrNativeBackendDisabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
func registers(thread *nativeThread, floatingPoint bool) (proc.Registers, error) {
|
func registers(thread *nativeThread) (proc.Registers, error) {
|
||||||
panic(ErrNativeBackendDisabled)
|
panic(ErrNativeBackendDisabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import (
|
|||||||
|
|
||||||
// SetPC sets EIP to the value specified by 'pc'.
|
// SetPC sets EIP to the value specified by 'pc'.
|
||||||
func (thread *nativeThread) SetPC(pc uint64) error {
|
func (thread *nativeThread) SetPC(pc uint64) error {
|
||||||
ir, err := registers(thread, false)
|
ir, err := registers(thread)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -24,7 +24,7 @@ func (thread *nativeThread) SetPC(pc uint64) error {
|
|||||||
// SetSP sets ESP to the value specified by 'sp'
|
// SetSP sets ESP to the value specified by 'sp'
|
||||||
func (thread *nativeThread) SetSP(sp uint64) (err error) {
|
func (thread *nativeThread) SetSP(sp uint64) (err error) {
|
||||||
var ir proc.Registers
|
var ir proc.Registers
|
||||||
ir, err = registers(thread, false)
|
ir, err = registers(thread)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -36,7 +36,7 @@ func (thread *nativeThread) SetSP(sp uint64) (err error) {
|
|||||||
|
|
||||||
func (thread *nativeThread) SetDX(dx uint64) (err error) {
|
func (thread *nativeThread) SetDX(dx uint64) (err error) {
|
||||||
var ir proc.Registers
|
var ir proc.Registers
|
||||||
ir, err = registers(thread, false)
|
ir, err = registers(thread)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -46,7 +46,7 @@ func (thread *nativeThread) SetDX(dx uint64) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func registers(thread *nativeThread, floatingPoint bool) (proc.Registers, error) {
|
func registers(thread *nativeThread) (proc.Registers, error) {
|
||||||
var (
|
var (
|
||||||
regs linutil.I386PtraceRegs
|
regs linutil.I386PtraceRegs
|
||||||
err error
|
err error
|
||||||
@ -55,15 +55,13 @@ func registers(thread *nativeThread, floatingPoint bool) (proc.Registers, error)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
r := &linutil.I386Registers{®s, nil, nil, 0}
|
r := linutil.NewI386Registers(®s, func(r *linutil.I386Registers) error {
|
||||||
if floatingPoint {
|
|
||||||
var fpregset linutil.I386Xstate
|
var fpregset linutil.I386Xstate
|
||||||
r.Fpregs, fpregset, err = thread.fpRegisters()
|
var floatLoadError error
|
||||||
|
r.Fpregs, fpregset, floatLoadError = thread.fpRegisters()
|
||||||
r.Fpregset = &fpregset
|
r.Fpregset = &fpregset
|
||||||
if err != nil {
|
return floatLoadError
|
||||||
return nil, err
|
})
|
||||||
}
|
|
||||||
}
|
|
||||||
thread.dbp.execPtraceFunc(func() {
|
thread.dbp.execPtraceFunc(func() {
|
||||||
tls, _ := ptraceGetTls(regs.Xgs, thread.ThreadID())
|
tls, _ := ptraceGetTls(regs.Xgs, thread.ThreadID())
|
||||||
r.Tls = uint64(tls)
|
r.Tls = uint64(tls)
|
||||||
|
|||||||
@ -41,7 +41,7 @@ type Regs struct {
|
|||||||
fpregs []proc.Register
|
fpregs []proc.Register
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Regs) Slice(floatingPoint bool) []proc.Register {
|
func (r *Regs) Slice(floatingPoint bool) ([]proc.Register, error) {
|
||||||
var regs = []struct {
|
var regs = []struct {
|
||||||
k string
|
k string
|
||||||
v uint64
|
v uint64
|
||||||
@ -80,7 +80,7 @@ func (r *Regs) Slice(floatingPoint bool) []proc.Register {
|
|||||||
if floatingPoint {
|
if floatingPoint {
|
||||||
out = append(out, r.fpregs...)
|
out = append(out, r.fpregs...)
|
||||||
}
|
}
|
||||||
return out
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PC returns the current program counter
|
// PC returns the current program counter
|
||||||
@ -285,7 +285,7 @@ func (r *Regs) Get(n int) (uint64, error) {
|
|||||||
return 0, proc.ErrUnknownRegister
|
return 0, proc.ErrUnknownRegister
|
||||||
}
|
}
|
||||||
|
|
||||||
func registers(thread *nativeThread, floatingPoint bool) (proc.Registers, error) {
|
func registers(thread *nativeThread) (proc.Registers, error) {
|
||||||
var state C.x86_thread_state64_t
|
var state C.x86_thread_state64_t
|
||||||
var identity C.thread_identifier_info_data_t
|
var identity C.thread_identifier_info_data_t
|
||||||
kret := C.get_registers(C.mach_port_name_t(thread.os.threadAct), &state)
|
kret := C.get_registers(C.mach_port_name_t(thread.os.threadAct), &state)
|
||||||
@ -333,37 +333,36 @@ func registers(thread *nativeThread, floatingPoint bool) (proc.Registers, error)
|
|||||||
gsBase: uint64(identity.thread_handle),
|
gsBase: uint64(identity.thread_handle),
|
||||||
}
|
}
|
||||||
|
|
||||||
if floatingPoint {
|
// https://opensource.apple.com/source/xnu/xnu-792.13.8/osfmk/mach/i386/thread_status.h?txt
|
||||||
// https://opensource.apple.com/source/xnu/xnu-792.13.8/osfmk/mach/i386/thread_status.h?txt
|
var fpstate C.x86_float_state64_t
|
||||||
var fpstate C.x86_float_state64_t
|
kret = C.get_fpu_registers(C.mach_port_name_t(thread.os.threadAct), &fpstate)
|
||||||
kret = C.get_fpu_registers(C.mach_port_name_t(thread.os.threadAct), &fpstate)
|
if kret != C.KERN_SUCCESS {
|
||||||
if kret != C.KERN_SUCCESS {
|
return nil, fmt.Errorf("could not get floating point registers")
|
||||||
return nil, fmt.Errorf("could not get floating point registers")
|
|
||||||
}
|
|
||||||
|
|
||||||
regs.fpregs = proc.AppendUint64Register(regs.fpregs, "CW", uint64(*((*uint16)(unsafe.Pointer(&fpstate.__fpu_fcw)))))
|
|
||||||
regs.fpregs = proc.AppendUint64Register(regs.fpregs, "SW", uint64(*((*uint16)(unsafe.Pointer(&fpstate.__fpu_fsw)))))
|
|
||||||
regs.fpregs = proc.AppendUint64Register(regs.fpregs, "TW", uint64(fpstate.__fpu_ftw))
|
|
||||||
regs.fpregs = proc.AppendUint64Register(regs.fpregs, "FOP", uint64(fpstate.__fpu_fop))
|
|
||||||
regs.fpregs = proc.AppendUint64Register(regs.fpregs, "FIP", uint64(fpstate.__fpu_cs)<<32|uint64(fpstate.__fpu_ip))
|
|
||||||
regs.fpregs = proc.AppendUint64Register(regs.fpregs, "FDP", uint64(fpstate.__fpu_ds)<<32|uint64(fpstate.__fpu_dp))
|
|
||||||
|
|
||||||
for i, st := range []*C.char{&fpstate.__fpu_stmm0.__mmst_reg[0], &fpstate.__fpu_stmm1.__mmst_reg[0], &fpstate.__fpu_stmm2.__mmst_reg[0], &fpstate.__fpu_stmm3.__mmst_reg[0], &fpstate.__fpu_stmm4.__mmst_reg[0], &fpstate.__fpu_stmm5.__mmst_reg[0], &fpstate.__fpu_stmm6.__mmst_reg[0], &fpstate.__fpu_stmm7.__mmst_reg[0]} {
|
|
||||||
stb := C.GoBytes(unsafe.Pointer(st), 10)
|
|
||||||
regs.fpregs = proc.AppendBytesRegister(regs.fpregs, fmt.Sprintf("ST(%d)", i), stb)
|
|
||||||
}
|
|
||||||
|
|
||||||
regs.fpregs = proc.AppendUint64Register(regs.fpregs, "MXCSR", uint64(fpstate.__fpu_mxcsr))
|
|
||||||
regs.fpregs = proc.AppendUint64Register(regs.fpregs, "MXCSR_MASK", uint64(fpstate.__fpu_mxcsrmask))
|
|
||||||
|
|
||||||
for i, xmm := range []*C.char{&fpstate.__fpu_xmm0.__xmm_reg[0], &fpstate.__fpu_xmm1.__xmm_reg[0], &fpstate.__fpu_xmm2.__xmm_reg[0], &fpstate.__fpu_xmm3.__xmm_reg[0], &fpstate.__fpu_xmm4.__xmm_reg[0], &fpstate.__fpu_xmm5.__xmm_reg[0], &fpstate.__fpu_xmm6.__xmm_reg[0], &fpstate.__fpu_xmm7.__xmm_reg[0], &fpstate.__fpu_xmm8.__xmm_reg[0], &fpstate.__fpu_xmm9.__xmm_reg[0], &fpstate.__fpu_xmm10.__xmm_reg[0], &fpstate.__fpu_xmm11.__xmm_reg[0], &fpstate.__fpu_xmm12.__xmm_reg[0], &fpstate.__fpu_xmm13.__xmm_reg[0], &fpstate.__fpu_xmm14.__xmm_reg[0], &fpstate.__fpu_xmm15.__xmm_reg[0]} {
|
|
||||||
regs.fpregs = proc.AppendBytesRegister(regs.fpregs, fmt.Sprintf("XMM%d", i), C.GoBytes(unsafe.Pointer(xmm), 16))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
regs.fpregs = proc.AppendUint64Register(regs.fpregs, "CW", uint64(*((*uint16)(unsafe.Pointer(&fpstate.__fpu_fcw)))))
|
||||||
|
regs.fpregs = proc.AppendUint64Register(regs.fpregs, "SW", uint64(*((*uint16)(unsafe.Pointer(&fpstate.__fpu_fsw)))))
|
||||||
|
regs.fpregs = proc.AppendUint64Register(regs.fpregs, "TW", uint64(fpstate.__fpu_ftw))
|
||||||
|
regs.fpregs = proc.AppendUint64Register(regs.fpregs, "FOP", uint64(fpstate.__fpu_fop))
|
||||||
|
regs.fpregs = proc.AppendUint64Register(regs.fpregs, "FIP", uint64(fpstate.__fpu_cs)<<32|uint64(fpstate.__fpu_ip))
|
||||||
|
regs.fpregs = proc.AppendUint64Register(regs.fpregs, "FDP", uint64(fpstate.__fpu_ds)<<32|uint64(fpstate.__fpu_dp))
|
||||||
|
|
||||||
|
for i, st := range []*C.char{&fpstate.__fpu_stmm0.__mmst_reg[0], &fpstate.__fpu_stmm1.__mmst_reg[0], &fpstate.__fpu_stmm2.__mmst_reg[0], &fpstate.__fpu_stmm3.__mmst_reg[0], &fpstate.__fpu_stmm4.__mmst_reg[0], &fpstate.__fpu_stmm5.__mmst_reg[0], &fpstate.__fpu_stmm6.__mmst_reg[0], &fpstate.__fpu_stmm7.__mmst_reg[0]} {
|
||||||
|
stb := C.GoBytes(unsafe.Pointer(st), 10)
|
||||||
|
regs.fpregs = proc.AppendBytesRegister(regs.fpregs, fmt.Sprintf("ST(%d)", i), stb)
|
||||||
|
}
|
||||||
|
|
||||||
|
regs.fpregs = proc.AppendUint64Register(regs.fpregs, "MXCSR", uint64(fpstate.__fpu_mxcsr))
|
||||||
|
regs.fpregs = proc.AppendUint64Register(regs.fpregs, "MXCSR_MASK", uint64(fpstate.__fpu_mxcsrmask))
|
||||||
|
|
||||||
|
for i, xmm := range []*C.char{&fpstate.__fpu_xmm0.__xmm_reg[0], &fpstate.__fpu_xmm1.__xmm_reg[0], &fpstate.__fpu_xmm2.__xmm_reg[0], &fpstate.__fpu_xmm3.__xmm_reg[0], &fpstate.__fpu_xmm4.__xmm_reg[0], &fpstate.__fpu_xmm5.__xmm_reg[0], &fpstate.__fpu_xmm6.__xmm_reg[0], &fpstate.__fpu_xmm7.__xmm_reg[0], &fpstate.__fpu_xmm8.__xmm_reg[0], &fpstate.__fpu_xmm9.__xmm_reg[0], &fpstate.__fpu_xmm10.__xmm_reg[0], &fpstate.__fpu_xmm11.__xmm_reg[0], &fpstate.__fpu_xmm12.__xmm_reg[0], &fpstate.__fpu_xmm13.__xmm_reg[0], &fpstate.__fpu_xmm14.__xmm_reg[0], &fpstate.__fpu_xmm15.__xmm_reg[0]} {
|
||||||
|
regs.fpregs = proc.AppendBytesRegister(regs.fpregs, fmt.Sprintf("XMM%d", i), C.GoBytes(unsafe.Pointer(xmm), 16))
|
||||||
|
}
|
||||||
|
|
||||||
return regs, nil
|
return regs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Regs) Copy() proc.Registers {
|
func (r *Regs) Copy() (proc.Registers, error) {
|
||||||
//TODO(aarzilli): implement this to support function calls
|
//TODO(aarzilli): implement this to support function calls
|
||||||
return nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import (
|
|||||||
|
|
||||||
// SetPC sets RIP to the value specified by 'pc'.
|
// SetPC sets RIP to the value specified by 'pc'.
|
||||||
func (thread *nativeThread) SetPC(pc uint64) error {
|
func (thread *nativeThread) SetPC(pc uint64) error {
|
||||||
ir, err := registers(thread, false)
|
ir, err := registers(thread)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -24,7 +24,7 @@ func (thread *nativeThread) SetPC(pc uint64) error {
|
|||||||
// SetSP sets RSP to the value specified by 'sp'
|
// SetSP sets RSP to the value specified by 'sp'
|
||||||
func (thread *nativeThread) SetSP(sp uint64) (err error) {
|
func (thread *nativeThread) SetSP(sp uint64) (err error) {
|
||||||
var ir proc.Registers
|
var ir proc.Registers
|
||||||
ir, err = registers(thread, false)
|
ir, err = registers(thread)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -36,7 +36,7 @@ func (thread *nativeThread) SetSP(sp uint64) (err error) {
|
|||||||
|
|
||||||
func (thread *nativeThread) SetDX(dx uint64) (err error) {
|
func (thread *nativeThread) SetDX(dx uint64) (err error) {
|
||||||
var ir proc.Registers
|
var ir proc.Registers
|
||||||
ir, err = registers(thread, false)
|
ir, err = registers(thread)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -46,7 +46,7 @@ func (thread *nativeThread) SetDX(dx uint64) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func registers(thread *nativeThread, floatingPoint bool) (proc.Registers, error) {
|
func registers(thread *nativeThread) (proc.Registers, error) {
|
||||||
var (
|
var (
|
||||||
regs fbsdutil.AMD64PtraceRegs
|
regs fbsdutil.AMD64PtraceRegs
|
||||||
err error
|
err error
|
||||||
@ -60,15 +60,13 @@ func registers(thread *nativeThread, floatingPoint bool) (proc.Registers, error)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
r := &fbsdutil.AMD64Registers{®s, nil, nil, uint64(fsbase)}
|
r := fbsdutil.NewAMD64Registers(®s, uint64(fsbase), func(r *fbsdutil.AMD64Registers) error {
|
||||||
if floatingPoint {
|
|
||||||
var fpregset fbsdutil.AMD64Xstate
|
var fpregset fbsdutil.AMD64Xstate
|
||||||
r.Fpregs, fpregset, err = thread.fpRegisters()
|
var floatLoadError error
|
||||||
|
r.Fpregs, fpregset, floatLoadError = thread.fpRegisters()
|
||||||
r.Fpregset = &fpregset
|
r.Fpregset = &fpregset
|
||||||
if err != nil {
|
return floatLoadError
|
||||||
return nil, err
|
})
|
||||||
}
|
|
||||||
}
|
|
||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import (
|
|||||||
|
|
||||||
// SetPC sets RIP to the value specified by 'pc'.
|
// SetPC sets RIP to the value specified by 'pc'.
|
||||||
func (thread *nativeThread) SetPC(pc uint64) error {
|
func (thread *nativeThread) SetPC(pc uint64) error {
|
||||||
ir, err := registers(thread, false)
|
ir, err := registers(thread)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -24,7 +24,7 @@ func (thread *nativeThread) SetPC(pc uint64) error {
|
|||||||
// SetSP sets RSP to the value specified by 'sp'
|
// SetSP sets RSP to the value specified by 'sp'
|
||||||
func (thread *nativeThread) SetSP(sp uint64) (err error) {
|
func (thread *nativeThread) SetSP(sp uint64) (err error) {
|
||||||
var ir proc.Registers
|
var ir proc.Registers
|
||||||
ir, err = registers(thread, false)
|
ir, err = registers(thread)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -36,7 +36,7 @@ func (thread *nativeThread) SetSP(sp uint64) (err error) {
|
|||||||
|
|
||||||
func (thread *nativeThread) SetDX(dx uint64) (err error) {
|
func (thread *nativeThread) SetDX(dx uint64) (err error) {
|
||||||
var ir proc.Registers
|
var ir proc.Registers
|
||||||
ir, err = registers(thread, false)
|
ir, err = registers(thread)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -46,7 +46,7 @@ func (thread *nativeThread) SetDX(dx uint64) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func registers(thread *nativeThread, floatingPoint bool) (proc.Registers, error) {
|
func registers(thread *nativeThread) (proc.Registers, error) {
|
||||||
var (
|
var (
|
||||||
regs linutil.AMD64PtraceRegs
|
regs linutil.AMD64PtraceRegs
|
||||||
err error
|
err error
|
||||||
@ -55,15 +55,13 @@ func registers(thread *nativeThread, floatingPoint bool) (proc.Registers, error)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
r := &linutil.AMD64Registers{Regs: ®s}
|
r := linutil.NewAMD64Registers(®s, func(r *linutil.AMD64Registers) error {
|
||||||
if floatingPoint {
|
|
||||||
var fpregset linutil.AMD64Xstate
|
var fpregset linutil.AMD64Xstate
|
||||||
r.Fpregs, fpregset, err = thread.fpRegisters()
|
var floatLoadError error
|
||||||
|
r.Fpregs, fpregset, floatLoadError = thread.fpRegisters()
|
||||||
r.Fpregset = &fpregset
|
r.Fpregset = &fpregset
|
||||||
if err != nil {
|
return floatLoadError
|
||||||
return nil, err
|
})
|
||||||
}
|
|
||||||
}
|
|
||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -56,7 +56,7 @@ func ptraceGetFpRegset(tid int) (fpregset []byte, err error) {
|
|||||||
|
|
||||||
// SetPC sets PC to the value specified by 'pc'.
|
// SetPC sets PC to the value specified by 'pc'.
|
||||||
func (thread *nativeThread) SetPC(pc uint64) error {
|
func (thread *nativeThread) SetPC(pc uint64) error {
|
||||||
ir, err := registers(thread, false)
|
ir, err := registers(thread)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -69,7 +69,7 @@ func (thread *nativeThread) SetPC(pc uint64) error {
|
|||||||
// SetSP sets RSP to the value specified by 'sp'
|
// SetSP sets RSP to the value specified by 'sp'
|
||||||
func (thread *nativeThread) SetSP(sp uint64) (err error) {
|
func (thread *nativeThread) SetSP(sp uint64) (err error) {
|
||||||
var ir proc.Registers
|
var ir proc.Registers
|
||||||
ir, err = registers(thread, false)
|
ir, err = registers(thread)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -83,7 +83,7 @@ func (thread *nativeThread) SetDX(dx uint64) (err error) {
|
|||||||
return fmt.Errorf("not supported")
|
return fmt.Errorf("not supported")
|
||||||
}
|
}
|
||||||
|
|
||||||
func registers(thread *nativeThread, floatingPoint bool) (proc.Registers, error) {
|
func registers(thread *nativeThread) (proc.Registers, error) {
|
||||||
var (
|
var (
|
||||||
regs linutil.ARM64PtraceRegs
|
regs linutil.ARM64PtraceRegs
|
||||||
err error
|
err error
|
||||||
@ -92,12 +92,10 @@ func registers(thread *nativeThread, floatingPoint bool) (proc.Registers, error)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
r := &linutil.ARM64Registers{®s, nil, nil}
|
r := linutil.NewARM64Registers(®s, func(r *linutil.ARM64Registers) error {
|
||||||
if floatingPoint {
|
var floatLoadError error
|
||||||
r.Fpregs, r.Fpregset, err = thread.fpRegisters()
|
r.Fpregs, r.Fpregset, floatLoadError = thread.fpRegisters()
|
||||||
if err != nil {
|
return floatLoadError
|
||||||
return nil, err
|
})
|
||||||
}
|
|
||||||
}
|
|
||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -52,7 +52,7 @@ func (thread *nativeThread) SetDX(dx uint64) error {
|
|||||||
return _SetThreadContext(thread.os.hThread, context)
|
return _SetThreadContext(thread.os.hThread, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
func registers(thread *nativeThread, floatingPoint bool) (proc.Registers, error) {
|
func registers(thread *nativeThread) (proc.Registers, error) {
|
||||||
context := winutil.NewCONTEXT()
|
context := winutil.NewCONTEXT()
|
||||||
|
|
||||||
context.ContextFlags = _CONTEXT_ALL
|
context.ContextFlags = _CONTEXT_ALL
|
||||||
@ -67,5 +67,5 @@ func registers(thread *nativeThread, floatingPoint bool) (proc.Registers, error)
|
|||||||
return nil, fmt.Errorf("NtQueryInformationThread failed: it returns 0x%x", status)
|
return nil, fmt.Errorf("NtQueryInformationThread failed: it returns 0x%x", status)
|
||||||
}
|
}
|
||||||
|
|
||||||
return winutil.NewAMD64Registers(context, uint64(threadInfo.TebBaseAddress), floatingPoint), nil
|
return winutil.NewAMD64Registers(context, uint64(threadInfo.TebBaseAddress)), nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -157,8 +157,8 @@ func (t *nativeThread) ClearBreakpoint(bp *proc.Breakpoint) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Registers obtains register values from the debugged process.
|
// Registers obtains register values from the debugged process.
|
||||||
func (t *nativeThread) Registers(floatingPoint bool) (proc.Registers, error) {
|
func (t *nativeThread) Registers() (proc.Registers, error) {
|
||||||
return registers(t, floatingPoint)
|
return registers(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RestoreRegisters will set the value of the CPU registers to those
|
// RestoreRegisters will set the value of the CPU registers to those
|
||||||
@ -169,7 +169,7 @@ func (t *nativeThread) RestoreRegisters(savedRegs proc.Registers) error {
|
|||||||
|
|
||||||
// PC returns the current program counter value for this thread.
|
// PC returns the current program counter value for this thread.
|
||||||
func (t *nativeThread) PC() (uint64, error) {
|
func (t *nativeThread) PC() (uint64, error) {
|
||||||
regs, err := t.Registers(false)
|
regs, err := t.Registers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|||||||
@ -87,7 +87,7 @@ func (t *nativeThread) resume() error {
|
|||||||
|
|
||||||
func (t *nativeThread) Blocked() bool {
|
func (t *nativeThread) Blocked() bool {
|
||||||
// TODO(dp) cache the func pc to remove this lookup
|
// TODO(dp) cache the func pc to remove this lookup
|
||||||
regs, err := t.Registers(false)
|
regs, err := t.Registers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@ -72,7 +72,7 @@ func (t *nativeThread) singleStep() (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *nativeThread) Blocked() bool {
|
func (t *nativeThread) Blocked() bool {
|
||||||
regs, err := t.Registers(false)
|
regs, err := t.Registers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@ -114,7 +114,7 @@ func (t *nativeThread) resume() error {
|
|||||||
func (t *nativeThread) Blocked() bool {
|
func (t *nativeThread) Blocked() bool {
|
||||||
// TODO: Probably incorrect - what are the runtime functions that
|
// TODO: Probably incorrect - what are the runtime functions that
|
||||||
// indicate blocking on Windows?
|
// indicate blocking on Windows?
|
||||||
regs, err := t.Registers(false)
|
regs, err := t.Registers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@ -90,7 +90,7 @@ func withTestProcessArgs(name string, t testing.TB, wd string, args []string, bu
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getRegisters(p *proc.Target, t *testing.T) proc.Registers {
|
func getRegisters(p *proc.Target, t *testing.T) proc.Registers {
|
||||||
regs, err := p.CurrentThread().Registers(false)
|
regs, err := p.CurrentThread().Registers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("Registers():", err)
|
t.Fatal("Registers():", err)
|
||||||
}
|
}
|
||||||
@ -113,7 +113,7 @@ func assertNoError(err error, t testing.TB, s string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func currentPC(p *proc.Target, t *testing.T) uint64 {
|
func currentPC(p *proc.Target, t *testing.T) uint64 {
|
||||||
regs, err := p.CurrentThread().Registers(false)
|
regs, err := p.CurrentThread().Registers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -280,7 +280,7 @@ func TestBreakpoint(t *testing.T) {
|
|||||||
bp := setFunctionBreakpoint(p, t, "main.helloworld")
|
bp := setFunctionBreakpoint(p, t, "main.helloworld")
|
||||||
assertNoError(p.Continue(), t, "Continue()")
|
assertNoError(p.Continue(), t, "Continue()")
|
||||||
|
|
||||||
regs, err := p.CurrentThread().Registers(false)
|
regs, err := p.CurrentThread().Registers()
|
||||||
assertNoError(err, t, "Registers")
|
assertNoError(err, t, "Registers")
|
||||||
pc := regs.PC()
|
pc := regs.PC()
|
||||||
|
|
||||||
@ -302,7 +302,7 @@ func TestBreakpointInSeparateGoRoutine(t *testing.T) {
|
|||||||
|
|
||||||
assertNoError(p.Continue(), t, "Continue")
|
assertNoError(p.Continue(), t, "Continue")
|
||||||
|
|
||||||
regs, err := p.CurrentThread().Registers(false)
|
regs, err := p.CurrentThread().Registers()
|
||||||
assertNoError(err, t, "Registers")
|
assertNoError(err, t, "Registers")
|
||||||
pc := regs.PC()
|
pc := regs.PC()
|
||||||
|
|
||||||
@ -409,7 +409,7 @@ func testseq2Args(wd string, args []string, buildFlags protest.BuildFlags, t *te
|
|||||||
if traceTestseq2 {
|
if traceTestseq2 {
|
||||||
t.Logf("initial breakpoint %v", bp)
|
t.Logf("initial breakpoint %v", bp)
|
||||||
}
|
}
|
||||||
regs, err := p.CurrentThread().Registers(false)
|
regs, err := p.CurrentThread().Registers()
|
||||||
assertNoError(err, t, "Registers")
|
assertNoError(err, t, "Registers")
|
||||||
|
|
||||||
f, ln := currentLineNumber(p, t)
|
f, ln := currentLineNumber(p, t)
|
||||||
@ -474,7 +474,7 @@ func testseq2Args(wd string, args []string, buildFlags protest.BuildFlags, t *te
|
|||||||
}
|
}
|
||||||
|
|
||||||
f, ln = currentLineNumber(p, t)
|
f, ln = currentLineNumber(p, t)
|
||||||
regs, _ = p.CurrentThread().Registers(false)
|
regs, _ = p.CurrentThread().Registers()
|
||||||
pc := regs.PC()
|
pc := regs.PC()
|
||||||
|
|
||||||
if traceTestseq2 {
|
if traceTestseq2 {
|
||||||
@ -710,7 +710,7 @@ func TestRuntimeBreakpoint(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
regs, err := p.CurrentThread().Registers(false)
|
regs, err := p.CurrentThread().Registers()
|
||||||
assertNoError(err, t, "Registers")
|
assertNoError(err, t, "Registers")
|
||||||
pc := regs.PC()
|
pc := regs.PC()
|
||||||
f, l, _ := p.BinInfo().PCToLine(pc)
|
f, l, _ := p.BinInfo().PCToLine(pc)
|
||||||
@ -1770,7 +1770,7 @@ func TestIssue332_Part2(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
regs, err := p.CurrentThread().Registers(false)
|
regs, err := p.CurrentThread().Registers()
|
||||||
assertNoError(err, t, "Registers()")
|
assertNoError(err, t, "Registers()")
|
||||||
pc := regs.PC()
|
pc := regs.PC()
|
||||||
pcAfterPrologue := findFunctionLocation(p, t, "main.changeMe")
|
pcAfterPrologue := findFunctionLocation(p, t, "main.changeMe")
|
||||||
@ -2502,7 +2502,7 @@ func TestStepOnCallPtrInstr(t *testing.T) {
|
|||||||
if ln != 10 {
|
if ln != 10 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
regs, err := p.CurrentThread().Registers(false)
|
regs, err := p.CurrentThread().Registers()
|
||||||
assertNoError(err, t, "Registers()")
|
assertNoError(err, t, "Registers()")
|
||||||
pc := regs.PC()
|
pc := regs.PC()
|
||||||
text, err := proc.Disassemble(p.CurrentThread(), regs, p.Breakpoints(), p.BinInfo(), pc, pc+uint64(p.BinInfo().Arch.MaxInstructionLength()))
|
text, err := proc.Disassemble(p.CurrentThread(), regs, p.Breakpoints(), p.BinInfo(), pc, pc+uint64(p.BinInfo().Arch.MaxInstructionLength()))
|
||||||
@ -3611,7 +3611,7 @@ func TestDisassembleGlobalVars(t *testing.T) {
|
|||||||
}
|
}
|
||||||
withTestProcess("teststepconcurrent", t, func(p *proc.Target, fixture protest.Fixture) {
|
withTestProcess("teststepconcurrent", t, func(p *proc.Target, fixture protest.Fixture) {
|
||||||
mainfn := p.BinInfo().LookupFunc["main.main"]
|
mainfn := p.BinInfo().LookupFunc["main.main"]
|
||||||
regs, _ := p.CurrentThread().Registers(false)
|
regs, _ := p.CurrentThread().Registers()
|
||||||
text, err := proc.Disassemble(p.CurrentThread(), regs, p.Breakpoints(), p.BinInfo(), mainfn.Entry, mainfn.End)
|
text, err := proc.Disassemble(p.CurrentThread(), regs, p.Breakpoints(), p.BinInfo(), mainfn.Entry, mainfn.End)
|
||||||
assertNoError(err, t, "Disassemble")
|
assertNoError(err, t, "Disassemble")
|
||||||
found := false
|
found := false
|
||||||
@ -4168,7 +4168,7 @@ func TestIssue1374(t *testing.T) {
|
|||||||
assertNoError(proc.EvalExpressionWithCalls(p, p.SelectedGoroutine(), "getNum()", normalLoadConfig, true), t, "Call")
|
assertNoError(proc.EvalExpressionWithCalls(p, p.SelectedGoroutine(), "getNum()", normalLoadConfig, true), t, "Call")
|
||||||
err := p.Continue()
|
err := p.Continue()
|
||||||
if _, isexited := err.(proc.ErrProcessExited); !isexited {
|
if _, isexited := err.(proc.ErrProcessExited); !isexited {
|
||||||
regs, _ := p.CurrentThread().Registers(false)
|
regs, _ := p.CurrentThread().Registers()
|
||||||
f, l, _ := p.BinInfo().PCToLine(regs.PC())
|
f, l, _ := p.BinInfo().PCToLine(regs.PC())
|
||||||
t.Fatalf("expected process exited error got %v at %s:%d", err, f, l)
|
t.Fatalf("expected process exited error got %v at %s:%d", err, f, l)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,10 +21,10 @@ type Registers interface {
|
|||||||
// GAddr returns the address of the G variable if it is known, 0 and false otherwise
|
// GAddr returns the address of the G variable if it is known, 0 and false otherwise
|
||||||
GAddr() (uint64, bool)
|
GAddr() (uint64, bool)
|
||||||
Get(int) (uint64, error)
|
Get(int) (uint64, error)
|
||||||
Slice(floatingPoint bool) []Register
|
Slice(floatingPoint bool) ([]Register, error)
|
||||||
// Copy returns a copy of the registers that is guaranteed not to change
|
// Copy returns a copy of the registers that is guaranteed not to change
|
||||||
// when the registers of the associated thread change.
|
// when the registers of the associated thread change.
|
||||||
Copy() Registers
|
Copy() (Registers, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register represents a CPU register.
|
// Register represents a CPU register.
|
||||||
|
|||||||
@ -95,7 +95,7 @@ func (frame *Stackframe) FramePointerOffset() int64 {
|
|||||||
func ThreadStacktrace(thread Thread, depth int) ([]Stackframe, error) {
|
func ThreadStacktrace(thread Thread, depth int) ([]Stackframe, error) {
|
||||||
g, _ := GetG(thread)
|
g, _ := GetG(thread)
|
||||||
if g == nil {
|
if g == nil {
|
||||||
regs, err := thread.Registers(true)
|
regs, err := thread.Registers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -114,7 +114,7 @@ func (g *G) stackIterator(opts StacktraceOptions) (*stackIterator, error) {
|
|||||||
|
|
||||||
bi := g.variable.bi
|
bi := g.variable.bi
|
||||||
if g.Thread != nil {
|
if g.Thread != nil {
|
||||||
regs, err := g.Thread.Registers(true)
|
regs, err := g.Thread.Registers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -456,8 +456,8 @@ func (it *stackIterator) advanceRegs() (callFrameRegs op.DwarfRegisters, ret uin
|
|||||||
}
|
}
|
||||||
|
|
||||||
if it.bi.Arch.Name == "arm64" {
|
if it.bi.Arch.Name == "arm64" {
|
||||||
if ret == 0 && it.regs.Regs[it.regs.LRRegNum] != nil {
|
if ret == 0 && it.regs.Reg(it.regs.LRRegNum) != nil {
|
||||||
ret = it.regs.Regs[it.regs.LRRegNum].Uint64Val
|
ret = it.regs.Reg(it.regs.LRRegNum).Uint64Val
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -666,7 +666,7 @@ func (d *Defer) EvalScope(thread Thread) (*EvalScope, error) {
|
|||||||
// the space occupied by pushing the return address on the stack during the
|
// the space occupied by pushing the return address on the stack during the
|
||||||
// CALL.
|
// CALL.
|
||||||
scope.Regs.CFA = (int64(d.variable.Addr) + d.variable.RealType.Common().ByteSize)
|
scope.Regs.CFA = (int64(d.variable.Addr) + d.variable.RealType.Common().ByteSize)
|
||||||
scope.Regs.Regs[scope.Regs.SPRegNum].Uint64Val = uint64(scope.Regs.CFA - int64(bi.Arch.PtrSize()))
|
scope.Regs.Reg(scope.Regs.SPRegNum).Uint64Val = uint64(scope.Regs.CFA - int64(bi.Arch.PtrSize()))
|
||||||
|
|
||||||
rdr := scope.Fn.cu.image.dwarfReader
|
rdr := scope.Fn.cu.image.dwarfReader
|
||||||
rdr.Seek(scope.Fn.offset)
|
rdr.Seek(scope.Fn.offset)
|
||||||
|
|||||||
@ -230,7 +230,7 @@ func pickCurrentThread(dbp *Target, trapthread Thread, threads []Thread) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func disassembleCurrentInstruction(p Process, thread Thread) ([]AsmInstruction, error) {
|
func disassembleCurrentInstruction(p Process, thread Thread) ([]AsmInstruction, error) {
|
||||||
regs, err := thread.Registers(false)
|
regs, err := thread.Registers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -474,7 +474,7 @@ func next(dbp *Target, stepInto, inlinedStepOut bool) error {
|
|||||||
var regs Registers
|
var regs Registers
|
||||||
if selg != nil && selg.Thread != nil {
|
if selg != nil && selg.Thread != nil {
|
||||||
thread = selg.Thread
|
thread = selg.Thread
|
||||||
regs, err = selg.Thread.Registers(false)
|
regs, err = selg.Thread.Registers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,7 +19,7 @@ type Thread interface {
|
|||||||
// SetPC/SetSP/etc.
|
// SetPC/SetSP/etc.
|
||||||
// To insure that the the returned variable won't change call the Copy
|
// To insure that the the returned variable won't change call the Copy
|
||||||
// method of Registers.
|
// method of Registers.
|
||||||
Registers(floatingPoint bool) (Registers, error)
|
Registers() (Registers, error)
|
||||||
|
|
||||||
// RestoreRegisters restores saved registers
|
// RestoreRegisters restores saved registers
|
||||||
RestoreRegisters(Registers) error
|
RestoreRegisters(Registers) error
|
||||||
|
|||||||
@ -422,7 +422,7 @@ func FindGoroutine(dbp *Target, gid int) (*G, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getGVariable(thread Thread) (*Variable, error) {
|
func getGVariable(thread Thread) (*Variable, error) {
|
||||||
regs, err := thread.Registers(false)
|
regs, err := thread.Registers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,7 +41,7 @@ type AMD64Registers struct {
|
|||||||
|
|
||||||
// NewAMD64Registers creates a new AMD64Registers struct from a CONTEXT
|
// NewAMD64Registers creates a new AMD64Registers struct from a CONTEXT
|
||||||
// struct and the TEB base address of the thread.
|
// struct and the TEB base address of the thread.
|
||||||
func NewAMD64Registers(context *CONTEXT, TebBaseAddress uint64, floatingPoint bool) *AMD64Registers {
|
func NewAMD64Registers(context *CONTEXT, TebBaseAddress uint64) *AMD64Registers {
|
||||||
regs := &AMD64Registers{
|
regs := &AMD64Registers{
|
||||||
rax: uint64(context.Rax),
|
rax: uint64(context.Rax),
|
||||||
rbx: uint64(context.Rbx),
|
rbx: uint64(context.Rbx),
|
||||||
@ -67,16 +67,14 @@ func NewAMD64Registers(context *CONTEXT, TebBaseAddress uint64, floatingPoint bo
|
|||||||
tls: TebBaseAddress,
|
tls: TebBaseAddress,
|
||||||
}
|
}
|
||||||
|
|
||||||
if floatingPoint {
|
regs.fltSave = &context.FltSave
|
||||||
regs.fltSave = &context.FltSave
|
|
||||||
}
|
|
||||||
regs.Context = context
|
regs.Context = context
|
||||||
|
|
||||||
return regs
|
return regs
|
||||||
}
|
}
|
||||||
|
|
||||||
// Slice returns the registers as a list of (name, value) pairs.
|
// Slice returns the registers as a list of (name, value) pairs.
|
||||||
func (r *AMD64Registers) Slice(floatingPoint bool) []proc.Register {
|
func (r *AMD64Registers) Slice(floatingPoint bool) ([]proc.Register, error) {
|
||||||
var regs = []struct {
|
var regs = []struct {
|
||||||
k string
|
k string
|
||||||
v uint64
|
v uint64
|
||||||
@ -134,7 +132,7 @@ func (r *AMD64Registers) Slice(floatingPoint bool) []proc.Register {
|
|||||||
out = proc.AppendBytesRegister(out, fmt.Sprintf("XMM%d", i/16), r.fltSave.XmmRegisters[i:i+16])
|
out = proc.AppendBytesRegister(out, fmt.Sprintf("XMM%d", i/16), r.fltSave.XmmRegisters[i:i+16])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return out
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PC returns the current program counter
|
// PC returns the current program counter
|
||||||
@ -325,13 +323,13 @@ func (r *AMD64Registers) Get(n int) (uint64, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Copy returns a copy of these registers that is guarenteed not to change.
|
// Copy returns a copy of these registers that is guarenteed not to change.
|
||||||
func (r *AMD64Registers) Copy() proc.Registers {
|
func (r *AMD64Registers) Copy() (proc.Registers, error) {
|
||||||
var rr AMD64Registers
|
var rr AMD64Registers
|
||||||
rr = *r
|
rr = *r
|
||||||
rr.Context = NewCONTEXT()
|
rr.Context = NewCONTEXT()
|
||||||
*(rr.Context) = *(r.Context)
|
*(rr.Context) = *(r.Context)
|
||||||
rr.fltSave = &rr.Context.FltSave
|
rr.fltSave = &rr.Context.FltSave
|
||||||
return &rr
|
return &rr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// M128A tracks the _M128A windows struct.
|
// M128A tracks the _M128A windows struct.
|
||||||
|
|||||||
@ -330,8 +330,11 @@ 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))
|
if floatingPoint {
|
||||||
for i := range in.Regs {
|
in.Reg(^uint64(0)) // force loading all registers
|
||||||
|
}
|
||||||
|
out = make([]Register, 0, in.CurrentSize())
|
||||||
|
for i := 0; i < in.CurrentSize(); i++ {
|
||||||
reg := in.Reg(uint64(i))
|
reg := in.Reg(uint64(i))
|
||||||
if reg == nil {
|
if reg == nil {
|
||||||
continue
|
continue
|
||||||
|
|||||||
@ -350,7 +350,7 @@ func (d *Debugger) FunctionReturnLocations(fnName string) ([]uint64, error) {
|
|||||||
var mem proc.MemoryReadWriter = p.CurrentThread()
|
var mem proc.MemoryReadWriter = p.CurrentThread()
|
||||||
if g != nil && g.Thread != nil {
|
if g != nil && g.Thread != nil {
|
||||||
mem = g.Thread
|
mem = g.Thread
|
||||||
regs, _ = g.Thread.Registers(false)
|
regs, _ = g.Thread.Registers()
|
||||||
}
|
}
|
||||||
instructions, err := proc.Disassemble(mem, regs, p.Breakpoints(), p.BinInfo(), fn.Entry, fn.End)
|
instructions, err := proc.Disassemble(mem, regs, p.Breakpoints(), p.BinInfo(), fn.Entry, fn.End)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1159,13 +1159,16 @@ func (d *Debugger) Registers(threadID int, scope *api.EvalScope, floatingPoint b
|
|||||||
if !found {
|
if !found {
|
||||||
return nil, fmt.Errorf("couldn't find thread %d", threadID)
|
return nil, fmt.Errorf("couldn't find thread %d", threadID)
|
||||||
}
|
}
|
||||||
regs, err := thread.Registers(floatingPoint)
|
regs, err := thread.Registers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
dregs = d.target.BinInfo().Arch.RegistersToDwarfRegisters(0, regs)
|
dregs = d.target.BinInfo().Arch.RegistersToDwarfRegisters(0, regs)
|
||||||
}
|
}
|
||||||
r := api.ConvertRegisters(dregs, d.target.BinInfo().Arch, floatingPoint)
|
r := api.ConvertRegisters(dregs, d.target.BinInfo().Arch, floatingPoint)
|
||||||
|
if floatingPoint && dregs.FloatLoadError != nil {
|
||||||
|
return nil, dregs.FloatLoadError
|
||||||
|
}
|
||||||
// Sort the registers in a canonical order we prefer, this is mostly
|
// Sort the registers in a canonical order we prefer, this is mostly
|
||||||
// because the DWARF register numbering for AMD64 is weird.
|
// because the DWARF register numbering for AMD64 is weird.
|
||||||
sort.Slice(r, func(i, j int) bool {
|
sort.Slice(r, func(i, j int) bool {
|
||||||
@ -1488,7 +1491,7 @@ func (d *Debugger) Disassemble(goroutineID int, addr1, addr2 uint64, flavour api
|
|||||||
if g != nil && g.Thread != nil {
|
if g != nil && g.Thread != nil {
|
||||||
curthread = g.Thread
|
curthread = g.Thread
|
||||||
}
|
}
|
||||||
regs, _ := curthread.Registers(false)
|
regs, _ := curthread.Registers()
|
||||||
|
|
||||||
insts, err := proc.Disassemble(curthread, regs, d.target.Breakpoints(), d.target.BinInfo(), addr1, addr2)
|
insts, err := proc.Disassemble(curthread, regs, d.target.Breakpoints(), d.target.BinInfo(), addr1, addr2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@ -1439,7 +1439,7 @@ func setFileBreakpoint(p *proc.Target, t *testing.T, fixture protest.Fixture, li
|
|||||||
}
|
}
|
||||||
|
|
||||||
func currentLocation(p *proc.Target, t *testing.T) (pc uint64, f string, ln int, fn *proc.Function) {
|
func currentLocation(p *proc.Target, t *testing.T) (pc uint64, f string, ln int, fn *proc.Function) {
|
||||||
regs, err := p.CurrentThread().Registers(false)
|
regs, err := p.CurrentThread().Registers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Registers error: %v", err)
|
t.Fatalf("Registers error: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user