diff --git a/_fixtures/issue1817.go b/_fixtures/issue1817.go new file mode 100644 index 0000000000000000000000000000000000000000..0483522b616cfddeb002617ceb8a5946b7dba4b4 --- /dev/null +++ b/_fixtures/issue1817.go @@ -0,0 +1,23 @@ +package main + +import ( + "fmt" + "runtime" + "unsafe" +) + +func main() { + l := int(51) + bs := make([]byte, l) + for i := 0; i < l; i++ { + bs[i] = byte(i + int(10)) + } + + p := uintptr(unsafe.Pointer(&bs)) + + fmt.Println(p) + + bs[0] = 254 + + runtime.KeepAlive(bs) +} diff --git a/pkg/dwarf/line/state_machine.go b/pkg/dwarf/line/state_machine.go index 1b841a3f303fd2eaee1912c05a302dabd2ec1ff4..d83d14221eccaedc778ed179a581c28bbfd7f9a7 100644 --- a/pkg/dwarf/line/state_machine.go +++ b/pkg/dwarf/line/state_machine.go @@ -313,13 +313,19 @@ func (lineInfo *DebugLineInfo) LineToPCIn(filename string, lineno int, basePC, s sm := lineInfo.stateMachineFor(basePC, startPC) + var fallbackPC uint64 + for { if sm.valid && sm.started { if sm.address >= endPC { - return 0 + break } - if sm.line == lineno && sm.file == filename && sm.address >= startPC && sm.isStmt { - return sm.address + if sm.line == lineno && sm.file == filename && sm.address >= startPC { + if sm.isStmt { + return sm.address + } else { + fallbackPC = sm.address + } } } if err := sm.next(); err != nil { @@ -331,7 +337,7 @@ func (lineInfo *DebugLineInfo) LineToPCIn(filename string, lineno int, basePC, s } - return 0 + return fallbackPC } // PrologueEndPC returns the first PC address marked as prologue_end in the half open interval [start, end) diff --git a/pkg/proc/proc_test.go b/pkg/proc/proc_test.go index e2f2e606cd6c2fca9ce9a454af229d28f8720bea..bd8c2ccd2adfb1d588be52c70181593be58ce57d 100644 --- a/pkg/proc/proc_test.go +++ b/pkg/proc/proc_test.go @@ -199,7 +199,7 @@ func setFileBreakpoint(p proc.Process, t *testing.T, path string, lineno int) *p t.Fatalf("%s:%d: FindFileLocation(%s, %d): %v", f, l, path, lineno, err) } if len(addrs) != 1 { - t.Fatalf("%s:%d: setFileLineBreakpoint(%s, %d): too many results %v", f, l, path, lineno, addrs) + t.Fatalf("%s:%d: setFileLineBreakpoint(%s, %d): too many (or not enough) results %v", f, l, path, lineno, addrs) } bp, err := p.SetBreakpoint(addrs[0], proc.UserBreakpoint, nil) if err != nil { @@ -4517,3 +4517,11 @@ func TestIssue1736(t *testing.T) { } }) } + +func TestIssue1817(t *testing.T) { + // Setting a breakpoint on a line that doesn't have any PC addresses marked + // is_stmt should work. + withTestProcess("issue1817", t, func(p proc.Process, fixture protest.Fixture) { + setFileBreakpoint(p, t, fixture.Source, 16) + }) +}