提交 c9cbaea2 编写于 作者: D Derek Parker

Optimize Next implementation

Now that I'm using the step strategy, I put in an optimization where if
stepping into another function, simply find the return address, put a
breakpoint there, and then continue.
上级 2231c0e7
......@@ -157,7 +157,7 @@ func (frame *FrameContext) ExecuteUntilPC(instructions []byte) {
// We only need to execute the instructions until
// ctx.loc > ctx.addess (which is the address we
// are currently at in the traced process).
for frame.loc <= frame.address && frame.buf.Len() > 0 {
for frame.address >= frame.loc && frame.buf.Len() > 0 {
executeDwarfInstruction(frame)
}
// make sure we get the update cfa offset
......
......@@ -289,20 +289,22 @@ func (dbp *DebuggedProcess) Next() error {
loc := dbp.DebugLine.NextLocation(pc, l)
if !fde.AddressRange.Cover(loc.Address) {
addr := dbp.ReturnAddressFromOffset(fde.ReturnAddressOffset(pc))
bp, err := dbp.Break(uintptr(addr))
if err != nil {
if _, ok := err.(BreakPointExistsError); !ok {
return err
// Unconditionally step out of current function
// Don't bother looking up ret addr, next line is
// outside of current fn, should only be a few
// instructions left to RET
for fde.AddressRange.Cover(pc) {
err = dbp.Step()
if err != nil {
return fmt.Errorf("next stepping failed: ", err.Error())
}
}
err = dbp.Continue()
if err != nil {
return err
pc, err = dbp.CurrentPC()
if err != nil {
return err
}
}
return dbp.clearTempBreakpoint(bp.Addr)
return nil
}
for {
......@@ -316,8 +318,10 @@ func (dbp *DebuggedProcess) Next() error {
return err
}
// TODO: if we have stepped into another function,
// find return address and continue there.
if !fde.AddressRange.Cover(pc) {
return dbp.continueToReturnAddress(pc, fde)
}
_, nl, nfn := dbp.GoSymTable.PCToLine(pc)
if nfn == fn && nl != l {
break
......@@ -327,6 +331,35 @@ func (dbp *DebuggedProcess) Next() error {
return nil
}
func (dbp *DebuggedProcess) continueToReturnAddress(pc uint64, fde *frame.FrameDescriptionEntry) error {
for !fde.AddressRange.Cover(pc) {
addr := dbp.ReturnAddressFromOffset(fde.ReturnAddressOffset(pc))
bp, err := dbp.Break(uintptr(addr))
if err != nil {
if _, ok := err.(BreakPointExistsError); !ok {
return err
}
}
err = dbp.Continue()
if err != nil {
return err
}
err = dbp.clearTempBreakpoint(bp.Addr)
if err != nil {
return err
}
pc, err = dbp.CurrentPC()
if err != nil {
return err
}
}
return nil
}
// Continue process until next breakpoint.
func (dbp *DebuggedProcess) Continue() error {
// Stepping first will ensure we are able to continue
......@@ -349,18 +382,18 @@ func (dbp *DebuggedProcess) CurrentPC() (uint64, error) {
}
func (dbp *DebuggedProcess) clearTempBreakpoint(pc uint64) error {
regs, err := dbp.Registers()
if err != nil {
return err
}
_, err = dbp.Clear(pc)
if err != nil {
return err
}
if bp, ok := dbp.PCtoBP(pc); ok {
regs, err := dbp.Registers()
if err != nil {
return err
}
if bp, ok := dbp.PCtoBP(regs.PC() - 1); ok {
// Reset program counter to our restored instruction.
bp, err = dbp.Clear(bp.Addr)
if err != nil {
return err
}
regs.SetPC(bp.Addr)
return syscall.PtraceSetRegs(dbp.Pid, regs)
}
......
......@@ -38,11 +38,11 @@ func currentPC(p *proctl.DebuggedProcess, t *testing.T) uint64 {
return pc
}
func currentLineNumber(p *proctl.DebuggedProcess, t *testing.T) int {
func currentLineNumber(p *proctl.DebuggedProcess, t *testing.T) (string, int) {
pc := currentPC(p, t)
_, l, _ := p.GoSymTable.PCToLine(pc)
f, l, _ := p.GoSymTable.PCToLine(pc)
return l
return f, l
}
func TestAttachProcess(t *testing.T) {
......@@ -158,7 +158,6 @@ func TestClearBreakPoint(t *testing.T) {
func TestNext(t *testing.T) {
var (
ln int
err error
executablePath = "../_fixtures/testnextprog"
)
......@@ -192,16 +191,16 @@ func TestNext(t *testing.T) {
assertNoError(p.Continue(), t, "Continue()")
for _, tc := range testcases {
ln = currentLineNumber(p, t)
f, ln := currentLineNumber(p, t)
if ln != tc.begin {
t.Fatalf("Program not stopped at correct spot expected %d was %d", tc.begin, ln)
t.Fatalf("Program not stopped at correct spot expected %d was %s:%d", tc.begin, f, ln)
}
assertNoError(p.Next(), t, "Next() returned an error")
ln = currentLineNumber(p, t)
f, ln = currentLineNumber(p, t)
if ln != tc.end {
t.Fatalf("Program did not continue to correct next location expected %d was %d", tc.end, ln)
t.Fatalf("Program did not continue to correct next location expected %d was %s:%d", tc.end, f, ln)
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册