diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go index bef049d7b26..603630c6bc9 100644 --- a/src/cmd/link/internal/ld/data.go +++ b/src/cmd/link/internal/ld/data.go @@ -1155,71 +1155,135 @@ func checkdatsize(ctxt *Link, datsize int64, symn sym.SymKind) { } } +// fixZeroSizedSymbols gives a few special symbols with zero size some space. +func fixZeroSizedSymbols(ctxt *Link) { + // 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. + // + // On AIX, as all DATA sections are merged together, ld might not put + // these symbols at the beginning of their respective section if there + // aren't real symbols, their alignment might not match the + // first symbol alignment. Therefore, there are explicitly put at the + // beginning of their section with the same alignment. + if !(ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin) && !(ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal) { + return + } + + bss := ctxt.Syms.Lookup("runtime.bss", 0) + bss.Size = 8 + bss.Attr.Set(sym.AttrSpecial, false) + + ctxt.Syms.Lookup("runtime.ebss", 0).Attr.Set(sym.AttrSpecial, false) + + data := ctxt.Syms.Lookup("runtime.data", 0) + data.Size = 8 + data.Attr.Set(sym.AttrSpecial, false) + + edata := ctxt.Syms.Lookup("runtime.edata", 0) + edata.Attr.Set(sym.AttrSpecial, false) + if ctxt.HeadType == objabi.Haix { + // XCOFFTOC symbols are part of .data section. + edata.Type = sym.SXCOFFTOC + } + + types := ctxt.Syms.Lookup("runtime.types", 0) + types.Type = sym.STYPE + types.Size = 8 + types.Attr.Set(sym.AttrSpecial, false) + + etypes := ctxt.Syms.Lookup("runtime.etypes", 0) + etypes.Type = sym.SFUNCTAB + etypes.Attr.Set(sym.AttrSpecial, false) + + if ctxt.HeadType == objabi.Haix { + rodata := ctxt.Syms.Lookup("runtime.rodata", 0) + rodata.Type = sym.SSTRING + rodata.Size = 8 + rodata.Attr.Set(sym.AttrSpecial, false) + + ctxt.Syms.Lookup("runtime.erodata", 0).Attr.Set(sym.AttrSpecial, false) + } +} + +// makeRelroForSharedLib creates a section of readonly data if necessary. +func makeRelroForSharedLib(target *Link, data *[sym.SXREF][]*sym.Symbol) { + if !target.UseRelro() { + return + } + + // "read only" data with relocations needs to go in its own section + // when building a shared library. We do this by boosting objects of + // type SXXX with relocations to type SXXXRELRO. + for _, symnro := range sym.ReadOnly { + symnrelro := sym.RelROMap[symnro] + + ro := []*sym.Symbol{} + relro := data[symnrelro] + + for _, s := range data[symnro] { + isRelro := len(s.R) > 0 + switch s.Type { + case sym.STYPE, sym.STYPERELRO, sym.SGOFUNCRELRO: + // Symbols are not sorted yet, so it is possible + // that an Outer symbol has been changed to a + // relro Type before it reaches here. + isRelro = true + case sym.SFUNCTAB: + if target.IsAIX() && s.Name == "runtime.etypes" { + // runtime.etypes must be at the end of + // the relro datas. + isRelro = true + } + } + if isRelro { + s.Type = symnrelro + if s.Outer != nil { + s.Outer.Type = s.Type + } + relro = append(relro, s) + } else { + ro = append(ro, s) + } + } + + // Check that we haven't made two symbols with the same .Outer into + // different types (because references two symbols with non-nil Outer + // become references to the outer symbol + offset it's vital that the + // symbol and the outer end up in the same section). + for _, s := range relro { + if s.Outer != nil && s.Outer.Type != s.Type { + Errorf(s, "inconsistent types for symbol and its Outer %s (%v != %v)", + s.Outer.Name, s.Type, s.Outer.Type) + } + } + + data[symnro] = ro + data[symnrelro] = relro + } +} + // datap is a collection of reachable data symbols in address order. // Generated by dodata. var datap []*sym.Symbol func (ctxt *Link) dodata() { - if (ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin) || (ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal) { - // 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. - // - // On AIX, as all DATA sections are merged together, ld might not put - // these symbols at the beginning of their respective section if there - // aren't real symbols, their alignment might not match the - // first symbol alignment. Therefore, there are explicitly put at the - // beginning of their section with the same alignment. - bss := ctxt.Syms.Lookup("runtime.bss", 0) - bss.Size = 8 - bss.Attr.Set(sym.AttrSpecial, false) - - ctxt.Syms.Lookup("runtime.ebss", 0).Attr.Set(sym.AttrSpecial, false) - - data := ctxt.Syms.Lookup("runtime.data", 0) - data.Size = 8 - data.Attr.Set(sym.AttrSpecial, false) - - edata := ctxt.Syms.Lookup("runtime.edata", 0) - edata.Attr.Set(sym.AttrSpecial, false) - if ctxt.HeadType == objabi.Haix { - // XCOFFTOC symbols are part of .data section. - edata.Type = sym.SXCOFFTOC - } - - types := ctxt.Syms.Lookup("runtime.types", 0) - types.Type = sym.STYPE - types.Size = 8 - types.Attr.Set(sym.AttrSpecial, false) - - etypes := ctxt.Syms.Lookup("runtime.etypes", 0) - etypes.Type = sym.SFUNCTAB - etypes.Attr.Set(sym.AttrSpecial, false) - - if ctxt.HeadType == objabi.Haix { - rodata := ctxt.Syms.Lookup("runtime.rodata", 0) - rodata.Type = sym.SSTRING - rodata.Size = 8 - rodata.Attr.Set(sym.AttrSpecial, false) - - ctxt.Syms.Lookup("runtime.erodata", 0).Attr.Set(sym.AttrSpecial, false) - - } - } + // Give zeros sized symbols space if necessary. + fixZeroSizedSymbols(ctxt) // Collect data symbols by type into data. var data [sym.SXREF][]*sym.Symbol @@ -1244,57 +1308,8 @@ func (ctxt *Link) dodata() { } dynreloc(ctxt, &data) - if ctxt.UseRelro() { - // "read only" data with relocations needs to go in its own section - // when building a shared library. We do this by boosting objects of - // type SXXX with relocations to type SXXXRELRO. - for _, symnro := range sym.ReadOnly { - symnrelro := sym.RelROMap[symnro] - - ro := []*sym.Symbol{} - relro := data[symnrelro] - - for _, s := range data[symnro] { - isRelro := len(s.R) > 0 - switch s.Type { - case sym.STYPE, sym.STYPERELRO, sym.SGOFUNCRELRO: - // Symbols are not sorted yet, so it is possible - // that an Outer symbol has been changed to a - // relro Type before it reaches here. - isRelro = true - case sym.SFUNCTAB: - if ctxt.HeadType == objabi.Haix && s.Name == "runtime.etypes" { - // runtime.etypes must be at the end of - // the relro datas. - isRelro = true - } - } - if isRelro { - s.Type = symnrelro - if s.Outer != nil { - s.Outer.Type = s.Type - } - relro = append(relro, s) - } else { - ro = append(ro, s) - } - } - - // Check that we haven't made two symbols with the same .Outer into - // different types (because references two symbols with non-nil Outer - // become references to the outer symbol + offset it's vital that the - // symbol and the outer end up in the same section). - for _, s := range relro { - if s.Outer != nil && s.Outer.Type != s.Type { - Errorf(s, "inconsistent types for symbol and its Outer %s (%v != %v)", - s.Outer.Name, s.Type, s.Outer.Type) - } - } - - data[symnro] = ro - data[symnrelro] = relro - } - } + // Move any RO data with relocations to a separate section. + makeRelroForSharedLib(ctxt, &data) // Sort symbols. var dataMaxAlign [sym.SXREF]int32 diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index e2051035c9c..1537bc662bc 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -251,17 +251,6 @@ func (ctxt *Link) CanUsePlugins() bool { return ctxt.canUsePlugins } -// UseRelro reports whether to make use of "read only relocations" aka -// relro. -func (ctxt *Link) UseRelro() bool { - switch ctxt.BuildMode { - case BuildModeCArchive, BuildModeCShared, BuildModeShared, BuildModePIE, BuildModePlugin: - return ctxt.IsELF || ctxt.HeadType == objabi.Haix - default: - return ctxt.linkShared || (ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal) - } -} - var ( dynexp []*sym.Symbol dynlib []string diff --git a/src/cmd/link/internal/ld/target.go b/src/cmd/link/internal/ld/target.go index 197c4122142..95f6ca17abd 100644 --- a/src/cmd/link/internal/ld/target.go +++ b/src/cmd/link/internal/ld/target.go @@ -64,6 +64,17 @@ func (t *Target) IsDynlinkingGo() bool { return t.IsShared() || t.IsSharedGoLink() || t.IsPlugin() || t.CanUsePlugins() } +// UseRelro reports whether to make use of "read only relocations" aka +// relro. +func (t *Target) UseRelro() bool { + switch t.BuildMode { + case BuildModeCArchive, BuildModeCShared, BuildModeShared, BuildModePIE, BuildModePlugin: + return t.IsELF || t.HeadType == objabi.Haix + default: + return t.linkShared || (t.HeadType == objabi.Haix && t.LinkMode == LinkExternal) + } +} + // // Processor functions //