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

Ludwig Rydberg ludwig.rydberg@gaisler.com
Fri Jun 13 10:22:41 GMT 2025


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

base-commit: daab2a6d19f8360248289840408e7d2e5c203c2e
-- 
2.35.3



More information about the Libc-alpha mailing list