]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link: handle runtime.type based on size, not GOOS
authorIan Lance Taylor <iant@golang.org>
Thu, 12 Feb 2026 05:23:49 +0000 (21:23 -0800)
committerGopher Robot <gobot@golang.org>
Thu, 12 Feb 2026 14:08:58 +0000 (06:08 -0800)
When handling type descriptors, we add some space at the start
to ensure that offset 0 does not refer to a valid type descriptor.
AIX has an initial runtime.types symbol with a non-zero size,
so we used that instead of adding some space.

In some cases Darwin also has a runtime.types symbol with a non-zero size.
Before CL 727021, this was always fine, because the 8 byte size of
runtime.types was swamped by the 32-byte alignment of type descriptors.
That didn't work for AIX with the external linker, because on AIX the
external linker lays out each symbol separately. Darwin doesn't have
that problem, so the layout of the internal linker was preserved.

However, CL 727021 changed the alignment of type descriptors to 8.
That means that on Darwin the 8 byte size of runtime.types was no
longer hidden by the alignment. In effect we were skipping twice:
once for runtime.types, and then again explicitly. This only failed
when runtime.types has a non-zero size, which is only in a few
specific cases.

This CL cleans this up by not skipping explicitly in any case
where runtime.types has a non-zero size. That handles both AIX
and Darwin consistently.

To make this clearer, I changed the skip from a single byte to
the size of a pointer in all cases.

I considered always giving runtime.types a non-zero size,
but that is a bigger change, and potentially confusing since
there really isn't any data associated with runtime.types.
The cases where we must give it a non-zero size are special,
and I think it's simpler to keep it that way.

For #6853
For #36313
Fixes #77569

Change-Id: I22ebbd0194527ecca96d48849aa00a4fc899e55c
Reviewed-on: https://go-review.googlesource.com/c/go/+/744820
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Michael Pratt <mpratt@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Keith Randall <khr@google.com>
Auto-Submit: Ian Lance Taylor <iant@golang.org>

src/cmd/link/internal/ld/data.go
src/runtime/type.go

index de9e9ea59ee768f50e69569f80d055e971b605b7..43c3cd38dbbaf3d95789844d4f92f73e2224b04c 100644 (file)
@@ -1498,7 +1498,7 @@ func fixZeroSizedSymbols(ctxt *Link) {
        defineRuntimeTypes := func() {
                types := ldr.CreateSymForUpdate("runtime.types", 0)
                types.SetType(sym.STYPE)
-               types.SetSize(8)
+               types.SetSize(int64(ctxt.Arch.PtrSize))
                types.SetAlign(int32(ctxt.Arch.PtrSize))
                ldr.SetAttrSpecial(types.Sym(), false)
        }
@@ -2206,20 +2206,20 @@ func (state *dodataState) allocateDataSections(ctxt *Link) {
        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
+               if symn == sym.STYPE {
+                       // Increment state.datsize so that no type
                        // reference uses a zero offset.
                        // This is unlikely but possible in small
                        // programs with no other read-only data.
                        //
-                       // Don't skip forward on AIX because the external
-                       // linker, when used, will align symbols itself.
-                       // The external linker won't know about this skip,
-                       // and will mess up the constant offsets we need
-                       // within the type section. On AIX we just live
-                       // with the possibility of a broken program
-                       // if there is no other read-only data.
-                       state.datsize++
+                       // But don't skip ahead if there is a runtime.types
+                       // symbol with non-zero size. That can be created
+                       // in fixZeroSizedSymbols. In that case the
+                       // runtime.types symbol itself serves as the skip.
+                       typesSym := ldr.Lookup("runtime.types", 0)
+                       if typesSym == 0 || ldr.SymSize(typesSym) == 0 {
+                               state.datsize += int64(ctxt.Arch.PtrSize)
+                       }
                }
 
                // Align to first symbol.
@@ -2479,10 +2479,13 @@ func (state *dodataState) dodataSect(ctxt *Link, symn sym.SymKind, syms []loader
                })
 
                // Find the end of the typelink descriptors.
-               // The size starts at 1 to match the increment in
+               // The size starts at PtrSize to match the value in
                // createRelroSect in allocateDataSections.
+               // Note that we skip runtime.types in the loop,
+               // so we don't need to worry about that case;
+               // there will be an increment either way.
                // TODO: This wastes some space.
-               typeLinkSize := int64(1)
+               typeLinkSize := int64(ctxt.Arch.PtrSize)
                for i := range sl {
                        si := sl[i].sym
                        if si == head || si == typeStar {
index 1abd271c3fe845c63231c6a725d5f85ff919d81e..58349e921a709b5965b3f6b982ec7f0946fb4466 100644 (file)
@@ -524,14 +524,15 @@ func moduleTypelinks(md *moduledata) []*_type {
 
        td := md.types
 
-       // We have to increment by 1 to match the increment done in
-       // cmd/link/internal/data.go createRelroSect in allocateDataSections.
+       // We have to increment by the pointer size to match the
+       // increment in cmd/link/internal/data.go createRelroSect
+       // in allocateDataSections.
        //
-       // We don't do that increment on AIX, but on AIX we need to adjust
-       // for the fact that the runtime.types symbol has a size of 8,
-       // and the type descriptors will follow that. This increment,
-       // followed by the forced alignment to 8, will do that.
-       td++
+       // The linker doesn't do that increment when runtime.types
+       // has a non-zero size, but in that case the runtime.types
+       // symbol itself pushes the other symbols forward.
+       // So either way this increment is correct.
+       td += goarch.PtrSize
 
        etypedesc := md.types + md.typedesclen
        for td < etypedesc {