]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
arm: Fix main-in-dso with non-BFD linkers (BZ 34098)
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>
Tue, 2 Jun 2026 18:05:47 +0000 (15:05 -0300)
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>
Wed, 3 Jun 2026 12:09:12 +0000 (09:09 -0300)
Commit c2d6afb4a010 changed the PIC && !SHARED path of start.S (used by
crt1.o and rcrt1.o) to load main via a R_ARM_REL32 data relocation.  When
main is provided by a shared object, BFD ld synthesizes a canonical PLT
entry for it, but other linkers (e.g. mold) do not, producing a broken
binary that crashes at startup.

Follow the aarch64 approach and reference main through a local __wrap_main
that tail-calls it with a branch relocation, which every linker turns into
a PLT entry.

Checked on armv7a-linux-gnueabihf with and without --enable-default-pie.

sysdeps/arm/start.S

index 3401daf89df0404ae8305d1cbcdd77bd2f470b1f..6b154dc7d33e3450b94991e9d827a3edf85acc9f 100644 (file)
@@ -105,7 +105,7 @@ _start:
        /* Let the libc call main and exit with its return code.  */
        bl __libc_start_main(PLT)
 # else
-       ldr a1, .L_main_rel     /* Load the relative offset of main. */
+       ldr a1, .L_main_rel     /* Load the relative offset of __wrap_main. */
        adr a4, .L_main_rel     /* Load the actual runtime address of the label. */
        add a1, a4, a1          /* Add them together to get the absolute address. */
 
@@ -136,13 +136,24 @@ _start:
        .word main(GOT)
 # else
 .L_main_rel:
-       .word main - .L_main_rel
+       .word __wrap_main - .L_main_rel
 # endif
 #endif
 
        .cantunwind
        .fnend
 
+#if defined PIC && !defined SHARED
+/* When main is not defined in the executable but in a shared library then
+   a wrapper is needed, because crt1.o and rcrt1.o share this code and the
+   latter (static PIE) must avoid GOT relocations before __libc_start_main
+   is called.  The branch to main is turned into a PLT entry by every linker,
+   unlike a REL32 data relocation against main.  */
+       .type __wrap_main, %function
+__wrap_main:
+       b main
+#endif
+
 /* Define a symbol for the first piece of initialized data.  */
        .data
        .globl __data_start