diff --git a/proc/proc.go b/proc/proc.go index 1ecafaa3..e821c831 100644 --- a/proc/proc.go +++ b/proc/proc.go @@ -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 diff --git a/proc/proc_test.go b/proc/proc_test.go index 33d0e629..220822f0 100644 --- a/proc/proc_test.go +++ b/proc/proc_test.go @@ -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) diff --git a/service/test/integration_test.go b/service/test/integration_test.go index ea065ab1..b221d199 100644 --- a/service/test/integration_test.go +++ b/service/test/integration_test.go @@ -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") } })