+2020-10-20 Siddhesh Poyarekar <siddesh.poyarekar@arm.com>
+
+ * elf-bfd.h (elf_backend_data): New callback
+ elf_backend_eh_frame_augmentation_char.
+ * elf-eh-frame.c (_bfd_elf_parse_eh_frame): Use it.
+ * elfnn-aarch64.c (elf64_aarch64_eh_frame_augmentation_char):
+ New function.
+ (elf_backend_eh_frame_augmentation_char): New macro.
+
+ * elfxx-target.h [!elf_backend_eh_frame_augmentation_char]:
+ Set elf_backend_eh_frame_augmentation_char to NULL.
+ (elfNN_bed): Initialise
+ elf_backend_eh_frame_augmentation_char.
+
2020-10-20 Siddhesh Poyarekar <siddesh.poyarekar@arm.com>
* elfnn-aarch64.c (STUB_ENTRY_NAME): Add format specifier for
(bfd *, struct bfd_link_info *, asection *);
bfd_boolean (*elf_backend_can_make_lsda_relative_eh_frame)
(bfd *, struct bfd_link_info *, asection *);
+ bfd_boolean (*elf_backend_eh_frame_augmentation_char)
+ (char);
/* This function returns an encoding after computing the encoded
value (and storing it in ENCODED) for the given OFFSET into OSEC,
unsigned int num_cies;
unsigned int num_entries;
elf_gc_mark_hook_fn gc_mark_hook;
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
htab = elf_hash_table (info);
hdr_info = &htab->eh_info;
it (it would need to use 64-bit .eh_frame format anyway). */
REQUIRE (sec->size == (unsigned int) sec->size);
- ptr_size = (get_elf_backend_data (abfd)
- ->elf_backend_eh_frame_address_size (abfd, sec));
+ ptr_size = bed->elf_backend_eh_frame_address_size (abfd, sec);
REQUIRE (ptr_size != 0);
/* Go through the section contents and work out how many FDEs and
buf = ehbuf;
cie_count = 0;
- gc_mark_hook = get_elf_backend_data (abfd)->gc_mark_hook;
+ gc_mark_hook = bed->gc_mark_hook;
while ((bfd_size_type) (buf - ehbuf) != sec->size)
{
char *aug;
}
break;
default:
- /* Unrecognized augmentation. Better bail out. */
- goto free_no_table;
+ /* Unrecognized augmentation. Better bail out if the target
+ cannot recognised it. */
+ if (bed->elf_backend_eh_frame_augmentation_char == NULL
+ || (!bed->elf_backend_eh_frame_augmentation_char
+ (*(aug - 1))))
+ goto free_no_table;
}
}
this_inf->u.cie.aug_data_len
/* For shared libraries, try to get rid of as many RELATIVE relocs
as possible. */
if (bfd_link_pic (info)
- && (get_elf_backend_data (abfd)
- ->elf_backend_can_make_relative_eh_frame
+ && (bed->elf_backend_can_make_relative_eh_frame
(abfd, info, sec)))
{
if ((cie->fde_encoding & 0x70) == DW_EH_PE_absptr)
return GOT_ENTRY_SIZE (htab) * GOT_RESERVED_HEADER_SLOTS;
}
+/* Identify the 'C' in the CIE augmentation string. */
+
+static bfd_boolean
+elf64_aarch64_eh_frame_augmentation_char (const char aug)
+{
+ return aug == 'C';
+}
+
/* We use this so we can override certain functions
(though currently we don't). */
#define elf_backend_got_elt_size \
elfNN_aarch64_got_elt_size
+#define elf_backend_eh_frame_augmentation_char \
+ elf64_aarch64_eh_frame_augmentation_char
+
#define elf_backend_can_refcount 1
#define elf_backend_can_gc_sections 1
#define elf_backend_plt_readonly 1
#ifndef elf_backend_can_make_lsda_relative_eh_frame
#define elf_backend_can_make_lsda_relative_eh_frame _bfd_elf_can_make_relative
#endif
+#ifndef elf_backend_eh_frame_augmentation_char
+#define elf_backend_eh_frame_augmentation_char NULL
+#endif
#ifndef elf_backend_encode_eh_address
#define elf_backend_encode_eh_address _bfd_elf_encode_eh_address
#endif
elf_backend_eh_frame_address_size,
elf_backend_can_make_relative_eh_frame,
elf_backend_can_make_lsda_relative_eh_frame,
+ elf_backend_eh_frame_augmentation_char,
elf_backend_encode_eh_address,
elf_backend_write_section,
elf_backend_elfsym_local_is_section,
+2020-10-20 Siddhesh Poyarekar <siddesh.poyarekar@arm.com>
+
+ * dwarf.c (dwarf_regnames_aarch64): Add capability registers.
+
2020-10-20 Alan Modra <amodra@gmail.com>
* readelf.c: Delete whitespace at end of line throughout.
"z8", "z9", "z10", "z11", "z12", "z13", "z14", "z15",
"z16", "z17", "z18", "z19", "z20", "z21", "z22", "z23",
"z24", "z25", "z26", "z27", "z28", "z29", "z30", "z31",
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, "c0", "c1",
+ "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9",
+ "c10", "c11", "c12", "c13", "c14", "c15", "c16", "c17",
+ "c18", "c19", "c20", "c21", "c22", "c23", "c24", "c25",
+ "c26", "c27", "c28", "c29", "c30", "csp", NULL, "ddc",
};
static void
+2020-10-20 Siddhesh Poyarekar <siddesh.poyarekar@arm.com>
+
+ * config/tc-aarch64.c (REG_DW_CSP, REG_DW_CLR): New macros.
+ (s_aarch64_cfi_b_key_frame): Adjust for new entry_extras
+ struct.
+ (tc_aarch64_frame_initial_instructions): Adjust for C64.
+ (tc_aarch64_fde_entry_init_extra,
+ tc_aarch64_cfi_startproc_exp): New functions.
+ (tc_aarch64_regname_to_dw2regnum): Support capability
+ registers.
+ * config/tc-aarch64.h (fde_entry): Forward declaration.
+ (eh_entry_extras): New struct.
+ (tc_fde_entry_extras, tc_cie_entry_extras): Use it.
+ (tc_fde_entry_init_extra): Set to
+ tc_aarch64_fde_entry_init_extra.
+ (tc_output_cie_extra): Emit 'C' for C64.
+ (tc_cie_fde_equivalent_extra): Adjust for C64.
+ (tc_cie_entry_init_extra): Likewise.
+ (tc_cfi_startproc_exp): New macro.
+ (tc_aarch64_cfi_startproc_exp,
+ tc_aarch64_fde_entry_init_extra): New function declarations.
+ * dw2gencfi.c (tc_cfi_startproc_exp): New macro.
+ (dot_cfi_startproc): Use it.
+ * testsuite/gas/aarch64/morello-eh.d: New test.
+ * testsuite/gas/aarch64/morello-eh.s: New test.
+
2020-10-20 Siddhesh Poyarekar <siddesh.poyarekar@arm.com>
* config/tc-aarch64.c (parse_operands): Choose C64 branch
/* Some well known registers that we refer to directly elsewhere. */
#define REG_SP 31
#define REG_ZR 31
+#define REG_DW_CSP (31 + 198)
+#define REG_DW_CLR (30 + 198)
/* Instructions take 4 bytes in the object file. */
#define INSN_SIZE 4
{
demand_empty_rest_of_line ();
struct fde_entry *fde = frchain_now->frch_cfi_data->cur_fde_data;
- fde->pauth_key = AARCH64_PAUTH_KEY_B;
+ fde->entry_extras.pauth_key = AARCH64_PAUTH_KEY_B;
}
#ifdef OBJ_ELF
void
tc_aarch64_frame_initial_instructions (void)
{
- cfi_add_CFA_def_cfa (REG_SP, 0);
+ if (IS_C64)
+ {
+ cfi_set_return_column (REG_DW_CLR);
+ cfi_add_CFA_def_cfa (REG_DW_CSP, 0);
+ }
+ else
+ cfi_add_CFA_def_cfa (REG_SP, 0);
+}
+
+
+/* The extra initialisation steps needed by AArch64 in alloc_fde_entry.
+ Currently only used to initialise the key used to sign the return
+ address. */
+void
+tc_aarch64_fde_entry_init_extra(struct fde_entry *fde)
+{
+ fde->entry_extras.pauth_key = AARCH64_PAUTH_KEY_A;
+ fde->entry_extras.c64 = IS_C64;
}
+
+bfd_boolean
+tc_aarch64_cfi_startproc_exp (const char *arg)
+{
+ // Allow purecap only for C64 functions.
+ if (!strcmp ("purecap", arg) && IS_C64)
+ return TRUE;
+
+ return FALSE;
+}
+
#endif /* OBJ_ELF */
/* Convert REGNAME to a DWARF-2 register number. */
case REG_TYPE_FP_Q:
return reg->number + 64;
+ case REG_TYPE_CA_N:
+ case REG_TYPE_CA_SP:
+ case REG_TYPE_CA_D:
+ return reg->number + 198;
+
default:
break;
}
| (((n) >> 24) & 0xff))
struct fix;
+struct fde_entry;
struct aarch64_fix
{
AARCH64_PAUTH_KEY_B
};
+struct eh_entry_extras
+{
+ bfd_boolean c64;
+ enum pointer_auth_key pauth_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;
-
-/* 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_extras struct eh_entry_extras entry_extras;
+#define tc_cie_entry_extras struct eh_entry_extras entry_extras;
+#define tc_fde_entry_init_extra(fde) tc_aarch64_fde_entry_init_extra(fde);
/* 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
#define tc_output_cie_extra(cie) \
do \
{ \
- if (cie->pauth_key == AARCH64_PAUTH_KEY_B) \
+ if (cie->entry_extras.pauth_key == AARCH64_PAUTH_KEY_B) \
out_one ('B'); \
+ if (cie->entry_extras.c64) \
+ out_one ('C'); \
} \
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)
+ to sign ther return address and whether they are either both A64 or both
+ C64. */
+#define tc_cie_fde_equivalent_extra(cie, fde) \
+ (cie->entry_extras.pauth_key == fde->entry_extras.pauth_key \
+ && cie->entry_extras.c64 == fde->entry_extras.c64)
/* 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->entry_extras.pauth_key = fde->entry_extras.pauth_key; \
+ cie->entry_extras.c64 = fde->entry_extras.c64; \
+ } \
+ while (0);
#define TC_FIX_TYPE struct aarch64_fix
#define TC_INIT_FIX_DATA(FIX) { (FIX)->tc_fix_data.inst = NULL; \
/* CFI hooks. */
#define tc_regname_to_dw2regnum tc_aarch64_regname_to_dw2regnum
#define tc_cfi_frame_initial_instructions tc_aarch64_frame_initial_instructions
+#define tc_cfi_startproc_exp tc_aarch64_cfi_startproc_exp
extern void aarch64_after_parse_args (void);
#define md_after_parse_args() aarch64_after_parse_args ()
extern void aarch64_handle_align (struct frag *);
extern int tc_aarch64_regname_to_dw2regnum (char *regname);
extern void tc_aarch64_frame_initial_instructions (void);
+extern bfd_boolean tc_aarch64_cfi_startproc_exp (const char *);
+void tc_aarch64_fde_entry_init_extra(struct fde_entry *);
#ifdef TE_PE
#define tc_cfi_frame_initial_instructions() ((void)0)
#endif
+#ifndef tc_cfi_startproc_exp
+# define tc_cfi_startproc_exp() (FALSE)
+#endif
+
#ifndef tc_cfi_startproc
# define tc_cfi_startproc() ((void)0)
#endif
simple = 1;
restore_line_pointer (c);
}
- else
+ /* Custom arguments to .cfi_startproc. */
+ else if (!tc_cfi_startproc_exp (name))
input_line_pointer = saved_ilp;
}
demand_empty_rest_of_line ();
--- /dev/null
+#objdump: --dwarf=frames
+#...
+Contents of the \.eh_frame section:
+#...
+ Augmentation: "zR"
+#...
+ Return address column: 30
+ Augmentation data: 1b
+ DW_CFA_def_cfa: r31 \(sp\) ofs 0
+#...
+ DW_CFA_def_cfa: r31 \(sp\) ofs 32
+ DW_CFA_offset: r30 \(x30\) at cfa-16
+ DW_CFA_offset_extended: r231 \(ddc\) at cfa-32
+#...
+ Augmentation: "zRC"
+#...
+ Return address column: 228
+ Augmentation data: 1b
+ DW_CFA_def_cfa: r229 \(csp\) ofs 0
+#...
+ DW_CFA_def_cfa: r229 \(csp\) ofs 32
+ DW_CFA_offset_extended: r228 \(c30\) at cfa-16
+ DW_CFA_offset_extended: r231 \(ddc\) at cfa-32
+#...
--- /dev/null
+ .text
+ .arch morello
+ .globl f1
+ .type f1,@function
+f1:
+ .cfi_startproc
+ mrs c29, ddc
+ sub csp, csp, #96
+ stp c29, c30, [sp, #64]
+ add c29, csp, #64
+ .cfi_def_cfa sp, 32
+ .cfi_offset x30, -16
+ .cfi_offset ddc, -32
+ ret
+ .size f1, .-f1
+ .cfi_endproc
+
+ .arch morello+c64
+ .globl f2
+ .type f2,@function
+f2:
+ .cfi_startproc purecap
+ mrs c29, ddc
+ sub csp, csp, #96
+ stp c29, c30, [csp, #64]
+ add c29, csp, #64
+ .cfi_def_cfa csp, 32
+ .cfi_offset c30, -16
+ .cfi_offset ddc, -32
+ .size f2, .-f2
+ .cfi_endproc