// Things without pointers should be in SNOPTRDATA or SNOPTRBSS;
// everything we see should have pointers and should therefore have a type.
if typ == nil {
+ switch s.Name {
+ case "runtime.data", "runtime.edata", "runtime.bss", "runtime.ebss":
+ // Ignore special symbols that are sometimes laid out
+ // as real symbols. See comment about dyld on darwin in
+ // the address function.
+ return
+ }
Errorf(s, "missing Go type information for global symbol: size %d", s.Size)
return
}
ctxt.Logf("%5.2f dodata\n", obj.Cputime())
}
+ if ctxt.DynlinkingGo() && Headtype == obj.Hdarwin {
+ // The values in moduledata are filled out by relocations
+ // pointing to the addresses of these special symbols.
+ // Typically these symbols have no size and are not laid
+ // out with their matching section.
+ //
+ // However on darwin, dyld will find the special symbol
+ // in the first loaded module, even though it is local.
+ //
+ // (An hypothesis, formed without looking in the dyld sources:
+ // these special symbols have no size, so their address
+ // matches a real symbol. The dynamic linker assumes we
+ // want the normal symbol with the same address and finds
+ // it in the other module.)
+ //
+ // To work around this we lay out the symbls whose
+ // addresses are vital for multi-module programs to work
+ // as normal symbols, and give them a little size.
+ bss := ctxt.Syms.Lookup("runtime.bss", 0)
+ bss.Size = 8
+ bss.Attr.Set(AttrSpecial, false)
+
+ ctxt.Syms.Lookup("runtime.ebss", 0).Attr.Set(AttrSpecial, false)
+
+ data := ctxt.Syms.Lookup("runtime.data", 0)
+ data.Size = 8
+ data.Attr.Set(AttrSpecial, false)
+
+ ctxt.Syms.Lookup("runtime.edata", 0).Attr.Set(AttrSpecial, false)
+
+ types := ctxt.Syms.Lookup("runtime.types", 0)
+ types.Type = obj.STYPE
+ types.Size = 8
+ types.Attr.Set(AttrSpecial, false)
+
+ etypes := ctxt.Syms.Lookup("runtime.etypes", 0)
+ etypes.Type = obj.SFUNCTAB
+ etypes.Attr.Set(AttrSpecial, false)
+ }
+
// Collect data symbols by type into data.
var data [obj.SXREF][]*Symbol
for _, s := range ctxt.Syms.Allsym {
syms = newSyms
}
- symsSort := make([]dataSortKey, len(syms))
- for i, s := range syms {
+ var head, tail *Symbol
+ symsSort := make([]dataSortKey, 0, len(syms))
+ for _, s := range syms {
if s.Attr.OnList() {
log.Fatalf("symbol %s listed multiple times", s.Name)
}
Errorf(s, "symbol too large (%d bytes)", s.Size)
}
- symsSort[i] = dataSortKey{
+ // If the usually-special section-marker symbols are being laid
+ // out as regular symbols, put them either at the beginning or
+ // end of their section.
+ if ctxt.DynlinkingGo() && Headtype == obj.Hdarwin {
+ switch s.Name {
+ case "runtime.text", "runtime.bss", "runtime.data", "runtime.types":
+ head = s
+ continue
+ case "runtime.etext", "runtime.ebss", "runtime.edata", "runtime.etypes":
+ tail = s
+ continue
+ }
+ }
+
+ key := dataSortKey{
size: s.Size,
name: s.Name,
sym: s,
// from input files. Both are type SELFGOT, so in that case
// we skip size comparison and fall through to the name
// comparison (conveniently, .got sorts before .toc).
- symsSort[i].size = 0
+ key.size = 0
case obj.STYPELINK:
// Sort typelinks by the rtype.string field so the reflect
// package can binary search type links.
- symsSort[i].name = string(decodetypeStr(s.R[0].Sym))
+ key.name = string(decodetypeStr(s.R[0].Sym))
}
+
+ symsSort = append(symsSort, key)
}
sort.Sort(bySizeAndName(symsSort))
+ off := 0
+ if head != nil {
+ syms[0] = head
+ off++
+ }
for i, symSort := range symsSort {
- syms[i] = symSort.sym
+ syms[i+off] = symSort.sym
align := symalign(symSort.sym)
if maxAlign < align {
maxAlign = align
}
}
+ if tail != nil {
+ syms[len(syms)-1] = tail
+ }
if Iself && symn == obj.SELFROSECT {
// Make .rela and .rela.plt contiguous, the ELF ABI requires this
// at the very beginning of the text segment.
// This ``header'' is read by cmd/go.
func (ctxt *Link) textbuildid() {
- if Iself || *flagBuildid == "" {
+ if Iself || Buildmode == BuildmodePlugin || *flagBuildid == "" {
return
}
sect := Segtext.Sect
sect.Align = int32(Funcalign)
- ctxt.Syms.Lookup("runtime.text", 0).Sect = sect
+
+ text := ctxt.Syms.Lookup("runtime.text", 0)
+ text.Sect = sect
+
+ if ctxt.DynlinkingGo() && Headtype == obj.Hdarwin {
+ etext := ctxt.Syms.Lookup("runtime.etext", 0)
+ etext.Sect = sect
+
+ ctxt.Textp = append(ctxt.Textp, etext, nil)
+ copy(ctxt.Textp[1:], ctxt.Textp)
+ ctxt.Textp[0] = text
+ }
+
if Headtype == obj.Hwindows || Headtype == obj.Hwindowsgui {
ctxt.Syms.Lookup(".text", 0).Sect = sect
}
switch Headtype {
case obj.Hdarwin:
- argv = append(argv, "-Wl,-no_pie,-headerpad,1144")
+ argv = append(argv, "-Wl,-headerpad,1144")
+ if l.DynlinkingGo() {
+ argv = append(argv, "-Wl,-flat_namespace")
+ } else {
+ argv = append(argv, "-Wl,-no_pie")
+ }
case obj.Hopenbsd:
argv = append(argv, "-Wl,-nopie")
case obj.Hwindows:
// non-closeable: a dlclose will do nothing.
argv = append(argv, "-shared", "-Wl,-z,nodelete")
}
- case BuildmodeShared, BuildmodePlugin:
+ case BuildmodeShared:
if UseRelro() {
argv = append(argv, "-Wl,-z,relro")
}
argv = append(argv, "-shared")
+ case BuildmodePlugin:
+ if Headtype == obj.Hdarwin {
+ argv = append(argv, "-dynamiclib")
+ } else {
+ if UseRelro() {
+ argv = append(argv, "-Wl,-z,relro")
+ }
+ argv = append(argv, "-shared")
+ }
}
if Iself && l.DynlinkingGo() {
var msect *MachoSect
if sect.Rwx&1 == 0 && segname != "__DWARF" && (SysArch.Family == sys.ARM64 ||
- (SysArch.Family == sys.AMD64 && (Buildmode == BuildmodeCShared || Buildmode == BuildmodeCArchive)) ||
- (SysArch.Family == sys.ARM && (Buildmode == BuildmodeCShared || Buildmode == BuildmodeCArchive))) {
+ (SysArch.Family == sys.AMD64 && (Buildmode == BuildmodeCShared || Buildmode == BuildmodeCArchive || Buildmode == BuildmodePlugin)) ||
+ (SysArch.Family == sys.ARM && (Buildmode == BuildmodeCShared || Buildmode == BuildmodeCArchive || Buildmode == BuildmodePlugin))) {
// Darwin external linker on arm64 and on amd64 and arm in c-shared/c-archive buildmode
// complains about absolute relocs in __TEXT, so if the section is not
// executable, put it in __DATA segment.
s := sortsym[i]
Adduint32(ctxt, symtab, uint32(symstr.Size))
- // Only add _ to C symbols. Go symbols have dot in the name.
- if !strings.Contains(s.Extname, ".") {
+ // In normal buildmodes, only add _ to C symbols, as
+ // Go symbols have dot in the name.
+ //
+ // When dynamically linking, prefix all non-local
+ // symbols with _ as dlsym on darwin requires it to
+ // resolve any symbol.
+ if !strings.Contains(s.Extname, ".") || (ctxt.DynlinkingGo() && !s.Attr.Local()) {
Adduint8(ctxt, symstr, '_')
}
Adduint16(ctxt, symtab, 0) // desc
adduintxx(ctxt, symtab, 0, SysArch.PtrSize) // no value
} else {
- if s.Attr.CgoExport() {
+ if s.Attr.CgoExport() || (ctxt.DynlinkingGo() && !s.Attr.Local()) {
Adduint8(ctxt, symtab, 0x0f)
} else {
Adduint8(ctxt, symtab, 0x0e)