go: cmd/link: Go c-archive doesn't work with new Xcode 15 beta ld-prime linker

We found that Go libraries (-buildmode=c-archive) linked into iOS apps crash on startup (during the dynamic loader?) when using the new Xcode 15 beta’s “ld-prime” linker.

The workaround for now is to force the old linker with LDFLAGS=-ld64, so filing this issue for people to find.

/cc @agottardo (who figured out the workaround and can probably provide more details)

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Reactions: 5
  • Comments: 21 (10 by maintainers)

Commits related to this issue

Most upvoted comments

This hack seems to make it work. Basically, for __mod_init_func, we need to use symbol-targeted relocation, instead of section+offset-targeted relocation (ld-prime just drops the offset, making it point to the start of the section…)… This seems to work for both ld64 and ld-prime.

diff --git a/src/cmd/link/internal/amd64/asm.go b/src/cmd/link/internal/amd64/asm.go
index 7082c839ee..58b29fb6ea 100644
--- a/src/cmd/link/internal/amd64/asm.go
+++ b/src/cmd/link/internal/amd64/asm.go
@@ -469,7 +469,7 @@ func machoreloc1(arch *sys.Arch, out *ld.OutBuf, ldr *loader.Loader, s loader.Sy
        rs := r.Xsym
        rt := r.Type
 
-       if ldr.SymType(rs) == sym.SHOSTOBJ || rt == objabi.R_PCREL || rt == objabi.R_GOTPCREL || rt == objabi.R_CALL {
+       if ldr.SymType(rs) == sym.SHOSTOBJ || rt == objabi.R_PCREL || rt == objabi.R_GOTPCREL || rt == objabi.R_CALL || ldr.SymType(s) == sym.SINITARR {
                if ldr.SymDynid(rs) < 0 {
                        ldr.Errorf(s, "reloc %d (%s) to non-macho symbol %s type=%d (%s)", rt, sym.RelocName(arch, rt), ldr.SymName(rs), ldr.SymType(rs), ldr.SymType(rs))
                        return false
diff --git a/src/cmd/link/internal/arm64/asm.go b/src/cmd/link/internal/arm64/asm.go
index f2a2b32232..2c3c994169 100644
--- a/src/cmd/link/internal/arm64/asm.go
+++ b/src/cmd/link/internal/arm64/asm.go
@@ -580,7 +580,7 @@ func machoreloc1(arch *sys.Arch, out *ld.OutBuf, ldr *loader.Loader, s loader.Sy
        if ldr.SymType(rs) == sym.SHOSTOBJ || rt == objabi.R_CALLARM64 ||
                rt == objabi.R_ARM64_PCREL_LDST8 || rt == objabi.R_ARM64_PCREL_LDST16 ||
                rt == objabi.R_ARM64_PCREL_LDST32 || rt == objabi.R_ARM64_PCREL_LDST64 ||
-               rt == objabi.R_ADDRARM64 || rt == objabi.R_ARM64_GOTPCREL {
+               rt == objabi.R_ADDRARM64 || rt == objabi.R_ARM64_GOTPCREL || ldr.SymType(s) == sym.SINITARR {
                if ldr.SymDynid(rs) < 0 {
                        ldr.Errorf(s, "reloc %d (%s) to non-macho symbol %s type=%d (%s)", rt, sym.RelocName(arch, rt), ldr.SymName(rs), ldr.SymType(rs), ldr.SymType(rs))
                        return false
diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go
index d651e2e346..891d7c7358 100644
--- a/src/cmd/link/internal/ld/data.go
+++ b/src/cmd/link/internal/ld/data.go
@@ -368,7 +368,7 @@ func (st *relocSymState) relocsym(s loader.Sym, P []byte) {
                                                o = 0
                                        }
                                } else if target.IsDarwin() {
-                                       if ldr.SymType(rs) != sym.SHOSTOBJ {
+                                       if ldr.SymType(rs) != sym.SHOSTOBJ && ldr.SymType(s) != sym.SINITARR {
                                                o += ldr.SymValue(rs)
                                        }
                                } else if target.IsWindows() {

@albertoAround the fix will be included in Go 1.21, which is to be released next week. You could also checkout the master branch and build the Go toolchain (you could also cherry-pick CL https://golang.org/cl/502616 but it is probably better and simpler to just use the master branch). Thanks.

@agottardo Thanks for sharing. I’ll look into it.

Also, I downloaded Xcode 15 beta, ran it on a macOS ARM64 machine using ld-prime with Go, and found a number of issues. While some of them are minor, I got SIGILL for the c-shared and plugin mode, which may also be related. I’ll look into them. Thanks.