[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.
This commit is contained in:
parent
90af06793e
commit
3a67e1a6b4
@ -1,3 +1,7 @@
|
||||
2018-12-05 Sam Tebbs <sam.tebbs@arm.com>
|
||||
|
||||
* elf-eh-frame.c (_bfd_elf_parse_eh_frame): Add check for 'B'.
|
||||
|
||||
2018-12-04 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
PR ld/23372
|
||||
|
@ -797,6 +797,8 @@ _bfd_elf_parse_eh_frame (bfd *abfd, struct bfd_link_info *info,
|
||||
while (*aug != '\0')
|
||||
switch (*aug++)
|
||||
{
|
||||
case 'B':
|
||||
break;
|
||||
case 'L':
|
||||
REQUIRE (read_byte (&buf, end, &cie->lsda_encoding));
|
||||
ENSURE_NO_RELOCS (buf);
|
||||
|
@ -1,3 +1,22 @@
|
||||
2018-12-05 Sam Tebbs <sam.tebbs@arm.com>
|
||||
|
||||
* 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.
|
||||
|
||||
2018-12-04 wu.heng <wu.heng@zte.com.cn>
|
||||
|
||||
PR 23939
|
||||
|
@ -1993,6 +1993,14 @@ s_aarch64_inst (int ignored ATTRIBUTE_UNUSED)
|
||||
demand_empty_rest_of_line ();
|
||||
}
|
||||
|
||||
static void
|
||||
s_aarch64_cfi_b_key_frame (int ignored ATTRIBUTE_UNUSED)
|
||||
{
|
||||
demand_empty_rest_of_line ();
|
||||
struct fde_entry *fde = frchain_now->frch_cfi_data->cur_fde_data;
|
||||
fde->pauth_key = AARCH64_PAUTH_KEY_B;
|
||||
}
|
||||
|
||||
#ifdef OBJ_ELF
|
||||
/* Emit BFD_RELOC_AARCH64_TLSDESC_ADD on the next ADD instruction. */
|
||||
|
||||
@ -2067,6 +2075,7 @@ const pseudo_typeS md_pseudo_table[] = {
|
||||
{"arch", s_aarch64_arch, 0},
|
||||
{"arch_extension", s_aarch64_arch_extension, 0},
|
||||
{"inst", s_aarch64_inst, 0},
|
||||
{"cfi_b_key_frame", s_aarch64_cfi_b_key_frame, 0},
|
||||
#ifdef OBJ_ELF
|
||||
{"tlsdescadd", s_tlsdescadd, 0},
|
||||
{"tlsdesccall", s_tlsdesccall, 0},
|
||||
|
@ -435,6 +435,14 @@ as the @code{.dword} directive.
|
||||
@c YYYYYYYYYYYYYYYYYYYYYYYYYY
|
||||
@c ZZZZZZZZZZZZZZZZZZZZZZZZZZ
|
||||
|
||||
@cindex @code{.cfi_b_key_frame} directive, AArch64
|
||||
@item @code{.cfi_b_key_frame}
|
||||
The @code{.cfi_b_key_frame} directive inserts a 'B' character into the CIE
|
||||
corresponding to the current frame's FDE, meaning that its return address has
|
||||
been signed with the B-key. If two frames are signed with differing keys then
|
||||
they will not share the same CIE. This information is intended to be used by
|
||||
the stack unwinder in order to properly authenticate return addresses.
|
||||
|
||||
@end table
|
||||
|
||||
@node AArch64 Opcodes
|
||||
|
@ -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
|
||||
|
@ -135,6 +135,27 @@ enum {
|
||||
EH_COMPACT_HAS_LSDA
|
||||
};
|
||||
|
||||
enum pointer_auth_key {
|
||||
AARCH64_PAUTH_KEY_A,
|
||||
AARCH64_PAUTH_KEY_B
|
||||
};
|
||||
|
||||
/* 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;
|
||||
};
|
||||
|
||||
struct fde_entry
|
||||
{
|
||||
struct fde_entry *next;
|
||||
@ -162,6 +183,8 @@ struct fde_entry
|
||||
/* For out of line tables and FDEs. */
|
||||
symbolS *eh_loc;
|
||||
int sections;
|
||||
/* The pointer authentication key used. Only used for AArch64. */
|
||||
enum pointer_auth_key pauth_key;
|
||||
};
|
||||
|
||||
/* The list of all FDEs that have been collected. */
|
||||
|
54
gas/testsuite/gas/aarch64/pac_ab_key.d
Normal file
54
gas/testsuite/gas/aarch64/pac_ab_key.d
Normal file
@ -0,0 +1,54 @@
|
||||
#objdump: --dwarf=frames
|
||||
# Test assembling a file with functions signed by two different pointer
|
||||
# authentication keys. It must interpret .cfi_b_key_frame properly and emit a
|
||||
# 'B' character into the correct CIE's augmentation string.
|
||||
|
||||
.+: file .+
|
||||
|
||||
Contents of the .eh_frame section:
|
||||
|
||||
00000000 0000000000000010 00000000 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
|
||||
|
||||
00000014 0000000000000018 00000018 FDE cie=00000000 pc=0000000000000000..0000000000000008
|
||||
DW_CFA_advance_loc: 4 to 0000000000000004
|
||||
DW_CFA_GNU_window_save
|
||||
DW_CFA_advance_loc: 4 to 0000000000000008
|
||||
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
|
||||
|
||||
00000030 0000000000000014 00000000 CIE
|
||||
Version: 1
|
||||
Augmentation: "zRB"
|
||||
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
|
||||
|
||||
00000048 000000000000001c 0000001c FDE cie=00000030 pc=0000000000000008..0000000000000010
|
||||
DW_CFA_advance_loc: 4 to 000000000000000c
|
||||
DW_CFA_GNU_window_save
|
||||
DW_CFA_advance_loc: 4 to 0000000000000010
|
||||
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
|
||||
DW_CFA_nop
|
||||
DW_CFA_nop
|
||||
|
31
gas/testsuite/gas/aarch64/pac_ab_key.s
Normal file
31
gas/testsuite/gas/aarch64/pac_ab_key.s
Normal file
@ -0,0 +1,31 @@
|
||||
.arch armv8-a
|
||||
.text
|
||||
.align 2
|
||||
.global _Z5foo_av
|
||||
.type _Z5foo_av, %function
|
||||
_Z5foo_av:
|
||||
.LFB0:
|
||||
.cfi_startproc
|
||||
hint 25 // paciasp
|
||||
.cfi_window_save
|
||||
stp x29, x30, [sp, -16]!
|
||||
.cfi_def_cfa_offset 16
|
||||
.cfi_offset 29, -16
|
||||
.cfi_offset 30, -8
|
||||
.cfi_endproc
|
||||
.LFE0:
|
||||
.size _Z5foo_av, .-_Z5foo_av
|
||||
.align 2
|
||||
.global _Z5foo_bv
|
||||
.type _Z5foo_bv, %function
|
||||
_Z5foo_bv:
|
||||
.LFB1:
|
||||
.cfi_startproc
|
||||
.cfi_b_key_frame
|
||||
hint 27 // pacibsp
|
||||
.cfi_window_save
|
||||
stp x29, x30, [sp, -16]!
|
||||
.cfi_def_cfa_offset 16
|
||||
.cfi_offset 29, -16
|
||||
.cfi_offset 30, -8
|
||||
.cfi_endproc
|
Loading…
x
Reference in New Issue
Block a user