mirror of
https://github.com/golang/go
synced 2024-11-23 23:10:09 -07:00
[dev.link] cmd/link: refactor some of dodata
This is a non-functional change, just moving things around, making dodata a more approachable piece of code. Change-Id: I06fa047cbef2313040a31998fa8d242ccb2fedea Reviewed-on: https://go-review.googlesource.com/c/go/+/222662 Run-TryBot: Jeremy Faller <jeremy@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Than McIntosh <thanm@google.com>
This commit is contained in:
parent
d44c9a046b
commit
4d5fdd74ab
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
//
|
||||
|
Loading…
Reference in New Issue
Block a user