PR 33593 Misplaced synthetic plt symbols in aarch64 PIE binaries

Alan Modra amodra@gmail.com
Sat Jan 31 05:52:41 GMT 2026


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 as well, but since this isn't an aarch64_plt_type
value I've made get_plt_type return an int.  Since the value is passed
to elfNN_aarch64_plt_sym_val via sw_protections.plt_type I've made
that an int too.

DF_1_PIE won't appear in sw_protections.plt_type for linker functions.
The changes there are just tidies.

	PR 33593
	* elfxx-aarch64.h (aarch64_protection_opts <plt_type>): Make it
	an int.
	* elfnn-aarch64.c (setup_plt_values): Change plt_type param
	to int.  Delete wrong ET_EXEC comments.
	(elfNN_aarch64_late_size_sections): Use an int plt_type.
	Remove excess parentheses.
	(elfNN_aarch64_finish_dynamic_sections): Use an int plt_type,
	and simplify test for PLT_BTI or PLT_BTI_PAC.
	(get_plt_type): Return an int.  Include DF_1_PIE in return
	value.
	(elfNN_aarch64_plt_sym_val): Handle PIEs as well as ET_EXEC.

diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 08077fb74f8..36df338718f 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -4969,8 +4969,7 @@ bfd_elfNN_aarch64_init_maps (bfd *abfd)
 }
 
 static void
-setup_plt_values (struct bfd_link_info *link_info,
-		  aarch64_plt_type plt_type)
+setup_plt_values (struct bfd_link_info *link_info, int plt_type)
 {
   struct elf_aarch64_link_hash_table *globals;
   globals = elf_aarch64_hash_table (link_info);
@@ -4979,7 +4978,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 +4995,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;
@@ -9835,18 +9832,17 @@ elfNN_aarch64_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
 	      && !add_dynamic_entry (DT_AARCH64_VARIANT_PCS, 0))
 	    return false;
 
-	  aarch64_plt_type plt_type
-	    = elf_aarch64_tdata (output_bfd)->sw_protections.plt_type;
-	  if ((plt_type == PLT_BTI_PAC)
+	  int plt_type = elf_aarch64_tdata (output_bfd)->sw_protections.plt_type;
+	  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 +10364,9 @@ 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
-	    = 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;
-	    }
+	  int plt_type = elf_aarch64_tdata (output_bfd)->sw_protections.plt_type;
+	  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 +10394,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,11 +10480,11 @@ elfNN_aarch64_finish_dynamic_sections (bfd *output_bfd,
 }
 
 /* Check if BTI-enabled (and/or PAC-enabled) PLTs are needed.
-   Returns the type needed.  */
-static aarch64_plt_type
+   Returns the type needed and whether DF_1_PIE is set.  */
+static int
 get_plt_type (bfd *abfd)
 {
-  aarch64_plt_type ret = PLT_NORMAL;
+  int ret = PLT_NORMAL;
   bfd_byte *contents, *extdyn, *extdynend;
   asection *sec = bfd_get_section_by_name (abfd, ".dynamic");
   if (!sec
@@ -10506,13 +10499,14 @@ 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)
 	{
+	case DT_FLAGS_1:
+	  BFD_ASSERT (((int) PLT_BTI_PAC & (int) DF_1_PIE) == 0);
+	  ret |= tag & DF_1_PIE;
+	  break;
+
 	case DT_AARCH64_BTI_PLT:
 	  ret |= PLT_BTI;
 	  break;
@@ -10551,21 +10545,24 @@ elfNN_aarch64_plt_sym_val (bfd_vma i, const asection *plt,
   size_t plt0_size = PLT_ENTRY_SIZE;
   size_t pltn_size = PLT_SMALL_ENTRY_SIZE;
 
-  aarch64_plt_type plt_type
-    = elf_aarch64_tdata (plt->owner)->sw_protections.plt_type;
-  if (plt_type == PLT_BTI_PAC)
+  int plt_type = elf_aarch64_tdata (plt->owner)->sw_protections.plt_type;
+  if ((plt_type & PLT_BTI_PAC) == 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
+	      && (plt_type & DF_1_PIE) != 0))
 	pltn_size = PLT_BTI_PAC_SMALL_ENTRY_SIZE;
       else
 	pltn_size = PLT_PAC_SMALL_ENTRY_SIZE;
     }
-  else if (plt_type == PLT_BTI)
+  else if ((plt_type & PLT_BTI_PAC) == 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
+	      && (plt_type & DF_1_PIE) != 0))
 	pltn_size = PLT_BTI_SMALL_ENTRY_SIZE;
     }
-  else if (plt_type == PLT_PAC)
+  else if ((plt_type & PLT_BTI_PAC) == PLT_PAC)
     {
       pltn_size = PLT_PAC_SMALL_ENTRY_SIZE;
     }
diff --git a/bfd/elfxx-aarch64.h b/bfd/elfxx-aarch64.h
index a312427bc75..97ce9397a92 100644
--- a/bfd/elfxx-aarch64.h
+++ b/bfd/elfxx-aarch64.h
@@ -71,7 +71,7 @@ typedef enum
 struct aarch64_protection_opts
 {
   /* PLT type to use depending on the selected software proctections.  */
-  aarch64_plt_type plt_type;
+  int plt_type;
 
   /* Report level for BTI issues.  */
   aarch64_feature_marking_report bti_report;

-- 
Alan Modra


More information about the Binutils mailing list