diff options
Diffstat (limited to 'src/cmd/link/internal/ld/deadcode.go')
| -rw-r--r-- | src/cmd/link/internal/ld/deadcode.go | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/src/cmd/link/internal/ld/deadcode.go b/src/cmd/link/internal/ld/deadcode.go index 0738a51deb..307a6dd42f 100644 --- a/src/cmd/link/internal/ld/deadcode.go +++ b/src/cmd/link/internal/ld/deadcode.go @@ -12,6 +12,7 @@ import ( "cmd/link/internal/sym" "fmt" "internal/buildcfg" + "strings" "unicode" ) @@ -29,6 +30,8 @@ type deadcodePass struct { dynlink bool methodsigstmp []methodsig // scratch buffer for decoding method signatures + pkginits []loader.Sym + mapinitnoop loader.Sym } func (d *deadcodePass) init() { @@ -105,6 +108,11 @@ func (d *deadcodePass) init() { } d.mark(s, 0) } + + d.mapinitnoop = d.ldr.Lookup("runtime.mapinitnoop", abiInternalVer) + if d.mapinitnoop == 0 { + panic("could not look up runtime.mapinitnoop") + } } func (d *deadcodePass) flood() { @@ -229,6 +237,12 @@ func (d *deadcodePass) flood() { } d.mark(a.Sym(), symIdx) } + // Record sym if package init func (here naux != 0 is a cheap way + // to check first if it is a function symbol). + if naux != 0 && d.ldr.IsPkgInit(symIdx) { + + d.pkginits = append(d.pkginits, symIdx) + } // Some host object symbols have an outer object, which acts like a // "carrier" symbol, or it holds all the symbols for a particular // section. We need to mark all "referenced" symbols from that carrier, @@ -262,6 +276,37 @@ func (d *deadcodePass) flood() { } } +// mapinitcleanup walks all pkg init functions and looks for weak relocations +// to mapinit symbols that are no longer reachable. It rewrites +// the relocs to target a new no-op routine in the runtime. +func (d *deadcodePass) mapinitcleanup() { + for _, idx := range d.pkginits { + relocs := d.ldr.Relocs(idx) + var su *loader.SymbolBuilder + for i := 0; i < relocs.Count(); i++ { + r := relocs.At(i) + rs := r.Sym() + if r.Weak() && r.Type().IsDirectCall() && !d.ldr.AttrReachable(rs) { + // double check to make sure target is indeed map.init + rsn := d.ldr.SymName(rs) + if !strings.Contains(rsn, "map.init") { + panic(fmt.Sprintf("internal error: expected map.init sym for weak call reloc, got %s -> %s", d.ldr.SymName(idx), rsn)) + } + d.ldr.SetAttrReachable(d.mapinitnoop, true) + if d.ctxt.Debugvlog > 1 { + d.ctxt.Logf("deadcode: %s rewrite %s ref to %s\n", + d.ldr.SymName(idx), rsn, + d.ldr.SymName(d.mapinitnoop)) + } + if su == nil { + su = d.ldr.MakeSymbolUpdater(idx) + } + su.SetRelocSym(i, d.mapinitnoop) + } + } + } +} + func (d *deadcodePass) mark(symIdx, parent loader.Sym) { if symIdx != 0 && !d.ldr.AttrReachable(symIdx) { d.wq.push(symIdx) @@ -370,6 +415,9 @@ func deadcode(ctxt *Link) { } d.flood() } + if *flagPruneWeakMap { + d.mapinitcleanup() + } } // methodsig is a typed method signature (name + type). |
