+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 *);
bool (*elf_backend_can_make_lsda_relative_eh_frame)
(bfd *, struct bfd_link_info *, asection *);
+ bool (*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 bool
+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.
+
2022-04-01 John Baldwin <jhb@FreeBSD.org>
* readelf.c (get_freebsd_elfcore_note_type): Handle
"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;
}
+
+bool
+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
+{
+ bool 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 bool 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