aboutsummaryrefslogtreecommitdiff
path: root/gas/dw2gencfi.c
diff options
context:
space:
mode:
authorSam Tebbs <sam.tebbs@arm.com>2018-12-05 18:27:23 +0000
committerThomas Preud'homme <thomas.preudhomme@linaro.org>2018-12-05 18:30:08 +0000
commit3a67e1a6b4430374f3073e51bb19347d4c421cfe (patch)
tree6a75b3b1a27561b0e395dc69889051b71e67eff5 /gas/dw2gencfi.c
parent90af06793e9d391c0aa33994f21bba6971d084f7 (diff)
downloadgdb-3a67e1a6b4430374f3073e51bb19347d4c421cfe.zip
gdb-3a67e1a6b4430374f3073e51bb19347d4c421cfe.tar.gz
gdb-3a67e1a6b4430374f3073e51bb19347d4c421cfe.tar.bz2
[aarch64] Add support for pointer authentication B key
Armv8.3-A has another key used in pointer authentication called the B-key (other than the A-key that is already supported). In order for stack unwinders to work it is necessary to be able to identify frames that have been signed with the B-key rather than the A-key and it was felt that keeping this as an augmentation character in the CIE was the best bet. The DWARF extensions for ARM therefore propose to add a new augmentation character 'B' to the CIE augmentation string and the corresponding cfi directive ".cfi_b_key_frame". I've made the relevant changes to GAS and LD to add support for B-key unwinding, which required modifying LD to check for 'B' in the augmentation string, adding the ".cfi_b_key_frame" directive to GAS and adding a "pauth_key" field to GAS's fde_entry and cie_entry structs. The pointer authentication instructions will behave as NOPs on architectures that don't support them, and so a check for the architecture being assembled for is not necessary since there will be no behavioural difference between augmentation strings with and without the 'B' character on such architectures. 2018-12-05 Sam Tebbs <sam.tebbs@arm.com> bfd/ * elf-eh-frame.c (_bfd_elf_parse_eh_frame): Add check for 'B'. gas/ * dw2gencfi.c (struct cie_entry): Add tc_cie_entry_extras invocation. (alloc_fde_entry): Add tc_fde_entry_init_extra invocation. (output_cie): Add tc_output_cie_extra invocation. (select_cie_for_fde): Add tc_cie_fde_equivalent_extra and tc_cie_entry_init_extra invocation. (frch_cfi_data, cfa_save_data): Move to dwgencfi.h. * config/tc-aarch64.c (s_aarch64_cfi_b_key_frame): Declare. (md_pseudo_table): Add "cfi_b_key_frame". * config/tc-aarch64.h (tc_fde_entry_extras, tc_cie_entry_extras, tc_fde_entry_init_extra, tc_output_cie_extra, tc_cie_fde_equivalent_extra, tc_cie_entry_init_extra): Define. * dw2gencfi.h (struct fde_entry): Add tc_fde_entry_extras invocation. (pointer_auth_key): Define. (frch_cfi_data, cfa_save_data): Move from dwgencfi.c. * doc/c-aarch64.texi (.cfi_b_key_frame): Add documentation. * testsuite/gas/aarch64/(pac_ab_key.d, pac_ab_key.s): New file.
Diffstat (limited to 'gas/dw2gencfi.c')
-rw-r--r--gas/dw2gencfi.c22
1 files changed, 6 insertions, 16 deletions
diff --git a/gas/dw2gencfi.c b/gas/dw2gencfi.c
index 4add173..ff5c0df 100644
--- a/gas/dw2gencfi.c
+++ b/gas/dw2gencfi.c
@@ -403,6 +403,7 @@ struct cie_entry
unsigned char per_encoding;
unsigned char lsda_encoding;
expressionS personality;
+ enum pointer_auth_key pauth_key;
struct cfi_insn_data *first, *last;
};
@@ -414,22 +415,6 @@ static struct fde_entry **last_fde_data = &all_fde_data;
/* List of CIEs so that they could be reused. */
static struct cie_entry *cie_root;
-/* Stack of old CFI data, for save/restore. */
-struct cfa_save_data
-{
- struct cfa_save_data *next;
- offsetT cfa_offset;
-};
-
-/* Current open FDE entry. */
-struct frch_cfi_data
-{
- struct fde_entry *cur_fde_data;
- symbolS *last_address;
- offsetT cur_cfa_offset;
- struct cfa_save_data *cfa_save_stack;
-};
-
/* Construct a new FDE structure and add it to the end of the fde list. */
static struct fde_entry *
@@ -448,6 +433,7 @@ alloc_fde_entry (void)
fde->per_encoding = DW_EH_PE_omit;
fde->lsda_encoding = DW_EH_PE_omit;
fde->eh_header_type = EH_COMPACT_UNKNOWN;
+ fde->pauth_key = AARCH64_PAUTH_KEY_A;
return fde;
}
@@ -1872,6 +1858,8 @@ output_cie (struct cie_entry *cie, bfd_boolean eh_frame, int align)
if (cie->lsda_encoding != DW_EH_PE_omit)
out_one ('L');
out_one ('R');
+ if (cie->pauth_key == AARCH64_PAUTH_KEY_B)
+ out_one ('B');
}
if (cie->signal_frame)
out_one ('S');
@@ -2052,6 +2040,7 @@ select_cie_for_fde (struct fde_entry *fde, bfd_boolean eh_frame,
if (CUR_SEG (cie) != CUR_SEG (fde))
continue;
if (cie->return_column != fde->return_column
+ || cie->pauth_key != fde->pauth_key
|| cie->signal_frame != fde->signal_frame
|| cie->per_encoding != fde->per_encoding
|| cie->lsda_encoding != fde->lsda_encoding)
@@ -2158,6 +2147,7 @@ select_cie_for_fde (struct fde_entry *fde, bfd_boolean eh_frame,
cie->lsda_encoding = fde->lsda_encoding;
cie->personality = fde->personality;
cie->first = fde->data;
+ cie->pauth_key = fde->pauth_key;
for (i = cie->first; i ; i = i->next)
if (i->insn == DW_CFA_advance_loc