[v4,04/17] riscv: Adjust assembly routines to support landing pad

Message ID 20260526061703.2188042-5-jesse.huang@sifive.com (mailing list archive)
State New
Headers
Series Support RISC-V Control Flow Integrifty (CFI) |

Checks

Context Check Description
redhat-pt-bot/TryBot-apply_patch success Patch applied to master at the time it was sent
linaro-tcwg-bot/tcwg_glibc_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_glibc_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_glibc_check--master-aarch64 success Test passed

Commit Message

Jesse Huang May 26, 2026, 6:16 a.m. UTC
  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>
Co-authored-by: Jerry Zhang Jian <jerry.zhangjian@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                | 42 ++++++------
 sysdeps/riscv/multiarch/memcpy_noalignment.S |  4 ++
 sysdeps/riscv/setjmp.S                       |  3 +
 sysdeps/riscv/start.S                        | 10 +++
 sysdeps/riscv/sys/asm.h                      | 12 +++-
 sysdeps/unix/sysv/linux/riscv/clone.S        |  2 +
 sysdeps/unix/sysv/linux/riscv/sysdep.S       |  1 +
 sysdeps/unix/sysv/linux/riscv/sysdep.h       | 70 ++++++++++++++++++++
 sysdeps/unix/sysv/linux/riscv/vfork.S        |  1 +
 13 files changed, 141 insertions(+), 21 deletions(-)
 create mode 100644 sysdeps/riscv/crti.S
 create mode 100644 sysdeps/riscv/crtn.S
  

Comments

Andreas Schwab May 26, 2026, 8:09 a.m. UTC | #1
On Mai 25 2026, Jesse Huang wrote:

> Frame offsets for floating point registers in _dl_runtime_resolve
> are also adjusted because now t2 has to be saved onto the stack.

Is this some kind of WIP?  Because I don't see any changes of that kind
in the patch.
  
Jesse Huang May 28, 2026, 5:43 a.m. UTC | #2
Thanks for pointing that out.
t2 was saved in the _dl_runtime_resolve before, but then we got a new PLT
implementation that no longer needed to save it, so it was removed and the
frame offset change was reverted. I squashed the patch but forgot to update
the commit message to reflect it, I will update it in the next version.


On Tue, May 26, 2026 at 5:09 PM Andreas Schwab <schwab@suse.de> wrote:

> On Mai 25 2026, Jesse Huang wrote:
>
> > Frame offsets for floating point registers in _dl_runtime_resolve
> > are also adjusted because now t2 has to be saved onto the stack.
>
> Is this some kind of WIP?  Because I don't see any changes of that kind
> in the patch.
>
> --
> Andreas Schwab, SUSE Labs, schwab@suse.de
> GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
> "And now for something completely different."
>
  

Patch

diff --git a/sysdeps/riscv/__longjmp.S b/sysdeps/riscv/__longjmp.S
index bea854199c..f43b0f4c32 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 babb52af20..05992c8705 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)						\
@@ -127,6 +134,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 6c731fcfd4..6e9a0f978c 100644
--- a/sysdeps/riscv/dl-trampoline.S
+++ b/sysdeps/riscv/dl-trampoline.S
@@ -29,9 +29,11 @@ 
 # define FRAME_SIZE (-((-10 * SZREG) & ALMASK))
 #else
 # define FRAME_SIZE (-((-10 * SZREG - 8 * SZFREG) & ALMASK))
+# define FREG_BASE_OFFSET (10*SZREG)
 #endif
 
 ENTRY (_dl_runtime_resolve)
+  LPAD
   # Save arguments to stack.
   addi sp, sp, -FRAME_SIZE
   REG_S ra, 9*SZREG(sp)
@@ -45,23 +47,23 @@  ENTRY (_dl_runtime_resolve)
   REG_S a7, 8*SZREG(sp)
 
 #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.
   slli a1, t1, 1
   mv a0, t0       # link map
   add a1, a1, t1  # reloc offset (== thrice the .got.plt offset)
-  la a2, _dl_fixup
-  jalr a2
-  mv t1, a0
+  la t2, _dl_fixup
+  jalr t2
+  mv t2, a0
 
   # Restore arguments from stack.
   REG_L ra, 9*SZREG(sp)
@@ -75,20 +77,20 @@  ENTRY (_dl_runtime_resolve)
   REG_L a7, 8*SZREG(sp)
 
 #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
 
   # Invoke the callee.
-  jr t1
+  jr t2
 END (_dl_runtime_resolve)
 
 #if !defined PROF && defined SHARED
diff --git a/sysdeps/riscv/multiarch/memcpy_noalignment.S b/sysdeps/riscv/multiarch/memcpy_noalignment.S
index 559e2b21e2..fd1d11239b 100644
--- a/sysdeps/riscv/multiarch/memcpy_noalignment.S
+++ b/sysdeps/riscv/multiarch/memcpy_noalignment.S
@@ -35,7 +35,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 af1910b86d..aecf2d2bab 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 bc3bc04219..c953b1ef51 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/riscv/sys/asm.h b/sysdeps/riscv/sys/asm.h
index 1ca3d46120..54217540f8 100644
--- a/sysdeps/riscv/sys/asm.h
+++ b/sysdeps/riscv/sys/asm.h
@@ -46,13 +46,23 @@ 
 # endif
 #endif
 
+/* Landing pad for Zicfilp CFI.  */
+#ifndef LPAD
+# ifdef __riscv_landing_pad_unlabeled
+#  define LPAD	lpad 0
+# else
+#  define LPAD
+# endif
+#endif
+
 /* Declare leaf routine.  */
 #define	LEAF(symbol)				\
 		.globl	symbol;			\
 		.align	2;			\
 		.type	symbol,@function;	\
 symbol:						\
-		cfi_startproc;
+		cfi_startproc;			\
+		LPAD;
 
 /* Mark end of function.  */
 #undef END
diff --git a/sysdeps/unix/sysv/linux/riscv/clone.S b/sysdeps/unix/sysv/linux/riscv/clone.S
index 1ce930a97e..42c26c3675 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 31947a1c70..05202eedb7 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 7f0eb07045..761a833609 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
+
+/* 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
@@ -111,6 +180,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 c1fcec8dd4..90cc523ecb 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