[PATCH v3 1/8] newlib: libc: define M-profile PACBTI-enablement macros
"Victor L. Do Nascimento" <[email protected]>
| Newsgroups | gmane.comp.lib.newlib |
|---|---|
| Message-ID | <[email protected]> |
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