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 a87e6cfc1b2fc0..f46a2531ca4ea4 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 e380bb5ad7321f..be0cc3eea7d4f7 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 d87b312b564b5e..e64d275cf3c410 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.