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. */
{"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},
/* 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
{ \
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; \
@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
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;
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)
--- /dev/null
+#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
--- /dev/null
+ .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