mirror of
https://github.com/go-delve/delve.git
synced 2025-10-27 12:05:21 +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() {
|
func main() {
|
||||||
runtime.LockOSThread()
|
runtime.LockOSThread()
|
||||||
for {
|
for {
|
||||||
sleepytime()
|
helloworld()
|
||||||
testnext()
|
testnext()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -56,7 +56,7 @@ func TestFindReturnAddress(t *testing.T) {
|
|||||||
syscall.PtracePeekText(p.Pid, uintptr(addr), data)
|
syscall.PtracePeekText(p.Pid, uintptr(addr), data)
|
||||||
addr = binary.LittleEndian.Uint64(data)
|
addr = binary.LittleEndian.Uint64(data)
|
||||||
|
|
||||||
expected := uint64(0x400f04)
|
expected := uint64(0x400ed4)
|
||||||
if addr != expected {
|
if addr != expected {
|
||||||
t.Fatalf("return address not found correctly, expected %#v got %#v", expected, addr)
|
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)
|
originalData = make([]byte, 1)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if fn == nil {
|
||||||
|
return nil, fmt.Errorf("could not set breakpoint")
|
||||||
|
}
|
||||||
|
|
||||||
_, err := syscall.PtracePeekData(dbp.Pid, addr, originalData)
|
_, err := syscall.PtracePeekData(dbp.Pid, addr, originalData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -280,9 +284,12 @@ func (dbp *DebuggedProcess) Next() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !fde.Cover(pc) {
|
if !fde.Cover(pc) {
|
||||||
// We've stepped into a function, keep going.
|
err = dbp.continueToReturnAddress(pc, fde)
|
||||||
// TODO: Use DWARF frame info to continue to return address.
|
if err != nil {
|
||||||
continue
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
pc, _ = dbp.CurrentPC()
|
||||||
}
|
}
|
||||||
|
|
||||||
_, nl, _ := dbp.GoSymTable.PCToLine(pc)
|
_, nl, _ := dbp.GoSymTable.PCToLine(pc)
|
||||||
@ -294,6 +301,47 @@ func (dbp *DebuggedProcess) Next() error {
|
|||||||
return nil
|
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.
|
// Continue process until next breakpoint.
|
||||||
func (dbp *DebuggedProcess) Continue() error {
|
func (dbp *DebuggedProcess) Continue() error {
|
||||||
// Stepping first will ensure we are able to continue
|
// Stepping first will ensure we are able to continue
|
||||||
|
|||||||
@ -2,7 +2,6 @@ package proctl_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"syscall"
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
|
|||||||
Reference in New Issue
Block a user