Skip to content

Commit

Permalink
cmd/link: Fix trampolines breaking DWARF line info
Browse files Browse the repository at this point in the history
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 golang#54320
  • Loading branch information
jquirke committed Aug 9, 2022
1 parent d75e186 commit 085bbc5
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 7 deletions.
79 changes: 79 additions & 0 deletions src/cmd/link/internal/ld/dwarf_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}
}
9 changes: 2 additions & 7 deletions src/cmd/link/internal/loader/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -1610,13 +1610,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() {
Expand Down

0 comments on commit 085bbc5

Please sign in to comment.