1
0
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:
Jeremy Faller 2020-03-09 10:35:31 -04:00
parent d44c9a046b
commit 4d5fdd74ab
3 changed files with 137 additions and 122 deletions

View File

@ -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

View File

@ -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

View File

@ -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
//