1
0
mirror of https://github.com/golang/go synced 2024-11-17 07:04:44 -07:00

cmd/link: build dynexp symbol list directly

Currently, setCgoAttr populates the cgo_export_{static,dynamic} maps
with symbol names of exported symbols, which are then re-looked-up by
deadcode and setupdynexp, which in turn puts the re-looked-up symbols
in ctxt.dynexp. setCgoAttr already looked up the Syms, so simplify all
of this by making setCgoAttr populate ctxt.dynexp directly and
eliminating the cgo_export_{static,dynamic} maps. Recording Syms
directly also sets us up to use correct symbol versions for these
exports, rather than just assuming version 0 for all lookups.

Since setupdynexp doesn't really do any "setting up" of dynexp any
more with this change, we fold the remaining logic from setupdynexp
directly into addexport, where it has better context anyway. This also
eliminates a sorting step, since we no longer do a non-deterministic
map iteration to build the dynexp slice.

For #40724.

Change-Id: I3e1a65165268da8c2bf50d7485f2624133433260
Reviewed-on: https://go-review.googlesource.com/c/go/+/309340
Trust: Austin Clements <austin@google.com>
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
This commit is contained in:
Austin Clements 2021-04-12 13:21:55 -04:00
parent 007e247af1
commit 48531da9e7
5 changed files with 37 additions and 57 deletions

View File

@ -88,14 +88,6 @@ func (d *deadcodePass) init() {
} }
} }
dynexpMap := d.ctxt.cgo_export_dynamic
if d.ctxt.LinkMode == LinkExternal {
dynexpMap = d.ctxt.cgo_export_static
}
for exp := range dynexpMap {
names = append(names, exp)
}
if d.ctxt.Debugvlog > 1 { if d.ctxt.Debugvlog > 1 {
d.ctxt.Logf("deadcode start names: %v\n", names) d.ctxt.Logf("deadcode start names: %v\n", names)
} }
@ -106,6 +98,14 @@ func (d *deadcodePass) init() {
// Also mark any Go functions (internal ABI). // Also mark any Go functions (internal ABI).
d.mark(d.ldr.Lookup(name, sym.SymVerABIInternal), 0) d.mark(d.ldr.Lookup(name, sym.SymVerABIInternal), 0)
} }
// All dynamic exports are roots.
for _, s := range d.ctxt.dynexp {
if d.ctxt.Debugvlog > 1 {
d.ctxt.Logf("deadcode start dynexp: %s<%d>\n", d.ldr.SymName(s), d.ldr.SymVersion(s))
}
d.mark(s, 0)
}
} }
func (d *deadcodePass) flood() { func (d *deadcodePass) flood() {

View File

@ -234,11 +234,19 @@ func setCgoAttr(ctxt *Link, file string, pkg string, directives [][]string, host
// Mark exported symbols and also add them to // Mark exported symbols and also add them to
// the lists used for roots in the deadcode pass. // the lists used for roots in the deadcode pass.
if f[0] == "cgo_export_static" { if f[0] == "cgo_export_static" {
if ctxt.LinkMode == LinkExternal && !l.AttrCgoExportStatic(s) {
// Static cgo exports appear
// in the exported symbol table.
ctxt.dynexp = append(ctxt.dynexp, s)
}
l.SetAttrCgoExportStatic(s, true) l.SetAttrCgoExportStatic(s, true)
ctxt.cgo_export_static[local] = true
} else { } else {
if ctxt.LinkMode == LinkInternal && !l.AttrCgoExportDynamic(s) {
// Dynamic cgo exports appear
// in the exported symbol table.
ctxt.dynexp = append(ctxt.dynexp, s)
}
l.SetAttrCgoExportDynamic(s, true) l.SetAttrCgoExportDynamic(s, true)
ctxt.cgo_export_dynamic[local] = true
} }
continue continue
@ -422,9 +430,26 @@ func (ctxt *Link) addexport() {
return return
} }
for _, exp := range ctxt.dynexp { // Add dynamic symbols.
Adddynsym(ctxt.loader, &ctxt.Target, &ctxt.ArchSyms, exp) for _, s := range ctxt.dynexp {
// Consistency check.
if !ctxt.loader.AttrReachable(s) {
panic("dynexp entry not reachable")
}
// Resolve ABI aliases in the list of cgo-exported functions.
// This is necessary because we load the ABI0 symbol for all
// cgo exports.
if ctxt.loader.SymType(s) == sym.SABIALIAS {
t := ctxt.loader.ResolveABIAlias(s)
ctxt.loader.CopyAttributes(s, t)
ctxt.loader.SetSymExtname(t, ctxt.loader.SymExtname(s))
s = t
}
Adddynsym(ctxt.loader, &ctxt.Target, &ctxt.ArchSyms, s)
} }
for _, lib := range dedupLibraries(ctxt, dynlib) { for _, lib := range dedupLibraries(ctxt, dynlib) {
adddynlib(ctxt, lib) adddynlib(ctxt, lib)
} }

View File

@ -56,7 +56,6 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"runtime" "runtime"
"sort"
"strings" "strings"
"sync" "sync"
) )
@ -508,9 +507,6 @@ func (ctxt *Link) loadlib() {
return ctxt.loader.SymName(s) return ctxt.loader.SymName(s)
} }
ctxt.cgo_export_static = make(map[string]bool)
ctxt.cgo_export_dynamic = make(map[string]bool)
// ctxt.Library grows during the loop, so not a range loop. // ctxt.Library grows during the loop, so not a range loop.
i := 0 i := 0
for ; i < len(ctxt.Library); i++ { for ; i < len(ctxt.Library); i++ {
@ -638,43 +634,6 @@ func (ctxt *Link) loadlib() {
strictDupMsgCount = ctxt.loader.NStrictDupMsgs() strictDupMsgCount = ctxt.loader.NStrictDupMsgs()
} }
// setupdynexp constructs ctxt.dynexp, a list of loader.Sym.
func setupdynexp(ctxt *Link) {
dynexpMap := ctxt.cgo_export_dynamic
if ctxt.LinkMode == LinkExternal {
dynexpMap = ctxt.cgo_export_static
}
d := make([]loader.Sym, 0, len(dynexpMap))
for exp := range dynexpMap {
s := ctxt.loader.LookupOrCreateSym(exp, 0)
d = append(d, s)
// sanity check
if !ctxt.loader.AttrReachable(s) {
panic("dynexp entry not reachable")
}
}
sort.Slice(d, func(i, j int) bool {
return ctxt.loader.SymName(d[i]) < ctxt.loader.SymName(d[j])
})
// Resolve ABI aliases in the list of cgo-exported functions.
// This is necessary because we load the ABI0 symbol for all
// cgo exports.
for i, s := range d {
if ctxt.loader.SymType(s) != sym.SABIALIAS {
continue
}
t := ctxt.loader.ResolveABIAlias(s)
ctxt.loader.CopyAttributes(s, t)
ctxt.loader.SetSymExtname(t, ctxt.loader.SymExtname(s))
d[i] = t
}
ctxt.dynexp = d
ctxt.cgo_export_static = nil
ctxt.cgo_export_dynamic = nil
}
// loadcgodirectives reads the previously discovered cgo directives, creating // loadcgodirectives reads the previously discovered cgo directives, creating
// symbols in preparation for host object loading or use later in the link. // symbols in preparation for host object loading or use later in the link.
func (ctxt *Link) loadcgodirectives() { func (ctxt *Link) loadcgodirectives() {

View File

@ -84,9 +84,6 @@ type Link struct {
loader *loader.Loader loader *loader.Loader
cgodata []cgodata // cgo directives to load, three strings are args for loadcgo cgodata []cgodata // cgo directives to load, three strings are args for loadcgo
cgo_export_static map[string]bool
cgo_export_dynamic map[string]bool
datap []loader.Sym datap []loader.Sym
dynexp []loader.Sym dynexp []loader.Sym

View File

@ -294,7 +294,6 @@ func Main(arch *sys.Arch, theArch Arch) {
bench.Start("textbuildid") bench.Start("textbuildid")
ctxt.textbuildid() ctxt.textbuildid()
bench.Start("addexport") bench.Start("addexport")
setupdynexp(ctxt)
ctxt.setArchSyms() ctxt.setArchSyms()
ctxt.addexport() ctxt.addexport()
bench.Start("Gentext") bench.Start("Gentext")