}
// Set symbol attributes or flags based on cgo directives.
-func setCgoAttr(ctxt *Link, lookup func(string, int) *sym.Symbol, file string, pkg string, directives [][]string) {
- for _, f := range directives {
- switch f[0] {
- case "cgo_import_dynamic":
- if len(f) < 2 || len(f) > 4 {
- break
- }
-
- local := f[1]
- remote := local
- if len(f) > 2 {
- remote = f[2]
- }
- lib := ""
- if len(f) > 3 {
- lib = f[3]
- }
-
- if *FlagD {
- fmt.Fprintf(os.Stderr, "%s: %s: cannot use dynamic imports with -d flag\n", os.Args[0], file)
- nerrors++
- return
- }
-
- if local == "_" && remote == "_" {
- // allow #pragma dynimport _ _ "foo.so"
- // to force a link of foo.so.
- havedynamic = 1
-
- if ctxt.HeadType == objabi.Hdarwin {
- machoadddynlib(lib, ctxt.LinkMode)
- } else {
- dynlib = append(dynlib, lib)
- }
- continue
- }
-
- local = expandpkg(local, pkg)
- q := ""
- if i := strings.Index(remote, "#"); i >= 0 {
- remote, q = remote[:i], remote[i+1:]
- }
- s := lookup(local, 0)
- if s.Type == 0 || s.Type == sym.SXREF || s.Type == sym.SBSS || s.Type == sym.SNOPTRBSS || s.Type == sym.SHOSTOBJ {
- s.SetDynimplib(lib)
- s.SetExtname(remote)
- s.SetDynimpvers(q)
- if s.Type != sym.SHOSTOBJ {
- s.Type = sym.SDYNIMPORT
- }
- havedynamic = 1
- }
-
- continue
-
- case "cgo_import_static":
- if len(f) != 2 {
- break
- }
- local := f[1]
-
- s := lookup(local, 0)
- s.Type = sym.SHOSTOBJ
- s.Size = 0
- continue
-
- case "cgo_export_static", "cgo_export_dynamic":
- if len(f) < 2 || len(f) > 3 {
- break
- }
- local := f[1]
- remote := local
- if len(f) > 2 {
- remote = f[2]
- }
- local = expandpkg(local, pkg)
-
- // The compiler arranges for an ABI0 wrapper
- // to be available for all cgo-exported
- // functions. Link.loadlib will resolve any
- // ABI aliases we find here (since we may not
- // yet know it's an alias).
- s := lookup(local, 0)
-
- switch ctxt.BuildMode {
- case BuildModeCShared, BuildModeCArchive, BuildModePlugin:
- if s == lookup("main", 0) {
- continue
- }
- }
-
- // export overrides import, for openbsd/cgo.
- // see issue 4878.
- if s.Dynimplib() != "" {
- s.ResetDyninfo()
- s.SetExtname("")
- s.Type = 0
- }
-
- if !s.Attr.CgoExport() {
- s.SetExtname(remote)
- } else if s.Extname() != remote {
- fmt.Fprintf(os.Stderr, "%s: conflicting cgo_export directives: %s as %s and %s\n", os.Args[0], s.Name, s.Extname(), remote)
- nerrors++
- return
- }
-
- if f[0] == "cgo_export_static" {
- s.Attr |= sym.AttrCgoExportStatic
- } else {
- s.Attr |= sym.AttrCgoExportDynamic
- }
- continue
-
- case "cgo_dynamic_linker":
- if len(f) != 2 {
- break
- }
-
- if *flagInterpreter == "" {
- if interpreter != "" && interpreter != f[1] {
- fmt.Fprintf(os.Stderr, "%s: conflict dynlinker: %s and %s\n", os.Args[0], interpreter, f[1])
- nerrors++
- return
- }
-
- interpreter = f[1]
- }
- continue
-
- case "cgo_ldflag":
- if len(f) != 2 {
- break
- }
- ldflag = append(ldflag, f[1])
- continue
- }
-
- fmt.Fprintf(os.Stderr, "%s: %s: invalid cgo directive: %q\n", os.Args[0], file, f)
- nerrors++
- }
-}
-
-// Set symbol attributes or flags based on cgo directives.
-// This version works with loader.Sym and not sym.Symbol.
// Any newly discovered HOSTOBJ syms are added to 'hostObjSyms'.
-func setCgoAttr2(ctxt *Link, lookup func(string, int) loader.Sym, file string, pkg string, directives [][]string, hostObjSyms map[loader.Sym]struct{}) {
+func setCgoAttr(ctxt *Link, lookup func(string, int) loader.Sym, file string, pkg string, directives [][]string, hostObjSyms map[loader.Sym]struct{}) {
l := ctxt.loader
for _, f := range directives {
switch f[0] {
ctxt.loader.LoadRefs(ctxt.Arch, ctxt.Syms)
// Process cgo directives (has to be done before host object loading).
- ctxt.loadcgodirectives(ctxt.loaderSupport())
+ ctxt.loadcgodirectives()
// Conditionally load host objects, or setup for external linking.
hostobjs(ctxt)
// If we have any undefined symbols in external
// objects, try to read them from the libgcc file.
any := false
- if ctxt.loaderSupport() {
- undefs := ctxt.loader.UndefinedRelocTargets(1)
- if len(undefs) > 0 {
- any = true
- }
- } else {
- for _, s := range ctxt.loader.Syms {
- if s == nil {
- continue
- }
- for i := range s.R {
- r := &s.R[i] // Copying sym.Reloc has measurable impact on performance
- if r.Sym != nil && r.Sym.Type == sym.SXREF && r.Sym.Name != ".got" {
- any = true
- break
- }
- }
- }
+ undefs := ctxt.loader.UndefinedRelocTargets(1)
+ if len(undefs) > 0 {
+ any = true
}
if any {
if *flagLibGCC == "" {
ctxt.cgo_export_dynamic = nil
}
-// loadcgodirectives reads the previously discovered cgo directives,
-// creating symbols (either sym.Symbol or loader.Sym) in preparation
-// for host object loading or use later in the link.
-func (ctxt *Link) loadcgodirectives(useLoader bool) {
- if useLoader {
- l := ctxt.loader
- hostObjSyms := make(map[loader.Sym]struct{})
- for _, d := range ctxt.cgodata {
- setCgoAttr2(ctxt, ctxt.loader.LookupOrCreateSym, d.file, d.pkg, d.directives, hostObjSyms)
- }
- ctxt.cgodata = nil
-
- if ctxt.LinkMode == LinkInternal {
- // Drop all the cgo_import_static declarations.
- // Turns out we won't be needing them.
- for symIdx := range hostObjSyms {
- if l.SymType(symIdx) == sym.SHOSTOBJ {
- // If a symbol was marked both
- // cgo_import_static and cgo_import_dynamic,
- // then we want to make it cgo_import_dynamic
- // now.
- su, _ := l.MakeSymbolUpdater(symIdx)
- if l.SymExtname(symIdx) != "" && l.SymDynimplib(symIdx) != "" && !(l.AttrCgoExportStatic(symIdx) || l.AttrCgoExportDynamic(symIdx)) {
- su.SetType(sym.SDYNIMPORT)
- } else {
- su.SetType(0)
- }
- }
- }
- }
- } else {
- // In newobj mode, we typically create sym.Symbols later therefore
- // also set cgo attributes later. However, for internal cgo linking,
- // the host object loaders still work with sym.Symbols (for now),
- // and they need cgo attributes set to work properly. So process
- // them now.
- for _, d := range ctxt.cgodata {
- setCgoAttr(ctxt, ctxt.loader.LookupOrCreate, d.file, d.pkg, d.directives)
- }
- ctxt.cgodata = nil
-
- if ctxt.LinkMode == LinkInternal {
- // Drop all the cgo_import_static declarations.
- // Turns out we won't be needing them.
- for _, s := range ctxt.loader.Syms {
- if s != nil && s.Type == sym.SHOSTOBJ {
- // If a symbol was marked both
- // cgo_import_static and cgo_import_dynamic,
- // then we want to make it cgo_import_dynamic
- // now.
- if s.Extname() != "" && s.Dynimplib() != "" && !s.Attr.CgoExport() {
- s.Type = sym.SDYNIMPORT
- } else {
- s.Type = 0
- }
+// loadcgodirectives reads the previously discovered cgo directives, creating
+// symbols in preparation for host object loading or use later in the link.
+func (ctxt *Link) loadcgodirectives() {
+ l := ctxt.loader
+ hostObjSyms := make(map[loader.Sym]struct{})
+ for _, d := range ctxt.cgodata {
+ setCgoAttr(ctxt, ctxt.loader.LookupOrCreateSym, d.file, d.pkg, d.directives, hostObjSyms)
+ }
+ ctxt.cgodata = nil
+
+ if ctxt.LinkMode == LinkInternal {
+ // Drop all the cgo_import_static declarations.
+ // Turns out we won't be needing them.
+ for symIdx := range hostObjSyms {
+ if l.SymType(symIdx) == sym.SHOSTOBJ {
+ // If a symbol was marked both
+ // cgo_import_static and cgo_import_dynamic,
+ // then we want to make it cgo_import_dynamic
+ // now.
+ su, _ := l.MakeSymbolUpdater(symIdx)
+ if l.SymExtname(symIdx) != "" && l.SymDynimplib(symIdx) != "" && !(l.AttrCgoExportStatic(symIdx) || l.AttrCgoExportDynamic(symIdx)) {
+ su.SetType(sym.SDYNIMPORT)
+ } else {
+ su.SetType(0)
}
}
}
}
}
-// Set up flags and special symbols depending on the platform build mode.
-func (ctxt *Link) linksetupold() {
- switch ctxt.BuildMode {
- case BuildModeCShared, BuildModePlugin:
- s := ctxt.Syms.Lookup("runtime.islibrary", 0)
- s.Type = sym.SNOPTRDATA
- s.Attr |= sym.AttrDuplicateOK
- s.AddUint8(1)
- case BuildModeCArchive:
- s := ctxt.Syms.Lookup("runtime.isarchive", 0)
- s.Type = sym.SNOPTRDATA
- s.Attr |= sym.AttrDuplicateOK
- s.AddUint8(1)
- }
-
- // Recalculate pe parameters now that we have ctxt.LinkMode set.
- if ctxt.HeadType == objabi.Hwindows {
- Peinit(ctxt)
- }
-
- if ctxt.HeadType == objabi.Hdarwin && ctxt.LinkMode == LinkExternal {
- *FlagTextAddr = 0
- }
-
- // If there are no dynamic libraries needed, gcc disables dynamic linking.
- // Because of this, glibc's dynamic ELF loader occasionally (like in version 2.13)
- // assumes that a dynamic binary always refers to at least one dynamic library.
- // Rather than be a source of test cases for glibc, disable dynamic linking
- // the same way that gcc would.
- //
- // Exception: on OS X, programs such as Shark only work with dynamic
- // binaries, so leave it enabled on OS X (Mach-O) binaries.
- // Also leave it enabled on Solaris which doesn't support
- // statically linked binaries.
- if ctxt.BuildMode == BuildModeExe {
- if havedynamic == 0 && ctxt.HeadType != objabi.Hdarwin && ctxt.HeadType != objabi.Hsolaris {
- *FlagD = true
- }
- }
-
- if ctxt.LinkMode == LinkExternal && ctxt.Arch.Family == sys.PPC64 && objabi.GOOS != "aix" {
- toc := ctxt.Syms.Lookup(".TOC.", 0)
- toc.Type = sym.SDYNIMPORT
- }
-
- // The Android Q linker started to complain about underalignment of the our TLS
- // section. We don't actually use the section on android, so dont't
- // generate it.
- if objabi.GOOS != "android" {
- tlsg := ctxt.Syms.Lookup("runtime.tlsg", 0)
-
- // runtime.tlsg is used for external linking on platforms that do not define
- // a variable to hold g in assembly (currently only intel).
- if tlsg.Type == 0 {
- tlsg.Type = sym.STLSBSS
- tlsg.Size = int64(ctxt.Arch.PtrSize)
- } else if tlsg.Type != sym.SDYNIMPORT {
- Errorf(nil, "runtime declared tlsg variable %v", tlsg.Type)
- }
- tlsg.Attr |= sym.AttrReachable
- ctxt.Tlsg = tlsg
- }
-
- var moduledata *sym.Symbol
- if ctxt.BuildMode == BuildModePlugin {
- moduledata = ctxt.Syms.Lookup("local.pluginmoduledata", 0)
- moduledata.Attr |= sym.AttrLocal
- } else {
- moduledata = ctxt.Syms.Lookup("runtime.firstmoduledata", 0)
- }
- if moduledata.Type != 0 && moduledata.Type != sym.SDYNIMPORT {
- // If the module (toolchain-speak for "executable or shared
- // library") we are linking contains the runtime package, it
- // will define the runtime.firstmoduledata symbol and we
- // truncate it back to 0 bytes so we can define its entire
- // contents in symtab.go:symtab().
- moduledata.Size = 0
-
- // In addition, on ARM, the runtime depends on the linker
- // recording the value of GOARM.
- if ctxt.Arch.Family == sys.ARM {
- s := ctxt.Syms.Lookup("runtime.goarm", 0)
- s.Type = sym.SDATA
- s.Size = 0
- s.AddUint8(uint8(objabi.GOARM))
- }
-
- if objabi.Framepointer_enabled(objabi.GOOS, objabi.GOARCH) {
- s := ctxt.Syms.Lookup("runtime.framepointer_enabled", 0)
- s.Type = sym.SDATA
- s.Size = 0
- s.AddUint8(1)
- }
- } else {
- // If OTOH the module does not contain the runtime package,
- // create a local symbol for the moduledata.
- moduledata = ctxt.Syms.Lookup("local.moduledata", 0)
- moduledata.Attr |= sym.AttrLocal
- }
- // In all cases way we mark the moduledata as noptrdata to hide it from
- // the GC.
- moduledata.Type = sym.SNOPTRDATA
- moduledata.Attr |= sym.AttrReachable
- ctxt.Moduledata = moduledata
-
- // If package versioning is required, generate a hash of the
- // packages used in the link.
- if ctxt.BuildMode == BuildModeShared || ctxt.BuildMode == BuildModePlugin || ctxt.CanUsePlugins() {
- for _, lib := range ctxt.Library {
- if lib.Shlib == "" {
- genhash(ctxt, lib)
- }
- }
- }
-
- if ctxt.Arch == sys.Arch386 && ctxt.HeadType != objabi.Hwindows {
- if (ctxt.BuildMode == BuildModeCArchive && ctxt.IsELF) || ctxt.BuildMode == BuildModeCShared || ctxt.BuildMode == BuildModePIE || ctxt.DynlinkingGo() {
- got := ctxt.Syms.Lookup("_GLOBAL_OFFSET_TABLE_", 0)
- got.Type = sym.SDYNIMPORT
- got.Attr |= sym.AttrReachable
- }
- }
-}
-
// mangleTypeSym shortens the names of symbols that represent Go types
// if they are visible in the symbol table.
//