[PATCH v3 1/8] newlib: libc: define M-profile PACBTI-enablement macros

Victor L. Do Nascimento victor.donascimento@arm.com
Wed Aug 24 10:27:11 GMT 2022


Hi all,

This patch augments the arm_asm.h header file to provide support for
PACBTI enablement via macros for hand-written assembly functions,
updating both prologues/epilogues as well as cfi-related directives
depending on the compile-time mbranch-protection argument values.

It defines the following preprocessor macros:
   * HAVE_PAC_LEAF: Indicates whether pac-signing has been requested for
   leaf functions.
   * PAC_LEAF_PUSH_IP: Whether leaf functions should push the pac code
   to the stack irrespective of whether the ip register is clobbered in
   the function or not.
   * PAC_CFI_ADJUST: Given values for the above two parameters, this
   holds the calculated offset applied to default CFI address/offset
   values as a consequence of potentially pushing the pac-code to the
   stack.

It also defines the following assembler macros:
   * prologue: In addition to pushing any callee-saved registers onto
   the stack, it generates any requested pacbti instructions.
   Pushed registers are specified via the optional `first', `last' and
   `savepac' macro argument parameters.
   when a single register number is provided, it pushes that
   register.  When two register numbers are provided, they specify a
   range to save.  If savepac is non-zero, the ip register is also
   saved.
   For example:

       prologue savepac=1 -> push {ip}
       prologue 1 -> push {r1}
       prologue 1 savepac=1 -> push {r1, ip}
       prologue 1 4 -> push {r1-r4}
       prologue 1 4 savepac=1 -> push {r1-r4, ip}

   * epilogue: pops registers off the stack and emits pac key signing
   instruction if requested. The optional `first', `last' and
   `savepac' function as per the prologue macro, generating a pop
   instead of push instruction.
   * cfisavelist - prologue macro helper function, generating
   necessary .cfi_offset directives associated with push instruction.
   Therefore, the net effect of calling `prologue 1 2 savepac=1' is
   to generate the following:

       push {r1-r2, ip}
       .cfi_adjust_cfa_offset 12
       .cfi_offset 143, -12
       .cfi_offset 2, -8
       .cfi_offset 1, -4

   * cfirestorelist - epilogue macro helper function, emitting
   .cfi_restore instructions prior to resetting the cfa offset.  As
   such, calling `epilogue 1 2 savepac=1' will produce:

        pop {r1-r2, ip}
	.cfi_restore 143
	.cfi_restore 2
	.cfi_restore 1
	.cfi_def_cfa_offset 0

Regards,
Victor

---
 newlib/libc/machine/arm/arm_asm.h | 130 ++++++++++++++++++++++++++++++
 1 file changed, 130 insertions(+)

diff --git a/newlib/libc/machine/arm/arm_asm.h b/newlib/libc/machine/arm/arm_asm.h
index 2708057de..d314094c9 100644
--- a/newlib/libc/machine/arm/arm_asm.h
+++ b/newlib/libc/machine/arm/arm_asm.h
@@ -60,4 +60,134 @@
 # define _ISA_THUMB_1
 #endif
 
+/* Check whether leaf function PAC signing has been requested in the
+   -mbranch-protect compile-time option.  */
+#define LEAF_PROTECT_BIT 2
+
+#ifdef __ARM_FEATURE_PAC_DEFAULT
+# define HAVE_PAC_LEAF \
+	__ARM_FEATURE_PAC_DEFAULT & (1 << LEAF_PROTECT_BIT)
+#else
+# define HAVE_PAC_LEAF 0
+#endif
+
+/* Provide default parameters for PAC-code handling in leaf-functions.  */
+#ifndef PAC_LEAF_PUSH_IP
+# define PAC_LEAF_PUSH_IP 0
+#endif
+
+#if HAVE_PAC_LEAF
+# if PAC_LEAF_PUSH_IP
+#   define PAC_CFI_ADJ 4
+# else
+#  define PAC_CFI_ADJ 0
+# endif /* PAC_LEAF_PUSH_IP*/
+#else
+# undef PAC_LEAF_PUSH_IP
+# define PAC_LEAF_PUSH_IP 0
+# define PAC_CFI_ADJ 0
+#endif /* HAVE_PAC_LEAF */
+
+#ifdef __ASSEMBLER__
+/* Emit .cfi_restore directives for a consecutive sequence of registers.  */
+	.macro cfirestorelist first, last
+	.cfi_restore \last
+	.if \last-\first
+	cfirestorelist \first, \last-1
+	.endif
+	.endm
+
+/* Emit .cfi_offset directives for a consecutive sequence of registers.  */
+	.macro cfisavelist first, last, index=1
+	.cfi_offset \last, -4*(\index) - PAC_CFI_ADJ
+	.if \last-\first
+	cfisavelist \first, \last-1, \index+1
+	.endif
+	.endm
+
+/* Create a prologue entry sequence handling PAC/BTI, if required and emitting
+   CFI directives for generated PAC code and any pushed registers.  */
+	.macro prologue first=-1, last=-1, savepac=PAC_LEAF_PUSH_IP
+#if HAVE_PAC_LEAF
+#if __ARM_FEATURE_BTI_DEFAULT
+	pacbti	ip, lr, sp
+#else
+	pac	ip, lr, sp
+#endif /* __ARM_FEATURE_BTI_DEFAULT */
+	.cfi_register 143, 12
+#else
+#if __ARM_FEATURE_BTI_DEFAULT
+	bti
+#endif /* __ARM_FEATURE_BTI_DEFAULT */
+#endif /* HAVE_PAC_LEAF */
+	.if \first != -1
+	.if \last != -1
+	.if \savepac
+	push {r\first-r\last, ip}
+	.cfi_adjust_cfa_offset ((\last-\first)+1)*4 + PAC_CFI_ADJ
+	.cfi_offset 143, -PAC_CFI_ADJ
+	cfisavelist \first, \last
+	.else
+	push {r\first-r\last}
+	.cfi_adjust_cfa_offset ((\last-\first)+1)*4
+	cfisavelist \first, \last
+	.endif
+	.else
+	.if \savepac
+	push {r\first, ip}
+	.cfi_adjust_cfa_offset 4 + PAC_CFI_ADJ
+	.cfi_offset 143, -PAC_CFI_ADJ 
+	cfisavelist \first, \first
+	.else // !\savepac
+	push {r\first}
+	.cfi_adjust_cfa_offset PAC_CFI_ADJ
+	cfisavelist \first, \first
+	.endif
+	.endif
+	.else // \first == -1
+	.if \savepac
+	push {ip}
+	.cfi_adjust_cfa_offset PAC_CFI_ADJ
+	.cfi_offset 143, -PAC_CFI_ADJ
+	.endif
+	.endif
+	.endm
+
+/* Create an epilogue exit sequence handling PAC/BTI, if required and emitting
+  CFI directives for all restored registers.  */
+	.macro epilogue first=-1, last=-1, savepac=PAC_LEAF_PUSH_IP
+	.if \first != -1
+	.if \last != -1
+	.if \savepac
+	pop {r\first-r\last, ip}
+	.cfi_restore 143
+	cfirestorelist \first, \last
+	.else
+	pop {r\first-r\last}
+	cfirestorelist \first, \last
+	.endif
+	.else
+	.if \savepac
+	pop {r\first, ip}
+	.cfi_restore 143
+	cfirestorelist \first, \first
+	.else
+	pop {r\first}
+	cfirestorelist \first, \first
+	.endif
+	.endif
+	.else
+	.if \savepac
+	pop {ip}
+	.cfi_restore 143
+	.endif
+	.endif
+	.cfi_def_cfa_offset 0
+#if HAVE_PAC_LEAF
+	aut	ip, lr, sp
+#endif /* HAVE_PAC_LEAF */
+	bx	lr
+	.endm
+#endif /* __ASSEMBLER__ */
+
 #endif /* ARM_ASM__H */
-- 
2.36.1


More information about the Newlib mailing list