cmd/link: move pclntab out of relro section

The .gopclntab section should not have any relocations.
Move it out of relro to regular rodata.

Note that this is tested by tests like TestNoTextrel in
cmd/cgo/internal/testshared.

The existing test TestMachoSectionsReadOnly looks for sections in a
Mach-O file that are read-only after relocations are applied
(this is marked by a segment with a flags field set to 0x10).
We remove the __gopclntab section, as that section is now read-only
at all times, not only after relocating.

For #76038

Change-Id: I7f837e423bf1e802509277f5dc7fdd1ed0228e32
Reviewed-on: https://go-review.googlesource.com/c/go/+/718065
Reviewed-by: Russ Cox <rsc@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
Ian Lance Taylor
2025-11-05 16:13:22 -08:00
committed by Gopher Robot
parent 43b91e7abd
commit ad3ccd92e4
6 changed files with 43 additions and 42 deletions

View File

@@ -1581,7 +1581,7 @@ func (state *dodataState) makeRelroForSharedLib(target *Link) {
// the relro data.
isRelro = true
}
case sym.SGOFUNC:
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.
@@ -2119,6 +2119,21 @@ func (state *dodataState) allocateDataSections(ctxt *Link) {
}
}
/* gopclntab */
sect = state.allocateNamedSectionAndAssignSyms(segro, ".gopclntab", sym.SPCLNTAB, sym.SRODATA, 04)
ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.pclntab", 0), sect)
ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.pcheader", 0), sect)
ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.funcnametab", 0), sect)
ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.cutab", 0), sect)
ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.filetab", 0), sect)
ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.pctab", 0), sect)
ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.functab", 0), sect)
ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.epclntab", 0), sect)
setCarrierSize(sym.SPCLNTAB, int64(sect.Length))
if ctxt.HeadType == objabi.Haix {
xcoffUpdateOuterSize(ctxt, int64(sect.Length), sym.SPCLNTAB)
}
/* read-only ELF, Mach-O sections */
state.allocateSingleSymSections(segro, sym.SELFROSECT, sym.SRODATA, 04)
@@ -2238,21 +2253,6 @@ func (state *dodataState) allocateDataSections(ctxt *Link) {
state.checkdatsize(sym.SITABLINK)
sect.Length = uint64(state.datsize) - sect.Vaddr
/* gopclntab */
sect = state.allocateNamedSectionAndAssignSyms(seg, genrelrosecname(".gopclntab"), sym.SPCLNTAB, sym.SRODATA, relroSecPerm)
ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.pclntab", 0), sect)
ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.pcheader", 0), sect)
ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.funcnametab", 0), sect)
ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.cutab", 0), sect)
ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.filetab", 0), sect)
ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.pctab", 0), sect)
ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.functab", 0), sect)
ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.epclntab", 0), sect)
setCarrierSize(sym.SPCLNTAB, int64(sect.Length))
if ctxt.HeadType == objabi.Haix {
xcoffUpdateOuterSize(ctxt, int64(sect.Length), sym.SPCLNTAB)
}
// 6g uses 4-byte relocation offsets, so the entire segment must fit in 32 bits.
if state.datsize != int64(uint32(state.datsize)) {
Errorf("read-only data segment too large: %d", state.datsize)

View File

@@ -1250,11 +1250,12 @@ func elfshbits(linkmode LinkMode, sect *sym.Section) *ElfShdr {
func elfshreloc(arch *sys.Arch, sect *sym.Section) *ElfShdr {
// If main section is SHT_NOBITS, nothing to relocate.
// Also nothing to relocate in .shstrtab or notes.
// Also nothing to relocate in .shstrtab or notes or .gopclntab.
if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
return nil
}
if sect.Name == ".shstrtab" || sect.Name == ".tbss" {
switch sect.Name {
case ".shstrtab", ".tbss", ".gopclntab":
return nil
}
if sect.Elfsect.(*ElfShdr).Type == uint32(elf.SHT_NOTE) {
@@ -1469,6 +1470,7 @@ func (ctxt *Link) doelf() {
}
shstrtabAddstring(".elfdata")
shstrtabAddstring(".rodata")
shstrtabAddstring(".gopclntab")
// See the comment about data.rel.ro.FOO section names in data.go.
relro_prefix := ""
if ctxt.UseRelro() {
@@ -1477,7 +1479,6 @@ func (ctxt *Link) doelf() {
}
shstrtabAddstring(relro_prefix + ".typelink")
shstrtabAddstring(relro_prefix + ".itablink")
shstrtabAddstring(relro_prefix + ".gopclntab")
if ctxt.IsExternal() {
*FlagD = true
@@ -1486,7 +1487,6 @@ func (ctxt *Link) doelf() {
shstrtabAddstring(elfRelType + ".rodata")
shstrtabAddstring(elfRelType + relro_prefix + ".typelink")
shstrtabAddstring(elfRelType + relro_prefix + ".itablink")
shstrtabAddstring(elfRelType + relro_prefix + ".gopclntab")
shstrtabAddstring(elfRelType + ".noptrdata")
shstrtabAddstring(elfRelType + ".data")
if ctxt.UseRelro() {

View File

@@ -408,7 +408,7 @@ func TestElfBindNow(t *testing.T) {
}
// This program is intended to be just big/complicated enough that
// we wind up with decent-sized .data.rel.ro.{typelink,itablink,gopclntab}
// we wind up with decent-sized .data.rel.ro.{typelink,itablink}
// sections.
const ifacecallsProg = `
package main

View File

@@ -37,14 +37,14 @@ func TestMachoSectionsReadOnly(t *testing.T) {
args: []string{"-ldflags", "-linkmode=internal"},
prog: prog,
mustInternalLink: true,
wantSecsRO: []string{"__got", "__rodata", "__itablink", "__typelink", "__gopclntab"},
wantSecsRO: []string{"__got", "__rodata", "__itablink", "__typelink"},
},
{
name: "linkmode-external",
args: []string{"-ldflags", "-linkmode=external"},
prog: prog,
mustHaveCGO: true,
wantSecsRO: []string{"__got", "__rodata", "__itablink", "__typelink", "__gopclntab"},
wantSecsRO: []string{"__got", "__rodata", "__itablink", "__typelink"},
},
{
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", "__gopclntab"},
wantSecsRO: []string{"__got", "__rodata", "__itablink", "__typelink"},
},
{
name: "cgo-linkmode-external",
args: []string{"-ldflags", "-linkmode=external"},
prog: progC,
mustHaveCGO: true,
wantSecsRO: []string{"__got", "__rodata", "__itablink", "__typelink", "__gopclntab"},
wantSecsRO: []string{"__got", "__rodata", "__itablink", "__typelink"},
},
}
@@ -111,7 +111,8 @@ func TestMachoSectionsReadOnly(t *testing.T) {
for _, wsroname := range test.wantSecsRO {
// Now walk the sections. Section should be part of
// some segment that is readonly.
// some segment that is made readonly after
// relocations are appied.
var wsro *macho.Section
foundRO := false
for _, s := range machoFile.Sections {

View File

@@ -64,6 +64,7 @@ const (
SRODATAFIPSEND // End of FIPS read-only data.
SRODATAEND // End of read-only data.
SFUNCTAB // Appears to be unused, except for runtime.etypes.
SPCLNTAB // Pclntab data.
SELFROSECT // ELF read-only data: relocs, dynamic linking info.
// Read-only, non-executable, dynamically relocatable segment.
@@ -91,7 +92,6 @@ const (
STYPELINK // Type links.
SITABLINK // Itab links.
SPCLNTAB // Pclntab data.
// Allocated writable segment.
SFirstWritable

View File

@@ -27,19 +27,19 @@ func _() {
_ = x[SRODATAFIPSEND-16]
_ = x[SRODATAEND-17]
_ = x[SFUNCTAB-18]
_ = x[SELFROSECT-19]
_ = x[STYPERELRO-20]
_ = x[SSTRINGRELRO-21]
_ = x[SGOSTRINGRELRO-22]
_ = x[SGOFUNCRELRO-23]
_ = x[SGCBITSRELRO-24]
_ = x[SRODATARELRO-25]
_ = x[SFUNCTABRELRO-26]
_ = x[SELFRELROSECT-27]
_ = x[SMACHORELROSECT-28]
_ = x[STYPELINK-29]
_ = x[SITABLINK-30]
_ = x[SPCLNTAB-31]
_ = 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]
@@ -90,9 +90,9 @@ func _() {
_ = x[SSEHSECT-79]
}
const _SymKind_name = "SxxxSTEXTSTEXTFIPSSTARTSTEXTFIPSSTEXTFIPSENDSTEXTENDSELFRXSECTSMACHOPLTSTYPESSTRINGSGOSTRINGSGOFUNCSGCBITSSRODATASRODATAFIPSSTARTSRODATAFIPSSRODATAFIPSENDSRODATAENDSFUNCTABSELFROSECTSTYPERELROSSTRINGRELROSGOSTRINGRELROSGOFUNCRELROSGCBITSRELROSRODATARELROSFUNCTABRELROSELFRELROSECTSMACHORELROSECTSTYPELINKSITABLINKSPCLNTABSFirstWritableSBUILDINFOSFIPSINFOSELFSECTSMACHOSMACHOGOTSWINDOWSSELFGOTSNOPTRDATASNOPTRDATAFIPSSTARTSNOPTRDATAFIPSSNOPTRDATAFIPSENDSNOPTRDATAENDSINITARRSDATASDATAFIPSSTARTSDATAFIPSSDATAFIPSENDSDATAENDSXCOFFTOCSBSSSNOPTRBSSSLIBFUZZER_8BIT_COUNTERSCOVERAGE_COUNTERSCOVERAGE_AUXVARSTLSBSSSFirstUnallocatedSXREFSMACHOSYMSTRSMACHOSYMTABSMACHOINDIRECTPLTSMACHOINDIRECTGOTSDYNIMPORTSHOSTOBJSUNDEFEXTSDWARFSECTSDWARFCUINFOSDWARFCONSTSDWARFFCNSDWARFABSFCNSDWARFTYPESDWARFVARSDWARFRANGESDWARFLOCSDWARFLINESSDWARFADDRSSEHUNWINDINFOSSEHSECT"
const _SymKind_name = "SxxxSTEXTSTEXTFIPSSTARTSTEXTFIPSSTEXTFIPSENDSTEXTENDSELFRXSECTSMACHOPLTSTYPESSTRINGSGOSTRINGSGOFUNCSGCBITSSRODATASRODATAFIPSSTARTSRODATAFIPSSRODATAFIPSENDSRODATAENDSFUNCTABSPCLNTABSELFROSECTSTYPERELROSSTRINGRELROSGOSTRINGRELROSGOFUNCRELROSGCBITSRELROSRODATARELROSFUNCTABRELROSELFRELROSECTSMACHORELROSECTSTYPELINKSITABLINKSFirstWritableSBUILDINFOSFIPSINFOSELFSECTSMACHOSMACHOGOTSWINDOWSSELFGOTSNOPTRDATASNOPTRDATAFIPSSTARTSNOPTRDATAFIPSSNOPTRDATAFIPSENDSNOPTRDATAENDSINITARRSDATASDATAFIPSSTARTSDATAFIPSSDATAFIPSENDSDATAENDSXCOFFTOCSBSSSNOPTRBSSSLIBFUZZER_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, 182, 192, 204, 218, 230, 242, 254, 267, 280, 295, 304, 313, 321, 335, 345, 354, 362, 368, 377, 385, 392, 402, 421, 435, 452, 465, 473, 478, 492, 501, 513, 521, 530, 534, 543, 566, 583, 599, 606, 623, 628, 640, 652, 669, 686, 696, 704, 713, 723, 735, 746, 755, 767, 777, 786, 797, 806, 817, 827, 841, 849}
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, 377, 385, 392, 402, 421, 435, 452, 465, 473, 478, 492, 501, 513, 521, 530, 534, 543, 566, 583, 599, 606, 623, 628, 640, 652, 669, 686, 696, 704, 713, 723, 735, 746, 755, 767, 777, 786, 797, 806, 817, 827, 841, 849}
func (i SymKind) String() string {
if i >= SymKind(len(_SymKind_index)-1) {