aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/link/internal/ld/deadcode2.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/link/internal/ld/deadcode2.go')
-rw-r--r--src/cmd/link/internal/ld/deadcode2.go156
1 files changed, 50 insertions, 106 deletions
diff --git a/src/cmd/link/internal/ld/deadcode2.go b/src/cmd/link/internal/ld/deadcode2.go
index 9197c700f5..3342efe39f 100644
--- a/src/cmd/link/internal/ld/deadcode2.go
+++ b/src/cmd/link/internal/ld/deadcode2.go
@@ -6,7 +6,6 @@ package ld
import (
"bytes"
- "cmd/internal/dwarf"
"cmd/internal/objabi"
"cmd/internal/sys"
"cmd/link/internal/loader"
@@ -37,7 +36,6 @@ type deadcodePass2 struct {
ctxt *Link
ldr *loader.Loader
wq workQueue
- rtmp []loader.Reloc
ifaceMethod map[methodsig]bool // methods declared in reached interfaces
markableMethods []methodref2 // methods of reached types
@@ -58,9 +56,7 @@ func (d *deadcodePass2) init() {
n := d.ldr.NDef()
for i := 1; i < n; i++ {
s := loader.Sym(i)
- if !d.ldr.IsDup(s) {
- d.mark(s, 0)
- }
+ d.mark(s, 0)
}
return
}
@@ -88,9 +84,9 @@ func (d *deadcodePass2) init() {
// but we do keep the symbols it refers to.
exportsIdx := d.ldr.Lookup("go.plugin.exports", 0)
if exportsIdx != 0 {
- d.ReadRelocs(exportsIdx)
- for i := 0; i < len(d.rtmp); i++ {
- d.mark(d.rtmp[i].Sym, 0)
+ relocs := d.ldr.Relocs(exportsIdx)
+ for i := 0; i < relocs.Count(); i++ {
+ d.mark(relocs.At2(i).Sym(), 0)
}
}
}
@@ -104,14 +100,6 @@ func (d *deadcodePass2) init() {
names = append(names, exp)
}
- // DWARF constant DIE symbols are not referenced, but needed by
- // the dwarf pass.
- if !*FlagW {
- for _, lib := range d.ctxt.Library {
- names = append(names, dwarf.ConstInfoPrefix+lib.Pkg)
- }
- }
-
for _, name := range names {
// Mark symbol as a data/ABI0 symbol.
d.mark(d.ldr.Lookup(name, 0), 0)
@@ -121,20 +109,18 @@ func (d *deadcodePass2) init() {
}
func (d *deadcodePass2) flood() {
- symRelocs := []loader.Reloc{}
- auxSyms := []loader.Sym{}
for !d.wq.empty() {
symIdx := d.wq.pop()
d.reflectSeen = d.reflectSeen || d.ldr.IsReflectMethod(symIdx)
+ isgotype := d.ldr.IsGoType(symIdx)
relocs := d.ldr.Relocs(symIdx)
- symRelocs = relocs.ReadAll(symRelocs)
- if d.ldr.IsGoType(symIdx) {
+ if isgotype {
p := d.ldr.Data(symIdx)
if len(p) != 0 && decodetypeKind(d.ctxt.Arch, p)&kindMask == kindInterface {
- for _, sig := range d.decodeIfaceMethods2(d.ldr, d.ctxt.Arch, symIdx, symRelocs) {
+ for _, sig := range d.decodeIfaceMethods2(d.ldr, d.ctxt.Arch, symIdx, &relocs) {
if d.ctxt.Debugvlog > 1 {
d.ctxt.Logf("reached iface method: %s\n", sig)
}
@@ -144,30 +130,31 @@ func (d *deadcodePass2) flood() {
}
var methods []methodref2
- for i := 0; i < relocs.Count; i++ {
- r := symRelocs[i]
- if r.Type == objabi.R_WEAKADDROFF {
+ for i := 0; i < relocs.Count(); i++ {
+ r := relocs.At2(i)
+ t := r.Type()
+ if t == objabi.R_WEAKADDROFF {
continue
}
- if r.Type == objabi.R_METHODOFF {
- if i+2 >= relocs.Count {
+ if t == objabi.R_METHODOFF {
+ if i+2 >= relocs.Count() {
panic("expect three consecutive R_METHODOFF relocs")
}
methods = append(methods, methodref2{src: symIdx, r: i})
i += 2
continue
}
- if r.Type == objabi.R_USETYPE {
+ if t == objabi.R_USETYPE {
// type symbol used for DWARF. we need to load the symbol but it may not
// be otherwise reachable in the program.
// do nothing for now as we still load all type symbols.
continue
}
- d.mark(r.Sym, symIdx)
+ d.mark(r.Sym(), symIdx)
}
- auxSyms = d.ldr.ReadAuxSyms(symIdx, auxSyms)
- for i := 0; i < len(auxSyms); i++ {
- d.mark(auxSyms[i], symIdx)
+ naux := d.ldr.NAux(symIdx)
+ for i := 0; i < naux; i++ {
+ d.mark(d.ldr.Aux2(symIdx, i).Sym(), symIdx)
}
// Some host object symbols have an outer object, which acts like a
// "carrier" symbol, or it holds all the symbols for a particular
@@ -175,14 +162,19 @@ func (d *deadcodePass2) flood() {
// so we make sure we're pulling in all outer symbols, and their sub
// symbols. This is not ideal, and these carrier/section symbols could
// be removed.
- d.mark(d.ldr.OuterSym(symIdx), symIdx)
- d.mark(d.ldr.SubSym(symIdx), symIdx)
+ if d.ldr.IsExternal(symIdx) {
+ d.mark(d.ldr.OuterSym(symIdx), symIdx)
+ d.mark(d.ldr.SubSym(symIdx), symIdx)
+ }
if len(methods) != 0 {
+ if !isgotype {
+ panic("method found on non-type symbol")
+ }
// Decode runtime type information for type methods
// to help work out which methods can be called
// dynamically via interfaces.
- methodsigs := d.decodetypeMethods2(d.ldr, d.ctxt.Arch, symIdx, symRelocs)
+ methodsigs := d.decodetypeMethods2(d.ldr, d.ctxt.Arch, symIdx, &relocs)
if len(methods) != len(methodsigs) {
panic(fmt.Sprintf("%q has %d method relocations for %d methods", d.ldr.SymName(symIdx), len(methods), len(methodsigs)))
}
@@ -195,9 +187,9 @@ func (d *deadcodePass2) flood() {
}
func (d *deadcodePass2) mark(symIdx, parent loader.Sym) {
- if symIdx != 0 && !d.ldr.Reachable.Has(symIdx) {
+ if symIdx != 0 && !d.ldr.AttrReachable(symIdx) {
d.wq.push(symIdx)
- d.ldr.Reachable.Set(symIdx)
+ d.ldr.SetAttrReachable(symIdx, true)
if d.ctxt.Reachparent != nil {
d.ldr.Reachparent[symIdx] = parent
}
@@ -215,10 +207,10 @@ func (d *deadcodePass2) mark(symIdx, parent loader.Sym) {
}
func (d *deadcodePass2) markMethod(m methodref2) {
- d.ReadRelocs(m.src)
- d.mark(d.rtmp[m.r].Sym, m.src)
- d.mark(d.rtmp[m.r+1].Sym, m.src)
- d.mark(d.rtmp[m.r+2].Sym, m.src)
+ relocs := d.ldr.Relocs(m.src)
+ d.mark(relocs.At2(m.r).Sym(), m.src)
+ d.mark(relocs.At2(m.r+1).Sym(), m.src)
+ d.mark(relocs.At2(m.r+2).Sym(), m.src)
}
func deadcode2(ctxt *Link) {
@@ -239,7 +231,7 @@ func deadcode2(ctxt *Link) {
// Methods might be called via reflection. Give up on
// static analysis, mark all exported methods of
// all reachable types as reachable.
- d.reflectSeen = d.reflectSeen || (callSym != 0 && ldr.Reachable.Has(callSym)) || (methSym != 0 && ldr.Reachable.Has(methSym))
+ d.reflectSeen = d.reflectSeen || (callSym != 0 && ldr.AttrReachable(callSym)) || (methSym != 0 && ldr.AttrReachable(methSym))
// Mark all methods that could satisfy a discovered
// interface as reachable. We recheck old marked interfaces
@@ -271,8 +263,8 @@ func deadcode2(ctxt *Link) {
s := loader.Sym(i)
if ldr.IsItabLink(s) {
relocs := ldr.Relocs(s)
- if relocs.Count > 0 && ldr.Reachable.Has(relocs.At(0).Sym) {
- ldr.Reachable.Set(s)
+ if relocs.Count() > 0 && ldr.AttrReachable(relocs.At2(0).Sym()) {
+ ldr.SetAttrReachable(s, true)
}
}
}
@@ -301,15 +293,15 @@ func (m methodref2) isExported() bool {
// the function type.
//
// Conveniently this is the layout of both runtime.method and runtime.imethod.
-func (d *deadcodePass2) decodeMethodSig2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, symRelocs []loader.Reloc, off, size, count int) []methodsig {
+func (d *deadcodePass2) decodeMethodSig2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, relocs *loader.Relocs, off, size, count int) []methodsig {
var buf bytes.Buffer
var methods []methodsig
for i := 0; i < count; i++ {
- buf.WriteString(decodetypeName2(ldr, symIdx, symRelocs, off))
- mtypSym := decodeRelocSym2(ldr, symIdx, symRelocs, int32(off+4))
+ buf.WriteString(decodetypeName2(ldr, symIdx, relocs, off))
+ mtypSym := decodeRelocSym2(ldr, symIdx, relocs, int32(off+4))
// FIXME: add some sort of caching here, since we may see some of the
// same symbols over time for param types.
- d.ReadRelocs(mtypSym)
+ mrelocs := ldr.Relocs(mtypSym)
mp := ldr.Data(mtypSym)
buf.WriteRune('(')
@@ -318,7 +310,7 @@ func (d *deadcodePass2) decodeMethodSig2(ldr *loader.Loader, arch *sys.Arch, sym
if i > 0 {
buf.WriteString(", ")
}
- a := d.decodetypeFuncInType2(ldr, arch, mtypSym, d.rtmp, i)
+ a := decodetypeFuncInType2(ldr, arch, mtypSym, &mrelocs, i)
buf.WriteString(ldr.SymName(a))
}
buf.WriteString(") (")
@@ -327,7 +319,7 @@ func (d *deadcodePass2) decodeMethodSig2(ldr *loader.Loader, arch *sys.Arch, sym
if i > 0 {
buf.WriteString(", ")
}
- a := d.decodetypeFuncOutType2(ldr, arch, mtypSym, d.rtmp, i)
+ a := decodetypeFuncOutType2(ldr, arch, mtypSym, &mrelocs, i)
buf.WriteString(ldr.SymName(a))
}
buf.WriteRune(')')
@@ -339,25 +331,26 @@ func (d *deadcodePass2) decodeMethodSig2(ldr *loader.Loader, arch *sys.Arch, sym
return methods
}
-func (d *deadcodePass2) decodeIfaceMethods2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, symRelocs []loader.Reloc) []methodsig {
+func (d *deadcodePass2) decodeIfaceMethods2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, relocs *loader.Relocs) []methodsig {
p := ldr.Data(symIdx)
if decodetypeKind(arch, p)&kindMask != kindInterface {
panic(fmt.Sprintf("symbol %q is not an interface", ldr.SymName(symIdx)))
}
- rel := decodeReloc2(ldr, symIdx, symRelocs, int32(commonsize(arch)+arch.PtrSize))
- if rel.Sym == 0 {
+ rel := decodeReloc2(ldr, symIdx, relocs, int32(commonsize(arch)+arch.PtrSize))
+ s := rel.Sym()
+ if s == 0 {
return nil
}
- if rel.Sym != symIdx {
+ if s != symIdx {
panic(fmt.Sprintf("imethod slice pointer in %q leads to a different symbol", ldr.SymName(symIdx)))
}
- off := int(rel.Add) // array of reflect.imethod values
+ off := int(rel.Add()) // array of reflect.imethod values
numMethods := int(decodetypeIfaceMethodCount(arch, p))
sizeofIMethod := 4 + 4
- return d.decodeMethodSig2(ldr, arch, symIdx, symRelocs, off, sizeofIMethod, numMethods)
+ return d.decodeMethodSig2(ldr, arch, symIdx, relocs, off, sizeofIMethod, numMethods)
}
-func (d *deadcodePass2) decodetypeMethods2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, symRelocs []loader.Reloc) []methodsig {
+func (d *deadcodePass2) decodetypeMethods2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, relocs *loader.Relocs) []methodsig {
p := ldr.Data(symIdx)
if !decodetypeHasUncommon(arch, p) {
panic(fmt.Sprintf("no methods on %q", ldr.SymName(symIdx)))
@@ -388,54 +381,5 @@ func (d *deadcodePass2) decodetypeMethods2(ldr *loader.Loader, arch *sys.Arch, s
moff := int(decodeInuxi(arch, p[off+4+2+2:], 4))
off += moff // offset to array of reflect.method values
const sizeofMethod = 4 * 4 // sizeof reflect.method in program
- return d.decodeMethodSig2(ldr, arch, symIdx, symRelocs, off, sizeofMethod, mcount)
-}
-
-func decodeReloc2(ldr *loader.Loader, symIdx loader.Sym, symRelocs []loader.Reloc, off int32) loader.Reloc {
- for j := 0; j < len(symRelocs); j++ {
- rel := symRelocs[j]
- if rel.Off == off {
- return rel
- }
- }
- return loader.Reloc{}
-}
-
-func decodeRelocSym2(ldr *loader.Loader, symIdx loader.Sym, symRelocs []loader.Reloc, off int32) loader.Sym {
- return decodeReloc2(ldr, symIdx, symRelocs, off).Sym
-}
-
-// decodetypeName2 decodes the name from a reflect.name.
-func decodetypeName2(ldr *loader.Loader, symIdx loader.Sym, symRelocs []loader.Reloc, off int) string {
- r := decodeRelocSym2(ldr, symIdx, symRelocs, int32(off))
- if r == 0 {
- return ""
- }
-
- data := ldr.Data(r)
- namelen := int(uint16(data[1])<<8 | uint16(data[2]))
- return string(data[3 : 3+namelen])
-}
-
-func (d *deadcodePass2) decodetypeFuncInType2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, symRelocs []loader.Reloc, i int) loader.Sym {
- uadd := commonsize(arch) + 4
- if arch.PtrSize == 8 {
- uadd += 4
- }
- if decodetypeHasUncommon(arch, ldr.Data(symIdx)) {
- uadd += uncommonSize()
- }
- return decodeRelocSym2(ldr, symIdx, symRelocs, int32(uadd+i*arch.PtrSize))
-}
-
-func (d *deadcodePass2) decodetypeFuncOutType2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, symRelocs []loader.Reloc, i int) loader.Sym {
- return d.decodetypeFuncInType2(ldr, arch, symIdx, symRelocs, i+decodetypeFuncInCount(arch, ldr.Data(symIdx)))
-}
-
-// readRelocs reads the relocations for the specified symbol into the
-// deadcode relocs work array. Use with care, since the work array
-// is a singleton.
-func (d *deadcodePass2) ReadRelocs(symIdx loader.Sym) {
- relocs := d.ldr.Relocs(symIdx)
- d.rtmp = relocs.ReadAll(d.rtmp)
+ return d.decodeMethodSig2(ldr, arch, symIdx, relocs, off, sizeofMethod, mcount)
}