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
|
||||
FrameBase int64
|
||||
ObjBase int64
|
||||
Regs []*DwarfRegister
|
||||
regs []*DwarfRegister
|
||||
|
||||
ByteOrder binary.ByteOrder
|
||||
PCRegNum uint64
|
||||
SPRegNum uint64
|
||||
BPRegNum uint64
|
||||
LRRegNum uint64
|
||||
|
||||
FloatLoadError error // error produced when loading floating point registers
|
||||
loadMoreCallback func()
|
||||
}
|
||||
|
||||
type DwarfRegister struct {
|
||||
@ -26,13 +29,38 @@ type DwarfRegister struct {
|
||||
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.
|
||||
func (regs *DwarfRegisters) Uint64Val(idx uint64) uint64 {
|
||||
reg := regs.Reg(idx)
|
||||
if reg == nil {
|
||||
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
|
||||
@ -50,12 +78,26 @@ func (regs *DwarfRegisters) Bytes(idx uint64) []byte {
|
||||
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.
|
||||
func (regs *DwarfRegisters) Reg(idx uint64) *DwarfRegister {
|
||||
if idx >= uint64(len(regs.Regs)) {
|
||||
return nil
|
||||
if idx >= uint64(len(regs.regs)) {
|
||||
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 {
|
||||
@ -72,12 +114,20 @@ func (regs *DwarfRegisters) BP() uint64 {
|
||||
|
||||
// AddReg adds register idx to regs.
|
||||
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)
|
||||
copy(newRegs, regs.Regs)
|
||||
regs.Regs = newRegs
|
||||
copy(newRegs, regs.regs)
|
||||
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 {
|
||||
|
||||
@ -345,21 +345,32 @@ func maxAmd64DwarfRegister() int {
|
||||
}
|
||||
|
||||
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) {
|
||||
if dwarfReg, ok := amd64NameToDwarf[strings.ToLower(reg.Name)]; ok {
|
||||
func initDwarfRegistersFromSlice(maxRegs int, regs Registers, nameToDwarf map[string]int) []*op.DwarfRegister {
|
||||
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
|
||||
}
|
||||
}
|
||||
return dregs
|
||||
}
|
||||
|
||||
return op.DwarfRegisters{
|
||||
StaticBase: staticBase,
|
||||
Regs: dregs,
|
||||
ByteOrder: binary.LittleEndian,
|
||||
PCRegNum: amd64DwarfIPRegNum,
|
||||
SPRegNum: amd64DwarfSPRegNum,
|
||||
BPRegNum: amd64DwarfBPRegNum,
|
||||
func loadMoreDwarfRegistersFromSliceFunc(dr *op.DwarfRegisters, regs Registers, nameToDwarf map[string]int) func() {
|
||||
return func() {
|
||||
regslice, err := regs.Slice(true)
|
||||
dr.FloatLoadError = err
|
||||
for _, reg := range regslice {
|
||||
if dwarfReg, ok := nameToDwarf[strings.ToLower(reg.Name)]; ok {
|
||||
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[amd64DwarfBPRegNum] = op.DwarfRegisterFromUint64(bp)
|
||||
|
||||
return op.DwarfRegisters{
|
||||
StaticBase: staticBase,
|
||||
Regs: dregs,
|
||||
ByteOrder: binary.LittleEndian,
|
||||
PCRegNum: amd64DwarfIPRegNum,
|
||||
SPRegNum: amd64DwarfSPRegNum,
|
||||
BPRegNum: amd64DwarfBPRegNum,
|
||||
}
|
||||
return *op.NewDwarfRegisters(staticBase, dregs, binary.LittleEndian, amd64DwarfIPRegNum, amd64DwarfSPRegNum, amd64DwarfBPRegNum, 0)
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
|
||||
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 {
|
||||
max := int(arm64DwarfIPRegNum)
|
||||
for i := range arm64DwarfToHardware {
|
||||
@ -339,15 +353,9 @@ func arm64RegistersToDwarfRegisters(staticBase uint64, regs Registers) op.DwarfR
|
||||
}
|
||||
}
|
||||
|
||||
return op.DwarfRegisters{
|
||||
StaticBase: staticBase,
|
||||
Regs: dregs,
|
||||
ByteOrder: binary.LittleEndian,
|
||||
PCRegNum: arm64DwarfIPRegNum,
|
||||
SPRegNum: arm64DwarfSPRegNum,
|
||||
BPRegNum: arm64DwarfBPRegNum,
|
||||
LRRegNum: arm64DwarfLRRegNum,
|
||||
}
|
||||
dr := op.NewDwarfRegisters(staticBase, dregs, binary.LittleEndian, arm64DwarfIPRegNum, arm64DwarfSPRegNum, arm64DwarfBPRegNum, arm64DwarfLRRegNum)
|
||||
dr.SetLoadMoreCallback(loadMoreDwarfRegistersFromSliceFunc(dr, regs, arm64NameToDwarf))
|
||||
return *dr
|
||||
}
|
||||
|
||||
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[arm64DwarfLRRegNum] = op.DwarfRegisterFromUint64(lr)
|
||||
|
||||
return op.DwarfRegisters{
|
||||
StaticBase: staticBase,
|
||||
Regs: dregs,
|
||||
ByteOrder: binary.LittleEndian,
|
||||
PCRegNum: arm64DwarfIPRegNum,
|
||||
SPRegNum: arm64DwarfSPRegNum,
|
||||
BPRegNum: arm64DwarfBPRegNum,
|
||||
LRRegNum: arm64DwarfLRRegNum,
|
||||
}
|
||||
return *op.NewDwarfRegisters(staticBase, dregs, binary.LittleEndian, arm64DwarfIPRegNum, arm64DwarfSPRegNum, arm64DwarfBPRegNum, arm64DwarfLRRegNum)
|
||||
}
|
||||
|
||||
func arm64DwarfRegisterToString(i int, reg *op.DwarfRegister) (name string, floatingPoint bool, repr string) {
|
||||
|
||||
@ -170,7 +170,7 @@ type thread struct {
|
||||
}
|
||||
|
||||
type osThread interface {
|
||||
registers(floatingPoint bool) (proc.Registers, error)
|
||||
registers() (proc.Registers, error)
|
||||
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
|
||||
// the value of the instruction pointer register.
|
||||
func (t *thread) Location() (*proc.Location, error) {
|
||||
regs, err := t.th.registers(false)
|
||||
regs, err := t.th.registers()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -303,8 +303,8 @@ func (t *thread) ThreadID() int {
|
||||
}
|
||||
|
||||
// Registers returns the current value of the registers for this thread.
|
||||
func (t *thread) Registers(floatingPoint bool) (proc.Registers, error) {
|
||||
return t.th.registers(floatingPoint)
|
||||
func (t *thread) Registers() (proc.Registers, error) {
|
||||
return t.th.registers()
|
||||
}
|
||||
|
||||
// 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) {
|
||||
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 {
|
||||
continue
|
||||
}
|
||||
@ -250,7 +252,7 @@ func TestCore(t *testing.T) {
|
||||
t.Errorf("main.msg = %q, want %q", msg.Value, "BOOM!")
|
||||
}
|
||||
|
||||
regs, err := p.CurrentThread().Registers(true)
|
||||
regs, err := p.CurrentThread().Registers()
|
||||
if err != nil {
|
||||
t.Fatalf("Couldn't get current thread registers: %v", err)
|
||||
}
|
||||
@ -286,7 +288,7 @@ func TestCoreFpRegisters(t *testing.T) {
|
||||
continue
|
||||
}
|
||||
if frames[i].Current.Fn.Name == "main.main" {
|
||||
regs, err = thread.Registers(true)
|
||||
regs, err = thread.Registers()
|
||||
if err != nil {
|
||||
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 {
|
||||
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)
|
||||
if reg != nil && regname == regtest.name {
|
||||
found = true
|
||||
|
||||
@ -154,21 +154,17 @@ type linuxARM64Thread struct {
|
||||
t *linuxPrStatusARM64
|
||||
}
|
||||
|
||||
func (t *linuxAMD64Thread) registers(floatingPoint bool) (proc.Registers, error) {
|
||||
func (t *linuxAMD64Thread) registers() (proc.Registers, error) {
|
||||
var r linutil.AMD64Registers
|
||||
r.Regs = t.regs.Regs
|
||||
if floatingPoint {
|
||||
r.Fpregs = t.regs.Fpregs
|
||||
}
|
||||
r.Fpregs = t.regs.Fpregs
|
||||
return &r, nil
|
||||
}
|
||||
|
||||
func (t *linuxARM64Thread) registers(floatingPoint bool) (proc.Registers, error) {
|
||||
func (t *linuxARM64Thread) registers() (proc.Registers, error) {
|
||||
var r linutil.ARM64Registers
|
||||
r.Regs = t.regs.Regs
|
||||
if floatingPoint {
|
||||
r.Fpregs = t.regs.Fpregs
|
||||
}
|
||||
r.Fpregs = t.regs.Fpregs
|
||||
return &r, nil
|
||||
}
|
||||
|
||||
|
||||
@ -54,6 +54,6 @@ func (th *windowsAMD64Thread) pid() int {
|
||||
return int(th.th.ID)
|
||||
}
|
||||
|
||||
func (th *windowsAMD64Thread) registers(floatingPoint bool) (proc.Registers, error) {
|
||||
return winutil.NewAMD64Registers(&th.th.Context, th.th.TEB, floatingPoint), nil
|
||||
func (th *windowsAMD64Thread) registers() (proc.Registers, error) {
|
||||
return winutil.NewAMD64Registers(&th.th.Context, th.th.TEB), nil
|
||||
}
|
||||
|
||||
@ -232,7 +232,7 @@ func TestDwarfExprLoclist(t *testing.T) {
|
||||
|
||||
uintExprCheck(t, scope, "a", before)
|
||||
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)
|
||||
}
|
||||
|
||||
|
||||
@ -14,6 +14,12 @@ type AMD64Registers struct {
|
||||
Fpregs []proc.Register
|
||||
Fpregset *AMD64Xstate
|
||||
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
|
||||
@ -49,7 +55,7 @@ type AMD64PtraceRegs struct {
|
||||
}
|
||||
|
||||
// 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 {
|
||||
k string
|
||||
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
|
||||
// "Rflags", but Linux still uses the old name.
|
||||
out = proc.AppendUint64Register(out, "Rflags", uint64(r.Regs.Rflags))
|
||||
var floatLoadError error
|
||||
if floatingPoint {
|
||||
if r.loadFpRegs != nil {
|
||||
floatLoadError = r.loadFpRegs(r)
|
||||
r.loadFpRegs = nil
|
||||
}
|
||||
out = append(out, r.Fpregs...)
|
||||
}
|
||||
return out
|
||||
return out, floatLoadError
|
||||
}
|
||||
|
||||
// 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.
|
||||
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
|
||||
rr.Regs = &AMD64PtraceRegs{}
|
||||
rr.Fpregset = &AMD64Xstate{}
|
||||
@ -314,7 +332,7 @@ func (r *AMD64Registers) Copy() proc.Registers {
|
||||
rr.Fpregs = make([]proc.Register, len(r.Fpregs))
|
||||
copy(rr.Fpregs, r.Fpregs)
|
||||
}
|
||||
return &rr
|
||||
return &rr, nil
|
||||
}
|
||||
|
||||
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
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
regs = regs.Copy()
|
||||
if regs.SP()-256 <= scope.g.stack.lo {
|
||||
return nil, errNotEnoughStack
|
||||
}
|
||||
@ -293,18 +296,13 @@ func evalFunctionCall(scope *EvalScope, node *ast.CallExpr) (*Variable, error) {
|
||||
scope.g = scope.callCtx.doContinue()
|
||||
|
||||
// adjust the value of registers inside scope
|
||||
for regnum := range scope.Regs.Regs {
|
||||
switch uint64(regnum) {
|
||||
case scope.Regs.PCRegNum, scope.Regs.SPRegNum, scope.Regs.BPRegNum:
|
||||
// leave these alone
|
||||
default:
|
||||
// every other register is dirty and unrecoverable
|
||||
scope.Regs.Regs[regnum] = nil
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
pcreg, bpreg, spreg := scope.Regs.Reg(scope.Regs.PCRegNum), scope.Regs.Reg(scope.Regs.BPRegNum), scope.Regs.Reg(scope.Regs.SPRegNum)
|
||||
scope.Regs.ClearRegisters()
|
||||
scope.Regs.AddReg(scope.Regs.PCRegNum, pcreg)
|
||||
scope.Regs.AddReg(scope.Regs.BPRegNum, bpreg)
|
||||
scope.Regs.AddReg(scope.Regs.SPRegNum, spreg)
|
||||
scope.Regs.Reg(scope.Regs.SPRegNum).Uint64Val = uint64(spoff + int64(scope.g.stack.hi))
|
||||
scope.Regs.Reg(scope.Regs.BPRegNum).Uint64Val = uint64(bpoff + int64(scope.g.stack.hi))
|
||||
scope.Regs.FrameBase = fboff + 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()
|
||||
|
||||
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 {
|
||||
fncall.err = err
|
||||
return true
|
||||
}
|
||||
regs = regs.Copy()
|
||||
|
||||
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.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)
|
||||
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.
|
||||
func (t *gdbThread) Location() (*proc.Location, error) {
|
||||
regs, err := t.Registers(false)
|
||||
regs, err := t.Registers()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -1311,7 +1311,7 @@ func (t *gdbThread) ThreadID() int {
|
||||
}
|
||||
|
||||
// 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 err := t.reloadRegisters(); err != nil {
|
||||
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.
|
||||
func (t *gdbThread) Blocked() bool {
|
||||
regs, err := t.Registers(false)
|
||||
regs, err := t.Registers()
|
||||
if err != nil {
|
||||
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
|
||||
// address correctly after hitting a breakpoint.
|
||||
t.clearBreakpointState()
|
||||
regs, err := t.Registers(false)
|
||||
regs, err := t.Registers()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -1865,6 +1865,10 @@ func (regs *gdbRegisters) Get(n int) (uint64, error) {
|
||||
return 0, proc.ErrUnknownRegister
|
||||
}
|
||||
|
||||
func (r *gdbRegisters) FloatLoadError() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetPC will set the value of the PC register to the given value.
|
||||
func (t *gdbThread) SetPC(pc uint64) error {
|
||||
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)
|
||||
}
|
||||
|
||||
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))
|
||||
for _, reginfo := range regs.regsInfo {
|
||||
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:])
|
||||
}
|
||||
}
|
||||
return r
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (regs *gdbRegisters) Copy() proc.Registers {
|
||||
func (regs *gdbRegisters) Copy() (proc.Registers, error) {
|
||||
savedRegs := &gdbRegisters{}
|
||||
savedRegs.init(regs.regsInfo)
|
||||
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 {
|
||||
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) {
|
||||
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,
|
||||
}
|
||||
return *dr
|
||||
}
|
||||
|
||||
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[i386DwarfBPRegNum] = op.DwarfRegisterFromUint64(bp)
|
||||
|
||||
return op.DwarfRegisters{
|
||||
StaticBase: staticBase,
|
||||
Regs: dregs,
|
||||
ByteOrder: binary.LittleEndian,
|
||||
PCRegNum: i386DwarfIPRegNum,
|
||||
SPRegNum: i386DwarfSPRegNum,
|
||||
BPRegNum: i386DwarfBPRegNum,
|
||||
}
|
||||
return *op.NewDwarfRegisters(staticBase, dregs, binary.LittleEndian, i386DwarfIPRegNum, i386DwarfSPRegNum, i386DwarfBPRegNum, 0)
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
default:
|
||||
if reg.Bytes != nil && strings.HasPrefix(name, "xmm") {
|
||||
if reg.Bytes != nil && strings.HasPrefix(n, "xmm") {
|
||||
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)
|
||||
} else if reg.Bytes == nil || (reg.Bytes != nil && len(reg.Bytes) <= 8) {
|
||||
return name, false, fmt.Sprintf("%#016x", reg.Uint64Val)
|
||||
|
||||
@ -16,6 +16,12 @@ type AMD64Registers struct {
|
||||
Regs *AMD64PtraceRegs
|
||||
Fpregs []proc.Register
|
||||
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
|
||||
@ -51,7 +57,7 @@ type AMD64PtraceRegs struct {
|
||||
}
|
||||
|
||||
// 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 {
|
||||
k string
|
||||
v uint64
|
||||
@ -88,10 +94,15 @@ func (r *AMD64Registers) Slice(floatingPoint bool) []proc.Register {
|
||||
for _, reg := range regs {
|
||||
out = proc.AppendUint64Register(out, reg.k, reg.v)
|
||||
}
|
||||
var floatLoadError error
|
||||
if floatingPoint {
|
||||
if r.loadFpRegs != nil {
|
||||
floatLoadError = r.loadFpRegs(r)
|
||||
r.loadFpRegs = nil
|
||||
}
|
||||
out = append(out, r.Fpregs...)
|
||||
}
|
||||
return out
|
||||
return out, floatLoadError
|
||||
}
|
||||
|
||||
// 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.
|
||||
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
|
||||
rr.Regs = &AMD64PtraceRegs{}
|
||||
rr.Fpregset = &AMD64Xstate{}
|
||||
@ -290,7 +308,7 @@ func (r *AMD64Registers) Copy() proc.Registers {
|
||||
rr.Fpregs = make([]proc.Register, len(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
|
||||
|
||||
@ -12,6 +12,12 @@ type ARM64Registers struct {
|
||||
Regs *ARM64PtraceRegs //general-purpose registers
|
||||
Fpregs []proc.Register //Formatted floating point registers
|
||||
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
|
||||
@ -25,7 +31,7 @@ type ARM64PtraceRegs struct {
|
||||
}
|
||||
|
||||
// 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 {
|
||||
k string
|
||||
v uint64
|
||||
@ -69,8 +75,15 @@ func (r *ARM64Registers) Slice(floatingPoint bool) []proc.Register {
|
||||
for _, reg := range regs64 {
|
||||
out = proc.AppendUint64Register(out, reg.k, reg.v)
|
||||
}
|
||||
out = append(out, r.Fpregs...)
|
||||
return out
|
||||
var floatLoadError error
|
||||
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.
|
||||
@ -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.
|
||||
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
|
||||
rr.Regs = &ARM64PtraceRegs{}
|
||||
*(rr.Regs) = *(r.Regs)
|
||||
@ -122,7 +142,7 @@ func (r *ARM64Registers) Copy() proc.Registers {
|
||||
rr.Fpregset = make([]byte, len(r.Fpregset))
|
||||
copy(rr.Fpregset, r.Fpregset)
|
||||
}
|
||||
return &rr
|
||||
return &rr, nil
|
||||
}
|
||||
|
||||
type ARM64PtraceFpRegs struct {
|
||||
|
||||
@ -15,6 +15,12 @@ type I386Registers struct {
|
||||
Fpregs []proc.Register
|
||||
Fpregset *I386Xstate
|
||||
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
|
||||
@ -40,7 +46,7 @@ type I386PtraceRegs struct {
|
||||
}
|
||||
|
||||
// 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 {
|
||||
k string
|
||||
v int32
|
||||
@ -67,10 +73,15 @@ func (r *I386Registers) Slice(floatingPoint bool) []proc.Register {
|
||||
for _, reg := range regs {
|
||||
out = proc.AppendUint64Register(out, reg.k, uint64(uint32(reg.v)))
|
||||
}
|
||||
var floatLoadError error
|
||||
if floatingPoint {
|
||||
if r.loadFpRegs != nil {
|
||||
floatLoadError = r.loadFpRegs(r)
|
||||
r.loadFpRegs = nil
|
||||
}
|
||||
out = append(out, r.Fpregs...)
|
||||
}
|
||||
return out
|
||||
return out, floatLoadError
|
||||
}
|
||||
|
||||
// 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.
|
||||
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
|
||||
rr.Regs = &I386PtraceRegs{}
|
||||
rr.Fpregset = &I386Xstate{}
|
||||
@ -190,7 +208,7 @@ func (r *I386Registers) Copy() proc.Registers {
|
||||
rr.Fpregs = make([]proc.Register, len(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
|
||||
|
||||
@ -104,6 +104,9 @@ func newCompositeMemory(mem MemoryReadWriter, regs op.DwarfRegisters, pieces []o
|
||||
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))
|
||||
}
|
||||
cmem.data = append(cmem.data, reg[:sz]...)
|
||||
|
||||
@ -39,7 +39,7 @@ func killProcess(pid int) error {
|
||||
panic(ErrNativeBackendDisabled)
|
||||
}
|
||||
|
||||
func registers(thread *nativeThread, floatingPoint bool) (proc.Registers, error) {
|
||||
func registers(thread *nativeThread) (proc.Registers, error) {
|
||||
panic(ErrNativeBackendDisabled)
|
||||
}
|
||||
|
||||
|
||||
@ -11,7 +11,7 @@ import (
|
||||
|
||||
// SetPC sets EIP to the value specified by 'pc'.
|
||||
func (thread *nativeThread) SetPC(pc uint64) error {
|
||||
ir, err := registers(thread, false)
|
||||
ir, err := registers(thread)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -24,7 +24,7 @@ func (thread *nativeThread) SetPC(pc uint64) error {
|
||||
// SetSP sets ESP to the value specified by 'sp'
|
||||
func (thread *nativeThread) SetSP(sp uint64) (err error) {
|
||||
var ir proc.Registers
|
||||
ir, err = registers(thread, false)
|
||||
ir, err = registers(thread)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -36,7 +36,7 @@ func (thread *nativeThread) SetSP(sp uint64) (err error) {
|
||||
|
||||
func (thread *nativeThread) SetDX(dx uint64) (err error) {
|
||||
var ir proc.Registers
|
||||
ir, err = registers(thread, false)
|
||||
ir, err = registers(thread)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -46,7 +46,7 @@ func (thread *nativeThread) SetDX(dx uint64) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func registers(thread *nativeThread, floatingPoint bool) (proc.Registers, error) {
|
||||
func registers(thread *nativeThread) (proc.Registers, error) {
|
||||
var (
|
||||
regs linutil.I386PtraceRegs
|
||||
err error
|
||||
@ -55,15 +55,13 @@ func registers(thread *nativeThread, floatingPoint bool) (proc.Registers, error)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r := &linutil.I386Registers{®s, nil, nil, 0}
|
||||
if floatingPoint {
|
||||
r := linutil.NewI386Registers(®s, func(r *linutil.I386Registers) error {
|
||||
var fpregset linutil.I386Xstate
|
||||
r.Fpregs, fpregset, err = thread.fpRegisters()
|
||||
var floatLoadError error
|
||||
r.Fpregs, fpregset, floatLoadError = thread.fpRegisters()
|
||||
r.Fpregset = &fpregset
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return floatLoadError
|
||||
})
|
||||
thread.dbp.execPtraceFunc(func() {
|
||||
tls, _ := ptraceGetTls(regs.Xgs, thread.ThreadID())
|
||||
r.Tls = uint64(tls)
|
||||
|
||||
@ -41,7 +41,7 @@ type Regs struct {
|
||||
fpregs []proc.Register
|
||||
}
|
||||
|
||||
func (r *Regs) Slice(floatingPoint bool) []proc.Register {
|
||||
func (r *Regs) Slice(floatingPoint bool) ([]proc.Register, error) {
|
||||
var regs = []struct {
|
||||
k string
|
||||
v uint64
|
||||
@ -80,7 +80,7 @@ func (r *Regs) Slice(floatingPoint bool) []proc.Register {
|
||||
if floatingPoint {
|
||||
out = append(out, r.fpregs...)
|
||||
}
|
||||
return out
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// PC returns the current program counter
|
||||
@ -285,7 +285,7 @@ func (r *Regs) Get(n int) (uint64, error) {
|
||||
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 identity C.thread_identifier_info_data_t
|
||||
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),
|
||||
}
|
||||
|
||||
if floatingPoint {
|
||||
// https://opensource.apple.com/source/xnu/xnu-792.13.8/osfmk/mach/i386/thread_status.h?txt
|
||||
var fpstate C.x86_float_state64_t
|
||||
kret = C.get_fpu_registers(C.mach_port_name_t(thread.os.threadAct), &fpstate)
|
||||
if kret != C.KERN_SUCCESS {
|
||||
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))
|
||||
}
|
||||
// https://opensource.apple.com/source/xnu/xnu-792.13.8/osfmk/mach/i386/thread_status.h?txt
|
||||
var fpstate C.x86_float_state64_t
|
||||
kret = C.get_fpu_registers(C.mach_port_name_t(thread.os.threadAct), &fpstate)
|
||||
if kret != C.KERN_SUCCESS {
|
||||
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))
|
||||
}
|
||||
|
||||
return regs, nil
|
||||
}
|
||||
|
||||
func (r *Regs) Copy() proc.Registers {
|
||||
func (r *Regs) Copy() (proc.Registers, error) {
|
||||
//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'.
|
||||
func (thread *nativeThread) SetPC(pc uint64) error {
|
||||
ir, err := registers(thread, false)
|
||||
ir, err := registers(thread)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -24,7 +24,7 @@ func (thread *nativeThread) SetPC(pc uint64) error {
|
||||
// SetSP sets RSP to the value specified by 'sp'
|
||||
func (thread *nativeThread) SetSP(sp uint64) (err error) {
|
||||
var ir proc.Registers
|
||||
ir, err = registers(thread, false)
|
||||
ir, err = registers(thread)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -36,7 +36,7 @@ func (thread *nativeThread) SetSP(sp uint64) (err error) {
|
||||
|
||||
func (thread *nativeThread) SetDX(dx uint64) (err error) {
|
||||
var ir proc.Registers
|
||||
ir, err = registers(thread, false)
|
||||
ir, err = registers(thread)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -46,7 +46,7 @@ func (thread *nativeThread) SetDX(dx uint64) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func registers(thread *nativeThread, floatingPoint bool) (proc.Registers, error) {
|
||||
func registers(thread *nativeThread) (proc.Registers, error) {
|
||||
var (
|
||||
regs fbsdutil.AMD64PtraceRegs
|
||||
err error
|
||||
@ -60,15 +60,13 @@ func registers(thread *nativeThread, floatingPoint bool) (proc.Registers, error)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r := &fbsdutil.AMD64Registers{®s, nil, nil, uint64(fsbase)}
|
||||
if floatingPoint {
|
||||
r := fbsdutil.NewAMD64Registers(®s, uint64(fsbase), func(r *fbsdutil.AMD64Registers) error {
|
||||
var fpregset fbsdutil.AMD64Xstate
|
||||
r.Fpregs, fpregset, err = thread.fpRegisters()
|
||||
var floatLoadError error
|
||||
r.Fpregs, fpregset, floatLoadError = thread.fpRegisters()
|
||||
r.Fpregset = &fpregset
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return floatLoadError
|
||||
})
|
||||
return r, nil
|
||||
}
|
||||
|
||||
|
||||
@ -11,7 +11,7 @@ import (
|
||||
|
||||
// SetPC sets RIP to the value specified by 'pc'.
|
||||
func (thread *nativeThread) SetPC(pc uint64) error {
|
||||
ir, err := registers(thread, false)
|
||||
ir, err := registers(thread)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -24,7 +24,7 @@ func (thread *nativeThread) SetPC(pc uint64) error {
|
||||
// SetSP sets RSP to the value specified by 'sp'
|
||||
func (thread *nativeThread) SetSP(sp uint64) (err error) {
|
||||
var ir proc.Registers
|
||||
ir, err = registers(thread, false)
|
||||
ir, err = registers(thread)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -36,7 +36,7 @@ func (thread *nativeThread) SetSP(sp uint64) (err error) {
|
||||
|
||||
func (thread *nativeThread) SetDX(dx uint64) (err error) {
|
||||
var ir proc.Registers
|
||||
ir, err = registers(thread, false)
|
||||
ir, err = registers(thread)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -46,7 +46,7 @@ func (thread *nativeThread) SetDX(dx uint64) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func registers(thread *nativeThread, floatingPoint bool) (proc.Registers, error) {
|
||||
func registers(thread *nativeThread) (proc.Registers, error) {
|
||||
var (
|
||||
regs linutil.AMD64PtraceRegs
|
||||
err error
|
||||
@ -55,15 +55,13 @@ func registers(thread *nativeThread, floatingPoint bool) (proc.Registers, error)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r := &linutil.AMD64Registers{Regs: ®s}
|
||||
if floatingPoint {
|
||||
r := linutil.NewAMD64Registers(®s, func(r *linutil.AMD64Registers) error {
|
||||
var fpregset linutil.AMD64Xstate
|
||||
r.Fpregs, fpregset, err = thread.fpRegisters()
|
||||
var floatLoadError error
|
||||
r.Fpregs, fpregset, floatLoadError = thread.fpRegisters()
|
||||
r.Fpregset = &fpregset
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return floatLoadError
|
||||
})
|
||||
return r, nil
|
||||
}
|
||||
|
||||
|
||||
@ -56,7 +56,7 @@ func ptraceGetFpRegset(tid int) (fpregset []byte, err error) {
|
||||
|
||||
// SetPC sets PC to the value specified by 'pc'.
|
||||
func (thread *nativeThread) SetPC(pc uint64) error {
|
||||
ir, err := registers(thread, false)
|
||||
ir, err := registers(thread)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -69,7 +69,7 @@ func (thread *nativeThread) SetPC(pc uint64) error {
|
||||
// SetSP sets RSP to the value specified by 'sp'
|
||||
func (thread *nativeThread) SetSP(sp uint64) (err error) {
|
||||
var ir proc.Registers
|
||||
ir, err = registers(thread, false)
|
||||
ir, err = registers(thread)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -83,7 +83,7 @@ func (thread *nativeThread) SetDX(dx uint64) (err error) {
|
||||
return fmt.Errorf("not supported")
|
||||
}
|
||||
|
||||
func registers(thread *nativeThread, floatingPoint bool) (proc.Registers, error) {
|
||||
func registers(thread *nativeThread) (proc.Registers, error) {
|
||||
var (
|
||||
regs linutil.ARM64PtraceRegs
|
||||
err error
|
||||
@ -92,12 +92,10 @@ func registers(thread *nativeThread, floatingPoint bool) (proc.Registers, error)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r := &linutil.ARM64Registers{®s, nil, nil}
|
||||
if floatingPoint {
|
||||
r.Fpregs, r.Fpregset, err = thread.fpRegisters()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
r := linutil.NewARM64Registers(®s, func(r *linutil.ARM64Registers) error {
|
||||
var floatLoadError error
|
||||
r.Fpregs, r.Fpregset, floatLoadError = thread.fpRegisters()
|
||||
return floatLoadError
|
||||
})
|
||||
return r, nil
|
||||
}
|
||||
|
||||
@ -52,7 +52,7 @@ func (thread *nativeThread) SetDX(dx uint64) error {
|
||||
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.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 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.
|
||||
func (t *nativeThread) Registers(floatingPoint bool) (proc.Registers, error) {
|
||||
return registers(t, floatingPoint)
|
||||
func (t *nativeThread) Registers() (proc.Registers, error) {
|
||||
return registers(t)
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (t *nativeThread) PC() (uint64, error) {
|
||||
regs, err := t.Registers(false)
|
||||
regs, err := t.Registers()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
@ -87,7 +87,7 @@ func (t *nativeThread) resume() error {
|
||||
|
||||
func (t *nativeThread) Blocked() bool {
|
||||
// TODO(dp) cache the func pc to remove this lookup
|
||||
regs, err := t.Registers(false)
|
||||
regs, err := t.Registers()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
@ -72,7 +72,7 @@ func (t *nativeThread) singleStep() (err error) {
|
||||
}
|
||||
|
||||
func (t *nativeThread) Blocked() bool {
|
||||
regs, err := t.Registers(false)
|
||||
regs, err := t.Registers()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
@ -114,7 +114,7 @@ func (t *nativeThread) resume() error {
|
||||
func (t *nativeThread) Blocked() bool {
|
||||
// TODO: Probably incorrect - what are the runtime functions that
|
||||
// indicate blocking on Windows?
|
||||
regs, err := t.Registers(false)
|
||||
regs, err := t.Registers()
|
||||
if err != nil {
|
||||
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 {
|
||||
regs, err := p.CurrentThread().Registers(false)
|
||||
regs, err := p.CurrentThread().Registers()
|
||||
if err != nil {
|
||||
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 {
|
||||
regs, err := p.CurrentThread().Registers(false)
|
||||
regs, err := p.CurrentThread().Registers()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -280,7 +280,7 @@ func TestBreakpoint(t *testing.T) {
|
||||
bp := setFunctionBreakpoint(p, t, "main.helloworld")
|
||||
assertNoError(p.Continue(), t, "Continue()")
|
||||
|
||||
regs, err := p.CurrentThread().Registers(false)
|
||||
regs, err := p.CurrentThread().Registers()
|
||||
assertNoError(err, t, "Registers")
|
||||
pc := regs.PC()
|
||||
|
||||
@ -302,7 +302,7 @@ func TestBreakpointInSeparateGoRoutine(t *testing.T) {
|
||||
|
||||
assertNoError(p.Continue(), t, "Continue")
|
||||
|
||||
regs, err := p.CurrentThread().Registers(false)
|
||||
regs, err := p.CurrentThread().Registers()
|
||||
assertNoError(err, t, "Registers")
|
||||
pc := regs.PC()
|
||||
|
||||
@ -409,7 +409,7 @@ func testseq2Args(wd string, args []string, buildFlags protest.BuildFlags, t *te
|
||||
if traceTestseq2 {
|
||||
t.Logf("initial breakpoint %v", bp)
|
||||
}
|
||||
regs, err := p.CurrentThread().Registers(false)
|
||||
regs, err := p.CurrentThread().Registers()
|
||||
assertNoError(err, t, "Registers")
|
||||
|
||||
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)
|
||||
regs, _ = p.CurrentThread().Registers(false)
|
||||
regs, _ = p.CurrentThread().Registers()
|
||||
pc := regs.PC()
|
||||
|
||||
if traceTestseq2 {
|
||||
@ -710,7 +710,7 @@ func TestRuntimeBreakpoint(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
regs, err := p.CurrentThread().Registers(false)
|
||||
regs, err := p.CurrentThread().Registers()
|
||||
assertNoError(err, t, "Registers")
|
||||
pc := regs.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()")
|
||||
pc := regs.PC()
|
||||
pcAfterPrologue := findFunctionLocation(p, t, "main.changeMe")
|
||||
@ -2502,7 +2502,7 @@ func TestStepOnCallPtrInstr(t *testing.T) {
|
||||
if ln != 10 {
|
||||
break
|
||||
}
|
||||
regs, err := p.CurrentThread().Registers(false)
|
||||
regs, err := p.CurrentThread().Registers()
|
||||
assertNoError(err, t, "Registers()")
|
||||
pc := regs.PC()
|
||||
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) {
|
||||
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)
|
||||
assertNoError(err, t, "Disassemble")
|
||||
found := false
|
||||
@ -4168,7 +4168,7 @@ func TestIssue1374(t *testing.T) {
|
||||
assertNoError(proc.EvalExpressionWithCalls(p, p.SelectedGoroutine(), "getNum()", normalLoadConfig, true), t, "Call")
|
||||
err := p.Continue()
|
||||
if _, isexited := err.(proc.ErrProcessExited); !isexited {
|
||||
regs, _ := p.CurrentThread().Registers(false)
|
||||
regs, _ := p.CurrentThread().Registers()
|
||||
f, l, _ := p.BinInfo().PCToLine(regs.PC())
|
||||
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() (uint64, bool)
|
||||
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
|
||||
// when the registers of the associated thread change.
|
||||
Copy() Registers
|
||||
Copy() (Registers, error)
|
||||
}
|
||||
|
||||
// Register represents a CPU register.
|
||||
|
||||
@ -95,7 +95,7 @@ func (frame *Stackframe) FramePointerOffset() int64 {
|
||||
func ThreadStacktrace(thread Thread, depth int) ([]Stackframe, error) {
|
||||
g, _ := GetG(thread)
|
||||
if g == nil {
|
||||
regs, err := thread.Registers(true)
|
||||
regs, err := thread.Registers()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -114,7 +114,7 @@ func (g *G) stackIterator(opts StacktraceOptions) (*stackIterator, error) {
|
||||
|
||||
bi := g.variable.bi
|
||||
if g.Thread != nil {
|
||||
regs, err := g.Thread.Registers(true)
|
||||
regs, err := g.Thread.Registers()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -456,8 +456,8 @@ func (it *stackIterator) advanceRegs() (callFrameRegs op.DwarfRegisters, ret uin
|
||||
}
|
||||
|
||||
if it.bi.Arch.Name == "arm64" {
|
||||
if ret == 0 && it.regs.Regs[it.regs.LRRegNum] != nil {
|
||||
ret = it.regs.Regs[it.regs.LRRegNum].Uint64Val
|
||||
if ret == 0 && it.regs.Reg(it.regs.LRRegNum) != nil {
|
||||
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
|
||||
// CALL.
|
||||
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.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) {
|
||||
regs, err := thread.Registers(false)
|
||||
regs, err := thread.Registers()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -474,7 +474,7 @@ func next(dbp *Target, stepInto, inlinedStepOut bool) error {
|
||||
var regs Registers
|
||||
if selg != nil && selg.Thread != nil {
|
||||
thread = selg.Thread
|
||||
regs, err = selg.Thread.Registers(false)
|
||||
regs, err = selg.Thread.Registers()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -19,7 +19,7 @@ type Thread interface {
|
||||
// SetPC/SetSP/etc.
|
||||
// To insure that the the returned variable won't change call the Copy
|
||||
// method of Registers.
|
||||
Registers(floatingPoint bool) (Registers, error)
|
||||
Registers() (Registers, error)
|
||||
|
||||
// RestoreRegisters restores saved registers
|
||||
RestoreRegisters(Registers) error
|
||||
|
||||
@ -422,7 +422,7 @@ func FindGoroutine(dbp *Target, gid int) (*G, error) {
|
||||
}
|
||||
|
||||
func getGVariable(thread Thread) (*Variable, error) {
|
||||
regs, err := thread.Registers(false)
|
||||
regs, err := thread.Registers()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -41,7 +41,7 @@ type AMD64Registers struct {
|
||||
|
||||
// NewAMD64Registers creates a new AMD64Registers struct from a CONTEXT
|
||||
// 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{
|
||||
rax: uint64(context.Rax),
|
||||
rbx: uint64(context.Rbx),
|
||||
@ -67,16 +67,14 @@ func NewAMD64Registers(context *CONTEXT, TebBaseAddress uint64, floatingPoint bo
|
||||
tls: TebBaseAddress,
|
||||
}
|
||||
|
||||
if floatingPoint {
|
||||
regs.fltSave = &context.FltSave
|
||||
}
|
||||
regs.fltSave = &context.FltSave
|
||||
regs.Context = context
|
||||
|
||||
return regs
|
||||
}
|
||||
|
||||
// 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 {
|
||||
k string
|
||||
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])
|
||||
}
|
||||
}
|
||||
return out
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (r *AMD64Registers) Copy() proc.Registers {
|
||||
func (r *AMD64Registers) Copy() (proc.Registers, error) {
|
||||
var rr AMD64Registers
|
||||
rr = *r
|
||||
rr.Context = NewCONTEXT()
|
||||
*(rr.Context) = *(r.Context)
|
||||
rr.fltSave = &rr.Context.FltSave
|
||||
return &rr
|
||||
return &rr, nil
|
||||
}
|
||||
|
||||
// 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.
|
||||
func ConvertRegisters(in op.DwarfRegisters, arch *proc.Arch, floatingPoint bool) (out []Register) {
|
||||
out = make([]Register, 0, len(in.Regs))
|
||||
for i := range in.Regs {
|
||||
if floatingPoint {
|
||||
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))
|
||||
if reg == nil {
|
||||
continue
|
||||
|
||||
@ -350,7 +350,7 @@ func (d *Debugger) FunctionReturnLocations(fnName string) ([]uint64, error) {
|
||||
var mem proc.MemoryReadWriter = p.CurrentThread()
|
||||
if g != nil && g.Thread != nil {
|
||||
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)
|
||||
if err != nil {
|
||||
@ -1159,13 +1159,16 @@ func (d *Debugger) Registers(threadID int, scope *api.EvalScope, floatingPoint b
|
||||
if !found {
|
||||
return nil, fmt.Errorf("couldn't find thread %d", threadID)
|
||||
}
|
||||
regs, err := thread.Registers(floatingPoint)
|
||||
regs, err := thread.Registers()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dregs = d.target.BinInfo().Arch.RegistersToDwarfRegisters(0, regs)
|
||||
}
|
||||
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
|
||||
// because the DWARF register numbering for AMD64 is weird.
|
||||
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 {
|
||||
curthread = g.Thread
|
||||
}
|
||||
regs, _ := curthread.Registers(false)
|
||||
regs, _ := curthread.Registers()
|
||||
|
||||
insts, err := proc.Disassemble(curthread, regs, d.target.Breakpoints(), d.target.BinInfo(), addr1, addr2)
|
||||
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) {
|
||||
regs, err := p.CurrentThread().Registers(false)
|
||||
regs, err := p.CurrentThread().Registers()
|
||||
if err != nil {
|
||||
t.Fatalf("Registers error: %v", err)
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user