]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link/internal/arm64: support Mach-O ARM64_RELOC_SUBTRACTOR in internal linking
authorqmuntal <quimmuntal@gmail.com>
Fri, 12 Sep 2025 14:31:01 +0000 (16:31 +0200)
committerQuim Muntal <quimmuntal@gmail.com>
Tue, 30 Sep 2025 14:38:03 +0000 (07:38 -0700)
ARM64_RELOC_SUBTRACTOR is the arm64 version of X86_64_RELOC_SUBTRACTOR, which
has been recently implemented in CL 660715.

The standard library still doesn't need it, but I've found it necessary
when statically linking against a library I own.

Change-Id: I138281b12f2304e3673f7dc92f7137e48bf68fdd
Reviewed-on: https://go-review.googlesource.com/c/go/+/703316
Reviewed-by: Carlos Amedee <carlos@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
src/cmd/link/internal/arm64/asm.go
src/cmd/link/internal/ld/macho.go

index b2572fd1040b0bdef82c44e88b58e33db53c3728..8d8ea8ac542c5095e92a268384039a502a980465 100644 (file)
@@ -224,6 +224,28 @@ func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loade
                }
                return true
 
+       case objabi.MachoRelocOffset + ld.MACHO_ARM64_RELOC_SUBTRACTOR*2:
+               // ARM64_RELOC_SUBTRACTOR must be followed by ARM64_RELOC_UNSIGNED.
+               // The pair of relocations resolves to the difference between two
+               // symbol addresses (each relocation specifies a symbol).
+               outer, off := ld.FoldSubSymbolOffset(ldr, targ)
+               if outer != s {
+                       // TODO: support subtracted symbol in different section.
+                       ldr.Errorf(s, "unsupported ARM64_RELOC_SUBTRACTOR reloc: target %s, outer %s", ldr.SymName(targ), ldr.SymName(outer))
+                       break
+               }
+               su := ldr.MakeSymbolUpdater(s)
+               relocs := su.Relocs()
+               if rIdx+1 >= relocs.Count() || relocs.At(rIdx+1).Type() != objabi.MachoRelocOffset+ld.MACHO_ARM64_RELOC_UNSIGNED*2 || relocs.At(rIdx+1).Off() != r.Off() {
+                       ldr.Errorf(s, "unexpected ARM64_RELOC_SUBTRACTOR reloc, must be followed by ARM64_RELOC_UNSIGNED at same offset")
+                       break
+               }
+               su.SetRelocType(rIdx+1, objabi.R_PCREL)
+               su.SetRelocAdd(rIdx+1, r.Add()+int64(r.Off())+int64(r.Siz())-off)
+               // Remove the other relocation
+               su.SetRelocSiz(rIdx, 0)
+               return true
+
        case objabi.MachoRelocOffset + ld.MACHO_ARM64_RELOC_BRANCH26*2 + pcrel:
                su := ldr.MakeSymbolUpdater(s)
                su.SetRelocType(rIdx, objabi.R_CALLARM64)
index 6920f42015b344660db31a3f7580339c563c3a6a..c26263466616f5c99164e8433b6bc572efb942a7 100644 (file)
@@ -106,6 +106,7 @@ const (
        MACHO_ARM_RELOC_SECTDIFF             = 2
        MACHO_ARM_RELOC_BR24                 = 5
        MACHO_ARM64_RELOC_UNSIGNED           = 0
+       MACHO_ARM64_RELOC_SUBTRACTOR         = 1
        MACHO_ARM64_RELOC_BRANCH26           = 2
        MACHO_ARM64_RELOC_PAGE21             = 3
        MACHO_ARM64_RELOC_PAGEOFF12          = 4