bugfix: Issue #170 (partial) set function breakpoints on the first instruction

the entry point of a function is the beginning of the prologue, which can be run multiple times for each invocation of a function if the stack needs to be expanded or the scheduler needs to be run.
This commit is contained in:
aarzilli 2015-07-10 17:16:03 +02:00 committed by Derek Parker
parent a353735715
commit a0115e3a15
3 changed files with 25 additions and 8 deletions

@ -172,7 +172,30 @@ func (dbp *Process) FindLocation(str string) (uint64, error) {
// Try to lookup by function name
fn := dbp.goSymTable.LookupFunc(str)
if fn != nil {
return fn.Entry, nil
// fn.Entry, the entry point of the function, is always a prologue, the prologue may call into the scheduler or grow the stack,
// this will result in the breakpoint getting hit multiple times without any apparent program progress inbetween.
// In order to avoid this confusing behaviour we try to find the first line of the function and set the breakpoint there.
filename, lineno, _ := dbp.goSymTable.PCToLine(fn.Entry)
var firstLinePC uint64
var err error
for {
lineno++
firstLinePC, _, err = dbp.goSymTable.LineToPC(filename, lineno)
if err == nil {
break
}
if _, unk := err.(*gosym.UnknownLineError); !unk {
return 0, err
}
}
var breakAddr uint64
if firstLinePC < fn.End {
breakAddr = firstLinePC
} else {
breakAddr = fn.Entry
}
return breakAddr, nil
}
// Attempt to parse as number for breakpoint id or raw address

@ -278,7 +278,6 @@ func testnext(program string, testcases []nextTest, initialLocation string, t *t
func TestNextGeneral(t *testing.T) {
testcases := []nextTest{
{17, 19},
{19, 20},
{20, 23},
{23, 24},
@ -299,7 +298,6 @@ func TestNextGeneral(t *testing.T) {
func TestNextGoroutine(t *testing.T) {
testcases := []nextTest{
{46, 47},
{47, 42},
}
testnext("testnextprog", testcases, "main.testgoroutine", t)
@ -307,7 +305,6 @@ func TestNextGoroutine(t *testing.T) {
func TestNextFunctionReturn(t *testing.T) {
testcases := []nextTest{
{13, 14},
{14, 35},
}
testnext("testnextprog", testcases, "main.helloworld", t)

@ -216,7 +216,6 @@ func testnext(testcases []nextTest, initialLocation string, t *testing.T) {
func TestNextGeneral(t *testing.T) {
testcases := []nextTest{
{17, 19},
{19, 20},
{20, 23},
{23, 24},
@ -237,7 +236,6 @@ func TestNextGeneral(t *testing.T) {
func TestNextGoroutine(t *testing.T) {
testcases := []nextTest{
{46, 47},
{47, 42},
}
testnext(testcases, "main.testgoroutine", t)
@ -245,7 +243,6 @@ func TestNextGoroutine(t *testing.T) {
func TestNextFunctionReturn(t *testing.T) {
testcases := []nextTest{
{13, 14},
{14, 35},
}
testnext(testcases, "main.helloworld", t)
@ -285,7 +282,7 @@ func TestClientServer_breakpointInSeparateGoroutine(t *testing.T) {
}
f, l := state.CurrentThread.File, state.CurrentThread.Line
if f != "testthreads.go" && l != 8 {
if f != "testthreads.go" && l != 9 {
t.Fatal("Program did not hit breakpoint")
}
})