From 7f5f1787eff2b4c06dfafc92f6e00f75c9852aa8 Mon Sep 17 00:00:00 2001 From: Frederic Branczyk Date: Sat, 4 Mar 2023 18:03:42 +0100 Subject: [PATCH] debug/gosym: read start line of a function from gopclntab This field was introduced in go 1.20 therefore we need to safeguard it to only be read for pclntabs of that version or higher, as otherwise nonsensical bytes would be read. The fallback is now the default value of 0. Fixes #58474 --- src/debug/gosym/pclntab.go | 7 +++++++ src/debug/gosym/pclntab_test.go | 18 ++++++++++++++++++ src/debug/gosym/symtab.go | 1 + 3 files changed, 26 insertions(+) diff --git a/src/debug/gosym/pclntab.go b/src/debug/gosym/pclntab.go index a87e6cfc1b..f46a2531ca 100644 --- a/src/debug/gosym/pclntab.go +++ b/src/debug/gosym/pclntab.go @@ -301,6 +301,9 @@ func (t *LineTable) go12Funcs() []Func { }() } + // The start line only exists in pclntab starting at version 1.20. + readStartLine := t.version >= ver120 + ft := t.funcTab() funcs := make([]Func, ft.Count()) syms := make([]Sym, len(funcs)) @@ -309,6 +312,9 @@ func (t *LineTable) go12Funcs() []Func { f.Entry = ft.pc(i) f.End = ft.pc(i + 1) info := t.funcData(uint32(i)) + if readStartLine { + f.StartLine = int(info.startLine()) + } f.LineTable = t f.FrameSize = int(info.deferreturn()) syms[i] = Sym{ @@ -461,6 +467,7 @@ func (f funcData) deferreturn() uint32 { return f.field(3) } func (f funcData) pcfile() uint32 { return f.field(5) } func (f funcData) pcln() uint32 { return f.field(6) } func (f funcData) cuOffset() uint32 { return f.field(8) } +func (f funcData) startLine() uint32 { return f.field(9) } // field returns the nth field of the _func struct. // It panics if n == 0 or n > 9; for n == 0, call f.entryPC. diff --git a/src/debug/gosym/pclntab_test.go b/src/debug/gosym/pclntab_test.go index e380bb5ad7..be0cc3eea7 100644 --- a/src/debug/gosym/pclntab_test.go +++ b/src/debug/gosym/pclntab_test.go @@ -201,6 +201,24 @@ func TestLineAline(t *testing.T) { } } +func TestStartLine(t *testing.T) { + dotest(t) + defer endtest() + + f, tab := crack(pclinetestBinary, t) + defer f.Close() + + sym := tab.LookupFunc("main.main") + wantLine := 6 + if sym == nil { + t.Fatal("no main.main") + } + + if sym.StartLine != wantLine { + t.Fatalf("StartLine = %d, want %d", sym.StartLine, wantLine) + } +} + func TestPCLine(t *testing.T) { dotest(t) defer endtest() diff --git a/src/debug/gosym/symtab.go b/src/debug/gosym/symtab.go index d87b312b56..e64d275cf3 100644 --- a/src/debug/gosym/symtab.go +++ b/src/debug/gosym/symtab.go @@ -137,6 +137,7 @@ type Func struct { FrameSize int LineTable *LineTable Obj *Obj + StartLine int } // An Obj represents a collection of functions in a symbol table.