]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
aarch64: Fix PLT fixups when BTI is used [PR32572]
authorRichard Earnshaw <rearnsha@arm.com>
Thu, 23 Jan 2025 10:53:54 +0000 (10:53 +0000)
committerRichard Earnshaw <rearnsha@arm.com>
Fri, 24 Jan 2025 14:54:48 +0000 (14:54 +0000)
PR ld/32572

There are two problems addressed in this PR.  Firstly, the choice of
whether or not a PLT stub needs a BTI on entry was too strict,
resulting in non-pie executables not having a BTI on their stub.  But
secondly, the logic to handle each stub types did not agree across the
various places where this information is used.

The first issue is fixed by using bfd_link_executable rather than
bfd_link_pde.  The second is addressed by recording a delta for PLT
stub alongside the stub itself.  This is then used without needing
additional logic later on since it has been pre-calculated.

A more comprehensive fix would involve creating a data structure to
describe each fixup, including a call-back function to apply any
relocations.  But that's a fairly large change and not appropriate for
backporting.

bfd/elfnn-aarch64.c

index 1fe0b615800c09eef2690cb78719593794abf5f1..9b8b86fd5d596f9d7bb66f7b431f97a0f12dccc2 100644 (file)
@@ -2631,6 +2631,11 @@ struct elf_aarch64_link_hash_table
   /* The bytes of the subsequent PLT entry.  */
   const bfd_byte *plt_entry;
 
+  /* PLT entries have a common shape, but may have some pre-amble
+     instructions (such as BTI).  This delta is used to factor this
+     out of the common code.  */
+  int plt_entry_delta;
+
   /* For convenience in allocate_dynrelocs.  */
   bfd *obfd;
 
@@ -2924,6 +2929,7 @@ elfNN_aarch64_link_hash_table_create (bfd *abfd)
   ret->plt_header_size = PLT_ENTRY_SIZE;
   ret->plt0_entry = elfNN_aarch64_small_plt0_entry;
   ret->plt_entry_size = PLT_SMALL_ENTRY_SIZE;
+  ret->plt_entry_delta = 0;
   ret->plt_entry = elfNN_aarch64_small_plt_entry;
   ret->tlsdesc_plt_entry_size = PLT_TLSDESC_ENTRY_SIZE;
   ret->obfd = abfd;
@@ -4959,15 +4965,17 @@ 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_pde (link_info))
+      if (bfd_link_executable (link_info))
        {
          globals->plt_entry_size = PLT_BTI_PAC_SMALL_ENTRY_SIZE;
          globals->plt_entry = elfNN_aarch64_small_plt_bti_pac_entry;
+         globals->plt_entry_delta = 4;
        }
       else
        {
          globals->plt_entry_size = PLT_PAC_SMALL_ENTRY_SIZE;
          globals->plt_entry = elfNN_aarch64_small_plt_pac_entry;
+         globals->plt_entry_delta = 0;
        }
     }
   else if (plt_type == PLT_BTI)
@@ -4975,10 +4983,11 @@ 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_pde (link_info))
+      if (bfd_link_executable (link_info))
        {
          globals->plt_entry_size = PLT_BTI_SMALL_ENTRY_SIZE;
          globals->plt_entry = elfNN_aarch64_small_plt_bti_entry;
+         globals->plt_entry_delta = 4;
        }
     }
   else if (plt_type == PLT_PAC)
@@ -9841,11 +9850,9 @@ elfNN_aarch64_create_small_pltn_entry (struct elf_link_hash_entry *h,
   /* Copy in the boiler-plate for the PLTn entry.  */
   memcpy (plt_entry, htab->plt_entry, htab->plt_entry_size);
 
-  /* First instruction in BTI enabled PLT stub is a BTI
-     instruction so skip it.  */
-  if (elf_aarch64_tdata (output_bfd)->sw_protections.plt_type & PLT_BTI
-      && elf_elfheader (output_bfd)->e_type == ET_EXEC)
-    plt_entry = plt_entry + 4;
+  /* Allow for any delta (such as a BTI instruction) before the common
+     sequence.  */
+  plt_entry += htab->plt_entry_delta;
 
   /* Fill in the top 21 bits for this: ADRP x16, PLT_GOT + n * 8.
      ADRP:   ((PG(S+A)-PG(P)) >> 12) & 0x1fffff */