]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: make static/dynamic startup detection work with musl on ppc64le
authorPaul E. Murphy <murp@ibm.com>
Tue, 22 Mar 2022 16:52:02 +0000 (11:52 -0500)
committerPaul Murphy <murp@ibm.com>
Tue, 22 Mar 2022 20:56:39 +0000 (20:56 +0000)
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 <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>

src/runtime/rt0_linux_ppc64le.s

index 4f7c6e6c99f60a1364cea4ab8424299ee70ba51c..66f7e7b22a411dd82092add7a9f2a38d6c0d6adb 100644 (file)
@@ -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