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:
parent
a353735715
commit
a0115e3a15
25
proc/proc.go
25
proc/proc.go
@ -172,7 +172,30 @@ func (dbp *Process) FindLocation(str string) (uint64, error) {
|
|||||||
// Try to lookup by function name
|
// Try to lookup by function name
|
||||||
fn := dbp.goSymTable.LookupFunc(str)
|
fn := dbp.goSymTable.LookupFunc(str)
|
||||||
if fn != nil {
|
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
|
// 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) {
|
func TestNextGeneral(t *testing.T) {
|
||||||
testcases := []nextTest{
|
testcases := []nextTest{
|
||||||
{17, 19},
|
|
||||||
{19, 20},
|
{19, 20},
|
||||||
{20, 23},
|
{20, 23},
|
||||||
{23, 24},
|
{23, 24},
|
||||||
@ -299,7 +298,6 @@ func TestNextGeneral(t *testing.T) {
|
|||||||
|
|
||||||
func TestNextGoroutine(t *testing.T) {
|
func TestNextGoroutine(t *testing.T) {
|
||||||
testcases := []nextTest{
|
testcases := []nextTest{
|
||||||
{46, 47},
|
|
||||||
{47, 42},
|
{47, 42},
|
||||||
}
|
}
|
||||||
testnext("testnextprog", testcases, "main.testgoroutine", t)
|
testnext("testnextprog", testcases, "main.testgoroutine", t)
|
||||||
@ -307,7 +305,6 @@ func TestNextGoroutine(t *testing.T) {
|
|||||||
|
|
||||||
func TestNextFunctionReturn(t *testing.T) {
|
func TestNextFunctionReturn(t *testing.T) {
|
||||||
testcases := []nextTest{
|
testcases := []nextTest{
|
||||||
{13, 14},
|
|
||||||
{14, 35},
|
{14, 35},
|
||||||
}
|
}
|
||||||
testnext("testnextprog", testcases, "main.helloworld", t)
|
testnext("testnextprog", testcases, "main.helloworld", t)
|
||||||
|
@ -216,7 +216,6 @@ func testnext(testcases []nextTest, initialLocation string, t *testing.T) {
|
|||||||
|
|
||||||
func TestNextGeneral(t *testing.T) {
|
func TestNextGeneral(t *testing.T) {
|
||||||
testcases := []nextTest{
|
testcases := []nextTest{
|
||||||
{17, 19},
|
|
||||||
{19, 20},
|
{19, 20},
|
||||||
{20, 23},
|
{20, 23},
|
||||||
{23, 24},
|
{23, 24},
|
||||||
@ -237,7 +236,6 @@ func TestNextGeneral(t *testing.T) {
|
|||||||
|
|
||||||
func TestNextGoroutine(t *testing.T) {
|
func TestNextGoroutine(t *testing.T) {
|
||||||
testcases := []nextTest{
|
testcases := []nextTest{
|
||||||
{46, 47},
|
|
||||||
{47, 42},
|
{47, 42},
|
||||||
}
|
}
|
||||||
testnext(testcases, "main.testgoroutine", t)
|
testnext(testcases, "main.testgoroutine", t)
|
||||||
@ -245,7 +243,6 @@ func TestNextGoroutine(t *testing.T) {
|
|||||||
|
|
||||||
func TestNextFunctionReturn(t *testing.T) {
|
func TestNextFunctionReturn(t *testing.T) {
|
||||||
testcases := []nextTest{
|
testcases := []nextTest{
|
||||||
{13, 14},
|
|
||||||
{14, 35},
|
{14, 35},
|
||||||
}
|
}
|
||||||
testnext(testcases, "main.helloworld", t)
|
testnext(testcases, "main.helloworld", t)
|
||||||
@ -285,7 +282,7 @@ func TestClientServer_breakpointInSeparateGoroutine(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
f, l := state.CurrentThread.File, state.CurrentThread.Line
|
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")
|
t.Fatal("Program did not hit breakpoint")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user