mirror of
https://github.com/go-delve/delve.git
synced 2025-10-27 20:23:41 +08:00
Optimize Next implementation
Once the program detects that we have stepped into another function, we simply calculate the return address and then set a breakpoint and continue to that location, avoiding numerous syscalls.
This commit is contained in:
@ -37,7 +37,7 @@ func testnext() {
|
||||
func main() {
|
||||
runtime.LockOSThread()
|
||||
for {
|
||||
sleepytime()
|
||||
helloworld()
|
||||
testnext()
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -2,7 +2,6 @@ package proctl_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
"testing"
|
||||
|
||||
Reference in New Issue
Block a user