[PATCH v2 04/14] riscv: Adjust assembly routines to support landing pad

Deepak Gupta debug@rivosinc.com
Tue Jul 22 20:27:59 GMT 2025


On Fri, Jul 11, 2025 at 06:52:45AM -0700, Jesse Huang wrote:
>Landing pads, instructions for setting the label value as well as
>alignment directives are inserted at where they should be.
>
>Frame offsets for floating point registers in _dl_runtime_resolve
>are also adjusted because now t2 has to be saved onto the stack.
>
>Co-authored-by: Hau Hsu <hau.hsu@sifive.com>
>Co-authored-by: Kito Cheng <kito.cheng@sifive.com>
>---
> sysdeps/riscv/__longjmp.S                    |  1 +
> sysdeps/riscv/crti.S                         |  4 ++
> sysdeps/riscv/crtn.S                         |  4 ++
> sysdeps/riscv/dl-machine.h                   |  8 +++
> sysdeps/riscv/dl-trampoline.S                | 61 +++++++++++------
> sysdeps/riscv/multiarch/memcpy_noalignment.S |  4 ++
> sysdeps/riscv/setjmp.S                       |  3 +
> sysdeps/riscv/start.S                        | 10 +++
> sysdeps/unix/sysv/linux/riscv/clone.S        |  2 +
> sysdeps/unix/sysv/linux/riscv/sysdep.S       |  1 +
> sysdeps/unix/sysv/linux/riscv/sysdep.h       | 71 ++++++++++++++++++++
> sysdeps/unix/sysv/linux/riscv/vfork.S        |  1 +
> 12 files changed, 150 insertions(+), 20 deletions(-)
> create mode 100644 sysdeps/riscv/crti.S
> create mode 100644 sysdeps/riscv/crtn.S
>
>diff --git a/sysdeps/riscv/__longjmp.S b/sysdeps/riscv/__longjmp.S
>index 7228b457a6..47ff3aa09e 100644
>--- a/sysdeps/riscv/__longjmp.S
>+++ b/sysdeps/riscv/__longjmp.S
>@@ -20,6 +20,7 @@
> #include <sys/asm.h>
>
> ENTRY (__longjmp)
>+	LPAD
> 	REG_L ra,  0*SZREG(a0)
> 	REG_L s0,  1*SZREG(a0)
> 	REG_L s1,  2*SZREG(a0)
>diff --git a/sysdeps/riscv/crti.S b/sysdeps/riscv/crti.S
>new file mode 100644
>index 0000000000..fb1097c5ca
>--- /dev/null
>+++ b/sysdeps/riscv/crti.S
>@@ -0,0 +1,4 @@
>+/* crti.S is empty because .init_array/.fini_array are used exclusively.
>+   Include sysdep.h to define gnu property if necessary. */
>+
>+#include <sysdep.h>
>diff --git a/sysdeps/riscv/crtn.S b/sysdeps/riscv/crtn.S
>new file mode 100644
>index 0000000000..b2e7cb692e
>--- /dev/null
>+++ b/sysdeps/riscv/crtn.S
>@@ -0,0 +1,4 @@
>+/* crtn.S is empty because .init_array/.fini_array are used exclusively.
>+   Include sysdep.h to define gnu property if necessary. */
>+
>+#include <sysdep.h>
>diff --git a/sysdeps/riscv/dl-machine.h b/sysdeps/riscv/dl-machine.h
>index dcc3e0883b..76f43a242b 100644
>--- a/sysdeps/riscv/dl-machine.h
>+++ b/sysdeps/riscv/dl-machine.h
>@@ -28,6 +28,13 @@
> #include <dl-irel.h>
> #include <dl-static-tls.h>
> #include <dl-machine-rel.h>
>+/* This is a marker to remind us to add real expansion to setup the label
>+   for the function signature label scheme in the future  */
>+#ifdef __riscv_landing_pad_unlabeled
>+# define SET_LPAD
>+#else
>+# define SET_LPAD
>+#endif
>
> #ifndef _RTLD_PROLOGUE
> # define _RTLD_PROLOGUE(entry)						\
>@@ -126,6 +133,7 @@ elf_machine_dynamic (void)
> 	# Pass our finalizer function to _start.\n\
> 	lla a0, _dl_fini\n\
> 	# Jump to the user entry point.\n\
>+        " STRINGXV (SET_LPAD) "\n\
> 	jr s0\n\
> 	" _RTLD_EPILOGUE (ENTRY_POINT) \
> 	  _RTLD_EPILOGUE (_dl_start_user) "\
>diff --git a/sysdeps/riscv/dl-trampoline.S b/sysdeps/riscv/dl-trampoline.S
>index 93d04af326..2b25f64a3b 100644
>--- a/sysdeps/riscv/dl-trampoline.S
>+++ b/sysdeps/riscv/dl-trampoline.S
>@@ -25,13 +25,27 @@
> /* Assembler veneer called from the PLT header code for lazy loading.
>    The PLT header passes its own args in t0-t2.  */
>
>-#ifdef __riscv_float_abi_soft
>-# define FRAME_SIZE (-((-10 * SZREG) & ALMASK))
>-#else
>-# define FRAME_SIZE (-((-10 * SZREG - 8 * SZFREG) & ALMASK))
>+#ifdef __riscv_landing_pad
>+
>+# ifdef __riscv_float_abi_soft
>+#  define FRAME_SIZE (-((-11 * SZREG) & ALMASK))
>+# else
>+#  define FRAME_SIZE (-((-11 * SZREG - 8 * SZFREG) & ALMASK))
>+#  define FREG_BASE_OFFSET (11*SZREG)
>+# endif
>+
>+# else
>+
>+# ifdef __riscv_float_abi_soft
>+#  define FRAME_SIZE (-((-10 * SZREG) & ALMASK))
>+# else
>+#  define FRAME_SIZE (-((-10 * SZREG - 8 * SZFREG) & ALMASK))
>+#  define FREG_BASE_OFFSET (10*SZREG)
>+# endif
> #endif
>
> ENTRY (_dl_runtime_resolve)
>+  LPAD
>   # Save arguments to stack.
>   addi sp, sp, -FRAME_SIZE
>   REG_S ra, 9*SZREG(sp)
>@@ -43,16 +57,19 @@ ENTRY (_dl_runtime_resolve)
>   REG_S a5, 6*SZREG(sp)
>   REG_S a6, 7*SZREG(sp)
>   REG_S a7, 8*SZREG(sp)
>+#ifdef __riscv_landing_pad
>+  REG_S t2, 10*SZREG(sp)
>+#endif
>
> #ifndef __riscv_float_abi_soft
>-  FREG_S fa0, (10*SZREG + 0*SZFREG)(sp)
>-  FREG_S fa1, (10*SZREG + 1*SZFREG)(sp)
>-  FREG_S fa2, (10*SZREG + 2*SZFREG)(sp)
>-  FREG_S fa3, (10*SZREG + 3*SZFREG)(sp)
>-  FREG_S fa4, (10*SZREG + 4*SZFREG)(sp)
>-  FREG_S fa5, (10*SZREG + 5*SZFREG)(sp)
>-  FREG_S fa6, (10*SZREG + 6*SZFREG)(sp)
>-  FREG_S fa7, (10*SZREG + 7*SZFREG)(sp)
>+  FREG_S fa0, (FREG_BASE_OFFSET + 0*SZFREG)(sp)
>+  FREG_S fa1, (FREG_BASE_OFFSET + 1*SZFREG)(sp)
>+  FREG_S fa2, (FREG_BASE_OFFSET + 2*SZFREG)(sp)
>+  FREG_S fa3, (FREG_BASE_OFFSET + 3*SZFREG)(sp)
>+  FREG_S fa4, (FREG_BASE_OFFSET + 4*SZFREG)(sp)
>+  FREG_S fa5, (FREG_BASE_OFFSET + 5*SZFREG)(sp)
>+  FREG_S fa6, (FREG_BASE_OFFSET + 6*SZFREG)(sp)
>+  FREG_S fa7, (FREG_BASE_OFFSET + 7*SZFREG)(sp)
> #endif
>
>   # Update .got.plt and obtain runtime address of callee.
>@@ -60,6 +77,7 @@ ENTRY (_dl_runtime_resolve)
>   mv a0, t0       # link map
>   add a1, a1, t1  # reloc offset (== thrice the .got.plt offset)
>   la a2, _dl_fixup
>+  SET_LPAD
>   jalr a2
>   mv t1, a0
>
>@@ -73,16 +91,19 @@ ENTRY (_dl_runtime_resolve)
>   REG_L a5, 6*SZREG(sp)
>   REG_L a6, 7*SZREG(sp)
>   REG_L a7, 8*SZREG(sp)
>+#ifdef __riscv_landing_pad
>+  REG_L t2, 10*SZREG(sp)
>+#endif
>
> #ifndef __riscv_float_abi_soft
>-  FREG_L fa0, (10*SZREG + 0*SZFREG)(sp)
>-  FREG_L fa1, (10*SZREG + 1*SZFREG)(sp)
>-  FREG_L fa2, (10*SZREG + 2*SZFREG)(sp)
>-  FREG_L fa3, (10*SZREG + 3*SZFREG)(sp)
>-  FREG_L fa4, (10*SZREG + 4*SZFREG)(sp)
>-  FREG_L fa5, (10*SZREG + 5*SZFREG)(sp)
>-  FREG_L fa6, (10*SZREG + 6*SZFREG)(sp)
>-  FREG_L fa7, (10*SZREG + 7*SZFREG)(sp)
>+  FREG_L fa0, (FREG_BASE_OFFSET + 0*SZFREG)(sp)
>+  FREG_L fa1, (FREG_BASE_OFFSET + 1*SZFREG)(sp)
>+  FREG_L fa2, (FREG_BASE_OFFSET + 2*SZFREG)(sp)
>+  FREG_L fa3, (FREG_BASE_OFFSET + 3*SZFREG)(sp)
>+  FREG_L fa4, (FREG_BASE_OFFSET + 4*SZFREG)(sp)
>+  FREG_L fa5, (FREG_BASE_OFFSET + 5*SZFREG)(sp)
>+  FREG_L fa6, (FREG_BASE_OFFSET + 6*SZFREG)(sp)
>+  FREG_L fa7, (FREG_BASE_OFFSET + 7*SZFREG)(sp)
> #endif
>
>   addi sp, sp, FRAME_SIZE
>diff --git a/sysdeps/riscv/multiarch/memcpy_noalignment.S b/sysdeps/riscv/multiarch/memcpy_noalignment.S
>index dd135f4a4d..e97748e82b 100644
>--- a/sysdeps/riscv/multiarch/memcpy_noalignment.S
>+++ b/sysdeps/riscv/multiarch/memcpy_noalignment.S
>@@ -34,7 +34,11 @@
> #define BLOCK_SIZE (16 * SZREG)
>
> 	.attribute unaligned_access, 1
>+#ifdef __riscv_landing_pad
>+        .align  2
>+#endif
> ENTRY (__memcpy_noalignment)
>+        LPAD
> 	beq	a2, zero, L(ret)
>
> 	/* if LEN < SZREG jump to tail handling.  */
>diff --git a/sysdeps/riscv/setjmp.S b/sysdeps/riscv/setjmp.S
>index 600ea84db6..df048cb544 100644
>--- a/sysdeps/riscv/setjmp.S
>+++ b/sysdeps/riscv/setjmp.S
>@@ -20,14 +20,17 @@
> #include <sys/asm.h>
>
> ENTRY (_setjmp)
>+  LPAD
>   li	a1, 0
>   j	HIDDEN_JUMPTARGET (__sigsetjmp)
> END (_setjmp)
> ENTRY (setjmp)
>+  LPAD
>   li	a1, 1
>   /* Fallthrough */
> END (setjmp)
> ENTRY (__sigsetjmp)
>+	LPAD
> 	REG_S ra,  0*SZREG(a0)
> 	REG_S s0,  1*SZREG(a0)
> 	REG_S s1,  2*SZREG(a0)
>diff --git a/sysdeps/riscv/start.S b/sysdeps/riscv/start.S
>index 2db79c0ae6..ff083b13a4 100644
>--- a/sysdeps/riscv/start.S
>+++ b/sysdeps/riscv/start.S
>@@ -47,12 +47,14 @@ ENTRY (ENTRY_POINT)
> 	   .cfi_label to force starting the FDE.  */
> 	.cfi_label .Ldummy
> 	cfi_undefined (ra)
>+	LPAD
> 	call  load_gp
> 	mv    a5, a0  /* rtld_fini.  */
> 	/* main may be in a shared library.  */
> #if defined PIC && !defined SHARED
> 	/* Avoid relocation in static PIE since _start is called before it
> 	   is relocated.  */
>+	SET_LPAD
> 	lla   a0, __wrap_main
> #else
> 	la   a0, main
>@@ -69,7 +71,11 @@ ENTRY (ENTRY_POINT)
> END (ENTRY_POINT)
>
> #if defined PIC && !defined SHARED
>+#ifdef __riscv_landing_pad
>+	.align 2
>+#endif /* __riscv_landing_pad  */
> __wrap_main:
>+	LPAD
> 	tail  main@plt
> #endif
>
>@@ -79,9 +85,13 @@ __wrap_main:
>    needs to be initialized before calling __libc_start_main in that case.
>    So we redundantly initialize it at the beginning of _start.  */
>
>+#ifdef __riscv_landing_pad
>+	.align 2
>+#endif /* __riscv_landing_pad  */
> load_gp:
> .option push
> .option norelax
>+	LPAD
> 	lla   gp, __global_pointer$
> .option pop
> 	ret
>diff --git a/sysdeps/unix/sysv/linux/riscv/clone.S b/sysdeps/unix/sysv/linux/riscv/clone.S
>index 1362dd9c22..d6a0996ec8 100644
>--- a/sysdeps/unix/sysv/linux/riscv/clone.S
>+++ b/sysdeps/unix/sysv/linux/riscv/clone.S
>@@ -31,6 +31,7 @@
>
> 	.text
> LEAF (__clone)
>+	LPAD
>
> 	/* Align stack to a 128-bit boundary as per RISC-V ABI.  */
> 	andi		a1,a1,ALMASK
>@@ -82,6 +83,7 @@ L (thread_start):
> 	REG_L		a0,SZREG(sp)	/* Argument pointer.  */
>
> 	/* Call the user's function.  */
>+	SET_LPAD
> 	jalr		a1
>
> 	/* Call exit with the function's return value.  */
>diff --git a/sysdeps/unix/sysv/linux/riscv/sysdep.S b/sysdeps/unix/sysv/linux/riscv/sysdep.S
>index b50671b9b7..e7ea424e45 100644
>--- a/sysdeps/unix/sysv/linux/riscv/sysdep.S
>+++ b/sysdeps/unix/sysv/linux/riscv/sysdep.S
>@@ -23,6 +23,7 @@
> #endif
>
> ENTRY (__syscall_error)
>+	LPAD
> 	mv t0, ra
> 	/* Fall through to __syscall_set_errno.  */
> END (__syscall_error)
>diff --git a/sysdeps/unix/sysv/linux/riscv/sysdep.h b/sysdeps/unix/sysv/linux/riscv/sysdep.h
>index ee015dfeb6..14a1f3a647 100644
>--- a/sysdeps/unix/sysv/linux/riscv/sysdep.h
>+++ b/sysdeps/unix/sysv/linux/riscv/sysdep.h
>@@ -53,6 +53,75 @@
>
> # include <sys/asm.h>
>
>+/* GNU_PROPERTY_RISCV_* macros from elf.h for use in asm code.  */
>+#define FEATURE_1_AND 0xc0000000
>+
>+/* Add a NT_GNU_PROPERTY_TYPE_0 note.  */
>+#if __riscv_xlen == 32
>+# define GNU_PROPERTY(type, value)	\
>+   .section .note.gnu.property, "a";	\
>+   .p2align 2;				\
>+   .word 4;				\
>+   .word 12;				\
>+   .word 5;				\
>+   .asciz "GNU";			\
>+   .word type;				\
>+   .word 4;				\
>+   .word value;				\
>+   .text
>+#else
>+# define GNU_PROPERTY(type, value)	\
>+   .section .note.gnu.property, "a";	\
>+   .p2align 3;				\
>+   .word 4;				\
>+   .word 16;				\
>+   .word 5;				\
>+   .asciz "GNU";			\
>+   .word type;				\
>+   .word 4;				\
>+   .word value;				\
>+   .word 0;				\
>+   .text
>+#endif

+ Heinrich

Do we need a version field for unlabeled landing pad scheme?
I have raised it with Kito, for labeled one's we need version for sure.
Although if we start with unlabaled gnu property, it will look
canonical.

>+
>+/* Add GNU property note with the supported features to all asm code
>+   where sysdep.h is included.  */
>+#undef __VALUE_FOR_FEATURE_1_AND
>+#if defined (__riscv_landing_pad) || defined (__riscv_shadow_stack)
>+#  if defined (__riscv_landing_pad_unlabeled)
>+#    if defined (__riscv_shadow_stack)
>+#      define __VALUE_FOR_FEATURE_1_AND 0x3
>+#    else
>+#      define __VALUE_FOR_FEATURE_1_AND 0x1
>+#    endif
>+#  elif defined (__riscv_landing_pad_func_sig)
>+#    if defined (__riscv_shadow_stack)
>+#      define __VALUE_FOR_FEATURE_1_AND 0x6
>+#    else
>+#      define __VALUE_FOR_FEATURE_1_AND 0x4
>+#    endif
>+#  else
>+#    if defined (__riscv_shadow_stack)
>+#      define __VALUE_FOR_FEATURE_1_AND 0x2
>+#    else
>+#      error "What?"
>+#    endif
>+#  endif
>+#endif
>+
>+#if defined (__VALUE_FOR_FEATURE_1_AND)
>+GNU_PROPERTY (FEATURE_1_AND, __VALUE_FOR_FEATURE_1_AND)
>+#endif
>+#undef __VALUE_FOR_FEATURE_1_AND
>+
>+#ifdef __riscv_landing_pad_unlabeled
>+# define SET_LPAD
>+# define LPAD       lpad 0
>+#else
>+# define SET_LPAD
>+# define LPAD
>+#endif
>+
> # define ENTRY(name) LEAF(name)
>
> # define L(label) .L ## label
>@@ -64,6 +133,7 @@
>   .text;							\
>   .align 2;							\
>   ENTRY (name);							\
>+  LPAD;           						\
>   li a7, SYS_ify (syscall_name);				\
>   scall;							\
>   li a7, -4096;							\
>@@ -111,6 +181,7 @@
> # define PSEUDO_NOERRNO(name, syscall_name, args)	\
>   .align 2;						\
>   ENTRY (name);						\
>+  LPAD;           					\
>   li a7, SYS_ify (syscall_name);			\
>   scall;
>
>diff --git a/sysdeps/unix/sysv/linux/riscv/vfork.S b/sysdeps/unix/sysv/linux/riscv/vfork.S
>index 1e39b7a057..4cf7b5a9d8 100644
>--- a/sysdeps/unix/sysv/linux/riscv/vfork.S
>+++ b/sysdeps/unix/sysv/linux/riscv/vfork.S
>@@ -29,6 +29,7 @@
>
> 	.text
> LEAF (__libc_vfork)
>+	LPAD
>
> 	li	a0, (CLONE_VFORK | CLONE_VM | SIGCHLD)
> 	mv	a1, sp
>-- 
>2.39.3
>


More information about the Libc-alpha mailing list