[PATCH] sparc: Fix argument passing to __libc_start_main on SPARC32

Adhemerval Zanella Netto adhemerval.zanella@linaro.org
Fri Jun 13 13:59:15 GMT 2025



On 13/06/25 07:22, Ludwig Rydberg wrote:
> Use a custom __libc_start_main function so the highest stack address can
> be provided to __libc_start_main_impl without altering the content of
> the stack (as there is no room for adding arguments to the stack).
> 
> The __libc_stack_end was written to [%sp+23*4] but that address is
> already in use (holds the pointer to argv) which led to corruption.
> 
> Fixes: d952c6efaa87 ("sparc: Fix argument passing to __libc_start_main (BZ 32981)")
> Signed-off-by: Ludwig Rydberg <ludwig.rydberg@gaisler.com>
> ---
>  sysdeps/sparc/sparc32/start.S                 |  6 ++--
>  .../sysv/linux/sparc/sparc32/libc-start.c     | 30 +++++++++++++++++++
>  2 files changed, 32 insertions(+), 4 deletions(-)
>  create mode 100644 sysdeps/unix/sysv/linux/sparc/sparc32/libc-start.c
> 
> diff --git a/sysdeps/sparc/sparc32/start.S b/sysdeps/sparc/sparc32/start.S
> index cef7c96cac72..9d97a2943efa 100644
> --- a/sysdeps/sparc/sparc32/start.S
> +++ b/sysdeps/sparc/sparc32/start.S
> @@ -64,18 +64,16 @@ _start:
>  	xor	%o0, %gdop_lox10(main), %o0
>  	ld	[%l7 + %o0], %o0, %gdop(main)
>  #endif
> -	mov	0, %o3		/* Used to be init.  */
> -	mov	0, %o4		/* Used to be fini.  */
>  
>    /* When starting a binary via the dynamic linker, %g1 contains the
>       address of the shared library termination function, which will be
>       registered with atexit().  If we are statically linked, this will
>       be NULL.  */
> -	mov	%g1, %o5
> +	mov	%g1, %o3
>  
>    /* Provide the highest stack address to update the __libc_stack_end (used
>       to enable executable stacks if required).  */
> -	st	%sp, [%sp+23*4]
> +	mov	%sp, %o4
>  
>    /* Let libc do the rest of the initialization, and call main.  */
>  	call	__libc_start_main
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc-start.c b/sysdeps/unix/sysv/linux/sparc/sparc32/libc-start.c
> new file mode 100644
> index 000000000000..c24c1539a41c
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc-start.c
> @@ -0,0 +1,30 @@
> +/* Copyright (C) 1998-2025 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#define LIBC_START_MAIN generic_start_main
> +#include <csu/libc-start.c>
> +
> +STATIC int
> +__libc_start_main_impl (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
> +			int argc, char **argv, void (*rtld_fini) (void),
> +			void *stack_end)
> +{
> +  return generic_start_main (main, argc, argv,
> +			     NULL, NULL, rtld_fini,
> +			     stack_end);
> +}
> +DEFINE_LIBC_START_MAIN_VERSION
> 

Wouldn't be simple we just adjust the initial stack frame to have minimal one:

diff --git a/sysdeps/sparc/sparc32/start.S b/sysdeps/sparc/sparc32/start.S
index cef7c96cac..8393760da6 100644
--- a/sysdeps/sparc/sparc32/start.S
+++ b/sysdeps/sparc/sparc32/start.S
@@ -35,6 +35,7 @@

 #include <sysdep.h>

+#define FRAME_SIZE 104

        .section ".text"
        .align 4
@@ -48,12 +49,12 @@ _start:
   /* Terminate the stack frame, and reserve space for functions to
      drop their arguments.  */
        mov     %g0, %fp
-       sub     %sp, 6*4, %sp
+       sub     %sp, FRAME_SIZE, %sp

   /* Extract the arguments and environment as encoded on the stack.  The
      argument info starts after one register window (16 words) past the SP.  */
-       ld      [%sp+22*4], %o1
-       add     %sp, 23*4, %o2
+       ld      [%sp+168], %o1
+       add     %sp, 172, %o2

   /* Load the addresses of the user entry points.  */
 #ifndef PIC

Sorry about that, I should have run some regressions tests before.



More information about the Libc-alpha mailing list