From 8205d83fe29e315eeb8f64f095a4d2594c9cd1c6 Mon Sep 17 00:00:00 2001 From: Than McIntosh Date: Tue, 1 Nov 2022 10:27:18 -0400 Subject: [PATCH] cmd/link: improved host archive debug trace output When ctxt.Debugvlog > 1, produce additional trace output to describe which object files are being pulled out of host archive libraries and why they were pulled (e.g. which symbol had a reference to something in a library). Intended to make it easier to debug problems with cgo internal linking. Change-Id: Icd64aff244b9145162a00cb51642ef32f26adfba Reviewed-on: https://go-review.googlesource.com/c/go/+/451736 Reviewed-by: Cherry Mui Run-TryBot: Than McIntosh Reviewed-by: David Chase TryBot-Result: Gopher Robot --- src/cmd/link/internal/ld/ar.go | 11 +++++++---- src/cmd/link/internal/ld/lib.go | 16 +++++++++++++--- src/cmd/link/internal/loader/loader.go | 20 ++++++++++++-------- 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/src/cmd/link/internal/ld/ar.go b/src/cmd/link/internal/ld/ar.go index 125a5d6fcb..1216b0c983 100644 --- a/src/cmd/link/internal/ld/ar.go +++ b/src/cmd/link/internal/ld/ar.go @@ -110,12 +110,15 @@ func hostArchive(ctxt *Link, name string) { for any { var load []uint64 returnAllUndefs := -1 - undefs := ctxt.loader.UndefinedRelocTargets(returnAllUndefs) - for _, symIdx := range undefs { - name := ctxt.loader.SymName(symIdx) - if off := armap[name]; off != 0 && !loaded[off] { + undefs, froms := ctxt.loader.UndefinedRelocTargets(returnAllUndefs) + for k, symIdx := range undefs { + sname := ctxt.loader.SymName(symIdx) + if off := armap[sname]; off != 0 && !loaded[off] { load = append(load, off) loaded[off] = true + if ctxt.Debugvlog > 1 { + ctxt.Logf("hostArchive(%s): selecting object at offset %x to resolve %s [%d] reference from %s [%d]\n", name, off, sname, symIdx, ctxt.loader.SymName(froms[k]), froms[k]) + } } } diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index 184ad20be4..a42a66ca6e 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -615,9 +615,14 @@ func (ctxt *Link) loadlib() { // If we have any undefined symbols in external // objects, try to read them from the libgcc file. any := false - undefs := ctxt.loader.UndefinedRelocTargets(1) + undefs, froms := ctxt.loader.UndefinedRelocTargets(1) if len(undefs) > 0 { any = true + if ctxt.Debugvlog > 1 { + ctxt.Logf("loadlib: first unresolved is %s [%d] from %s [%d]\n", + ctxt.loader.SymName(undefs[0]), undefs[0], + ctxt.loader.SymName(froms[0]), froms[0]) + } } if any { if *flagLibGCC == "" { @@ -681,9 +686,14 @@ func loadWindowsHostArchives(ctxt *Link) { hostArchive(ctxt, p) } any = false - undefs := ctxt.loader.UndefinedRelocTargets(1) + undefs, froms := ctxt.loader.UndefinedRelocTargets(1) if len(undefs) > 0 { any = true + if ctxt.Debugvlog > 1 { + ctxt.Logf("loadWindowsHostArchives: remaining unresolved is %s [%d] from %s [%d]\n", + ctxt.loader.SymName(undefs[0]), undefs[0], + ctxt.loader.SymName(froms[0]), froms[0]) + } } } // If needed, create the __CTOR_LIST__ and __DTOR_LIST__ @@ -2141,7 +2151,7 @@ func ldobj(ctxt *Link, f *bio.Reader, lib *sym.Library, length int64, pn string, // to true if there is an unresolved reference to the symbol in want[K]. func symbolsAreUnresolved(ctxt *Link, want []string) []bool { returnAllUndefs := -1 - undefs := ctxt.loader.UndefinedRelocTargets(returnAllUndefs) + undefs, _ := ctxt.loader.UndefinedRelocTargets(returnAllUndefs) seen := make(map[loader.Sym]struct{}) rval := make([]bool, len(want)) wantm := make(map[string]int) diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go index 23837379b5..8e1575a5a2 100644 --- a/src/cmd/link/internal/loader/loader.go +++ b/src/cmd/link/internal/loader/loader.go @@ -2392,12 +2392,15 @@ func (l *Loader) RelocVariant(s Sym, ri int) sym.RelocVariant { // space, looking for symbols with relocations targeting undefined // references. The linker's loadlib method uses this to determine if // there are unresolved references to functions in system libraries -// (for example, libgcc.a), presumably due to CGO code. Return -// value is a list of loader.Sym's corresponding to the undefined -// cross-refs. The "limit" param controls the maximum number of -// results returned; if "limit" is -1, then all undefs are returned. -func (l *Loader) UndefinedRelocTargets(limit int) []Sym { - result := []Sym{} +// (for example, libgcc.a), presumably due to CGO code. Return value +// is a pair of lists of loader.Sym's. First list corresponds to the +// corresponding to the undefined symbols themselves, the second list +// is the symbol that is making a reference to the undef. The "limit" +// param controls the maximum number of results returned; if "limit" +// is -1, then all undefs are returned. +func (l *Loader) UndefinedRelocTargets(limit int) ([]Sym, []Sym) { + result, fromr := []Sym{}, []Sym{} +outerloop: for si := Sym(1); si < Sym(len(l.objSyms)); si++ { relocs := l.Relocs(si) for ri := 0; ri < relocs.Count(); ri++ { @@ -2405,13 +2408,14 @@ func (l *Loader) UndefinedRelocTargets(limit int) []Sym { rs := r.Sym() if rs != 0 && l.SymType(rs) == sym.SXREF && l.SymName(rs) != ".got" { result = append(result, rs) + fromr = append(fromr, si) if limit != -1 && len(result) >= limit { - break + break outerloop } } } } - return result + return result, fromr } // AssignTextSymbolOrder populates the Textp slices within each -- 2.50.0