mirror of
https://github.com/golang/go
synced 2024-11-06 10:26:10 -07:00
[dev.link] cmd/link: remove old host object loader vestiges
Change-Id: Ic27d1d62d1b411fa7cdf66af44f9843aa644e776 Reviewed-on: https://go-review.googlesource.com/c/go/+/217558 Run-TryBot: Jeremy Faller <jeremy@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
parent
9857e5c815
commit
1152c6d3f0
@ -151,153 +151,8 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set symbol attributes or flags based on cgo directives.
|
// 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'.
|
// 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
|
l := ctxt.loader
|
||||||
for _, f := range directives {
|
for _, f := range directives {
|
||||||
switch f[0] {
|
switch f[0] {
|
||||||
|
@ -459,7 +459,7 @@ func (ctxt *Link) loadlib() {
|
|||||||
ctxt.loader.LoadRefs(ctxt.Arch, ctxt.Syms)
|
ctxt.loader.LoadRefs(ctxt.Arch, ctxt.Syms)
|
||||||
|
|
||||||
// Process cgo directives (has to be done before host object loading).
|
// 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.
|
// Conditionally load host objects, or setup for external linking.
|
||||||
hostobjs(ctxt)
|
hostobjs(ctxt)
|
||||||
@ -469,25 +469,10 @@ func (ctxt *Link) loadlib() {
|
|||||||
// If we have any undefined symbols in external
|
// If we have any undefined symbols in external
|
||||||
// objects, try to read them from the libgcc file.
|
// objects, try to read them from the libgcc file.
|
||||||
any := false
|
any := false
|
||||||
if ctxt.loaderSupport() {
|
|
||||||
undefs := ctxt.loader.UndefinedRelocTargets(1)
|
undefs := ctxt.loader.UndefinedRelocTargets(1)
|
||||||
if len(undefs) > 0 {
|
if len(undefs) > 0 {
|
||||||
any = true
|
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if any {
|
if any {
|
||||||
if *flagLibGCC == "" {
|
if *flagLibGCC == "" {
|
||||||
*flagLibGCC = ctxt.findLibPathCmd("--print-libgcc-file-name", "libgcc")
|
*flagLibGCC = ctxt.findLibPathCmd("--print-libgcc-file-name", "libgcc")
|
||||||
@ -563,15 +548,13 @@ func setupdynexp(ctxt *Link) {
|
|||||||
ctxt.cgo_export_dynamic = nil
|
ctxt.cgo_export_dynamic = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// loadcgodirectives reads the previously discovered cgo directives,
|
// loadcgodirectives reads the previously discovered cgo directives, creating
|
||||||
// creating symbols (either sym.Symbol or loader.Sym) in preparation
|
// symbols in preparation for host object loading or use later in the link.
|
||||||
// for host object loading or use later in the link.
|
func (ctxt *Link) loadcgodirectives() {
|
||||||
func (ctxt *Link) loadcgodirectives(useLoader bool) {
|
|
||||||
if useLoader {
|
|
||||||
l := ctxt.loader
|
l := ctxt.loader
|
||||||
hostObjSyms := make(map[loader.Sym]struct{})
|
hostObjSyms := make(map[loader.Sym]struct{})
|
||||||
for _, d := range ctxt.cgodata {
|
for _, d := range ctxt.cgodata {
|
||||||
setCgoAttr2(ctxt, ctxt.loader.LookupOrCreateSym, d.file, d.pkg, d.directives, hostObjSyms)
|
setCgoAttr(ctxt, ctxt.loader.LookupOrCreateSym, d.file, d.pkg, d.directives, hostObjSyms)
|
||||||
}
|
}
|
||||||
ctxt.cgodata = nil
|
ctxt.cgodata = nil
|
||||||
|
|
||||||
@ -593,35 +576,6 @@ func (ctxt *Link) loadcgodirectives(useLoader bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up flags and special symbols depending on the platform build mode.
|
// Set up flags and special symbols depending on the platform build mode.
|
||||||
@ -758,130 +712,6 @@ func (ctxt *Link) linksetup() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
// mangleTypeSym shortens the names of symbols that represent Go types
|
||||||
// if they are visible in the symbol table.
|
// if they are visible in the symbol table.
|
||||||
//
|
//
|
||||||
|
@ -100,10 +100,6 @@ var (
|
|||||||
benchmarkFlag = flag.String("benchmark", "", "set to 'mem' or 'cpu' to enable phase benchmarking")
|
benchmarkFlag = flag.String("benchmark", "", "set to 'mem' or 'cpu' to enable phase benchmarking")
|
||||||
)
|
)
|
||||||
|
|
||||||
func (ctxt *Link) loaderSupport() bool {
|
|
||||||
return true //ctxt.IsELF || ctxt.HeadType == objabi.Hdarwin || ctxt.HeadType == objabi.Haix
|
|
||||||
}
|
|
||||||
|
|
||||||
// Main is the main entry point for the linker code.
|
// Main is the main entry point for the linker code.
|
||||||
func Main(arch *sys.Arch, theArch Arch) {
|
func Main(arch *sys.Arch, theArch Arch) {
|
||||||
thearch = theArch
|
thearch = theArch
|
||||||
@ -235,18 +231,12 @@ func Main(arch *sys.Arch, theArch Arch) {
|
|||||||
bench.Start("deadcode")
|
bench.Start("deadcode")
|
||||||
deadcode(ctxt)
|
deadcode(ctxt)
|
||||||
|
|
||||||
if ctxt.loaderSupport() {
|
|
||||||
bench.Start("linksetup")
|
bench.Start("linksetup")
|
||||||
ctxt.linksetup()
|
ctxt.linksetup()
|
||||||
}
|
|
||||||
|
|
||||||
bench.Start("loadlibfull")
|
bench.Start("loadlibfull")
|
||||||
ctxt.loadlibfull() // XXX do it here for now
|
ctxt.loadlibfull() // XXX do it here for now
|
||||||
|
|
||||||
if !ctxt.loaderSupport() {
|
|
||||||
bench.Start("linksetupold")
|
|
||||||
ctxt.linksetupold()
|
|
||||||
}
|
|
||||||
bench.Start("dostrdata")
|
bench.Start("dostrdata")
|
||||||
ctxt.dostrdata()
|
ctxt.dostrdata()
|
||||||
bench.Start("dwarfGenerateDebugInfo")
|
bench.Start("dwarfGenerateDebugInfo")
|
||||||
|
Loading…
Reference in New Issue
Block a user