diff options
-rw-r--r-- | gas/config/tc-aarch64.c | 9 | ||||
-rw-r--r-- | gas/config/tc-aarch64.h | 33 | ||||
-rw-r--r-- | gas/doc/c-aarch64.texi | 8 | ||||
-rw-r--r-- | gas/dw2gencfi.c | 4 | ||||
-rw-r--r-- | gas/testsuite/gas/aarch64/mte_tagged_stack.d | 47 | ||||
-rw-r--r-- | gas/testsuite/gas/aarch64/mte_tagged_stack.s | 24 |
6 files changed, 116 insertions, 9 deletions
diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c index 7187117..cd9ae58 100644 --- a/gas/config/tc-aarch64.c +++ b/gas/config/tc-aarch64.c @@ -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}, diff --git a/gas/config/tc-aarch64.h b/gas/config/tc-aarch64.h index 0d8066c..fce34ed 100644 --- a/gas/config/tc-aarch64.h +++ b/gas/config/tc-aarch64.h @@ -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; \ diff --git a/gas/doc/c-aarch64.texi b/gas/doc/c-aarch64.texi index ba0940c..dc64e09 100644 --- a/gas/doc/c-aarch64.texi +++ b/gas/doc/c-aarch64.texi @@ -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 diff --git a/gas/dw2gencfi.c b/gas/dw2gencfi.c index 5c63054..57fffab 100644 --- a/gas/dw2gencfi.c +++ b/gas/dw2gencfi.c @@ -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 index 0000000..5e8afb8 --- /dev/null +++ b/gas/testsuite/gas/aarch64/mte_tagged_stack.d @@ -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 index 0000000..64a92b4 --- /dev/null +++ b/gas/testsuite/gas/aarch64/mte_tagged_stack.s @@ -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 |