diff --git a/_fixtures/testnextprog.go b/_fixtures/testnextprog.go index 05651acb..9334f2d2 100644 --- a/_fixtures/testnextprog.go +++ b/_fixtures/testnextprog.go @@ -37,7 +37,7 @@ func testnext() { func main() { runtime.LockOSThread() for { - sleepytime() + helloworld() testnext() } } diff --git a/dwarf/frame/table_test.go b/dwarf/frame/table_test.go index 839a9092..de8c2c68 100644 --- a/dwarf/frame/table_test.go +++ b/dwarf/frame/table_test.go @@ -56,7 +56,7 @@ func TestFindReturnAddress(t *testing.T) { syscall.PtracePeekText(p.Pid, uintptr(addr), data) addr = binary.LittleEndian.Uint64(data) - expected := uint64(0x400f04) + expected := uint64(0x400ed4) if addr != expected { t.Fatalf("return address not found correctly, expected %#v got %#v", expected, addr) } diff --git a/proctl/proctl_linux_amd64.go b/proctl/proctl_linux_amd64.go index 9f6f4199..22d7f152 100644 --- a/proctl/proctl_linux_amd64.go +++ b/proctl/proctl_linux_amd64.go @@ -140,6 +140,10 @@ func (dbp *DebuggedProcess) Break(addr uintptr) (*BreakPoint, error) { originalData = make([]byte, 1) ) + if fn == nil { + return nil, fmt.Errorf("could not set breakpoint") + } + _, err := syscall.PtracePeekData(dbp.Pid, addr, originalData) if err != nil { return nil, err @@ -280,9 +284,12 @@ func (dbp *DebuggedProcess) Next() error { } if !fde.Cover(pc) { - // We've stepped into a function, keep going. - // TODO: Use DWARF frame info to continue to return address. - continue + err = dbp.continueToReturnAddress(pc, fde) + if err != nil { + return err + } + + pc, _ = dbp.CurrentPC() } _, nl, _ := dbp.GoSymTable.PCToLine(pc) @@ -294,6 +301,47 @@ func (dbp *DebuggedProcess) Next() error { return nil } +func (dbp *DebuggedProcess) continueToReturnAddress(pc uint64, fde *frame.FrameDescriptionEntry) error { + for !fde.Cover(pc) { + // Our offset here is be 0 because we + // have stepped into the first instruction + // of this function. Therefore the function + // has not had a chance to modify its' stack + // and change our offset. + addr := dbp.ReturnAddressFromOffset(0) + bp, err := dbp.Break(uintptr(addr)) + if err != nil { + if _, ok := err.(BreakPointExistsError); !ok { + for !fde.Cover(pc) { + err = dbp.Step() + if err != nil { + return err + } + + pc, err = dbp.CurrentPC() + if err != nil { + return err + } + } + return nil + } + } + + err = dbp.Continue() + if err != nil { + return err + } + err = dbp.clearTempBreakpoint(bp.Addr) + if err != nil { + return err + } + + pc, _ = dbp.CurrentPC() + } + + return nil +} + // Continue process until next breakpoint. func (dbp *DebuggedProcess) Continue() error { // Stepping first will ensure we are able to continue diff --git a/proctl/proctl_test.go b/proctl/proctl_test.go index 23280404..8bb4f9a0 100644 --- a/proctl/proctl_test.go +++ b/proctl/proctl_test.go @@ -2,7 +2,6 @@ package proctl_test import ( "bytes" - "path/filepath" "syscall" "testing"