From 1152c6d3f07559f3eccbd3026f6ab63639fdea74 Mon Sep 17 00:00:00 2001 From: Jeremy Faller Date: Fri, 31 Jan 2020 14:35:37 -0500 Subject: [PATCH] [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 TryBot-Result: Gobot Gobot Reviewed-by: Cherry Zhang --- src/cmd/link/internal/ld/go.go | 147 +------------------- src/cmd/link/internal/ld/lib.go | 224 ++++--------------------------- src/cmd/link/internal/ld/main.go | 14 +- 3 files changed, 30 insertions(+), 355 deletions(-) diff --git a/src/cmd/link/internal/ld/go.go b/src/cmd/link/internal/ld/go.go index 555d3b09ab..871420792d 100644 --- a/src/cmd/link/internal/ld/go.go +++ b/src/cmd/link/internal/ld/go.go @@ -151,153 +151,8 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) { } // 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] { diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index 8b26d4a6b2..7ced27ec79 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -459,7 +459,7 @@ func (ctxt *Link) loadlib() { 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) @@ -469,24 +469,9 @@ func (ctxt *Link) loadlib() { // 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 == "" { @@ -563,61 +548,30 @@ func setupdynexp(ctxt *Link) { 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 +// 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) - } - } - } - } - } 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 - } + 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) } } } @@ -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 // if they are visible in the symbol table. // diff --git a/src/cmd/link/internal/ld/main.go b/src/cmd/link/internal/ld/main.go index 81e7997c0b..d3d903cef5 100644 --- a/src/cmd/link/internal/ld/main.go +++ b/src/cmd/link/internal/ld/main.go @@ -100,10 +100,6 @@ var ( 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. func Main(arch *sys.Arch, theArch Arch) { thearch = theArch @@ -235,18 +231,12 @@ func Main(arch *sys.Arch, theArch Arch) { bench.Start("deadcode") deadcode(ctxt) - if ctxt.loaderSupport() { - bench.Start("linksetup") - ctxt.linksetup() - } + bench.Start("linksetup") + ctxt.linksetup() bench.Start("loadlibfull") ctxt.loadlibfull() // XXX do it here for now - if !ctxt.loaderSupport() { - bench.Start("linksetupold") - ctxt.linksetupold() - } bench.Start("dostrdata") ctxt.dostrdata() bench.Start("dwarfGenerateDebugInfo")