aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul E. Murphy <murp@ibm.com>2022-03-22 11:52:02 -0500
committerCherry Mui <cherryyz@google.com>2022-04-04 20:27:32 +0000
commit0bf8319883298dbeea81444cb704d8c0e9935bae (patch)
treece7c3b2939b8d924cad5f4188dbeba5155397b28
parent78b8b4a1760ce212c05edd14f52711936ee60930 (diff)
downloadgo-0bf8319883298dbeea81444cb704d8c0e9935bae.tar.gz
go-0bf8319883298dbeea81444cb704d8c0e9935bae.zip
[release-branch.go1.18] 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 #51874 Change-Id: I5de33862c161900d9161817388bbc13a65fdc69c Reviewed-on: https://go-review.googlesource.com/c/go/+/394654 Reviewed-by: Cherry Mui <cherryyz@google.com> Run-TryBot: Paul Murphy <murp@ibm.com> TryBot-Result: Gopher Robot <gobot@golang.org> Trust: Paul Murphy <murp@ibm.com> Trust: Lynn Boger <laboger@linux.vnet.ibm.com> Reviewed-on: https://go-review.googlesource.com/c/go/+/394794 Trust: Emmanuel Odeke <emmanuel@orijtech.com>
-rw-r--r--src/runtime/rt0_linux_ppc64le.s32
1 files changed, 21 insertions, 11 deletions
diff --git a/src/runtime/rt0_linux_ppc64le.s b/src/runtime/rt0_linux_ppc64le.s
index 4f7c6e6c99..66f7e7b22a 100644
--- a/src/runtime/rt0_linux_ppc64le.s
+++ b/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