]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gas: aarch64: suppport CFI directive .cfi_mte_tagged_frame
authorIndu Bhagat <indu.bhagat@oracle.com>
Sat, 12 Jul 2025 09:05:15 +0000 (11:05 +0200)
committerJose E. Marchesi <jose.marchesi@oracle.com>
Sat, 12 Jul 2025 09:33:25 +0000 (11:33 +0200)
Process a new aarch64-specific CFI directive: .cfi_mte_tagged_frame
(LLVM uses this CFI directive already).  The CFI directive, when
present for a function, indicates that the stack frame for the
function may modify the MTE tags of the stack space it uses.  The
assembler emits char 'G' in the CIE augmentation string to indicate
the same.

ChangeLog:

        * gas/config/tc-aarch64.c (s_aarch64_mte_tagged_frame): New
definition.
        * gas/config/tc-aarch64.h (tc_fde_entry_extras): Add
memtag_frame_p.
        (tc_cie_entry_extras): Likewise.
        (tc_fde_entry_init_extra): Likewise.
        (tc_cie_fde_equivalent_extra): Likewise.
        (tc_cie_entry_init_extra): Likewise.
        * gas/doc/c-aarch64.texi: Add documentation for
.cfi_mte_tagged_frame directive.
        * gas/testsuite/gas/aarch64/mte_tagged_stack.d: New test.
        * gas/testsuite/gas/aarch64/mte_tagged_stack.s: New test.

gas/config/tc-aarch64.c
gas/config/tc-aarch64.h
gas/doc/c-aarch64.texi
gas/dw2gencfi.c
gas/testsuite/gas/aarch64/mte_tagged_stack.d [new file with mode: 0644]
gas/testsuite/gas/aarch64/mte_tagged_stack.s [new file with mode: 0644]

index 7187117f60d2f7af6a09fb20131ac3a7e35592a7..cd9ae581b9ade18676a756281a955e78c7bd3dc5 100644 (file)
@@ -2351,6 +2351,14 @@ s_aarch64_cfi_b_key_frame (int ignored ATTRIBUTE_UNUSED)
   fde->pauth_key = AARCH64_PAUTH_KEY_B;
 }
 
+static void
+s_aarch64_mte_tagged_frame (int ignored ATTRIBUTE_UNUSED)
+{
+  demand_empty_rest_of_line ();
+  struct fde_entry *fde = frchain_now->frch_cfi_data->cur_fde_data;
+  fde->memtag_frame_p = true;
+}
+
 #ifdef OBJ_ELF
 /* Emit BFD_RELOC_AARCH64_TLSDESC_ADD on the next ADD instruction.  */
 
@@ -2476,6 +2484,7 @@ const pseudo_typeS md_pseudo_table[] = {
   {"arch_extension", s_aarch64_arch_extension, 0},
   {"inst", s_aarch64_inst, 0},
   {"cfi_b_key_frame", s_aarch64_cfi_b_key_frame, 0},
+  {"cfi_mte_tagged_frame", s_aarch64_mte_tagged_frame, 0},
 #ifdef OBJ_ELF
   {"tlsdescadd", s_tlsdescadd, 0},
   {"tlsdesccall", s_tlsdesccall, 0},
index 0d8066c1ab8c33f6fd1f96b25e8d6b3d1b313ca0..fce34ed48d14440a9d29dff1125bdd170bc3984c 100644 (file)
@@ -90,13 +90,21 @@ enum pointer_auth_key {
 
 /* The extra fields required by AArch64 in fde_entry and cie_entry.  Currently
    only used to store the key used to sign the frame's return address.  */
-#define tc_fde_entry_extras enum pointer_auth_key pauth_key;
-#define tc_cie_entry_extras enum pointer_auth_key pauth_key;
+#define tc_fde_entry_extras enum pointer_auth_key pauth_key; \
+                           bool memtag_frame_p;
+#define tc_cie_entry_extras enum pointer_auth_key pauth_key; \
+                           bool memtag_frame_p;
 
 /* The extra initialisation steps needed by AArch64 in alloc_fde_entry.
    Currently only used to initialise the key used to sign the return
    address.  */
-#define tc_fde_entry_init_extra(fde) fde->pauth_key = AARCH64_PAUTH_KEY_A;
+#define tc_fde_entry_init_extra(fde)                                   \
+  do                                                                   \
+    {                                                                  \
+      fde->pauth_key = AARCH64_PAUTH_KEY_A;                            \
+      fde->memtag_frame_p = false;                                     \
+    }                                                                  \
+  while (0)
 
 /* Extra checks required by AArch64 when outputting the current cie_entry.
    Currently only used to output a 'B' if the return address is signed with the
@@ -106,18 +114,29 @@ enum pointer_auth_key {
       { \
        if (cie->pauth_key == AARCH64_PAUTH_KEY_B) \
          out_one ('B'); \
+       if (cie->memtag_frame_p) \
+         out_one ('G'); \
       } \
     while (0)
 
 /* Extra equivalence checks required by AArch64 when selecting the correct cie
-   for some fde.  Currently only used to check for quivalence between keys used
-   to sign ther return address.  */
-#define tc_cie_fde_equivalent_extra(cie, fde) (cie->pauth_key == fde->pauth_key)
+   for some fde.  Currently used to check for equivalence between - keys used
+   to sign the return address, and if stack locations have MTE tagging
+   enabled.  */
+#define tc_cie_fde_equivalent_extra(cie, fde) \
+  ((cie->pauth_key == fde->pauth_key) \
+   && (cie->memtag_frame_p == fde->memtag_frame_p))
 
 /* The extra initialisation steps needed by AArch64 in select_cie_for_fde.
    Currently only used to initialise the key used to sign the return
    address.  */
-#define tc_cie_entry_init_extra(cie, fde) cie->pauth_key = fde->pauth_key;
+#define tc_cie_entry_init_extra(cie, fde)                              \
+  do                                                                   \
+    {                                                                  \
+      cie->pauth_key = fde->pauth_key;                                 \
+      cie->memtag_frame_p = fde->memtag_frame_p;                       \
+    }                                                                  \
+  while (0)
 
 #define TC_FIX_TYPE struct aarch64_fix
 #define TC_INIT_FIX_DATA(FIX) { (FIX)->tc_fix_data.inst = NULL;        \
index ba0940c5fafd094f79ef4a465a2c2ce8a3d72089..dc64e09e766768c7699bd236be44f39736986981 100644 (file)
@@ -499,6 +499,14 @@ incrementally to the architecture being compiled for.
 @c BBBBBBBBBBBBBBBBBBBBBBBBBB
 @c CCCCCCCCCCCCCCCCCCCCCCCCCC
 
+@cindex @code{.cfi_mte_tagged_frame} directive, AArch64
+@item  @code{.cfi_mte_tagged_frame}
+The @code{.cfi_mte_tagged_frame} directive inserts a 'G' character into the
+CIE corresponding to the current frame's FDE, meaning that the associated
+frames may modify MTE tags on the stack space they use.  This information is
+intended to be used by the stack unwinder in order to properly untag stack
+frames.
+
 @cindex @code{.cpu} directive, AArch64
 @item .cpu @var{name}
 Set the target processor.  Valid values for @var{name} are the same as
index 5c63054292f4ec569dce6a7004ac4fdae610ba7f..57fffab2951b5d0e8d76c2bfb9ec370dc70d6dca 100644 (file)
@@ -409,7 +409,7 @@ alloc_fde_entry (void)
   fde->lsda_encoding = DW_EH_PE_omit;
   fde->eh_header_type = EH_COMPACT_UNKNOWN;
 #ifdef tc_fde_entry_init_extra
-  tc_fde_entry_init_extra (fde)
+  tc_fde_entry_init_extra (fde);
 #endif
 
   return fde;
@@ -2272,7 +2272,7 @@ select_cie_for_fde (struct fde_entry *fde, bool eh_frame,
   cie->personality = fde->personality;
   cie->first = fde->data;
 #ifdef tc_cie_entry_init_extra
-  tc_cie_entry_init_extra (cie, fde)
+  tc_cie_entry_init_extra (cie, fde);
 #endif
 
   for (i = cie->first; i ; i = i->next)
diff --git a/gas/testsuite/gas/aarch64/mte_tagged_stack.d b/gas/testsuite/gas/aarch64/mte_tagged_stack.d
new file mode 100644 (file)
index 0000000..5e8afb8
--- /dev/null
@@ -0,0 +1,47 @@
+#objdump: --dwarf=frames
+# This test is only valid on ELF based ports.
+#notarget: *-*-*coff *-*-pe *-*-wince *-*-*aout* *-*-netbsd
+# Test assembling a file with functions using MTE tagged stack or not
+# It must interpret .cfi_mte_tagged_frame properly and emit a
+# 'G' character into the correct CIE's augmentation string.
+
+.+:     file .+
+
+Contents of the .eh_frame section:
+
+0+ 0+14 0+ CIE
+  Version:               1
+  Augmentation:          "zRG"
+  Code alignment factor: 4
+  Data alignment factor: -8
+  Return address column: 30
+  Augmentation data:     1b
+  DW_CFA_def_cfa: r31 \(sp\) ofs 0
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+0+18 0+14 0+1c FDE cie=0+ pc=0+\.\.0+4
+  DW_CFA_advance_loc: 4 to 0+4
+  DW_CFA_def_cfa_offset: 16
+  DW_CFA_offset: r29 \(x29\) at cfa-16
+  DW_CFA_offset: r30 \(x30\) at cfa-8
+
+0+30 0+10 0+0 CIE
+  Version:               1
+  Augmentation:          "zR"
+  Code alignment factor: 4
+  Data alignment factor: -8
+  Return address column: 30
+  Augmentation data:     1b
+  DW_CFA_def_cfa: r31 \(sp\) ofs 0
+
+0+44 0+1(4|8) 0+18 FDE cie=0+30 pc=0+4\.\.0+8
+  DW_CFA_advance_loc: 4 to 0+8
+  DW_CFA_def_cfa_offset: 16
+  DW_CFA_offset: r29 \(x29\) at cfa-16
+  DW_CFA_offset: r30 \(x30\) at cfa-8
+#?  DW_CFA_nop
+#?  DW_CFA_nop
+#?  DW_CFA_nop
+#?  DW_CFA_nop
diff --git a/gas/testsuite/gas/aarch64/mte_tagged_stack.s b/gas/testsuite/gas/aarch64/mte_tagged_stack.s
new file mode 100644 (file)
index 0000000..64a92b4
--- /dev/null
@@ -0,0 +1,24 @@
+       .arch armv8-a+memtag
+       .text
+       .align  2
+       .global foo
+       .type   foo, %function
+foo:
+       .cfi_startproc
+       .cfi_mte_tagged_frame
+       stp     x29, x30, [sp, -16]!
+       .cfi_def_cfa_offset 16
+       .cfi_offset 29, -16
+       .cfi_offset 30, -8
+       .cfi_endproc
+       .size   foo, .-foo
+       .align  2
+       .global bar
+       .type   bar, %function
+bar:
+       .cfi_startproc
+       stp     x29, x30, [sp, -16]!
+       .cfi_def_cfa_offset 16
+       .cfi_offset 29, -16
+       .cfi_offset 30, -8
+       .cfi_endproc