From ad3ccd92e4c2ddfc1499a5e038eb0aa0012c0dda Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 5 Nov 2025 16:13:22 -0800 Subject: [PATCH] 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 Reviewed-by: Cherry Mui LUCI-TryBot-Result: Go LUCI Auto-Submit: Ian Lance Taylor --- src/cmd/link/internal/ld/data.go | 32 ++++++++++----------- src/cmd/link/internal/ld/elf.go | 8 +++--- src/cmd/link/internal/ld/elf_test.go | 2 +- src/cmd/link/internal/ld/macho_test.go | 11 +++---- src/cmd/link/internal/sym/symkind.go | 2 +- src/cmd/link/internal/sym/symkind_string.go | 30 +++++++++---------- 6 files changed, 43 insertions(+), 42 deletions(-) diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go index fcc3272760..e7e202fc1f 100644 --- a/src/cmd/link/internal/ld/data.go +++ b/src/cmd/link/internal/ld/data.go @@ -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) diff --git a/src/cmd/link/internal/ld/elf.go b/src/cmd/link/internal/ld/elf.go index 8981f1c3f0..90f9388ed7 100644 --- a/src/cmd/link/internal/ld/elf.go +++ b/src/cmd/link/internal/ld/elf.go @@ -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() { diff --git a/src/cmd/link/internal/ld/elf_test.go b/src/cmd/link/internal/ld/elf_test.go index c2a1bc0b94..c56d27f29e 100644 --- a/src/cmd/link/internal/ld/elf_test.go +++ b/src/cmd/link/internal/ld/elf_test.go @@ -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 diff --git a/src/cmd/link/internal/ld/macho_test.go b/src/cmd/link/internal/ld/macho_test.go index adf159ab6d..905de67f60 100644 --- a/src/cmd/link/internal/ld/macho_test.go +++ b/src/cmd/link/internal/ld/macho_test.go @@ -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 { diff --git a/src/cmd/link/internal/sym/symkind.go b/src/cmd/link/internal/sym/symkind.go index 9f62e809e1..8709e7b48f 100644 --- a/src/cmd/link/internal/sym/symkind.go +++ b/src/cmd/link/internal/sym/symkind.go @@ -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 diff --git a/src/cmd/link/internal/sym/symkind_string.go b/src/cmd/link/internal/sym/symkind_string.go index 4e3a0a3431..019e7c746a 100644 --- a/src/cmd/link/internal/sym/symkind_string.go +++ b/src/cmd/link/internal/sym/symkind_string.go @@ -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) { -- 2.52.0