cmd/link: fix trampolines breaking DWARF line info

When trampolines are needed (e.g. Darwin ARM64), the DWARF LPT (Line
Program Table - see DWARF section 6.1) generation fails because the
replacement symbols are marked as external symbols and skipped during
the DWARF LPT generation phase.

Fixes #54320

Change-Id: I6c93f5378f50e5edf30d5121402a48214abb1ce2
GitHub-Last-Rev: 085bbc55db
GitHub-Pull-Request: golang/go#54321
Reviewed-on: https://go-review.googlesource.com/c/go/+/422154
Reviewed-by: Cherry Mui <cherryyz@google.com>
Run-TryBot: Than McIntosh <thanm@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
Jeremy Quirke 2022-08-09 17:20:33 +00:00 committed by Than McIntosh
parent a1337ef40c
commit 2340d37179
2 changed files with 81 additions and 7 deletions

View file

@ -1842,3 +1842,82 @@ func main() {
}
}
}
func TestIssue54320(t *testing.T) {
// Check that when trampolines are used, the DWARF LPT is correctly
// emitted in the final binary
testenv.MustHaveGoBuild(t)
if runtime.GOOS == "plan9" {
t.Skip("skipping on plan9; no DWARF symbol table in executables")
}
t.Parallel()
const prog = `
package main
import "fmt"
func main() {
fmt.Printf("Hello world\n");
}
`
dir := t.TempDir()
f := gobuild(t, dir, prog, "-ldflags=-debugtramp=2")
defer f.Close()
d, err := f.DWARF()
if err != nil {
t.Fatalf("error reading DWARF: %v", err)
}
rdr := d.Reader()
found := false
var entry *dwarf.Entry
for entry, err = rdr.Next(); entry != nil; entry, err = rdr.Next() {
if err != nil {
t.Fatalf("error reading DWARF: %v", err)
}
if entry.Tag != dwarf.TagCompileUnit {
continue
}
name, _ := entry.Val(dwarf.AttrName).(string)
if name == "main" {
found = true
break
}
rdr.SkipChildren()
}
if !found {
t.Fatalf("could not find main compile unit")
}
lr, err := d.LineReader(entry)
if err != nil {
t.Fatalf("error obtaining linereader: %v", err)
}
var le dwarf.LineEntry
found = false
for {
if err := lr.Next(&le); err != nil {
if err == io.EOF {
break
}
t.Fatalf("error reading linentry: %v", err)
}
// check LE contains an entry to test.go
if le.File == nil {
continue
}
file := filepath.Base(le.File.Name)
if file == "test.go" {
found = true
break
}
}
if !found {
t.Errorf("no LPT entries for test.go")
}
}

View file

@ -1611,13 +1611,8 @@ func (l *Loader) GetFuncDwarfAuxSyms(fnSymIdx Sym) (auxDwarfInfo, auxDwarfLoc, a
if l.SymType(fnSymIdx) != sym.STEXT {
log.Fatalf("error: non-function sym %d/%s t=%s passed to GetFuncDwarfAuxSyms", fnSymIdx, l.SymName(fnSymIdx), l.SymType(fnSymIdx).String())
}
if l.IsExternal(fnSymIdx) {
// Current expectation is that any external function will
// not have auxsyms.
return
}
r, li := l.toLocal(fnSymIdx)
auxs := r.Auxs(li)
r, auxs := l.auxs(fnSymIdx)
for i := range auxs {
a := &auxs[i]
switch a.Type() {