[PATCH V4 8/8] ld/aarch64elf: add support for DT_AARCH64_MEMTAG_STACK dynamic tag

Richard Earnshaw Richard.Earnshaw@arm.com
Fri Jul 11 14:01:38 GMT 2025


On 09/07/2025 22:44, Jose E. Marchesi via Binutils wrote:
> From: Indu Bhagat <indu.bhagat@oracle.com>
> 
> 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.
> ---
>   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(+)
>   create mode 100644 ld/testsuite/ld-aarch64/dt-memtag-stack.d
> 
> 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 2ae6eea810f..e1964906661 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 129aef9a524..a4ef1118402 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 f196f1e5870..4460a084404 100644
> --- a/ld/ld.texi
> +++ b/ld/ld.texi
> @@ -8383,6 +8383,11 @@ 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.
>   
> +@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
> +#...


OK

R


More information about the Binutils mailing list