aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/link/internal/ld/deadcode.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/link/internal/ld/deadcode.go')
-rw-r--r--src/cmd/link/internal/ld/deadcode.go48
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).