diff options
author | Indu Bhagat <indu.bhagat@oracle.com> | 2025-07-12 11:10:23 +0200 |
---|---|---|
committer | Jose E. Marchesi <jose.marchesi@oracle.com> | 2025-07-12 11:33:25 +0200 |
commit | 97d71f2366fdbe506bcfad0c0abd3914ba334ada (patch) | |
tree | 5a42070b9d41b28465e3789ce8b567c53057d3a1 | |
parent | 427363b461dc40e4e03bef27d2d52623b800f312 (diff) | |
download | gdb-97d71f2366fdbe506bcfad0c0abd3914ba334ada.zip gdb-97d71f2366fdbe506bcfad0c0abd3914ba334ada.tar.gz gdb-97d71f2366fdbe506bcfad0c0abd3914ba334ada.tar.bz2 |
ld/aarch64elf: add support for DT_AARCH64_MEMTAG_MODE dynamic tag
Add new command line option -z memtag-mode=<mode> to aarch64 elf,
where <mode> can be one of none, sync, or async. For mode of sync or
async, a DT_AARCH64_MEMTAG_MODE dynamic tag with a value of 0 or 1
respectively is emitted.
readelf displays the dynamic tag when present:
$ readelf -d <exectutable>
Dynamic section at offset 0xfdd8 contains XX entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000000c (INIT) 0x400520
0x000000000000000d (FINI) 0x400b64
0x0000000000000019 (INIT_ARRAY) 0x41fdc8
... ... ...
0x0000000070000009 (AARCH64_MEMTAG_MODE) 0x1
... ... ...
Note that this patch doesn't add support for the "asymm" MTE mode,
which is an Armv8.7 extension.
ChangeLog:
* bfd/elfnn-aarch64.c (struct elf_aarch64_link_hash_table): Add
new member for memtag properties.
(bfd_elfNN_aarch64_set_options): New argument to pass memtag
properties.
(elfNN_aarch64_late_size_sections): Emit DT_AARCH64_MEMTAG_MODE
dynamic tag.
* bfd/elfxx-aarch64.h: New definition for the various memtag
properties.
* binutils/readelf.c (get_aarch64_dynamic_type): Handle
DT_AARCH64_MEMTAG_MODE.
* ld/emultempl/aarch64elf.em: Likewise.
* ld/ld.texi: Add documentation for the new option
-z memtag-mode.
* ld/testsuite/ld-aarch64/aarch64-elf.exp: New test.
* ld/testsuite/ld-aarch64/dt-memtag.d: New test.
* ld/testsuite/ld-aarch64/dt-memtag-mode.s: New test.
include/ChangeLog:
* elf/aarch64.h (DT_AARCH64_MEMTAG_MODE): New definition.
-rw-r--r-- | bfd/elfnn-aarch64.c | 14 | ||||
-rw-r--r-- | bfd/elfxx-aarch64.h | 26 | ||||
-rw-r--r-- | binutils/readelf.c | 6 | ||||
-rw-r--r-- | include/elf/aarch64.h | 1 | ||||
-rw-r--r-- | ld/emultempl/aarch64elf.em | 43 | ||||
-rw-r--r-- | ld/ld.texi | 10 | ||||
-rw-r--r-- | ld/testsuite/ld-aarch64/aarch64-elf.exp | 1 | ||||
-rw-r--r-- | ld/testsuite/ld-aarch64/dt-memtag-mode.d | 7 | ||||
-rw-r--r-- | ld/testsuite/ld-aarch64/dt-memtag.s | 7 |
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" @@ -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 |