]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
PR 33593 Misplaced synthetic plt symbols in aarch64 PIE binaries
authorAlan Modra <amodra@gmail.com>
Wed, 4 Feb 2026 22:04:31 +0000 (08:34 +1030)
committerAlan Modra <amodra@gmail.com>
Wed, 4 Feb 2026 22:04:31 +0000 (08:34 +1030)
elfNN_aarch64_plt_sym_val wrongly treats PIEs.  PIEs are an executable
but not ET_EXEC, instead being ET_DYN with DF_1_PIE set in DT_FLAGS_1
to distinguish them from shared libraries.

get_plt_type scans .dynamic for DT_AARCH64_BTI_PLT and
DT_AARCH64_PAC_PLT, setting PLT_BTI and PLT_PAC in the function return
value respectively.  It's easy enough to extend the .dynamic scan to
also return DF_1_PIE in tdata is_pie.

The patch also makes a few tidies, things I noticed when scanning all
the code dealing with sw_protections.plt_type.

PR 33593
* elfnn-aarch64.c (get_plt_type): Return DF_1_PIE via tdata is_pie.
(elfNN_aarch64_plt_sym_val): Handle PIEs as well as ET_EXEC.
(setup_plt_values): Delete wrong ET_EXEC comments.
(elfNN_aarch64_late_size_sections): Remove excess parentheses.
(elfNN_aarch64_finish_dynamic_sections): Rename type to plt_type,
and simplify test for PLT_BTI or PLT_BTI_PAC.

Co-Authored-By: Michael Matz <matz@suse.de>
bfd/elfnn-aarch64.c

index 08077fb74f84412e1b2c6e7b75e2e4d546ad8473..1ba7dd393e68e454819360726cd6b30e07031e2f 100644 (file)
@@ -4979,7 +4979,6 @@ setup_plt_values (struct bfd_link_info *link_info,
     {
       globals->plt0_entry = elfNN_aarch64_small_plt0_bti_entry;
 
-      /* Only in ET_EXEC we need PLTn with BTI.  */
       if (bfd_link_executable (link_info))
        {
          globals->plt_entry_size = PLT_BTI_PAC_SMALL_ENTRY_SIZE;
@@ -4997,7 +4996,6 @@ setup_plt_values (struct bfd_link_info *link_info,
     {
       globals->plt0_entry = elfNN_aarch64_small_plt0_bti_entry;
 
-      /* Only in ET_EXEC we need PLTn with BTI.  */
       if (bfd_link_executable (link_info))
        {
          globals->plt_entry_size = PLT_BTI_SMALL_ENTRY_SIZE;
@@ -9837,16 +9835,16 @@ elfNN_aarch64_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
 
          aarch64_plt_type plt_type
            = elf_aarch64_tdata (output_bfd)->sw_protections.plt_type;
-         if ((plt_type == PLT_BTI_PAC)
+         if (plt_type == PLT_BTI_PAC
              && (!add_dynamic_entry (DT_AARCH64_BTI_PLT, 0)
                  || !add_dynamic_entry (DT_AARCH64_PAC_PLT, 0)))
            return false;
 
-         else if ((plt_type == PLT_BTI)
+         else if (plt_type == PLT_BTI
                   && !add_dynamic_entry (DT_AARCH64_BTI_PLT, 0))
            return false;
 
-         else if ((plt_type == PLT_PAC)
+         else if (plt_type == PLT_PAC
                   && !add_dynamic_entry (DT_AARCH64_PAC_PLT, 0))
            return false;
        }
@@ -10368,12 +10366,10 @@ elfNN_aarch64_finish_dynamic_sections (bfd *output_bfd,
          const bfd_byte *entry = elfNN_aarch64_tlsdesc_small_plt_entry;
          htab->tlsdesc_plt_entry_size = PLT_TLSDESC_ENTRY_SIZE;
 
-         aarch64_plt_type type
+         aarch64_plt_type plt_type
            = elf_aarch64_tdata (output_bfd)->sw_protections.plt_type;
-         if (type == PLT_BTI || type == PLT_BTI_PAC)
-           {
-             entry = elfNN_aarch64_tlsdesc_small_plt_bti_entry;
-           }
+         if (plt_type & PLT_BTI)
+           entry = elfNN_aarch64_tlsdesc_small_plt_bti_entry;
 
          memcpy (htab->root.splt->contents + htab->root.tlsdesc_plt,
                  entry, htab->tlsdesc_plt_entry_size);
@@ -10401,7 +10397,7 @@ elfNN_aarch64_finish_dynamic_sections (bfd *output_bfd,
 
           /* First instruction in BTI enabled PLT stub is a BTI
              instruction so skip it.  */
-           if (type & PLT_BTI)
+           if (plt_type & PLT_BTI)
              {
                plt_entry = plt_entry + 4;
                adrp1_addr = adrp1_addr + 4;
@@ -10487,7 +10483,7 @@ elfNN_aarch64_finish_dynamic_sections (bfd *output_bfd,
 }
 
 /* Check if BTI-enabled (and/or PAC-enabled) PLTs are needed.
-   Returns the type needed.  */
+   Returns the type needed, and whether DF_1_PIE is set via tdata is_pie.  */
 static aarch64_plt_type
 get_plt_type (bfd *abfd)
 {
@@ -10506,13 +10502,12 @@ get_plt_type (bfd *abfd)
       Elf_Internal_Dyn dyn;
       bfd_elfNN_swap_dyn_in (abfd, extdyn, &dyn);
 
-      /* Let's check the processor specific dynamic array tags.  */
-      bfd_vma tag = dyn.d_tag;
-      if (tag < DT_LOPROC || tag > DT_HIPROC)
-       continue;
-
-      switch (tag)
+      switch (dyn.d_tag)
        {
+       case DT_FLAGS_1:
+         elf_tdata (abfd)->is_pie = (dyn.d_un.d_val & DF_1_PIE) != 0;
+         break;
+
        case DT_AARCH64_BTI_PLT:
          ret |= PLT_BTI;
          break;
@@ -10555,14 +10550,18 @@ elfNN_aarch64_plt_sym_val (bfd_vma i, const asection *plt,
     = elf_aarch64_tdata (plt->owner)->sw_protections.plt_type;
   if (plt_type == PLT_BTI_PAC)
     {
-      if (elf_elfheader (plt->owner)->e_type == ET_EXEC)
+      if (elf_elfheader (plt->owner)->e_type == ET_EXEC
+         || (elf_elfheader (plt->owner)->e_type == ET_DYN
+             && elf_tdata (plt->owner)->is_pie))
        pltn_size = PLT_BTI_PAC_SMALL_ENTRY_SIZE;
       else
        pltn_size = PLT_PAC_SMALL_ENTRY_SIZE;
     }
   else if (plt_type == PLT_BTI)
     {
-      if (elf_elfheader (plt->owner)->e_type == ET_EXEC)
+      if (elf_elfheader (plt->owner)->e_type == ET_EXEC
+         || (elf_elfheader (plt->owner)->e_type == ET_DYN
+             && elf_tdata (plt->owner)->is_pie))
        pltn_size = PLT_BTI_SMALL_ENTRY_SIZE;
     }
   else if (plt_type == PLT_PAC)