提交 218c2b95 编写于 作者: D dr2chase 提交者: Derek Parker

proc: Fix stepping into runtime.duff* (#575)

Detect calls that do not target a function's entrypoint
(i.e, calls to runtime.duffzero and runtime.duffcopy) and
instead step into them directly.  StepInto sets a breakpoint
past the called function's prologue and expects that continue
will hit that breakpoint, but because the call is into the
interior of the function (well past the prologue) this fails.

Fixes #573
上级 16f16cf8
package main
// A debugger test.
// dlv debug
// b main.foo
// c
// s
// s
// Expect to be stopped in fmt.Printf or runtime.duffzero
// In bug, s #2 runs to the process exit because the call
// to duffzero enters duffzero well after the nominal entry
// and skips the temporary breakpoint placed by StepZero().
import "fmt"
var v int = 99
func foo(x, y int) (z int) { // c stops here
fmt.Printf("x=%d, y=%d, z=%d\n", x, y, z) // s #1 stops here; s #2 is supposed to stop in Printf or duffzero.
z = x + y
return
}
func main() {
x := v
y := x * x
z := foo(x, y)
fmt.Printf("z=%d\n", z)
}
......@@ -406,7 +406,13 @@ func (dbp *Process) Step() (err error) {
}
text, err := dbp.CurrentThread.Disassemble(pc, pc+maxInstructionLength, true)
if err == nil && len(text) > 0 && text[0].IsCall() && text[0].DestLoc != nil && text[0].DestLoc.Fn != nil {
return dbp.StepInto(text[0].DestLoc.Fn)
fn := text[0].DestLoc.Fn
// Ensure PC and Entry match, otherwise StepInto is likely to set
// its breakpoint before DestLoc.PC and hence run too far ahead.
// Calls to runtime.duffzero and duffcopy have this problem.
if fn.Entry == text[0].DestLoc.PC {
return dbp.StepInto(fn)
}
}
err = dbp.CurrentThread.StepInstruction()
......
......@@ -1881,3 +1881,17 @@ func TestUnsupportedArch(t *testing.T) {
t.Fatal(err)
}
}
func Test1Issue573(t *testing.T) {
// calls to runtime.duffzero and runtime.duffcopy jump directly into the middle
// of the function and the temp breakpoint set by StepInto may be missed.
withTestProcess("issue573", t, func(p *Process, fixture protest.Fixture) {
f := p.goSymTable.LookupFunc("main.foo")
_, err := p.SetBreakpoint(f.Entry)
assertNoError(err, t, "SetBreakpoint()")
assertNoError(p.Continue(), t, "Continue()")
assertNoError(p.Step(), t, "Step() #1")
assertNoError(p.Step(), t, "Step() #2") // Bug exits here.
assertNoError(p.Step(), t, "Step() #3") // Third step ought to be possible; program ought not have exited.
})
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册