public inbox for newlib@sourceware.org
 help / color / mirror / Atom feed
From: "Victor L. Do Nascimento" <victor.donascimento@arm.com>
To: <newlib@sourceware.org>
Cc: <Richard.Earnshaw@arm.com>
Subject: [PATCH v3 1/8] newlib: libc: define M-profile PACBTI-enablement macros
Date: Wed, 24 Aug 2022 11:27:11 +0100	[thread overview]
Message-ID: <yw8j8rne2ayo.fsf@arm.com> (raw)
In-Reply-To: <yw8jedx62bdi.fsf@arm.com> (Victor L. Do Nascimento's message of "Wed, 24 Aug 2022 11:18:17 +0100")

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

  reply	other threads:[~2022-08-24 10:27 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-08-24 10:18 [PATCH v3 0/8] Implement assembly cortex-M PACBTI functionality Victor L. Do Nascimento
2022-08-24 10:27 ` Victor L. Do Nascimento [this message]
2022-08-24 10:30 ` [PATCH v3 2/8] newlib: libc: strcmp M-profile PACBTI-enablement Victor L. Do Nascimento
2022-08-24 10:33 ` [PATCH v3 3/8] newlib: libc: strlen " Victor L. Do Nascimento
2022-08-24 10:34 ` [PATCH v3 4/8] newlib: libc: memchr " Victor L. Do Nascimento
2022-08-24 10:36 ` [PATCH v3 5/8] newlib: libc: memcpy " Victor L. Do Nascimento
2022-08-24 10:38 ` [PATCH v3 6/8] newlib: libc: setjmp/longjmp " Victor L. Do Nascimento
2022-08-24 10:40 ` [PATCH v3 7/8] newlib: libc: aeabi_memmove " Victor L. Do Nascimento
2022-08-24 10:41 ` [PATCH v3 8/8] newlib: libc: aeabi_memset " Victor L. Do Nascimento

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=yw8j8rne2ayo.fsf@arm.com \
    --to=victor.donascimento@arm.com \
    --cc=Richard.Earnshaw@arm.com \
    --cc=newlib@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).