mirror of
https://github.com/golang/go.git
synced 2026-02-07 02:09:55 +00:00
cmd/link: put type descriptors in .go.type section
This change rewrites and simplifies the relro handling. We eliminate the separate relro SymKind values and the complex shifting of symbol kinds. Instead, we put the possible relro data into their own sections, and make those sections relro when appropriate. We put type descriptors and their associated data into a new .go.type section. As part of this we change the runtime.etypes symbol to be the end of the new section, rather than the end of rodata as it was before. We put function descriptors into a new .go.func section. Ordinary rodata relro stays in the .data.rel.ro section. We stop making the typelink section relro, as it only contains offsets and never has dynamic relocations. We drop the typerel:* and go:funcdescrel symbols. For #76038 Change-Id: I7aab7cfad3f2623ff06c09a70b756fe1e43f4169 Reviewed-on: https://go-review.googlesource.com/c/go/+/723580 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Cherry Mui <cherryyz@google.com> Reviewed-by: Keith Randall <khr@google.com> Reviewed-by: Keith Randall <khr@golang.org> Auto-Submit: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
6edb9f9c51
commit
13096a62e6
8 changed files with 457 additions and 333 deletions
|
|
@ -1536,7 +1536,7 @@ func fixZeroSizedSymbols(ctxt *Link) {
|
|||
ldr.SetAttrSpecial(types.Sym(), false)
|
||||
|
||||
etypes := ldr.CreateSymForUpdate("runtime.etypes", 0)
|
||||
etypes.SetType(sym.SFUNCTAB)
|
||||
etypes.SetType(sym.STYPE)
|
||||
ldr.SetAttrSpecial(etypes.Sym(), false)
|
||||
|
||||
if ctxt.HeadType == objabi.Haix {
|
||||
|
|
@ -1558,67 +1558,40 @@ func (state *dodataState) makeRelroForSharedLib(target *Link) {
|
|||
|
||||
// "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.
|
||||
// type SRODATA with relocations to type SRODATARELRO.
|
||||
ldr := target.loader
|
||||
for _, symnro := range sym.ReadOnly {
|
||||
symnrelro := sym.RelROMap[symnro]
|
||||
|
||||
ro := []loader.Sym{}
|
||||
relro := state.data[symnrelro]
|
||||
|
||||
for _, s := range state.data[symnro] {
|
||||
relocs := ldr.Relocs(s)
|
||||
isRelro := relocs.Count() > 0
|
||||
switch state.symType(s) {
|
||||
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 ldr.SymName(s) == "runtime.etypes" {
|
||||
// runtime.etypes must be at the end of
|
||||
// the relro data.
|
||||
isRelro = true
|
||||
}
|
||||
case sym.SGOFUNC, sym.SPCLNTAB:
|
||||
// The only SGOFUNC symbols that contain relocations are .stkobj,
|
||||
// and their relocations are of type objabi.R_ADDROFF,
|
||||
// which always get resolved during linking.
|
||||
isRelro = false
|
||||
}
|
||||
if isRelro {
|
||||
if symnrelro == sym.Sxxx {
|
||||
state.ctxt.Errorf(s, "cannot contain relocations (type %v)", symnro)
|
||||
}
|
||||
state.setSymType(s, symnrelro)
|
||||
if outer := ldr.OuterSym(s); outer != 0 {
|
||||
state.setSymType(outer, symnrelro)
|
||||
}
|
||||
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 {
|
||||
ro := []loader.Sym{}
|
||||
relro := state.data[sym.SRODATARELRO]
|
||||
for _, s := range state.data[sym.SRODATA] {
|
||||
relocs := ldr.Relocs(s)
|
||||
if relocs.Count() == 0 {
|
||||
ro = append(ro, s)
|
||||
} else {
|
||||
state.setSymType(s, sym.SRODATARELRO)
|
||||
if outer := ldr.OuterSym(s); outer != 0 {
|
||||
st := state.symType(s)
|
||||
ost := state.symType(outer)
|
||||
if st != ost {
|
||||
state.ctxt.Errorf(s, "inconsistent types for symbol and its Outer %s (%v != %v)",
|
||||
ldr.SymName(outer), st, ost)
|
||||
}
|
||||
state.setSymType(outer, sym.SRODATARELRO)
|
||||
}
|
||||
relro = append(relro, 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 outer := ldr.OuterSym(s); outer != 0 {
|
||||
st := state.symType(s)
|
||||
ost := state.symType(outer)
|
||||
if st != ost {
|
||||
state.ctxt.Errorf(s, "inconsistent types for symbol and its Outer %s (%v != %v)",
|
||||
ldr.SymName(outer), st, ost)
|
||||
}
|
||||
}
|
||||
|
||||
state.data[symnro] = ro
|
||||
state.data[symnrelro] = relro
|
||||
}
|
||||
|
||||
state.data[sym.SRODATA] = ro
|
||||
state.data[sym.SRODATARELRO] = relro
|
||||
}
|
||||
|
||||
// dodataState holds bits of state information needed by dodata() and the
|
||||
|
|
@ -2119,10 +2092,6 @@ func (state *dodataState) allocateDataSections(ctxt *Link) {
|
|||
sect = state.allocateNamedDataSection(segro, ".rodata", sym.ReadOnly, 04)
|
||||
ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.rodata", 0), sect)
|
||||
ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.erodata", 0), sect)
|
||||
if !ctxt.UseRelro() {
|
||||
ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.types", 0), sect)
|
||||
ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.etypes", 0), sect)
|
||||
}
|
||||
for _, symn := range sym.ReadOnly {
|
||||
symnStartValue := state.datsize
|
||||
if len(state.data[symn]) != 0 {
|
||||
|
|
@ -2155,107 +2124,8 @@ func (state *dodataState) allocateDataSections(ctxt *Link) {
|
|||
xcoffUpdateOuterSize(ctxt, int64(sect.Length), sym.SPCLNTAB)
|
||||
}
|
||||
|
||||
/* read-only ELF, Mach-O sections */
|
||||
state.allocateSingleSymSections(segro, sym.SELFROSECT, sym.SRODATA, 04)
|
||||
|
||||
// There is some data that are conceptually read-only but are written to by
|
||||
// relocations. On GNU systems, we can arrange for the dynamic linker to
|
||||
// mprotect sections after relocations are applied by giving them write
|
||||
// permissions in the object file and calling them ".data.rel.ro.FOO". We
|
||||
// divide the .rodata section between actual .rodata and .data.rel.ro.rodata,
|
||||
// but for the other sections that this applies to, we just write a read-only
|
||||
// .FOO section or a read-write .data.rel.ro.FOO section depending on the
|
||||
// situation.
|
||||
// TODO(mwhudson): It would make sense to do this more widely, but it makes
|
||||
// the system linker segfault on darwin.
|
||||
const relroPerm = 06
|
||||
const fallbackPerm = 04
|
||||
relroSecPerm := fallbackPerm
|
||||
genrelrosecname := func(suffix string) string {
|
||||
if suffix == "" {
|
||||
return ".rodata"
|
||||
}
|
||||
return suffix
|
||||
}
|
||||
seg := segro
|
||||
|
||||
if ctxt.UseRelro() {
|
||||
segrelro := &Segrelrodata
|
||||
if ctxt.LinkMode == LinkExternal && !ctxt.IsAIX() && !ctxt.IsDarwin() {
|
||||
// Using a separate segment with an external
|
||||
// linker results in some programs moving
|
||||
// their data sections unexpectedly, which
|
||||
// corrupts the moduledata. So we use the
|
||||
// rodata segment and let the external linker
|
||||
// sort out a rel.ro segment.
|
||||
segrelro = segro
|
||||
} else {
|
||||
// Reset datsize for new segment.
|
||||
state.datsize = 0
|
||||
}
|
||||
|
||||
if !ctxt.IsDarwin() { // We don't need the special names on darwin.
|
||||
genrelrosecname = func(suffix string) string {
|
||||
return ".data.rel.ro" + suffix
|
||||
}
|
||||
}
|
||||
|
||||
relroReadOnly := []sym.SymKind{}
|
||||
for _, symnro := range sym.ReadOnly {
|
||||
symn := sym.RelROMap[symnro]
|
||||
relroReadOnly = append(relroReadOnly, symn)
|
||||
}
|
||||
seg = segrelro
|
||||
relroSecPerm = relroPerm
|
||||
|
||||
/* data only written by relocations */
|
||||
sect = state.allocateNamedDataSection(segrelro, genrelrosecname(""), relroReadOnly, relroSecPerm)
|
||||
|
||||
ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.types", 0), sect)
|
||||
ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.etypes", 0), sect)
|
||||
|
||||
for i, symnro := range sym.ReadOnly {
|
||||
if i == 0 && symnro == sym.STYPE && ctxt.HeadType != objabi.Haix {
|
||||
// Skip forward so that no type
|
||||
// reference uses a zero offset.
|
||||
// This is unlikely but possible in small
|
||||
// programs with no other read-only data.
|
||||
state.datsize++
|
||||
}
|
||||
|
||||
symn := sym.RelROMap[symnro]
|
||||
if symn == sym.Sxxx {
|
||||
continue
|
||||
}
|
||||
symnStartValue := state.datsize
|
||||
if len(state.data[symn]) != 0 {
|
||||
symnStartValue = aligndatsize(state, symnStartValue, state.data[symn][0])
|
||||
}
|
||||
|
||||
for _, s := range state.data[symn] {
|
||||
outer := ldr.OuterSym(s)
|
||||
if s != 0 && ldr.SymSect(outer) != nil && ldr.SymSect(outer) != sect {
|
||||
ctxt.Errorf(s, "s.Outer (%s) in different section from s, %s != %s", ldr.SymName(outer), ldr.SymSect(outer).Name, sect.Name)
|
||||
}
|
||||
}
|
||||
state.assignToSection(sect, symn, sym.SRODATA)
|
||||
setCarrierSize(symn, state.datsize-symnStartValue)
|
||||
if ctxt.HeadType == objabi.Haix {
|
||||
// Read-only symbols might be wrapped inside their outer
|
||||
// symbol.
|
||||
// XCOFF symbol table needs to know the size of
|
||||
// these outer symbols.
|
||||
xcoffUpdateOuterSize(ctxt, state.datsize-symnStartValue, symn)
|
||||
}
|
||||
}
|
||||
sect.Length = uint64(state.datsize) - sect.Vaddr
|
||||
|
||||
state.allocateSingleSymSections(segrelro, sym.SELFRELROSECT, sym.SRODATA, relroSecPerm)
|
||||
state.allocateSingleSymSections(segrelro, sym.SMACHORELROSECT, sym.SRODATA, relroSecPerm)
|
||||
}
|
||||
|
||||
/* typelink */
|
||||
sect = state.allocateNamedDataSection(seg, genrelrosecname(".typelink"), []sym.SymKind{sym.STYPELINK}, relroSecPerm)
|
||||
sect = state.allocateNamedDataSection(segro, ".typelink", []sym.SymKind{sym.STYPELINK}, 04)
|
||||
|
||||
typelink := ldr.CreateSymForUpdate("runtime.typelink", 0)
|
||||
ldr.SetSymSect(typelink.Sym(), sect)
|
||||
|
|
@ -2264,8 +2134,105 @@ func (state *dodataState) allocateDataSections(ctxt *Link) {
|
|||
state.checkdatsize(sym.STYPELINK)
|
||||
sect.Length = uint64(state.datsize) - sect.Vaddr
|
||||
|
||||
/* read-only ELF, Mach-O sections */
|
||||
state.allocateSingleSymSections(segro, sym.SELFROSECT, sym.SRODATA, 04)
|
||||
|
||||
// Read-only data that may require dynamic relocations at run time.
|
||||
//
|
||||
// On GNU systems, we can arrange for the dynamic linker to
|
||||
// mprotect sections after relocations are applied by giving them write
|
||||
// permissions in the object file and calling them ".data.rel.ro.FOO".
|
||||
|
||||
relroPerm := 04
|
||||
genrelrosecname := func(suffix string) string {
|
||||
if suffix == "" {
|
||||
return ".rodata"
|
||||
}
|
||||
return suffix
|
||||
}
|
||||
segRelro := segro
|
||||
|
||||
if ctxt.UseRelro() {
|
||||
if ctxt.LinkMode == LinkExternal && !ctxt.IsAIX() && !ctxt.IsDarwin() {
|
||||
// Using a separate segment with an external
|
||||
// linker results in some programs moving
|
||||
// their data sections unexpectedly, which
|
||||
// corrupts the moduledata. So we use the
|
||||
// rodata segment and let the external linker
|
||||
// sort out a rel.ro segment.
|
||||
} else {
|
||||
segRelro = &Segrelrodata
|
||||
// Reset datsize for new segment.
|
||||
state.datsize = 0
|
||||
}
|
||||
|
||||
relroPerm = 06
|
||||
|
||||
if !ctxt.IsDarwin() { // We don't need the special names on darwin.
|
||||
genrelrosecname = func(suffix string) string {
|
||||
return ".data.rel.ro" + suffix
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// checkOuter is a sanity check that for all the symbols of some kind,
|
||||
// which are in a given section, any carrier symbol is also in
|
||||
// that section.
|
||||
checkOuter := func(sect *sym.Section, symn sym.SymKind) {
|
||||
for _, s := range state.data[symn] {
|
||||
outer := ldr.OuterSym(s)
|
||||
if s != 0 && ldr.SymSect(outer) != nil && ldr.SymSect(outer) != sect {
|
||||
ctxt.Errorf(s, "s.Outer (%s) in different section from s, %s != %s", ldr.SymName(outer), ldr.SymSect(outer).Name, sect.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// createRelroSect will create a section that wil be a relro
|
||||
// section if this link is using relro.
|
||||
createRelroSect := func(name string, symn sym.SymKind) *sym.Section {
|
||||
sect := state.allocateNamedDataSection(segRelro, genrelrosecname(name), []sym.SymKind{symn}, relroPerm)
|
||||
|
||||
if symn == sym.STYPE && ctxt.HeadType != objabi.Haix {
|
||||
// Skip forward so that no type
|
||||
// reference uses a zero offset.
|
||||
// This is unlikely but possible in small
|
||||
// programs with no other read-only data.
|
||||
state.datsize++
|
||||
}
|
||||
|
||||
// Align to first symbol.
|
||||
symnStartValue := state.datsize
|
||||
if len(state.data[symn]) > 0 {
|
||||
symnStartValue = aligndatsize(state, state.datsize, state.data[symn][0])
|
||||
}
|
||||
|
||||
checkOuter(sect, symn)
|
||||
state.assignToSection(sect, symn, sym.SRODATA)
|
||||
setCarrierSize(symn, state.datsize-symnStartValue)
|
||||
if ctxt.HeadType == objabi.Haix {
|
||||
// XCOFF symbol table needs to know the size
|
||||
// of outer symbols.
|
||||
xcoffUpdateOuterSize(ctxt, state.datsize-symnStartValue, symn)
|
||||
}
|
||||
sect.Length = uint64(state.datsize) - sect.Vaddr
|
||||
return sect
|
||||
}
|
||||
|
||||
if len(state.data[sym.SRODATARELRO]) > 0 {
|
||||
createRelroSect("", sym.SRODATARELRO)
|
||||
}
|
||||
|
||||
sect = createRelroSect(".go.type", sym.STYPE)
|
||||
ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.types", 0), sect)
|
||||
ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.etypes", 0), sect)
|
||||
|
||||
sect = createRelroSect(".go.func", sym.SGOFUNC)
|
||||
|
||||
state.allocateSingleSymSections(segRelro, sym.SELFRELROSECT, sym.SRODATA, relroPerm)
|
||||
state.allocateSingleSymSections(segRelro, sym.SMACHORELROSECT, sym.SRODATA, relroPerm)
|
||||
|
||||
/* itablink */
|
||||
sect = state.allocateNamedDataSection(seg, genrelrosecname(".itablink"), []sym.SymKind{sym.SITABLINK}, relroSecPerm)
|
||||
sect = state.allocateNamedDataSection(segRelro, genrelrosecname(".itablink"), []sym.SymKind{sym.SITABLINK}, relroPerm)
|
||||
|
||||
itablink := ldr.CreateSymForUpdate("runtime.itablink", 0)
|
||||
ldr.SetSymSect(itablink.Sym(), sect)
|
||||
|
|
|
|||
|
|
@ -37,14 +37,14 @@ func TestMachoSectionsReadOnly(t *testing.T) {
|
|||
args: []string{"-ldflags", "-linkmode=internal"},
|
||||
prog: prog,
|
||||
mustInternalLink: true,
|
||||
wantSecsRO: []string{"__got", "__rodata", "__itablink", "__typelink"},
|
||||
wantSecsRO: []string{"__got", "__rodata", "__itablink"},
|
||||
},
|
||||
{
|
||||
name: "linkmode-external",
|
||||
args: []string{"-ldflags", "-linkmode=external"},
|
||||
prog: prog,
|
||||
mustHaveCGO: true,
|
||||
wantSecsRO: []string{"__got", "__rodata", "__itablink", "__typelink"},
|
||||
wantSecsRO: []string{"__got", "__rodata", "__itablink"},
|
||||
},
|
||||
{
|
||||
name: "cgo-linkmode-internal",
|
||||
|
|
@ -52,14 +52,14 @@ func TestMachoSectionsReadOnly(t *testing.T) {
|
|||
prog: progC,
|
||||
mustHaveCGO: true,
|
||||
mustInternalLink: true,
|
||||
wantSecsRO: []string{"__got", "__rodata", "__itablink", "__typelink"},
|
||||
wantSecsRO: []string{"__got", "__rodata", "__itablink"},
|
||||
},
|
||||
{
|
||||
name: "cgo-linkmode-external",
|
||||
args: []string{"-ldflags", "-linkmode=external"},
|
||||
prog: progC,
|
||||
mustHaveCGO: true,
|
||||
wantSecsRO: []string{"__got", "__rodata", "__itablink", "__typelink"},
|
||||
wantSecsRO: []string{"__got", "__rodata", "__itablink"},
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -459,30 +459,14 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind {
|
|||
ctxt.xdefine("runtime.egcbss", sym.SRODATA, 0)
|
||||
|
||||
// pseudo-symbols to mark locations of type, string, and go string data.
|
||||
var symtype, symtyperel loader.Sym
|
||||
var symtype loader.Sym
|
||||
if !ctxt.DynlinkingGo() {
|
||||
if ctxt.UseRelro() && (ctxt.BuildMode == BuildModeCArchive || ctxt.BuildMode == BuildModeCShared || ctxt.BuildMode == BuildModePIE) {
|
||||
s = ldr.CreateSymForUpdate("type:*", 0)
|
||||
s.SetType(sym.STYPE)
|
||||
s.SetSize(0)
|
||||
s.SetAlign(int32(ctxt.Arch.PtrSize))
|
||||
symtype = s.Sym()
|
||||
|
||||
s = ldr.CreateSymForUpdate("typerel.*", 0)
|
||||
s.SetType(sym.STYPERELRO)
|
||||
s.SetSize(0)
|
||||
s.SetAlign(int32(ctxt.Arch.PtrSize))
|
||||
symtyperel = s.Sym()
|
||||
} else {
|
||||
s = ldr.CreateSymForUpdate("type:*", 0)
|
||||
s.SetType(sym.STYPE)
|
||||
s.SetSize(0)
|
||||
s.SetAlign(int32(ctxt.Arch.PtrSize))
|
||||
symtype = s.Sym()
|
||||
symtyperel = s.Sym()
|
||||
}
|
||||
s = ldr.CreateSymForUpdate("type:*", 0)
|
||||
s.SetType(sym.STYPE)
|
||||
s.SetSize(0)
|
||||
s.SetAlign(int32(ctxt.Arch.PtrSize))
|
||||
symtype = s.Sym()
|
||||
setCarrierSym(sym.STYPE, symtype)
|
||||
setCarrierSym(sym.STYPERELRO, symtyperel)
|
||||
}
|
||||
|
||||
groupSym := func(name string, t sym.SymKind) loader.Sym {
|
||||
|
|
@ -500,11 +484,6 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind {
|
|||
symgcbits = groupSym("runtime.gcbits.*", sym.SGCBITS)
|
||||
)
|
||||
|
||||
symgofuncrel := symgofunc
|
||||
if ctxt.UseRelro() {
|
||||
symgofuncrel = groupSym("go:funcdescrel", sym.SGOFUNCRELRO)
|
||||
}
|
||||
|
||||
// assign specific types so that they sort together.
|
||||
// within a type they sort by size, so the .* symbols
|
||||
// just defined above will be first.
|
||||
|
|
@ -537,31 +516,17 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind {
|
|||
case strings.HasSuffix(name, "·f"):
|
||||
if !ctxt.DynlinkingGo() {
|
||||
ldr.SetAttrNotInSymbolTable(s, true)
|
||||
}
|
||||
if ctxt.UseRelro() {
|
||||
symGroupType[s] = sym.SGOFUNCRELRO
|
||||
if !ctxt.DynlinkingGo() {
|
||||
ldr.SetCarrierSym(s, symgofuncrel)
|
||||
}
|
||||
} else {
|
||||
symGroupType[s] = sym.SGOFUNC
|
||||
ldr.SetCarrierSym(s, symgofunc)
|
||||
}
|
||||
symGroupType[s] = sym.SGOFUNC
|
||||
|
||||
case strings.HasPrefix(name, "type:"):
|
||||
if !ctxt.DynlinkingGo() {
|
||||
ldr.SetAttrNotInSymbolTable(s, true)
|
||||
}
|
||||
if ctxt.UseRelro() {
|
||||
symGroupType[s] = sym.STYPERELRO
|
||||
if symtyperel != 0 {
|
||||
ldr.SetCarrierSym(s, symtyperel)
|
||||
}
|
||||
} else {
|
||||
symGroupType[s] = sym.STYPE
|
||||
if symtyperel != 0 {
|
||||
ldr.SetCarrierSym(s, symtype)
|
||||
}
|
||||
symGroupType[s] = sym.STYPE
|
||||
if symtype != 0 {
|
||||
ldr.SetCarrierSym(s, symtype)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -583,17 +583,12 @@ func xcoffUpdateOuterSize(ctxt *Link, size int64, stype sym.SymKind) {
|
|||
switch stype {
|
||||
default:
|
||||
Errorf("unknown XCOFF outer symbol for type %s", stype.String())
|
||||
case sym.SRODATA, sym.SRODATARELRO, sym.SFUNCTAB, sym.SSTRING:
|
||||
case sym.SRODATA, sym.SFUNCTAB, sym.SSTRING:
|
||||
// Nothing to do
|
||||
case sym.STYPERELRO:
|
||||
case sym.STYPE:
|
||||
if ctxt.UseRelro() && (ctxt.BuildMode == BuildModeCArchive || ctxt.BuildMode == BuildModeCShared || ctxt.BuildMode == BuildModePIE) {
|
||||
// runtime.types size must be removed, as it's a real symbol.
|
||||
tsize := ldr.SymSize(ldr.Lookup("runtime.types", 0))
|
||||
outerSymSize["typerel.*"] = size - tsize
|
||||
return
|
||||
}
|
||||
fallthrough
|
||||
case sym.STYPE:
|
||||
if !ctxt.DynlinkingGo() {
|
||||
// runtime.types size must be removed, as it's a real symbol.
|
||||
tsize := ldr.SymSize(ldr.Lookup("runtime.types", 0))
|
||||
|
|
@ -605,8 +600,6 @@ func xcoffUpdateOuterSize(ctxt *Link, size int64, stype sym.SymKind) {
|
|||
if !ctxt.DynlinkingGo() {
|
||||
outerSymSize["go:funcdesc"] = size
|
||||
}
|
||||
case sym.SGOFUNCRELRO:
|
||||
outerSymSize["go:funcdescrel"] = size
|
||||
case sym.SGCBITS:
|
||||
outerSymSize["runtime.gcbits.*"] = size
|
||||
case sym.SPCLNTAB:
|
||||
|
|
|
|||
|
|
@ -52,11 +52,9 @@ const (
|
|||
SELFRXSECT // Executable PLT; PPC64 .glink.
|
||||
SMACHOPLT // Mach-O PLT.
|
||||
|
||||
// Read-only, non-executable, segment.
|
||||
STYPE // Type descriptors.
|
||||
// Read-only, non-executable, unrelocated segment.
|
||||
SSTRING // Used only for XCOFF runtime.rodata symbol?
|
||||
SGOSTRING // Go string constants.
|
||||
SGOFUNC // Function descriptors and funcdata symbols.
|
||||
SGCBITS // GC bit masks and programs.
|
||||
SRODATA // General read-only data.
|
||||
SRODATAFIPSSTART // Start of FIPS read-only data.
|
||||
|
|
@ -65,32 +63,26 @@ const (
|
|||
SRODATAEND // End of read-only data.
|
||||
SFUNCTAB // Appears to be unused, except for runtime.etypes.
|
||||
SPCLNTAB // Pclntab data.
|
||||
STYPELINK // Type links.
|
||||
SELFROSECT // ELF read-only data: relocs, dynamic linking info.
|
||||
|
||||
// Read-only, non-executable, dynamically relocatable segment.
|
||||
//
|
||||
// Types STYPE-SFUNCTAB above are written to the .rodata section by default.
|
||||
// When linking a shared object, some conceptually "read only" types need to
|
||||
// be written to by relocations and putting them in a section called
|
||||
// ".rodata" interacts poorly with the system linkers. The GNU linkers
|
||||
// support this situation by arranging for sections of the name
|
||||
// ".data.rel.ro.XXX" to be mprotected read only by the dynamic linker after
|
||||
// relocations have applied, so when the Go linker is creating a shared
|
||||
// object it checks all objects of the above types and bumps any object that
|
||||
// has a relocation to it to the corresponding type below, which are then
|
||||
// written to sections with appropriate magic names.
|
||||
STYPERELRO
|
||||
SSTRINGRELRO
|
||||
SGOSTRINGRELRO
|
||||
SGOFUNCRELRO
|
||||
SGCBITSRELRO
|
||||
// This segment holds read-only data that contains pointers to
|
||||
// other parts of the program. When generating a position
|
||||
// independent executable or a shared library, these sections
|
||||
// are "relro", meaning that they start as writable, and are
|
||||
// changed to be read-only after dynamic relocations are applied.
|
||||
//
|
||||
// When no dynamic relocations are required, as when generating
|
||||
// an executable that is not position independent, this is just
|
||||
// part of the normal read-only segment.
|
||||
SRODATARELRO
|
||||
SFUNCTABRELRO
|
||||
|
||||
STYPE
|
||||
SGOFUNC
|
||||
SELFRELROSECT // ELF-specific read-only relocatable: PLT, etc.
|
||||
SMACHORELROSECT // Mach-O specific read-only relocatable.
|
||||
|
||||
STYPELINK // Type links.
|
||||
SITABLINK // Itab links.
|
||||
|
||||
// Allocated writable segment.
|
||||
|
|
@ -185,14 +177,11 @@ var AbiSymKindToSymKind = [...]SymKind{
|
|||
objabi.SSEHUNWINDINFO: SSEHUNWINDINFO,
|
||||
}
|
||||
|
||||
// ReadOnly are the symbol kinds that form read-only sections. In some
|
||||
// cases, if they will require relocations, they are transformed into
|
||||
// rel-ro sections using relROMap.
|
||||
// ReadOnly are the symbol kinds that form read-only sections
|
||||
// that never require runtime relocations.
|
||||
var ReadOnly = []SymKind{
|
||||
STYPE,
|
||||
SSTRING,
|
||||
SGOSTRING,
|
||||
SGOFUNC,
|
||||
SGCBITS,
|
||||
SRODATA,
|
||||
SRODATAFIPSSTART,
|
||||
|
|
@ -202,18 +191,6 @@ var ReadOnly = []SymKind{
|
|||
SFUNCTAB,
|
||||
}
|
||||
|
||||
// RelROMap describes the transformation of read-only symbols to rel-ro
|
||||
// symbols.
|
||||
var RelROMap = map[SymKind]SymKind{
|
||||
STYPE: STYPERELRO,
|
||||
SSTRING: SSTRINGRELRO,
|
||||
SGOSTRING: SGOSTRINGRELRO,
|
||||
SGOFUNC: SGOFUNCRELRO,
|
||||
SGCBITS: SGCBITSRELRO,
|
||||
SRODATA: SRODATARELRO,
|
||||
SFUNCTAB: SFUNCTABRELRO,
|
||||
}
|
||||
|
||||
// IsText returns true if t is a text type.
|
||||
func (t SymKind) IsText() bool {
|
||||
return STEXT <= t && t <= STEXTEND
|
||||
|
|
|
|||
|
|
@ -16,84 +16,78 @@ func _() {
|
|||
_ = x[STEXTEND-5]
|
||||
_ = x[SELFRXSECT-6]
|
||||
_ = x[SMACHOPLT-7]
|
||||
_ = x[STYPE-8]
|
||||
_ = x[SSTRING-9]
|
||||
_ = x[SGOSTRING-10]
|
||||
_ = x[SGOFUNC-11]
|
||||
_ = x[SGCBITS-12]
|
||||
_ = x[SRODATA-13]
|
||||
_ = x[SRODATAFIPSSTART-14]
|
||||
_ = x[SRODATAFIPS-15]
|
||||
_ = x[SRODATAFIPSEND-16]
|
||||
_ = x[SRODATAEND-17]
|
||||
_ = x[SFUNCTAB-18]
|
||||
_ = x[SPCLNTAB-19]
|
||||
_ = x[SELFROSECT-20]
|
||||
_ = x[STYPERELRO-21]
|
||||
_ = x[SSTRINGRELRO-22]
|
||||
_ = x[SGOSTRINGRELRO-23]
|
||||
_ = x[SGOFUNCRELRO-24]
|
||||
_ = x[SGCBITSRELRO-25]
|
||||
_ = x[SRODATARELRO-26]
|
||||
_ = x[SFUNCTABRELRO-27]
|
||||
_ = x[SELFRELROSECT-28]
|
||||
_ = x[SMACHORELROSECT-29]
|
||||
_ = x[STYPELINK-30]
|
||||
_ = x[SITABLINK-31]
|
||||
_ = x[SFirstWritable-32]
|
||||
_ = x[SBUILDINFO-33]
|
||||
_ = x[SFIPSINFO-34]
|
||||
_ = x[SELFSECT-35]
|
||||
_ = x[SMACHO-36]
|
||||
_ = x[SWINDOWS-37]
|
||||
_ = x[SMODULEDATA-38]
|
||||
_ = x[SELFGOT-39]
|
||||
_ = x[SMACHOGOT-40]
|
||||
_ = x[SNOPTRDATA-41]
|
||||
_ = x[SNOPTRDATAFIPSSTART-42]
|
||||
_ = x[SNOPTRDATAFIPS-43]
|
||||
_ = x[SNOPTRDATAFIPSEND-44]
|
||||
_ = x[SNOPTRDATAEND-45]
|
||||
_ = x[SINITARR-46]
|
||||
_ = x[SDATA-47]
|
||||
_ = x[SDATAFIPSSTART-48]
|
||||
_ = x[SDATAFIPS-49]
|
||||
_ = x[SDATAFIPSEND-50]
|
||||
_ = x[SDATAEND-51]
|
||||
_ = x[SXCOFFTOC-52]
|
||||
_ = x[SBSS-53]
|
||||
_ = x[SNOPTRBSS-54]
|
||||
_ = x[SLIBFUZZER_8BIT_COUNTER-55]
|
||||
_ = x[SCOVERAGE_COUNTER-56]
|
||||
_ = x[SCOVERAGE_AUXVAR-57]
|
||||
_ = x[STLSBSS-58]
|
||||
_ = x[SFirstUnallocated-59]
|
||||
_ = x[SXREF-60]
|
||||
_ = x[SMACHOSYMSTR-61]
|
||||
_ = x[SMACHOSYMTAB-62]
|
||||
_ = x[SMACHOINDIRECTPLT-63]
|
||||
_ = x[SMACHOINDIRECTGOT-64]
|
||||
_ = x[SDYNIMPORT-65]
|
||||
_ = x[SHOSTOBJ-66]
|
||||
_ = x[SUNDEFEXT-67]
|
||||
_ = x[SDWARFSECT-68]
|
||||
_ = x[SDWARFCUINFO-69]
|
||||
_ = x[SDWARFCONST-70]
|
||||
_ = x[SDWARFFCN-71]
|
||||
_ = x[SDWARFABSFCN-72]
|
||||
_ = x[SDWARFTYPE-73]
|
||||
_ = x[SDWARFVAR-74]
|
||||
_ = x[SDWARFRANGE-75]
|
||||
_ = x[SDWARFLOC-76]
|
||||
_ = x[SDWARFLINES-77]
|
||||
_ = x[SDWARFADDR-78]
|
||||
_ = x[SSEHUNWINDINFO-79]
|
||||
_ = x[SSEHSECT-80]
|
||||
_ = x[SSTRING-8]
|
||||
_ = x[SGOSTRING-9]
|
||||
_ = x[SGCBITS-10]
|
||||
_ = x[SRODATA-11]
|
||||
_ = x[SRODATAFIPSSTART-12]
|
||||
_ = x[SRODATAFIPS-13]
|
||||
_ = x[SRODATAFIPSEND-14]
|
||||
_ = x[SRODATAEND-15]
|
||||
_ = x[SFUNCTAB-16]
|
||||
_ = x[SPCLNTAB-17]
|
||||
_ = x[STYPELINK-18]
|
||||
_ = x[SELFROSECT-19]
|
||||
_ = x[SRODATARELRO-20]
|
||||
_ = x[STYPE-21]
|
||||
_ = x[SGOFUNC-22]
|
||||
_ = x[SELFRELROSECT-23]
|
||||
_ = x[SMACHORELROSECT-24]
|
||||
_ = x[SITABLINK-25]
|
||||
_ = x[SFirstWritable-26]
|
||||
_ = x[SBUILDINFO-27]
|
||||
_ = x[SFIPSINFO-28]
|
||||
_ = x[SELFSECT-29]
|
||||
_ = x[SMACHO-30]
|
||||
_ = x[SWINDOWS-31]
|
||||
_ = x[SMODULEDATA-32]
|
||||
_ = x[SELFGOT-33]
|
||||
_ = x[SMACHOGOT-34]
|
||||
_ = x[SNOPTRDATA-35]
|
||||
_ = x[SNOPTRDATAFIPSSTART-36]
|
||||
_ = x[SNOPTRDATAFIPS-37]
|
||||
_ = x[SNOPTRDATAFIPSEND-38]
|
||||
_ = x[SNOPTRDATAEND-39]
|
||||
_ = x[SINITARR-40]
|
||||
_ = x[SDATA-41]
|
||||
_ = x[SDATAFIPSSTART-42]
|
||||
_ = x[SDATAFIPS-43]
|
||||
_ = x[SDATAFIPSEND-44]
|
||||
_ = x[SDATAEND-45]
|
||||
_ = x[SXCOFFTOC-46]
|
||||
_ = x[SBSS-47]
|
||||
_ = x[SNOPTRBSS-48]
|
||||
_ = x[SLIBFUZZER_8BIT_COUNTER-49]
|
||||
_ = x[SCOVERAGE_COUNTER-50]
|
||||
_ = x[SCOVERAGE_AUXVAR-51]
|
||||
_ = x[STLSBSS-52]
|
||||
_ = x[SFirstUnallocated-53]
|
||||
_ = x[SXREF-54]
|
||||
_ = x[SMACHOSYMSTR-55]
|
||||
_ = x[SMACHOSYMTAB-56]
|
||||
_ = x[SMACHOINDIRECTPLT-57]
|
||||
_ = x[SMACHOINDIRECTGOT-58]
|
||||
_ = x[SDYNIMPORT-59]
|
||||
_ = x[SHOSTOBJ-60]
|
||||
_ = x[SUNDEFEXT-61]
|
||||
_ = x[SDWARFSECT-62]
|
||||
_ = x[SDWARFCUINFO-63]
|
||||
_ = x[SDWARFCONST-64]
|
||||
_ = x[SDWARFFCN-65]
|
||||
_ = x[SDWARFABSFCN-66]
|
||||
_ = x[SDWARFTYPE-67]
|
||||
_ = x[SDWARFVAR-68]
|
||||
_ = x[SDWARFRANGE-69]
|
||||
_ = x[SDWARFLOC-70]
|
||||
_ = x[SDWARFLINES-71]
|
||||
_ = x[SDWARFADDR-72]
|
||||
_ = x[SSEHUNWINDINFO-73]
|
||||
_ = x[SSEHSECT-74]
|
||||
}
|
||||
|
||||
const _SymKind_name = "SxxxSTEXTSTEXTFIPSSTARTSTEXTFIPSSTEXTFIPSENDSTEXTENDSELFRXSECTSMACHOPLTSTYPESSTRINGSGOSTRINGSGOFUNCSGCBITSSRODATASRODATAFIPSSTARTSRODATAFIPSSRODATAFIPSENDSRODATAENDSFUNCTABSPCLNTABSELFROSECTSTYPERELROSSTRINGRELROSGOSTRINGRELROSGOFUNCRELROSGCBITSRELROSRODATARELROSFUNCTABRELROSELFRELROSECTSMACHORELROSECTSTYPELINKSITABLINKSFirstWritableSBUILDINFOSFIPSINFOSELFSECTSMACHOSWINDOWSSMODULEDATASELFGOTSMACHOGOTSNOPTRDATASNOPTRDATAFIPSSTARTSNOPTRDATAFIPSSNOPTRDATAFIPSENDSNOPTRDATAENDSINITARRSDATASDATAFIPSSTARTSDATAFIPSSDATAFIPSENDSDATAENDSXCOFFTOCSBSSSNOPTRBSSSLIBFUZZER_8BIT_COUNTERSCOVERAGE_COUNTERSCOVERAGE_AUXVARSTLSBSSSFirstUnallocatedSXREFSMACHOSYMSTRSMACHOSYMTABSMACHOINDIRECTPLTSMACHOINDIRECTGOTSDYNIMPORTSHOSTOBJSUNDEFEXTSDWARFSECTSDWARFCUINFOSDWARFCONSTSDWARFFCNSDWARFABSFCNSDWARFTYPESDWARFVARSDWARFRANGESDWARFLOCSDWARFLINESSDWARFADDRSSEHUNWINDINFOSSEHSECT"
|
||||
const _SymKind_name = "SxxxSTEXTSTEXTFIPSSTARTSTEXTFIPSSTEXTFIPSENDSTEXTENDSELFRXSECTSMACHOPLTSSTRINGSGOSTRINGSGCBITSSRODATASRODATAFIPSSTARTSRODATAFIPSSRODATAFIPSENDSRODATAENDSFUNCTABSPCLNTABSTYPELINKSELFROSECTSRODATARELROSTYPESGOFUNCSELFRELROSECTSMACHORELROSECTSITABLINKSFirstWritableSBUILDINFOSFIPSINFOSELFSECTSMACHOSWINDOWSSMODULEDATASELFGOTSMACHOGOTSNOPTRDATASNOPTRDATAFIPSSTARTSNOPTRDATAFIPSSNOPTRDATAFIPSENDSNOPTRDATAENDSINITARRSDATASDATAFIPSSTARTSDATAFIPSSDATAFIPSENDSDATAENDSXCOFFTOCSBSSSNOPTRBSSSLIBFUZZER_8BIT_COUNTERSCOVERAGE_COUNTERSCOVERAGE_AUXVARSTLSBSSSFirstUnallocatedSXREFSMACHOSYMSTRSMACHOSYMTABSMACHOINDIRECTPLTSMACHOINDIRECTGOTSDYNIMPORTSHOSTOBJSUNDEFEXTSDWARFSECTSDWARFCUINFOSDWARFCONSTSDWARFFCNSDWARFABSFCNSDWARFTYPESDWARFVARSDWARFRANGESDWARFLOCSDWARFLINESSDWARFADDRSSEHUNWINDINFOSSEHSECT"
|
||||
|
||||
var _SymKind_index = [...]uint16{0, 4, 9, 23, 32, 44, 52, 62, 71, 76, 83, 92, 99, 106, 113, 129, 140, 154, 164, 172, 180, 190, 200, 212, 226, 238, 250, 262, 275, 288, 303, 312, 321, 335, 345, 354, 362, 368, 376, 387, 394, 403, 413, 432, 446, 463, 476, 484, 489, 503, 512, 524, 532, 541, 545, 554, 577, 594, 610, 617, 634, 639, 651, 663, 680, 697, 707, 715, 724, 734, 746, 757, 766, 778, 788, 797, 808, 817, 828, 838, 852, 860}
|
||||
var _SymKind_index = [...]uint16{0, 4, 9, 23, 32, 44, 52, 62, 71, 78, 87, 94, 101, 117, 128, 142, 152, 160, 168, 177, 187, 199, 204, 211, 224, 239, 248, 262, 272, 281, 289, 295, 303, 314, 321, 330, 340, 359, 373, 390, 403, 411, 416, 430, 439, 451, 459, 468, 472, 481, 504, 521, 537, 544, 561, 566, 578, 590, 607, 624, 634, 642, 651, 661, 673, 684, 693, 705, 715, 724, 735, 744, 755, 765, 779, 787}
|
||||
|
||||
func (i SymKind) String() string {
|
||||
if i >= SymKind(len(_SymKind_index)-1) {
|
||||
|
|
|
|||
|
|
@ -127,6 +127,8 @@ func asmb(ctxt *ld.Link, ldr *loader.Loader) {
|
|||
ldr.SymSect(ldr.Lookup("runtime.rodata", 0)),
|
||||
ldr.SymSect(ldr.Lookup("runtime.typelink", 0)),
|
||||
ldr.SymSect(ldr.Lookup("runtime.itablink", 0)),
|
||||
ldr.SymSect(ldr.Lookup("runtime.types", 0)),
|
||||
ldr.SymSect(ldr.Lookup("go:funcdesc", 0)),
|
||||
ldr.SymSect(ldr.Lookup("runtime.firstmoduledata", 0)),
|
||||
ldr.SymSect(ldr.Lookup("runtime.pclntab", 0)),
|
||||
ldr.SymSect(ldr.Lookup("runtime.noptrdata", 0)),
|
||||
|
|
|
|||
|
|
@ -2221,3 +2221,229 @@ func TestModuledataPlacement(t *testing.T) {
|
|||
// so there is nothing to test here.
|
||||
}
|
||||
}
|
||||
|
||||
const typeSrc = `
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type MyInt int
|
||||
|
||||
var vals = []any{
|
||||
0,
|
||||
0.1,
|
||||
"",
|
||||
MyInt(0),
|
||||
struct{ f int }{0},
|
||||
func() {},
|
||||
}
|
||||
|
||||
var global int
|
||||
|
||||
func main() {
|
||||
fmt.Printf("global %#x\n", &global)
|
||||
for _, v := range vals {
|
||||
// Unsafe assumption: the first word of a value
|
||||
// of type any is the type descriptor.
|
||||
td := *(*uintptr)(unsafe.Pointer(&v))
|
||||
fmt.Printf("%#x\n", td)
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
// Test that type data is stored in the types section.
|
||||
func TestTypePlacement(t *testing.T) {
|
||||
testenv.MustHaveGoRun(t)
|
||||
t.Parallel()
|
||||
|
||||
tmpdir := t.TempDir()
|
||||
src := filepath.Join(tmpdir, "x.go")
|
||||
if err := os.WriteFile(src, []byte(typeSrc), 0o444); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
exe := filepath.Join(tmpdir, "x.exe")
|
||||
cmd := goCmd(t, "build", "-o", exe, src)
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
t.Fatalf("build failed; %v, output:\n%s", err, out)
|
||||
}
|
||||
|
||||
cmd = testenv.Command(t, exe)
|
||||
var stdout, stderr strings.Builder
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
if err := cmd.Run(); err != nil {
|
||||
t.Fatalf("running test program failed: %v, stdout:\n%s\nstderr:\n%s", err, &stdout, &stderr)
|
||||
}
|
||||
stderrString := stderr.String()
|
||||
if stderrString != "" {
|
||||
t.Fatalf("running test program printed to stderr:\n%s", stderrString)
|
||||
}
|
||||
|
||||
t.Logf("\n%s", &stdout)
|
||||
|
||||
var globalExeAddr uint64
|
||||
var addrs []uint64
|
||||
globalNext := false
|
||||
for s := range strings.FieldsSeq(stdout.String()) {
|
||||
if globalNext {
|
||||
v, err := strconv.ParseUint(s, 0, 64)
|
||||
if err != nil {
|
||||
t.Errorf("failed to parse test program output %s: %v", s, err)
|
||||
}
|
||||
globalExeAddr = v
|
||||
globalNext = false
|
||||
} else if s == "global" {
|
||||
globalNext = true
|
||||
} else {
|
||||
addr, err := strconv.ParseUint(s, 0, 64)
|
||||
if err != nil {
|
||||
t.Errorf("failed to parse test program output %q: %v", s, err)
|
||||
}
|
||||
addrs = append(addrs, addr)
|
||||
}
|
||||
}
|
||||
|
||||
ef, _ := elf.Open(exe)
|
||||
mf, _ := macho.Open(exe)
|
||||
pf, _ := pe.Open(exe)
|
||||
xf, _ := xcoff.Open(exe)
|
||||
// TODO: plan9
|
||||
if ef == nil && mf == nil && pf == nil && xf == nil {
|
||||
t.Skip("unrecognized executable file format")
|
||||
}
|
||||
|
||||
const globalName = "main.global"
|
||||
var typeStart, typeEnd uint64
|
||||
var globalObjAddr uint64
|
||||
switch {
|
||||
case ef != nil:
|
||||
defer ef.Close()
|
||||
|
||||
for _, sec := range ef.Sections {
|
||||
if sec.Name == ".go.type" {
|
||||
typeStart = sec.Addr
|
||||
typeEnd = sec.Addr + sec.Size
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
syms, err := ef.Symbols()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if typeStart == 0 && typeEnd == 0 {
|
||||
// We can fail to find the section for PIE.
|
||||
// Fall back to symbols.
|
||||
for _, sym := range syms {
|
||||
switch sym.Name {
|
||||
case "runtime.types":
|
||||
typeStart = sym.Value
|
||||
case "runtime.etypes":
|
||||
typeEnd = sym.Value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, sym := range syms {
|
||||
if sym.Name == globalName {
|
||||
globalObjAddr = sym.Value
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
case mf != nil:
|
||||
defer mf.Close()
|
||||
|
||||
for _, sec := range mf.Sections {
|
||||
if sec.Name == "__go_type" {
|
||||
typeStart = sec.Addr
|
||||
typeEnd = sec.Addr + sec.Size
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for _, sym := range mf.Symtab.Syms {
|
||||
if sym.Name == globalName {
|
||||
globalObjAddr = sym.Value
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
case pf != nil:
|
||||
defer pf.Close()
|
||||
|
||||
var imageBase uint64
|
||||
switch ohdr := pf.OptionalHeader.(type) {
|
||||
case *pe.OptionalHeader32:
|
||||
imageBase = uint64(ohdr.ImageBase)
|
||||
case *pe.OptionalHeader64:
|
||||
imageBase = ohdr.ImageBase
|
||||
}
|
||||
|
||||
var typeSym, eTypeSym *pe.Symbol
|
||||
for _, sym := range pf.Symbols {
|
||||
switch sym.Name {
|
||||
case "runtime.types":
|
||||
typeSym = sym
|
||||
case "runtime.etypes":
|
||||
eTypeSym = sym
|
||||
case globalName:
|
||||
globalSec := pf.Sections[sym.SectionNumber-1]
|
||||
globalObjAddr = imageBase + uint64(globalSec.VirtualAddress+sym.Value)
|
||||
}
|
||||
}
|
||||
|
||||
if typeSym == nil {
|
||||
t.Fatal("could not find symbol runtime.types")
|
||||
}
|
||||
if eTypeSym == nil {
|
||||
t.Fatal("could not find symbol runtime.etypes")
|
||||
}
|
||||
if typeSym.SectionNumber != eTypeSym.SectionNumber {
|
||||
t.Fatalf("runtime.types section %d != runtime.etypes section %d", typeSym.SectionNumber, eTypeSym.SectionNumber)
|
||||
}
|
||||
|
||||
sec := pf.Sections[typeSym.SectionNumber-1]
|
||||
|
||||
typeStart = imageBase + uint64(sec.VirtualAddress+typeSym.Value)
|
||||
typeEnd = imageBase + uint64(sec.VirtualAddress+eTypeSym.Value)
|
||||
|
||||
case xf != nil:
|
||||
defer xf.Close()
|
||||
|
||||
for _, sec := range xf.Sections {
|
||||
if sec.Name == ".go.type" {
|
||||
typeStart = sec.VirtualAddress
|
||||
typeEnd = sec.VirtualAddress + sec.Size
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for _, sym := range xf.Symbols {
|
||||
if sym.Name == globalName {
|
||||
globalObjAddr = sym.Value
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if typeStart == 0 || typeEnd == 0 {
|
||||
t.Fatalf("failed to find type descriptor addresses; found %#x to %#x", typeStart, typeEnd)
|
||||
}
|
||||
t.Logf("type start: %#x type end: %#x", typeStart, typeEnd)
|
||||
|
||||
offset := globalExeAddr - globalObjAddr
|
||||
t.Logf("execution offset: %#x", offset)
|
||||
|
||||
for _, addr := range addrs {
|
||||
addr -= offset
|
||||
if addr < typeStart || addr >= typeEnd {
|
||||
t.Errorf("type descriptor address %#x out of range: not between %#x and %#x", addr, typeStart, typeEnd)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue