diff options
Diffstat (limited to 'src/cmd/link/internal/ld/lib.go')
| -rw-r--r-- | src/cmd/link/internal/ld/lib.go | 53 |
1 files changed, 37 insertions, 16 deletions
diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index 9c95d478b5..dada4cb7a7 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -164,14 +164,18 @@ type Section struct { // DynlinkingGo returns whether we are producing Go code that can live // in separate shared libraries linked together at runtime. func (ctxt *Link) DynlinkingGo() bool { - return Buildmode == BuildmodeShared || *FlagLinkshared + if !ctxt.Loaded { + panic("DynlinkingGo called before all symbols loaded") + } + canUsePlugins := Linkrlookup(ctxt, "plugin.Open", 0) != nil + return Buildmode == BuildmodeShared || *FlagLinkshared || Buildmode == BuildmodePlugin || canUsePlugins } // UseRelro returns whether to make use of "read only relocations" aka // relro. func UseRelro() bool { switch Buildmode { - case BuildmodeCArchive, BuildmodeCShared, BuildmodeShared, BuildmodePIE: + case BuildmodeCArchive, BuildmodeCShared, BuildmodeShared, BuildmodePIE, BuildmodePlugin: return Iself default: return *FlagLinkshared @@ -299,16 +303,12 @@ func libinit(ctxt *Link) { *flagEntrySymbol = fmt.Sprintf("_rt0_%s_%s_lib", obj.GOARCH, obj.GOOS) case BuildmodeExe, BuildmodePIE: *flagEntrySymbol = fmt.Sprintf("_rt0_%s_%s", obj.GOARCH, obj.GOOS) - case BuildmodeShared: - // No *flagEntrySymbol for -buildmode=shared + case BuildmodeShared, BuildmodePlugin: + // No *flagEntrySymbol for -buildmode=shared and plugin default: ctxt.Diag("unknown *flagEntrySymbol for buildmode %v", Buildmode) } } - - if !ctxt.DynlinkingGo() { - Linklookup(ctxt, *flagEntrySymbol, 0).Type = obj.SXREF - } } func Exitf(format string, a ...interface{}) { @@ -400,7 +400,7 @@ func (ctxt *Link) findLibPath(libname string) string { func (ctxt *Link) loadlib() { switch Buildmode { - case BuildmodeCShared: + case BuildmodeCShared, BuildmodePlugin: s := Linklookup(ctxt, "runtime.islibrary", 0) s.Attr |= AttrDuplicateOK Adduint8(ctxt, s, 1) @@ -453,9 +453,14 @@ func (ctxt *Link) loadlib() { Linkmode = LinkExternal } - // Force external linking for PIE binaries on systems - // that do not support internal PIE linking. - if Buildmode == BuildmodePIE { + // These build modes depend on the external linker + // to handle some relocations (such as TLS IE) not + // yet supported by the internal linker. + switch Buildmode { + case BuildmodeCArchive, BuildmodeCShared, BuildmodePIE, BuildmodePlugin, BuildmodeShared: + Linkmode = LinkExternal + } + if *FlagLinkshared { Linkmode = LinkExternal } @@ -492,7 +497,7 @@ func (ctxt *Link) loadlib() { if ctxt.Library[i].Shlib != "" { ldshlibsyms(ctxt, ctxt.Library[i].Shlib) } else { - if ctxt.DynlinkingGo() { + if Buildmode == BuildmodeShared || *FlagLinkshared { Exitf("cannot implicitly include runtime/cgo in a shared library") } objfile(ctxt, ctxt.Library[i]) @@ -531,7 +536,13 @@ func (ctxt *Link) loadlib() { tlsg.Attr |= AttrReachable ctxt.Tlsg = tlsg - moduledata := Linklookup(ctxt, "runtime.firstmoduledata", 0) + var moduledata *Symbol + if Buildmode == BuildmodePlugin { + moduledata = Linklookup(ctxt, "local.pluginmoduledata", 0) + moduledata.Attr |= AttrLocal + } else { + moduledata = Linklookup(ctxt, "runtime.firstmoduledata", 0) + } if moduledata.Type != 0 && moduledata.Type != obj.SDYNIMPORT { // If the module (toolchain-speak for "executable or shared // library") we are linking contains the runtime package, it @@ -626,6 +637,8 @@ func (ctxt *Link) loadlib() { } // We've loaded all the code now. + ctxt.Loaded = true + // 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. @@ -642,6 +655,14 @@ func (ctxt *Link) loadlib() { } } + if SysArch == sys.Arch386 { + if (Buildmode == BuildmodeCArchive && Iself) || Buildmode == BuildmodeCShared || Buildmode == BuildmodePIE || ctxt.DynlinkingGo() { + got := Linklookup(ctxt, "_GLOBAL_OFFSET_TABLE_", 0) + got.Type = obj.SDYNIMPORT + got.Attr |= AttrReachable + } + } + importcycles() } @@ -1012,7 +1033,7 @@ func (l *Link) hostlink() { // non-closeable: a dlclose will do nothing. argv = append(argv, "-shared", "-Wl,-z,nodelete") } - case BuildmodeShared: + case BuildmodeShared, BuildmodePlugin: if UseRelro() { argv = append(argv, "-Wl,-z,relro") } @@ -1658,7 +1679,7 @@ func stkcheck(ctxt *Link, up *chain, depth int) int { // onlyctxt.Diagnose the direct caller. // TODO(mwhudson): actually think about this. if depth == 1 && s.Type != obj.SXREF && !ctxt.DynlinkingGo() && - Buildmode != BuildmodeCArchive && Buildmode != BuildmodePIE && Buildmode != BuildmodeCShared { + Buildmode != BuildmodeCArchive && Buildmode != BuildmodePIE && Buildmode != BuildmodeCShared && Buildmode != BuildmodePlugin { ctxt.Diag("call to external function %s", s.Name) } return -1 |
