aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/elfnn-aarch64.c14
-rw-r--r--bfd/elfxx-aarch64.h26
-rw-r--r--binutils/readelf.c6
-rw-r--r--include/elf/aarch64.h1
-rw-r--r--ld/emultempl/aarch64elf.em43
-rw-r--r--ld/ld.texi10
-rw-r--r--ld/testsuite/ld-aarch64/aarch64-elf.exp1
-rw-r--r--ld/testsuite/ld-aarch64/dt-memtag-mode.d7
-rw-r--r--ld/testsuite/ld-aarch64/dt-memtag.s7
9 files changed, 109 insertions, 6 deletions
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 8f39920..0e9e22e 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -2622,6 +2622,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;
@@ -5009,13 +5012,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. */
@@ -9775,7 +9780,14 @@ elfNN_aarch64_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
&& !add_dynamic_entry (DT_AARCH64_PAC_PLT, 0))
return false;
}
+
+ 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;
diff --git a/bfd/elfxx-aarch64.h b/bfd/elfxx-aarch64.h
index 506f4a9..66c1f48 100644
--- a/bfd/elfxx-aarch64.h
+++ b/bfd/elfxx-aarch64.h
@@ -129,13 +129,35 @@ 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.
+ At this time, except AARCH64_MEMTAG_MODE_NONE, the enumerator constants are
+ the same as specified in the Memtag ABI Extension to ELF for the Arm 64-bit
+ Architecture (AArch64) document (the intent being that this keeps the
+ emission of the associated dynamic tag simple).*/
+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
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 4a3307e..0d8daf3 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -2584,9 +2584,11 @@ get_aarch64_dynamic_type (unsigned long type)
{
switch (type)
{
- case DT_AARCH64_BTI_PLT: return "AARCH64_BTI_PLT";
- case DT_AARCH64_PAC_PLT: return "AARCH64_PAC_PLT";
+ 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;
}
diff --git a/include/elf/aarch64.h b/include/elf/aarch64.h
index e218e07..747d8dc 100644
--- a/include/elf/aarch64.h
+++ b/include/elf/aarch64.h
@@ -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
diff --git a/ld/emultempl/aarch64elf.em b/ld/emultempl/aarch64elf.em
index afa91af..d7e4eb7 100644
--- a/ld/emultempl/aarch64elf.em
+++ b/ld/emultempl/aarch64elf.em
@@ -42,6 +42,10 @@ static aarch64_protection_opts sw_protections = {
.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 +339,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 +445,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 +548,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 +572,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"
diff --git a/ld/ld.texi b/ld/ld.texi
index afcc3fe..f5350e7 100644
--- a/ld/ld.texi
+++ b/ld/ld.texi
@@ -8374,6 +8374,16 @@ 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}, @samp{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
diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp
index 2d444e7..56e68c5 100644
--- a/ld/testsuite/ld-aarch64/aarch64-elf.exp
+++ b/ld/testsuite/ld-aarch64/aarch64-elf.exp
@@ -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}
diff --git a/ld/testsuite/ld-aarch64/dt-memtag-mode.d b/ld/testsuite/ld-aarch64/dt-memtag-mode.d
new file mode 100644
index 0000000..21670bc
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/dt-memtag-mode.d
@@ -0,0 +1,7 @@
+#source: dt-memtag.s
+#ld: -shared -z memtag-mode=async
+#readelf: -d
+
+#...
+ 0x0000000070000009 \(AARCH64_MEMTAG_MODE\) 0x1
+#...
diff --git a/ld/testsuite/ld-aarch64/dt-memtag.s b/ld/testsuite/ld-aarch64/dt-memtag.s
new file mode 100644
index 0000000..51f3ba5
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/dt-memtag.s
@@ -0,0 +1,7 @@
+// Test DT_AARCH64_MEMTAG_MODE.
+
+.text
+.p2align 3
+.global foo
+foo:
+.xword foo