]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link: move pclntab out of relro section
authorIan Lance Taylor <iant@golang.org>
Thu, 6 Nov 2025 00:13:22 +0000 (16:13 -0800)
committerGopher Robot <gobot@golang.org>
Thu, 6 Nov 2025 17:58:44 +0000 (09:58 -0800)
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>

src/cmd/link/internal/ld/data.go
src/cmd/link/internal/ld/elf.go
src/cmd/link/internal/ld/elf_test.go
src/cmd/link/internal/ld/macho_test.go
src/cmd/link/internal/sym/symkind.go
src/cmd/link/internal/sym/symkind_string.go

index fcc327276079569a90ff7468d57678bfcd7acad9..e7e202fc1f638ef7fb748d16c62848cd960e40b0 100644 (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)
index 8981f1c3f02272c63c2a18eaa0cb3ba34fda854d..90f9388ed7410ceb794e076510a68da4fa527d15 100644 (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() {
index c2a1bc0b9442e0534e3fabf1d21b4722a481b1df..c56d27f29e459d39fc60f47f099281149847394c 100644 (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
index adf159ab6d2ce8eb8bc475d419f723a643adfbc9..905de67f6016ed13f672aeb6982b02b01dce423a 100644 (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 {
index 9f62e809e14ca32e070395b523717ee06326d042..8709e7b48f8a2a20085591540865386d3ba2b5cb 100644 (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
index 4e3a0a3431ae0b26bdba6ddf1b5c4aad90b516d6..019e7c746a679db5f6723bc5a20ac7a8ae872d21 100644 (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) {