diff mbox series

[v6,4/4] aarch64: Move ld.so _start to separate file and drop _dl_skip_args

Message ID 30ecd158a7425badc5996450816a3ca3dd86e9c9.1651757640.git.szabolcs.nagy@arm.com
State New
Headers show
Series Args adjustment with ./ld.so exe [BZ #23293] | expand

Commit Message

Szabolcs Nagy May 5, 2022, 1:59 p.m. UTC
A separate asm file is easier to maintain than a macro that expands to
inline asm.

The RTLD_START macro is only needed now because _dl_start is local in
rtld.c, but _start has to call it, if _dl_start was made hidden then it
could be empty.

_dl_skip_args is no longer needed.

---
v4:
- adjust commit message about _dl_skip_args.
v3:
- mention _dl_skip_args
v2:
- fix typo in commit message.
---
 sysdeps/aarch64/Makefile     |  1 +
 sysdeps/aarch64/dl-machine.h | 77 +-----------------------------------
 sysdeps/aarch64/dl-start.S   | 53 +++++++++++++++++++++++++
 3 files changed, 56 insertions(+), 75 deletions(-)
 create mode 100644 sysdeps/aarch64/dl-start.S

Comments

Adhemerval Zanella Netto May 13, 2022, 8:46 p.m. UTC | #1
On 05/05/2022 10:59, Szabolcs Nagy via Libc-alpha wrote:
> A separate asm file is easier to maintain than a macro that expands to
> inline asm.
> 
> The RTLD_START macro is only needed now because _dl_start is local in
> rtld.c, but _start has to call it, if _dl_start was made hidden then it
> could be empty.
> 
> _dl_skip_args is no longer needed.

LGTM, thanks.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>

> 
> ---
> v4:
> - adjust commit message about _dl_skip_args.
> v3:
> - mention _dl_skip_args
> v2:
> - fix typo in commit message.
> ---
>  sysdeps/aarch64/Makefile     |  1 +
>  sysdeps/aarch64/dl-machine.h | 77 +-----------------------------------
>  sysdeps/aarch64/dl-start.S   | 53 +++++++++++++++++++++++++
>  3 files changed, 56 insertions(+), 75 deletions(-)
>  create mode 100644 sysdeps/aarch64/dl-start.S
> 
> diff --git a/sysdeps/aarch64/Makefile b/sysdeps/aarch64/Makefile
> index 7183895d04..17fb1c5b72 100644
> --- a/sysdeps/aarch64/Makefile
> +++ b/sysdeps/aarch64/Makefile
> @@ -33,6 +33,7 @@ tst-audit27-ENV = LD_AUDIT=$(objpfx)tst-auditmod27.so
>  endif
>  
>  ifeq ($(subdir),elf)
> +sysdep-rtld-routines += dl-start
>  sysdep-dl-routines += tlsdesc dl-tlsdesc
>  gen-as-const-headers += dl-link.sym
>  
> diff --git a/sysdeps/aarch64/dl-machine.h b/sysdeps/aarch64/dl-machine.h
> index b40050a981..fe120bb507 100644
> --- a/sysdeps/aarch64/dl-machine.h
> +++ b/sysdeps/aarch64/dl-machine.h
> @@ -105,81 +105,8 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
>    return lazy;
>  }
>  
> -/* Initial entry point for the dynamic linker. The C function
> -   _dl_start is the real entry point, its return value is the user
> -   program's entry point */
> -#ifdef __LP64__
> -# define RTLD_START RTLD_START_1 ("x", "3", "sp")
> -#else
> -# define RTLD_START RTLD_START_1 ("w", "2", "wsp")
> -#endif
> -
> -
> -#define RTLD_START_1(PTR, PTR_SIZE_LOG, PTR_SP) asm ("\
> -.text									\n\
> -.globl _start								\n\
> -.type _start, %function							\n\
> -.globl _dl_start_user							\n\
> -.type _dl_start_user, %function						\n\
> -_start:									\n\
> -	// bti c							\n\
> -	hint	34							\n\
> -	mov	" PTR "0, " PTR_SP "					\n\
> -	bl	_dl_start						\n\
> -	// returns user entry point in x0				\n\
> -	mov	x21, x0							\n\
> -_dl_start_user:								\n\
> -	// get the original arg count					\n\
> -	ldr	" PTR "1, [sp]						\n\
> -	// get the argv address						\n\
> -	add	" PTR "2, " PTR_SP ", #(1<<"  PTR_SIZE_LOG ")		\n\
> -	// get _dl_skip_args to see if we were				\n\
> -	// invoked as an executable					\n\
> -	adrp	x4, _dl_skip_args					\n\
> -        ldr	w4, [x4, #:lo12:_dl_skip_args]				\n\
> -	// do we need to adjust argc/argv				\n\
> -        cmp	w4, 0							\n\
> -	beq	.L_done_stack_adjust					\n\
> -	// subtract _dl_skip_args from original arg count		\n\
> -	sub	" PTR "1, " PTR "1, " PTR "4				\n\
> -	// store adjusted argc back to stack				\n\
> -	str	" PTR "1, [sp]						\n\
> -	// find the first unskipped argument				\n\
> -	mov	" PTR "3, " PTR "2					\n\
> -	add	" PTR "4, " PTR "2, " PTR "4, lsl #" PTR_SIZE_LOG "	\n\
> -	// shuffle argv down						\n\
> -1:	ldr	" PTR "5, [x4], #(1<<"  PTR_SIZE_LOG ")			\n\
> -	str	" PTR "5, [x3], #(1<<"  PTR_SIZE_LOG ")			\n\
> -	cmp	" PTR "5, #0						\n\
> -	bne	1b							\n\
> -	// shuffle envp down						\n\
> -1:	ldr	" PTR "5, [x4], #(1<<"  PTR_SIZE_LOG ")			\n\
> -	str	" PTR "5, [x3], #(1<<"  PTR_SIZE_LOG ")			\n\
> -	cmp	" PTR "5, #0						\n\
> -	bne	1b							\n\
> -	// shuffle auxv down						\n\
> -1:	ldp	" PTR "0, " PTR "5, [x4, #(2<<"  PTR_SIZE_LOG ")]!	\n\
> -	stp	" PTR "0, " PTR "5, [x3], #(2<<"  PTR_SIZE_LOG ")	\n\
> -	cmp	" PTR "0, #0						\n\
> -	bne	1b							\n\
> -	// Update _dl_argv						\n\
> -	adrp	x3, __GI__dl_argv					\n\
> -	str	" PTR "2, [x3, #:lo12:__GI__dl_argv]			\n\
> -.L_done_stack_adjust:							\n\
> -	// compute envp							\n\
> -	add	" PTR "3, " PTR "2, " PTR "1, lsl #" PTR_SIZE_LOG "	\n\
> -	add	" PTR "3, " PTR "3, #(1<<"  PTR_SIZE_LOG ")		\n\
> -	adrp	x16, _rtld_local					\n\
> -        add	" PTR "16, " PTR "16, #:lo12:_rtld_local		\n\
> -        ldr	" PTR "0, [x16]						\n\
> -	bl	_dl_init						\n\
> -	// load the finalizer function					\n\
> -	adrp	x0, _dl_fini						\n\
> -	add	" PTR "0, " PTR "0, #:lo12:_dl_fini			\n\
> -	// jump to the user_s entry point				\n\
> -	mov     x16, x21						\n\
> -	br      x16							\n\
> -");
> +/* In elf/rtld.c _dl_start should be global so dl-start.S can reference it.  */
> +#define RTLD_START asm (".globl _dl_start");
>  
>  #define elf_machine_type_class(type)					\
>    ((((type) == AARCH64_R(JUMP_SLOT)					\
> diff --git a/sysdeps/aarch64/dl-start.S b/sysdeps/aarch64/dl-start.S
> new file mode 100644
> index 0000000000..a3a57bd5a1
> --- /dev/null
> +++ b/sysdeps/aarch64/dl-start.S
> @@ -0,0 +1,53 @@
> +/* ld.so _start code.
> +   Copyright (C) 2022 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/>.  */
> +
> +#include <sysdep.h>
> +
> +ENTRY (_start)
> +	/* Create an initial frame with 0 LR and FP */
> +	cfi_undefined (x30)
> +	mov	x29, #0
> +	mov	x30, #0
> +
> +	mov	x0, sp
> +	PTR_ARG (0)
> +	bl	_dl_start
> +	/* Returns user entry point in x0.  */
> +	mov	PTR_REG (21), PTR_REG (0)
> +.globl _dl_start_user
> +.type _dl_start_user, %function
> +_dl_start_user:
> +	/* Get argc.  */
> +	ldr	PTR_REG (1), [sp]
> +	/* Get argv.  */
> +	add	x2, sp, PTR_SIZE
> +	/* Compute envp.  */
> +	add	PTR_REG (3), PTR_REG (2), PTR_REG (1), lsl PTR_LOG_SIZE
> +	add	PTR_REG (3), PTR_REG (3), PTR_SIZE
> +	adrp	x16, _rtld_local
> +	add	PTR_REG (16), PTR_REG (16), :lo12:_rtld_local
> +	ldr	PTR_REG (0), [x16]
> +	bl	_dl_init
> +	/* Load the finalizer function.  */
> +	adrp	x0, _dl_fini
> +	add	PTR_REG (0), PTR_REG (0), :lo12:_dl_fini
> +	/* Jump to the user's entry point.  */
> +	mov     x16, x21
> +	br      x16
> +END (_start)
diff mbox series

Patch

diff --git a/sysdeps/aarch64/Makefile b/sysdeps/aarch64/Makefile
index 7183895d04..17fb1c5b72 100644
--- a/sysdeps/aarch64/Makefile
+++ b/sysdeps/aarch64/Makefile
@@ -33,6 +33,7 @@  tst-audit27-ENV = LD_AUDIT=$(objpfx)tst-auditmod27.so
 endif
 
 ifeq ($(subdir),elf)
+sysdep-rtld-routines += dl-start
 sysdep-dl-routines += tlsdesc dl-tlsdesc
 gen-as-const-headers += dl-link.sym
 
diff --git a/sysdeps/aarch64/dl-machine.h b/sysdeps/aarch64/dl-machine.h
index b40050a981..fe120bb507 100644
--- a/sysdeps/aarch64/dl-machine.h
+++ b/sysdeps/aarch64/dl-machine.h
@@ -105,81 +105,8 @@  elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
   return lazy;
 }
 
-/* Initial entry point for the dynamic linker. The C function
-   _dl_start is the real entry point, its return value is the user
-   program's entry point */
-#ifdef __LP64__
-# define RTLD_START RTLD_START_1 ("x", "3", "sp")
-#else
-# define RTLD_START RTLD_START_1 ("w", "2", "wsp")
-#endif
-
-
-#define RTLD_START_1(PTR, PTR_SIZE_LOG, PTR_SP) asm ("\
-.text									\n\
-.globl _start								\n\
-.type _start, %function							\n\
-.globl _dl_start_user							\n\
-.type _dl_start_user, %function						\n\
-_start:									\n\
-	// bti c							\n\
-	hint	34							\n\
-	mov	" PTR "0, " PTR_SP "					\n\
-	bl	_dl_start						\n\
-	// returns user entry point in x0				\n\
-	mov	x21, x0							\n\
-_dl_start_user:								\n\
-	// get the original arg count					\n\
-	ldr	" PTR "1, [sp]						\n\
-	// get the argv address						\n\
-	add	" PTR "2, " PTR_SP ", #(1<<"  PTR_SIZE_LOG ")		\n\
-	// get _dl_skip_args to see if we were				\n\
-	// invoked as an executable					\n\
-	adrp	x4, _dl_skip_args					\n\
-        ldr	w4, [x4, #:lo12:_dl_skip_args]				\n\
-	// do we need to adjust argc/argv				\n\
-        cmp	w4, 0							\n\
-	beq	.L_done_stack_adjust					\n\
-	// subtract _dl_skip_args from original arg count		\n\
-	sub	" PTR "1, " PTR "1, " PTR "4				\n\
-	// store adjusted argc back to stack				\n\
-	str	" PTR "1, [sp]						\n\
-	// find the first unskipped argument				\n\
-	mov	" PTR "3, " PTR "2					\n\
-	add	" PTR "4, " PTR "2, " PTR "4, lsl #" PTR_SIZE_LOG "	\n\
-	// shuffle argv down						\n\
-1:	ldr	" PTR "5, [x4], #(1<<"  PTR_SIZE_LOG ")			\n\
-	str	" PTR "5, [x3], #(1<<"  PTR_SIZE_LOG ")			\n\
-	cmp	" PTR "5, #0						\n\
-	bne	1b							\n\
-	// shuffle envp down						\n\
-1:	ldr	" PTR "5, [x4], #(1<<"  PTR_SIZE_LOG ")			\n\
-	str	" PTR "5, [x3], #(1<<"  PTR_SIZE_LOG ")			\n\
-	cmp	" PTR "5, #0						\n\
-	bne	1b							\n\
-	// shuffle auxv down						\n\
-1:	ldp	" PTR "0, " PTR "5, [x4, #(2<<"  PTR_SIZE_LOG ")]!	\n\
-	stp	" PTR "0, " PTR "5, [x3], #(2<<"  PTR_SIZE_LOG ")	\n\
-	cmp	" PTR "0, #0						\n\
-	bne	1b							\n\
-	// Update _dl_argv						\n\
-	adrp	x3, __GI__dl_argv					\n\
-	str	" PTR "2, [x3, #:lo12:__GI__dl_argv]			\n\
-.L_done_stack_adjust:							\n\
-	// compute envp							\n\
-	add	" PTR "3, " PTR "2, " PTR "1, lsl #" PTR_SIZE_LOG "	\n\
-	add	" PTR "3, " PTR "3, #(1<<"  PTR_SIZE_LOG ")		\n\
-	adrp	x16, _rtld_local					\n\
-        add	" PTR "16, " PTR "16, #:lo12:_rtld_local		\n\
-        ldr	" PTR "0, [x16]						\n\
-	bl	_dl_init						\n\
-	// load the finalizer function					\n\
-	adrp	x0, _dl_fini						\n\
-	add	" PTR "0, " PTR "0, #:lo12:_dl_fini			\n\
-	// jump to the user_s entry point				\n\
-	mov     x16, x21						\n\
-	br      x16							\n\
-");
+/* In elf/rtld.c _dl_start should be global so dl-start.S can reference it.  */
+#define RTLD_START asm (".globl _dl_start");
 
 #define elf_machine_type_class(type)					\
   ((((type) == AARCH64_R(JUMP_SLOT)					\
diff --git a/sysdeps/aarch64/dl-start.S b/sysdeps/aarch64/dl-start.S
new file mode 100644
index 0000000000..a3a57bd5a1
--- /dev/null
+++ b/sysdeps/aarch64/dl-start.S
@@ -0,0 +1,53 @@ 
+/* ld.so _start code.
+   Copyright (C) 2022 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/>.  */
+
+#include <sysdep.h>
+
+ENTRY (_start)
+	/* Create an initial frame with 0 LR and FP */
+	cfi_undefined (x30)
+	mov	x29, #0
+	mov	x30, #0
+
+	mov	x0, sp
+	PTR_ARG (0)
+	bl	_dl_start
+	/* Returns user entry point in x0.  */
+	mov	PTR_REG (21), PTR_REG (0)
+.globl _dl_start_user
+.type _dl_start_user, %function
+_dl_start_user:
+	/* Get argc.  */
+	ldr	PTR_REG (1), [sp]
+	/* Get argv.  */
+	add	x2, sp, PTR_SIZE
+	/* Compute envp.  */
+	add	PTR_REG (3), PTR_REG (2), PTR_REG (1), lsl PTR_LOG_SIZE
+	add	PTR_REG (3), PTR_REG (3), PTR_SIZE
+	adrp	x16, _rtld_local
+	add	PTR_REG (16), PTR_REG (16), :lo12:_rtld_local
+	ldr	PTR_REG (0), [x16]
+	bl	_dl_init
+	/* Load the finalizer function.  */
+	adrp	x0, _dl_fini
+	add	PTR_REG (0), PTR_REG (0), :lo12:_dl_fini
+	/* Jump to the user's entry point.  */
+	mov     x16, x21
+	br      x16
+END (_start)