diff --git a/pkg/proc/core/core.go b/pkg/proc/core/core.go index d181387a..3d0ef859 100644 --- a/pkg/proc/core/core.go +++ b/pkg/proc/core/core.go @@ -319,18 +319,6 @@ func (t *thread) ProcessMemory() proc.MemoryReadWriter { return t.p } -// 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.Registers() - if err != nil { - return nil, err - } - pc := regs.PC() - f, l, fn := t.p.bi.PCToLine(pc) - return &proc.Location{PC: pc, File: f, Line: l, Fn: fn}, nil -} - // Breakpoint returns the current breakpoint this thread is stopped at. // For core files this always returns an empty BreakpointState struct, as // there are no breakpoints when debugging core files. diff --git a/pkg/proc/fncall.go b/pkg/proc/fncall.go index 9b4f8c85..856d8b05 100644 --- a/pkg/proc/fncall.go +++ b/pkg/proc/fncall.go @@ -815,7 +815,7 @@ func funcCallStep(callScope *EvalScope, stack *evalStack, thread Thread) bool { regval := bi.Arch.RegistersToDwarfRegisters(0, regs).Uint64Val(fncall.protocolReg) if logflags.FnCall() { - loc, _ := thread.Location() + loc, _ := ThreadLocation(thread) var pc uint64 var fnname string if loc != nil { @@ -1151,7 +1151,7 @@ func callInjectionProtocol(t *Target, trapthread Thread, threads []Thread) (done t.currentThread = currentThread }() for _, thread := range threads { - loc, err := thread.Location() + loc, err := ThreadLocation(thread) if err != nil { continue } diff --git a/pkg/proc/gdbserial/gdbserver.go b/pkg/proc/gdbserial/gdbserver.go index 35d7091d..b58d0387 100644 --- a/pkg/proc/gdbserial/gdbserver.go +++ b/pkg/proc/gdbserial/gdbserver.go @@ -1523,22 +1523,6 @@ func (t *gdbThread) ProcessMemory() proc.MemoryReadWriter { return t.p } -// Location returns the current location of this thread. -func (t *gdbThread) Location() (*proc.Location, error) { - regs, err := t.Registers() - if err != nil { - return nil, err - } - if pcreg, ok := regs.(*gdbRegisters).regs[regs.(*gdbRegisters).regnames.PC]; !ok { - t.p.conn.log.Errorf("thread %d could not find RIP register", t.ID) - } else if len(pcreg.value) < t.p.bi.Arch.PtrSize() { - t.p.conn.log.Errorf("thread %d bad length for RIP register: %d", t.ID, len(pcreg.value)) - } - pc := regs.PC() - f, l, fn := t.p.bi.PCToLine(pc) - return &proc.Location{PC: pc, File: f, Line: l, Fn: fn}, nil -} - // Breakpoint returns the current active breakpoint for this thread. func (t *gdbThread) Breakpoint() *proc.BreakpointState { return &t.CurrentBreakpoint diff --git a/pkg/proc/gdbserial/rr_test.go b/pkg/proc/gdbserial/rr_test.go index 3dc3d1e2..23fdd6dd 100644 --- a/pkg/proc/gdbserial/rr_test.go +++ b/pkg/proc/gdbserial/rr_test.go @@ -73,7 +73,7 @@ func TestRestartAfterExit(t *testing.T) { p := grp.Selected setFunctionBreakpoint(p, t, "main.main") assertNoError(grp.Continue(), t, "Continue") - loc, err := p.CurrentThread().Location() + loc, err := proc.ThreadLocation(p.CurrentThread()) assertNoError(err, t, "CurrentThread().Location()") err = grp.Continue() if !errors.As(err, &proc.ErrProcessExited{}) { @@ -83,7 +83,7 @@ func TestRestartAfterExit(t *testing.T) { assertNoError(grp.Restart(""), t, "Restart") assertNoError(grp.Continue(), t, "Continue (after restart)") - loc2, err := p.CurrentThread().Location() + loc2, err := proc.ThreadLocation(p.CurrentThread()) assertNoError(err, t, "CurrentThread().Location() (after restart)") if loc2.Line != loc.Line { t.Fatalf("stopped at %d (expected %d)", loc2.Line, loc.Line) @@ -101,13 +101,13 @@ func TestRestartDuringStop(t *testing.T) { p := grp.Selected setFunctionBreakpoint(p, t, "main.main") assertNoError(grp.Continue(), t, "Continue") - loc, err := p.CurrentThread().Location() + loc, err := proc.ThreadLocation(p.CurrentThread()) assertNoError(err, t, "CurrentThread().Location()") assertNoError(grp.Restart(""), t, "Restart") assertNoError(grp.Continue(), t, "Continue (after restart)") - loc2, err := p.CurrentThread().Location() + loc2, err := proc.ThreadLocation(p.CurrentThread()) assertNoError(err, t, "CurrentThread().Location() (after restart)") if loc2.Line != loc.Line { t.Fatalf("stopped at %d (expected %d)", loc2.Line, loc.Line) @@ -143,7 +143,7 @@ func TestReverseBreakpointCounts(t *testing.T) { p := grp.Selected endbp := setFileBreakpoint(p, t, fixture, 28) assertNoError(grp.Continue(), t, "Continue()") - loc, _ := p.CurrentThread().Location() + loc, _ := proc.ThreadLocation(p.CurrentThread()) if loc.PC != endbp.Addr { t.Fatalf("did not reach end of main.main function: %s:%d (%#x)", loc.File, loc.Line, loc.PC) } @@ -156,7 +156,7 @@ func TestReverseBreakpointCounts(t *testing.T) { countLoop: for { assertNoError(grp.Continue(), t, "Continue()") - loc, _ := p.CurrentThread().Location() + loc, _ := proc.ThreadLocation(p.CurrentThread()) switch loc.PC { case startbp.Addr: break countLoop @@ -188,7 +188,7 @@ func getPosition(grp *proc.TargetGroup, t *testing.T) (when string, loc *proc.Lo var err error when, err = grp.When() assertNoError(err, t, "When") - loc, err = grp.Selected.CurrentThread().Location() + loc, err = proc.ThreadLocation(grp.Selected.CurrentThread()) assertNoError(err, t, "Location") return } diff --git a/pkg/proc/native/threads.go b/pkg/proc/native/threads.go index daf38d71..56ae4529 100644 --- a/pkg/proc/native/threads.go +++ b/pkg/proc/native/threads.go @@ -77,18 +77,6 @@ func (procgrp *processGroup) stepInstruction(t *nativeThread) (err error) { return nil } -// Location returns the threads location, including the file:line -// of the corresponding source code, the function we're in -// and the current instruction address. -func (t *nativeThread) Location() (*proc.Location, error) { - pc, err := t.PC() - if err != nil { - return nil, err - } - f, l, fn := t.dbp.bi.PCToLine(pc) - return &proc.Location{PC: pc, File: f, Line: l, Fn: fn}, nil -} - // BinInfo returns information on the binary. func (t *nativeThread) BinInfo() *proc.BinaryInfo { return t.dbp.bi diff --git a/pkg/proc/proc_test.go b/pkg/proc/proc_test.go index 9ecfec7e..e8de4107 100644 --- a/pkg/proc/proc_test.go +++ b/pkg/proc/proc_test.go @@ -1627,7 +1627,7 @@ func TestStepIntoFunction(t *testing.T) { // Step into function assertNoError(grp.Step(), t, "Step() returned an error") // We should now be inside the function. - loc, err := p.CurrentThread().Location() + loc, err := proc.ThreadLocation(p.CurrentThread()) if err != nil { t.Fatal(err) } @@ -2462,7 +2462,7 @@ func TestNextInDeferReturn(t *testing.T) { // point where the target program panics. setFunctionBreakpoint(p, t, "main.sampleFunction") for i := 0; i < 20; i++ { - loc, err := p.CurrentThread().Location() + loc, err := proc.ThreadLocation(p.CurrentThread()) assertNoError(err, t, "CurrentThread().Location()") t.Logf("at %#x %s:%d", loc.PC, loc.File, loc.Line) if loc.Fn != nil && loc.Fn.Name == "main.sampleFunction" { @@ -3184,7 +3184,7 @@ func TestIssue1008(t *testing.T) { withTestProcess("cgostacktest/", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { setFunctionBreakpoint(p, t, "main.main") assertNoError(grp.Continue(), t, "Continue()") - loc, err := p.CurrentThread().Location() + loc, err := proc.ThreadLocation(p.CurrentThread()) assertNoError(err, t, "CurrentThread().Location()") t.Logf("location %v\n", loc) if !strings.HasSuffix(loc.File, "/main.go") { @@ -5176,7 +5176,7 @@ func TestFollowExec(t *testing.T) { if grp.Selected.CurrentThread().Breakpoint().Breakpoint.LogicalID() != 1 { t.Fatalf("wrong breakpoint %#v", grp.Selected.CurrentThread().Breakpoint().Breakpoint) } - loc, err := grp.Selected.CurrentThread().Location() + loc, err := proc.ThreadLocation(grp.Selected.CurrentThread()) assertNoError(err, t, "Location") if loc.Fn.Name != "main.traceme1" { t.Fatalf("wrong stop location %#v", loc) @@ -5188,7 +5188,7 @@ func TestFollowExec(t *testing.T) { if p.CurrentThread().Breakpoint().Breakpoint.LogicalID() != 3 { t.Fatalf("wrong breakpoint %#v", p.CurrentThread().Breakpoint().Breakpoint) } - loc, err := p.CurrentThread().Location() + loc, err := proc.ThreadLocation(p.CurrentThread()) assertNoError(err, t, "Location") if loc.Fn.Name != "main.traceme3" { t.Fatalf("wrong stop location %#v", loc) @@ -5208,7 +5208,7 @@ func TestFollowExec(t *testing.T) { t.Fatalf("wrong breakpoint %#v", grp.Selected.CurrentThread().Breakpoint().Breakpoint) } pids[tgt.Pid()]++ - loc, err := tgt.CurrentThread().Location() + loc, err := proc.ThreadLocation(tgt.CurrentThread()) assertNoError(err, t, "Location") if loc.Fn.Name != "main.traceme2" { t.Fatalf("wrong stop location %#v", loc) @@ -5268,7 +5268,7 @@ func TestStepShadowConcurrentBreakpoint(t *testing.T) { for { t.Logf("stop (%d %d):", stacktraceme1calls, stacktraceme2calls) for _, th := range p.ThreadList() { - loc, _ := th.Location() + loc, _ := proc.ThreadLocation(th) t.Logf("\t%s:%d\n", loc.File, loc.Line) bp := th.Breakpoint().Breakpoint if bp != nil && bp.Addr == break2.Addr { diff --git a/pkg/proc/target_exec.go b/pkg/proc/target_exec.go index dc716457..8839279a 100644 --- a/pkg/proc/target_exec.go +++ b/pkg/proc/target_exec.go @@ -444,7 +444,7 @@ func stepInstructionOut(grp *TargetGroup, dbp *Target, curthread Thread, fnname1 if err := grp.procgrp.StepInstruction(curthread.ThreadID()); err != nil { return err } - loc, err := curthread.Location() + loc, err := ThreadLocation(curthread) var locFnName string if loc.Fn != nil && !loc.Fn.cu.image.Stripped() { locFnName = loc.Fn.Name @@ -995,7 +995,7 @@ func stepIntoCallback(curthread Thread, p *Target) (bool, error) { } var fn *Function - if loc, _ := curthread.Location(); loc != nil { + if loc, _ := ThreadLocation(curthread); loc != nil { fn = loc.Fn } g, _ := GetG(curthread) @@ -1675,7 +1675,7 @@ func (t *Target) handleHardcodedBreakpoints(grp *TargetGroup, trapthread Thread, continue } - loc, err := thread.Location() + loc, err := ThreadLocation(thread) if err != nil || loc.Fn == nil { continue } diff --git a/pkg/proc/threads.go b/pkg/proc/threads.go index d349c30a..4fb78b3b 100644 --- a/pkg/proc/threads.go +++ b/pkg/proc/threads.go @@ -8,7 +8,6 @@ import ( // Thread represents a thread. type Thread interface { - Location() (*Location, error) // Breakpoint will return the breakpoint that this thread is stopped at or // nil if the thread is not stopped at any breakpoint. Breakpoint() *BreakpointState @@ -103,3 +102,16 @@ func setClosureReg(thread Thread, newClosureReg uint64) error { func setLR(thread Thread, newLR uint64) error { return thread.SetReg(thread.BinInfo().Arch.LRRegNum, op.DwarfRegisterFromUint64(newLR)) } + +// ThreadLocation returns the threads location, including the file:line +// of the corresponding source code, the function we're in +// and the current instruction address. +func ThreadLocation(thread Thread) (*Location, error) { + regs, err := thread.Registers() + if err != nil { + return nil, err + } + pc := regs.PC() + f, l, fn := thread.BinInfo().PCToLine(pc) + return &Location{PC: pc, File: f, Line: l, Fn: fn}, nil +} diff --git a/pkg/proc/variables.go b/pkg/proc/variables.go index 6be6c1e3..cf75d3f1 100644 --- a/pkg/proc/variables.go +++ b/pkg/proc/variables.go @@ -257,7 +257,8 @@ func GetG(thread Thread) (*G, error) { if thread.Common().g != nil { return thread.Common().g, nil } - if loc, _ := thread.Location(); loc != nil && loc.Fn != nil && loc.Fn.Name == "runtime.clone" { + loc, _ := ThreadLocation(thread) + if loc != nil && loc.Fn != nil && loc.Fn.Name == "runtime.clone" { // When threads are executing runtime.clone the value of TLS is unreliable. return nil, nil } @@ -296,7 +297,7 @@ func GetG(thread Thread) (*G, error) { g.SystemStack = true } g.Thread = thread - if loc, err := thread.Location(); err == nil { + if err == nil { g.CurrentLoc = *loc } thread.Common().g = g @@ -354,7 +355,7 @@ func GoroutinesInfo(dbp *Target, start, count int) ([]*G, int, error) { continue } if thg, allocated := threadg[g.ID]; allocated { - loc, err := thg.Thread.Location() + loc, err := ThreadLocation(thg.Thread) if err != nil { return nil, -1, err } diff --git a/pkg/proc/variables_fuzz_test.go b/pkg/proc/variables_fuzz_test.go index 9f7aac1b..6431981d 100644 --- a/pkg/proc/variables_fuzz_test.go +++ b/pkg/proc/variables_fuzz_test.go @@ -136,7 +136,7 @@ func doFuzzEvalExpressionSetup(f *testing.F) { assertNoError(err, f, "Stacktrace") mem := c.Memory() - loc, _ := c.CurrentThread().Location() + loc, _ := proc.ThreadLocation(c.CurrentThread()) tmem := &tracingMem{make(map[uint64]int), mem} scope := &proc.EvalScope{Location: *loc, Regs: frames[0].Regs, Mem: tmem, BinInfo: c.BinInfo()} diff --git a/service/api/conversions.go b/service/api/conversions.go index fb90e414..14bf025a 100644 --- a/service/api/conversions.go +++ b/service/api/conversions.go @@ -97,7 +97,7 @@ func ConvertThread(th proc.Thread, bp *Breakpoint) *Thread { gid int64 ) - loc, err := th.Location() + loc, err := proc.ThreadLocation(th) if err == nil { pc = loc.PC file = loc.File diff --git a/service/debugger/debugger.go b/service/debugger/debugger.go index d99c22d9..ba73428c 100644 --- a/service/debugger/debugger.go +++ b/service/debugger/debugger.go @@ -1893,7 +1893,7 @@ func (d *Debugger) CurrentPackage() (string, error) { if _, err := d.target.Valid(); err != nil { return "", err } - loc, err := d.target.Selected.CurrentThread().Location() + loc, err := proc.ThreadLocation(d.target.Selected.CurrentThread()) if err != nil { return "", err } @@ -2231,7 +2231,7 @@ func (d *Debugger) TargetGroup() *proc.TargetGroup { } func (d *Debugger) BuildID() string { - loc, err := d.target.Selected.CurrentThread().Location() + loc, err := proc.ThreadLocation(d.target.Selected.CurrentThread()) if err != nil { return "" }