loadobjfile(ctxt, lib)
}
}
+ // At this point, the Go objects are "preloaded". Not all the symbols are
+ // added to the symbol table (only defined package symbols are). Looking
+ // up symbol by name may not get expected result.
- iscgo = ctxt.loader.Lookup("x_cgo_init", 0) != 0
- ctxt.canUsePlugins = ctxt.loader.Lookup("plugin.Open", sym.SymVerABIInternal) != 0
+ iscgo = ctxt.LibraryByPkg["runtime/cgo"] != nil
+ ctxt.canUsePlugins = ctxt.LibraryByPkg["plugin"] != nil
// We now have enough information to determine the link mode.
determineLinkMode(ctxt)
- if ctxt.LinkMode == LinkExternal && !iscgo && ctxt.LibraryByPkg["runtime/cgo"] == nil && !(objabi.GOOS == "darwin" && ctxt.BuildMode != BuildModePlugin && (ctxt.Arch.Family == sys.AMD64 || ctxt.Arch.Family == sys.I386)) {
+ if ctxt.LinkMode == LinkExternal && !iscgo && !(objabi.GOOS == "darwin" && ctxt.BuildMode != BuildModePlugin && (ctxt.Arch.Family == sys.AMD64 || ctxt.Arch.Family == sys.I386)) {
// This indicates a user requested -linkmode=external.
// The startup code uses an import of runtime/cgo to decide
// whether to initialize the TLS. So give it one. This could
// be handled differently but it's an unusual case.
- if lib := loadinternal(ctxt, "runtime/cgo"); lib != nil {
- if lib.Shlib != "" {
- ldshlibsyms(ctxt, lib.Shlib)
- } else {
- if ctxt.BuildMode == BuildModeShared || ctxt.linkShared {
- Exitf("cannot implicitly include runtime/cgo in a shared library")
- }
- loadobjfile(ctxt, lib)
+ if lib := loadinternal(ctxt, "runtime/cgo"); lib != nil && lib.Shlib == "" {
+ if ctxt.BuildMode == BuildModeShared || ctxt.linkShared {
+ Exitf("cannot implicitly include runtime/cgo in a shared library")
}
+ loadobjfile(ctxt, lib)
}
}
+ // Add non-package symbols and references of externally defined symbols.
+ ctxt.loader.LoadNonpkgSyms(ctxt.Arch, ctxt.Syms)
+
+ // Load symbols from shared libraries, after all Go object symbols are loaded.
for _, lib := range ctxt.Library {
if lib.Shlib != "" {
if ctxt.Debugvlog > 1 {
}
}
- // Add references of externally defined symbols.
- ctxt.loader.LoadRefs(ctxt.Arch, ctxt.Syms)
-
// Process cgo directives (has to be done before host object loading).
ctxt.loadcgodirectives()
//
// Notes on the layout of global symbol index space:
//
-// TODO: rework index space reservation.
-//
// - Go object files are read before host object files; each Go object
-// read adds its defined (package + non-package) symbols to the global
-// index space.
+// read adds its defined package symbols to the global index space.
+// Nonpackage symbols are not yet added.
//
-// - In loader.LoadRefs(), the loader makes a sweep through all of the
-// non-package references in each object file and allocates sym indices
-// for any symbols that have not yet been defined (start of this space
-// is marked by loader.extStart).
+// - In loader.LoadNonpkgSyms, add non-package defined symbols and
+// references in all object files to the global index space.
//
// - Host object file loading happens; the host object loader does a
// name/version lookup for each symbol it finds; this can wind up
// extending the external symbol index space range. The host object
-// loader currently stores symbol payloads in sym.Symbol objects,
-// which get handed off to the loader.
+// loader stores symbol payloads in loader.payloads using SymbolBuilder.
//
-// - A given external symbol (Sym) either has a sym.Symbol acting as
-// its backing store (this will continue to be the case until we
-// finish rewriting the host object loader to work entirely with
-// loader.Sym) or it has a "payload" backing store (represented by
-// extSymPayload). Newly created external symbols (created by
-// a call to AddExtSym or equivalent) start out in the "has payload"
-// state, and continue until installSym is called for the sym
-// index in question.
+// - For now, in loader.LoadFull we convert all symbols (Go + external)
+// to sym.Symbols.
//
// - At some point (when the wayfront is pushed through all of the
// linker), all external symbols will be payload-based, and we can
elfsetstring elfsetstringFunc
}
+const (
+ pkgDef = iota
+ nonPkgDef
+ nonPkgRef
+)
+
type elfsetstringFunc func(s *sym.Symbol, str string, off int)
// extSymPayload holds the payload (data + relocations) for linker-synthesized
if _, ok := l.objByPkg[pkg]; !ok {
l.objByPkg[pkg] = r
}
- n := r.NSym() + r.NNonpkgdef()
i := Sym(len(l.objSyms))
l.start[r] = i
l.objs = append(l.objs, objIdx{r, i})
- l.growValues(int(i) + n - 1)
return i
}
// Add a symbol from an object file, return the global index and whether it is added.
// If the symbol already exist, it returns the index of that symbol.
-func (l *Loader) AddSym(name string, ver int, r *oReader, li int, dupok bool, typ sym.SymKind) (Sym, bool) {
+func (l *Loader) AddSym(name string, ver int, r *oReader, li int, kind int, dupok bool, typ sym.SymKind) (Sym, bool) {
if l.extStart != 0 {
panic("AddSym called after AddExtSym is called")
}
addToGlobal()
return i, true
}
+ if kind == pkgDef {
+ // Defined package symbols cannot be dup to each other.
+ // We load all the package symbols first, so we don't need
+ // to check dup here.
+ // We still add it to the lookup table, as it may still be
+ // referenced by name (e.g. through linkname).
+ l.symsByName[ver][name] = i
+ addToGlobal()
+ return i, true
+ }
+
+ // Non-package (named) symbol. Check if it already exists.
oldi, existed := l.symsByName[ver][name]
if !existed {
l.symsByName[ver][name] = i
func (x RelocByOff) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
func (x RelocByOff) Less(i, j int) bool { return x[i].Off < x[j].Off }
-// Preload a package: add autolibs, add symbols to the symbol table.
-// Does not read symbol data yet.
+// Preload a package: add autolibs, add defined package symbols to the symbol table.
+// Does not add non-package symbols yet, which will be done in LoadNonpkgSyms.
+// Does not read symbol data.
func (l *Loader) Preload(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, lib *sym.Library, unit *sym.CompilationUnit, length int64, pn string, flags int) {
roObject, readonly, err := f.Slice(uint64(length))
if err != nil {
unit.DWARFFileTable[i] = r.DwarfFile(i)
}
- istart := l.addObj(lib.Pkg, or)
- l.growAttrBitmaps(int(istart) + ndef + nnonpkgdef)
- for i, n := 0, ndef+nnonpkgdef; i < n; i++ {
+ l.addObj(lib.Pkg, or)
+ l.preloadSyms(or, pkgDef)
+
+ // The caller expects us consuming all the data
+ f.MustSeek(length, os.SEEK_CUR)
+}
+
+// Preload symbols of given kind from an object.
+func (l *Loader) preloadSyms(r *oReader, kind int) {
+ ndef := r.NSym()
+ nnonpkgdef := r.NNonpkgdef()
+ var start, end int
+ switch kind {
+ case pkgDef:
+ start = 0
+ end = ndef
+ case nonPkgDef:
+ start = ndef
+ end = ndef + nnonpkgdef
+ default:
+ panic("preloadSyms: bad kind")
+ }
+ l.growSyms(len(l.objSyms) + end - start)
+ l.growAttrBitmaps(len(l.objSyms) + end - start)
+ for i := start; i < end; i++ {
osym := goobj2.Sym{}
- osym.Read(r, r.SymOff(i))
- name := strings.Replace(osym.Name, "\"\".", pkgprefix, -1)
- v := abiToVer(osym.ABI, localSymVersion)
+ osym.Read(r.Reader, r.SymOff(i))
+ name := strings.Replace(osym.Name, "\"\".", r.pkgprefix, -1)
+ v := abiToVer(osym.ABI, r.version)
dupok := osym.Dupok()
- gi, added := l.AddSym(name, v, or, i, dupok, sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type)])
- or.syms[i] = gi
+ gi, added := l.AddSym(name, v, r, i, kind, dupok, sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type)])
+ r.syms[i] = gi
if !added {
continue
}
l.SetAttrNotInSymbolTable(gi, true)
}
}
-
- // The caller expects us consuming all the data
- f.MustSeek(length, os.SEEK_CUR)
}
-// Make sure referenced symbols are added. Most of them should already be added.
-// This should only be needed for referenced external symbols.
-func (l *Loader) LoadRefs(arch *sys.Arch, syms *sym.Symbols) {
+// Add non-package symbols and references to external symbols (which are always
+// named).
+func (l *Loader) LoadNonpkgSyms(arch *sys.Arch, syms *sym.Symbols) {
+ for _, o := range l.objs[1:] {
+ l.preloadSyms(o.r, nonPkgDef)
+ }
for _, o := range l.objs[1:] {
loadObjRefs(l, o.r, arch, syms)
}