[binutils-gdb] ld/aarch64elf: add support for DT_AARCH64_MEMTAG_STACK dynamic tag

Jose E. Marchesi jemarch@sourceware.org
Sat Jul 12 09:38:05 GMT 2025


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=b9b7bbb466efc2955c80204250eedeecfacbecd7

commit b9b7bbb466efc2955c80204250eedeecfacbecd7
Author: Indu Bhagat <indu.bhagat@oracle.com>
Date:   Wed Jul 9 23:13:58 2025 +0200

    ld/aarch64elf: add support for DT_AARCH64_MEMTAG_STACK dynamic tag
    
    Add new command line option -z memtag-stack for aarch64 elf.  This
    option instructs the linker to generate the necessary dynamic tag
    DT_AARCH64_MEMTAG_STACK, which the dynamic loader can then use to
    protect the stack memory with PROT_MTE.  Linker issues an
    'unrecognized option' error when -z memtag-stack is specified for
    non-aarch64 based emulations.
    
    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
    ...                 ...                 ...
    0x000000007000000c (AARCH64_MEMTAG_STACK) 0x1
    ...                 ...                 ...
    
    ChangeLog:
    
            * bfd/elfnn-aarch64.c (elfNN_aarch64_late_size_sections): Emit
            DT_AARCH64_MEMTAG_STACK dynamic tag.
            * bfd/elfxx-aarch64.h (struct aarch64_memtag_opts): Add new
            member for tracking whether stack access uses MTE insns.
            * binutils/readelf.c (get_aarch64_dynamic_type): Handle
            DT_AARCH64_MEMTAG_STACK.
            * ld/emultempl/aarch64elf.em: Add new command line option.
            * ld/ld.texi: Add documentation for -z memtag-stack.
            * ld/testsuite/ld-aarch64/aarch64-elf.exp: Add new test.
            * ld/testsuite/ld-aarch64/dt-memtag-stack.d: New test.
    
    include/ChangeLog:
    
            * elf/aarch64.h (DT_AARCH64_MEMTAG_STACK): New definition.

Diff:
---
 bfd/elfnn-aarch64.c                       | 6 ++++++
 bfd/elfxx-aarch64.h                       | 3 +++
 binutils/readelf.c                        | 1 +
 include/elf/aarch64.h                     | 1 +
 ld/emultempl/aarch64elf.em                | 5 +++++
 ld/ld.texi                                | 5 +++++
 ld/testsuite/ld-aarch64/aarch64-elf.exp   | 1 +
 ld/testsuite/ld-aarch64/dt-memtag-stack.d | 7 +++++++
 8 files changed, 29 insertions(+)

diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 0e9e22e210b..9e98215d638 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -9786,6 +9786,12 @@ elfNN_aarch64_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
 	  && !add_dynamic_entry (DT_AARCH64_MEMTAG_MODE,
 				 htab->memtag_opts.memtag_mode == AARCH64_MEMTAG_MODE_ASYNC))
 	return false;
+
+      if (is_aarch64_elf (output_bfd)
+	  && htab->memtag_opts.memtag_stack == 1
+	  && !add_dynamic_entry (DT_AARCH64_MEMTAG_STACK,
+				 htab->memtag_opts.memtag_stack == 1))
+	return false;
     }
 
 #undef add_dynamic_entry
diff --git a/bfd/elfxx-aarch64.h b/bfd/elfxx-aarch64.h
index 66c1f48d450..bd3642cbefe 100644
--- a/bfd/elfxx-aarch64.h
+++ b/bfd/elfxx-aarch64.h
@@ -147,6 +147,9 @@ struct aarch64_memtag_opts
 {
   /* Mode of MTE operation.  */
   aarch64_memtag_mode_type memtag_mode;
+
+  /* Whether stack accesses use MTE insns.  */
+  unsigned int memtag_stack;
 };
 
 typedef struct aarch64_memtag_opts aarch64_memtag_opts;
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 0d8daf3626f..cfccdd2ba65 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -2588,6 +2588,7 @@ get_aarch64_dynamic_type (unsigned long type)
     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";
+    case DT_AARCH64_MEMTAG_STACK: return "AARCH64_MEMTAG_STACK";
 
     default:
       return NULL;
diff --git a/include/elf/aarch64.h b/include/elf/aarch64.h
index 747d8dc022f..74bd7b402e0 100644
--- a/include/elf/aarch64.h
+++ b/include/elf/aarch64.h
@@ -53,6 +53,7 @@
 #define DT_AARCH64_PAC_PLT	(DT_LOPROC + 3)
 #define DT_AARCH64_VARIANT_PCS	(DT_LOPROC + 5)
 #define DT_AARCH64_MEMTAG_MODE	(DT_LOPROC + 9)
+#define DT_AARCH64_MEMTAG_STACK (DT_LOPROC + 12)
 
 /* 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 d7e4eb78059..66eaf1cd861 100644
--- a/ld/emultempl/aarch64elf.em
+++ b/ld/emultempl/aarch64elf.em
@@ -44,6 +44,7 @@ static aarch64_protection_opts sw_protections = {
 
 static aarch64_memtag_opts memtag_opts = {
   .memtag_mode = AARCH64_MEMTAG_MODE_NONE,
+  .memtag_stack = 0,
 };
 
 #define COMPILE_TIME_STRLEN(s) \
@@ -557,6 +558,8 @@ PARSE_AND_LIST_OPTIONS='
                                          sync: Enable precise exceptions when mismatched address and\n\
                                                allocation tags detected on load/store operations.\n\
                                          async: Enable imprecise exceptions.\n"));
+  fprintf (file, _("\
+  -z memtag-stack               Mark program stack with MTE protection.\n"));
 '
 
 PARSE_AND_LIST_ARGS_CASE_Z_AARCH64='
@@ -574,6 +577,8 @@ PARSE_AND_LIST_ARGS_CASE_Z_AARCH64='
 	{}
      else if (aarch64_parse_memtag_mode_option (optarg))
 	{}
+     else if (strcmp (optarg, "memtag-stack") == 0)
+	memtag_opts.memtag_stack = 1;
 '
 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 f5350e799bb..413335ad765 100644
--- a/ld/ld.texi
+++ b/ld/ld.texi
@@ -8384,6 +8384,11 @@ 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.
 
+@kindex -z memtag-stack
+@cindex Mark program stack for MTE protection
+The @samp{-z memtag-stack} specifies that output object uses MTE
+instructions for stack memory usage.
+
 @ifclear GENERIC
 @lowersections
 @end ifclear
diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp
index 56e68c584fb..8d56beb64c7 100644
--- a/ld/testsuite/ld-aarch64/aarch64-elf.exp
+++ b/ld/testsuite/ld-aarch64/aarch64-elf.exp
@@ -378,6 +378,7 @@ run_dump_test_lp64 "variant_pcs-now"
 
 run_dump_test_lp64 "mte-tagged-frame"
 run_dump_test_lp64 "dt-memtag-mode"
+run_dump_test_lp64 "dt-memtag-stack"
 
 set aarch64elflinktests {
   {"ld-aarch64/so with global symbol" "-shared" "" "" {copy-reloc-so.s}
diff --git a/ld/testsuite/ld-aarch64/dt-memtag-stack.d b/ld/testsuite/ld-aarch64/dt-memtag-stack.d
new file mode 100644
index 00000000000..242f61fa172
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/dt-memtag-stack.d
@@ -0,0 +1,7 @@
+#source: dt-memtag.s
+#ld: -shared -z memtag-stack
+#readelf: -d
+
+#...
+ 0x000000007000000c \(AARCH64_MEMTAG_STACK\) 0x1
+#...


More information about the Binutils-cvs mailing list