[PATCH] arm-nacl .iplt fix

Roland McGrath mcgrathr@google.com
Tue Apr 23 21:13:00 GMT 2013


When I did the arm-nacl target support for PLT generation, I forgot about
the .iplt case.  Since arm-nacl PLT entries jump into part of the PLT
header code, .iplt needs this header code too.

If there are no objections, I'll put this on the trunk and the 2.23 branch.


Thanks,
Roland


bfd/
2013-04-23  Roland McGrath  <mcgrathr@google.com>

	* elf32-arm.c (elf32_arm_allocate_plt_entry): If HTAB->nacl_p,
	allocate space for PLT header even if IS_IPLT_ENTRY.
	(arm_nacl_put_plt0): New function, broken out of ...
	(elf32_arm_finish_dynamic_sections): ... here.  Call it.
	If HTAB->nacl_p, set up the PLT header in .iplt too.
	(elf32_arm_output_arch_local_syms): If HTAB->nacl_p, write
	a mapping symbol for the start of .iplt too.

--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -1,6 +1,6 @@
 /* 32-bit ELF support for ARM
    Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
-   2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
+   2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.

    This file is part of BFD, the Binary File Descriptor library.

@@ -7394,6 +7394,10 @@ elf32_arm_allocate_plt_entry (struct bfd_link_info *info,
       splt = htab->root.iplt;
       sgotplt = htab->root.igotplt;

+      /* NaCl uses a special first entry in .iplt too.  */
+      if (htab->nacl_p && splt->size == 0)
+	splt->size += htab->plt_header_size;
+
       /* Allocate room for an R_ARM_IRELATIVE relocation in .rel.iplt.  */
       elf32_arm_allocate_irelocs (info, htab->root.irelplt, 1);
     }
@@ -14034,6 +14038,38 @@ arm_put_trampoline (struct
elf32_arm_link_hash_table *htab, bfd *output_bfd,
     }
 }

+/* Install the special first PLT entry for elf32-arm-nacl.  Unlike
+   other variants, NaCl needs this entry in a static executable's
+   .iplt too.  When we're handling that case, GOT_DISPLACEMENT is
+   zero.  For .iplt really only the last bundle is useful, and .iplt
+   could have a shorter first entry, with each individual PLT entry's
+   relative branch calculated differently so it targets the last
+   bundle instead of the instruction before it (labelled .Lplt_tail
+   above).  But it's simpler to keep the size and layout of PLT0
+   consistent with the dynamic case, at the cost of some dead code at
+   the start of .iplt and the one dead store to the stack at the start
+   of .Lplt_tail.  */
+static void
+arm_nacl_put_plt0 (struct elf32_arm_link_hash_table *htab, bfd *output_bfd,
+		   asection *plt, bfd_vma got_displacement)
+{
+  unsigned int i;
+
+  put_arm_insn (htab, output_bfd,
+		elf32_arm_nacl_plt0_entry[0]
+		| arm_movw_immediate (got_displacement),
+		plt->contents + 0);
+  put_arm_insn (htab, output_bfd,
+		elf32_arm_nacl_plt0_entry[1]
+		| arm_movt_immediate (got_displacement),
+		plt->contents + 4);
+
+  for (i = 2; i < ARRAY_SIZE (elf32_arm_nacl_plt0_entry); ++i)
+    put_arm_insn (htab, output_bfd,
+		  elf32_arm_nacl_plt0_entry[i],
+		  plt->contents + (i * 4));
+}
+
 /* Finish up the dynamic sections.  */

 static bfd_boolean
@@ -14272,24 +14308,8 @@ elf32_arm_finish_dynamic_sections (bfd *
output_bfd, struct bfd_link_info * info
 				     htab->srelplt2->contents);
 	    }
 	  else if (htab->nacl_p)
-	    {
-	      unsigned int i;
-
-	      got_displacement = got_address + 8 - (plt_address + 16);
-
-	      put_arm_insn (htab, output_bfd,
-			    elf32_arm_nacl_plt0_entry[0]
-			    | arm_movw_immediate (got_displacement),
-			    splt->contents + 0);
-	      put_arm_insn (htab, output_bfd,
-			    elf32_arm_nacl_plt0_entry[1]
-			    | arm_movt_immediate (got_displacement),
-			    splt->contents + 4);
-	      for (i = 2; i < ARRAY_SIZE (elf32_arm_nacl_plt0_entry); ++i)
-		put_arm_insn (htab, output_bfd,
-			      elf32_arm_nacl_plt0_entry[i],
-			      splt->contents + (i * 4));
-	    }
+	    arm_nacl_put_plt0 (htab, output_bfd, splt,
+			       got_address + 8 - (plt_address + 16));
 	  else
 	    {
 	      got_displacement = got_address - (plt_address + 16);
@@ -14382,6 +14402,10 @@ elf32_arm_finish_dynamic_sections (bfd *
output_bfd, struct bfd_link_info * info
 	}
     }

+  if (htab->nacl_p && htab->root.iplt != NULL && htab->root.iplt->size > 0)
+    /* NaCl uses a special first entry in .iplt too.  */
+    arm_nacl_put_plt0 (htab, output_bfd, htab->root.iplt, 0);
+
   /* Fill in the first three entries in the global offset table.  */
   if (sgot)
     {
@@ -14965,6 +14989,15 @@ elf32_arm_output_arch_local_syms (bfd *output_bfd,
 #endif
 	}
     }
+  if (htab->nacl_p && htab->root.iplt && htab->root.iplt->size > 0)
+    {
+      /* NaCl uses a special first entry in .iplt too.  */
+      osi.sec = htab->root.iplt;
+      osi.sec_shndx = (_bfd_elf_section_from_bfd_section
+		       (output_bfd, osi.sec->output_section));
+      if (!elf32_arm_output_map_sym (&osi, ARM_MAP_ARM, 0))
+	return FALSE;
+    }
   if ((htab->root.splt && htab->root.splt->size > 0)
       || (htab->root.iplt && htab->root.iplt->size > 0))
     {



More information about the Binutils mailing list