@@ -2619,6 +2619,9 @@ struct elf_aarch64_link_hash_table
/* Don't apply link-time values for dynamic relocations. */
int no_apply_dynamic_relocs;
+ /* Memtag Extension mode of operation. */
+ aarch64_memtag_opts memtag_opts;
+
/* The number of bytes in the initial entry in the PLT. */
bfd_size_type plt_header_size;
@@ -5006,13 +5009,15 @@ bfd_elfNN_aarch64_set_options (struct bfd *output_bfd,
int fix_erratum_835769,
erratum_84319_opts fix_erratum_843419,
int no_apply_dynamic_relocs,
- const aarch64_protection_opts *sw_protections)
+ const aarch64_protection_opts *sw_protections,
+ const aarch64_memtag_opts *memtag_opts)
{
struct elf_aarch64_link_hash_table *globals;
globals = elf_aarch64_hash_table (link_info);
globals->pic_veneer = pic_veneer;
globals->fix_erratum_835769 = fix_erratum_835769;
+ globals->memtag_opts = *memtag_opts;
/* If the default options are used, then ERRAT_ADR will be set by default
which will enable the ADRP->ADR workaround for the erratum 843419
workaround. */
@@ -9772,7 +9777,15 @@ elfNN_aarch64_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
&& !add_dynamic_entry (DT_AARCH64_PAC_PLT, 0))
return false;
}
+
+ /* FIXME - what about asymm ? */
+ if (is_aarch64_elf (output_bfd)
+ && htab->memtag_opts.memtag_mode != AARCH64_MEMTAG_MODE_NONE
+ && !add_dynamic_entry (DT_AARCH64_MEMTAG_MODE,
+ htab->memtag_opts.memtag_mode == AARCH64_MEMTAG_MODE_ASYNC))
+ return false;
}
+
#undef add_dynamic_entry
return true;
@@ -129,13 +129,33 @@ typedef enum
ERRAT_ADRP = (1 << 2), /* Erratum workarounds using ADRP are allowed. */
} erratum_84319_opts;
+/* An enum to define the various modes of MTE operation.
+ The enumerator constants must be the same as specified in the Memtag ABI
+ Extension to ELF for the Arm® 64-bit Architecture (AArch64) document. */
+typedef enum
+{
+ AARCH64_MEMTAG_MODE_SYNC = 0,
+ AARCH64_MEMTAG_MODE_ASYNC = 1,
+ AARCH64_MEMTAG_MODE_NONE = 2,
+} aarch64_memtag_mode_type;
+
+/* A structure to encompass all information about memtag feature related
+ command line options. */
+struct aarch64_memtag_opts
+{
+ /* Mode of MTE operation. */
+ aarch64_memtag_mode_type memtag_mode;
+};
+
+typedef struct aarch64_memtag_opts aarch64_memtag_opts;
+
extern void bfd_elf64_aarch64_set_options
(bfd *, struct bfd_link_info *, int, int, int, int, erratum_84319_opts, int,
- const aarch64_protection_opts *);
+ const aarch64_protection_opts *, const aarch64_memtag_opts *);
extern void bfd_elf32_aarch64_set_options
(bfd *, struct bfd_link_info *, int, int, int, int, erratum_84319_opts, int,
- const aarch64_protection_opts *);
+ const aarch64_protection_opts *, const aarch64_memtag_opts *);
/* AArch64 stub generation support for ELF64. Called from the linker. */
extern int elf64_aarch64_setup_section_lists
@@ -2587,6 +2587,8 @@ get_aarch64_dynamic_type (unsigned long type)
case DT_AARCH64_BTI_PLT: return "AARCH64_BTI_PLT";
case DT_AARCH64_PAC_PLT: return "AARCH64_PAC_PLT";
case DT_AARCH64_VARIANT_PCS: return "AARCH64_VARIANT_PCS";
+ case DT_AARCH64_MEMTAG_MODE: return "AARCH64_MEMTAG_MODE";
+
default:
return NULL;
}
@@ -52,6 +52,7 @@
#define DT_AARCH64_BTI_PLT (DT_LOPROC + 1)
#define DT_AARCH64_PAC_PLT (DT_LOPROC + 3)
#define DT_AARCH64_VARIANT_PCS (DT_LOPROC + 5)
+#define DT_AARCH64_MEMTAG_MODE (DT_LOPROC + 9)
/* AArch64-specific values for st_other. */
#define STO_AARCH64_VARIANT_PCS 0x80 /* Symbol may follow different call
@@ -41,6 +41,9 @@ static aarch64_protection_opts sw_protections = {
.gcs_report = MARKING_WARN,
.gcs_report_dynamic = MARKING_UNSET,
};
+static aarch64_memtag_opts memtag_opts = {
+ .memtag_mode = AARCH64_MEMTAG_MODE_NONE,
+};
#define COMPILE_TIME_STRLEN(s) \
(sizeof(s) - 1)
@@ -335,7 +338,8 @@ aarch64_elf_create_output_section_statements (void)
pic_veneer,
fix_erratum_835769, fix_erratum_843419,
no_apply_dynamic_relocs,
- &sw_protections);
+ &sw_protections,
+ &memtag_opts);
stub_file = lang_add_input_file ("linker stubs",
lang_input_file_is_fake_enum,
@@ -440,6 +444,31 @@ aarch64_parse_gcs_option (const char *_optarg)
#undef GCS
#undef GCS_LEN
}
+
+static bool
+aarch64_parse_memtag_mode_option (const char *optarg)
+{
+ #define MEMTAG_MODE "memtag-mode"
+ #define MEMTAG_MODE_LEN COMPILE_TIME_STRLEN (MEMTAG_MODE)
+
+ if (strncmp (optarg, MEMTAG_MODE, MEMTAG_MODE_LEN) != 0)
+ return false;
+
+ if (strcmp (optarg + MEMTAG_MODE_LEN, "=none") == 0)
+ memtag_opts.memtag_mode = AARCH64_MEMTAG_MODE_NONE;
+ else if (strcmp (optarg + MEMTAG_MODE_LEN, "=sync") == 0)
+ memtag_opts.memtag_mode = AARCH64_MEMTAG_MODE_SYNC;
+ else if (strcmp (optarg + MEMTAG_MODE_LEN, "=async") == 0)
+ memtag_opts.memtag_mode = AARCH64_MEMTAG_MODE_ASYNC;
+ else
+ einfo (_("%X%P: error: unrecognized value '-z %s'\n"), optarg);
+
+ return true;
+
+ #undef MEMTAG_MODE
+ #undef MEMTAG_MODE_LEN
+}
+
EOF
# Define some shell vars to insert bits of code into the standard elf
@@ -518,6 +547,15 @@ PARSE_AND_LIST_OPTIONS='
and output have GCS marking.\n\
error: Emit error when the input objects are missing GCS markings\n\
and output have GCS marking.\n"));
+ fprintf (file, _("\
+ -z memtag-mode[=none|sync|async] Select Memory Tagging Extension mode of operation to use.\n\
+ Emits a DT_AARCH64_MEMTAG_MODE dynamic tag for the binary.\n\
+ This entry is only valid on the main executable. It is\n\
+ ignored in the dynamically loaded objects by the loader.\n\
+ none (default): Disable MTE checking of memory reads and writes.\n\
+ sync: Enable precise exceptions when mismatched address and\n\
+ allocation tags detected on load/store operations.\n\
+ async: Enable imprecise exceptions.\n"));
'
PARSE_AND_LIST_ARGS_CASE_Z_AARCH64='
@@ -533,6 +571,8 @@ PARSE_AND_LIST_ARGS_CASE_Z_AARCH64='
{}
else if (aarch64_parse_gcs_option (optarg))
{}
+ else if (aarch64_parse_memtag_mode_option (optarg))
+ {}
'
PARSE_AND_LIST_ARGS_CASE_Z="$PARSE_AND_LIST_ARGS_CASE_Z $PARSE_AND_LIST_ARGS_CASE_Z_AARCH64"
@@ -8371,6 +8371,15 @@ GCS markings.
If issues are found, a maximum of 20 messages will be emitted, and then a summary
with the total number of issues will be displayed at the end.
+@kindex -z memtag-mode=@var{mode}
+@cindex MTE modes of operation
+The @samp{-z memtag-mode=mode} specifies the MTE mode of operation. The
+value of @samp{mode} can be one of @samp{none, sync} or @samp{async}. The
+specified modes determine the value of the @samp{DT_AARCH64_MEMTAG_MODE}
+dynamic tag. The @samp{sync} mode implies precise exceptions, with the runtime
+providing the exact instruction where the fault occurred, and the exact
+faulting address. The @samp{async} mode implies imprecise exceptions.
+
@ifclear GENERIC
@lowersections
@end ifclear
@@ -377,6 +377,7 @@ run_dump_test_lp64 "variant_pcs-shared"
run_dump_test_lp64 "variant_pcs-now"
run_dump_test_lp64 "mte-tagged-frame"
+run_dump_test_lp64 "dt-memtag-mode"
set aarch64elflinktests {
{"ld-aarch64/so with global symbol" "-shared" "" "" {copy-reloc-so.s}
new file mode 100644
@@ -0,0 +1,7 @@
+#source: dt-memtag.s
+#ld: -shared -z memtag-mode=async
+#readelf: -d
+
+#...
+ 0x0000000070000009 \(AARCH64_MEMTAG_MODE\) 0x1
+#...
new file mode 100644
@@ -0,0 +1,7 @@
+// Test DT_AARCH64_MEMTAG_MODE.
+
+.text
+.p2align 3
+.global foo
+foo:
+.xword foo