diff --git a/srcpkgs/go/patches/fix-ppc64le-startup-detection.patch b/srcpkgs/go/patches/fix-ppc64le-startup-detection.patch new file mode 100644 index 00000000000..6cc2ab33724 --- /dev/null +++ b/srcpkgs/go/patches/fix-ppc64le-startup-detection.patch @@ -0,0 +1,81 @@ +From 946167906ed8646c433c257b074a10e01f0a7dab Mon Sep 17 00:00:00 2001 +From: "Paul E. Murphy" +Date: Tue, 22 Mar 2022 11:52:02 -0500 +Subject: [PATCH] runtime: make static/dynamic startup detection work with musl + on ppc64le + +The glibc loader explicitly sets the first doubleword on the stack (R1) +to $0 to indicate it was dynamically loaded. + +An ELFv2 ABI compliant loader will set R3/R4 to argc/argv when starting +the process, and R13 to TLS. musl is not compliant. Instead it passes +argc/argv like the kernel, but R3/R4 are in an undefined state and R13 +is valid. + +With the knowledge above, the startup code can be modified to +dynamically handle all three cases when linked internally. + +Fixes #51787 + +Change-Id: I5de33862c161900d9161817388bbc13a65fdc69c +Reviewed-on: https://go-review.googlesource.com/c/go/+/394654 +Reviewed-by: Cherry Mui +Run-TryBot: Paul Murphy +TryBot-Result: Gopher Robot +Trust: Paul Murphy +Trust: Lynn Boger +--- + src/runtime/rt0_linux_ppc64le.s | 32 +++++++++++++++++++++----------- + 1 file changed, 21 insertions(+), 11 deletions(-) + +diff --git a/src/runtime/rt0_linux_ppc64le.s b/src/runtime/rt0_linux_ppc64le.s +index 4f7c6e6c99f6..66f7e7b22a41 100644 +--- a/go/src/runtime/rt0_linux_ppc64le.s ++++ b/go/src/runtime/rt0_linux_ppc64le.s +@@ -147,25 +147,35 @@ TEXT _main<>(SB),NOSPLIT,$-8 + // In a statically linked binary, the stack contains argc, + // argv as argc string pointers followed by a NULL, envv as a + // sequence of string pointers followed by a NULL, and auxv. +- // There is no TLS base pointer. ++ // The TLS pointer should be initialized to 0. + // +- // In a dynamically linked binary, r3 contains argc, r4 +- // contains argv, r5 contains envp, r6 contains auxv, and r13 ++ // In an ELFv2 compliant dynamically linked binary, R3 contains argc, ++ // R4 contains argv, R5 contains envp, R6 contains auxv, and R13 + // contains the TLS pointer. + // +- // Figure out which case this is by looking at r4: if it's 0, +- // we're statically linked; otherwise we're dynamically +- // linked. +- CMP R0, R4 +- BNE dlink +- +- // Statically linked ++ // When loading via glibc, the first doubleword on the stack points ++ // to NULL a value. (that is *(uintptr)(R1) == 0). This is used to ++ // differentiate static vs dynamicly linked binaries. ++ // ++ // If loading with the musl loader, it doesn't follow the ELFv2 ABI. It ++ // passes argc/argv similar to the linux kernel, R13 (TLS) is ++ // initialized, and R3/R4 are undefined. ++ MOVD (R1), R12 ++ CMP R0, R12 ++ BEQ tls_and_argcv_in_reg ++ ++ // Arguments are passed via the stack (musl loader or a static binary) + MOVD 0(R1), R3 // argc + ADD $8, R1, R4 // argv ++ ++ // Did the TLS pointer get set? If so, don't change it (e.g musl). ++ CMP R0, R13 ++ BNE tls_and_argcv_in_reg ++ + MOVD $runtimeĀ·m0+m_tls(SB), R13 // TLS + ADD $0x7000, R13 + +-dlink: ++tls_and_argcv_in_reg: + BR main(SB) + + TEXT main(SB),NOSPLIT,$-8