This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] parameterize elf64-x86-64 PLT generation


This changes the elf64-x86-64 backend to parameterize the details
of PLT generation using the arch_data member of struct elf_backend_data.
This is quite similar to what I did in elf32-i386, though here I put all
the PLT stuff directly in the new struct elf_x86_64_backend_data rather
than having it point to another struct of PLT-related parameters, since
there is nothing else to put there.

Once this goes in, I will have elf64-x86-64-nacl backend support that
takes advantage of the flexibility to define its PLT details differently.

Ok for trunk?


Thanks,
Roland


bfd/
	* elf64-x86-64.c (struct elf_x86_64_backend_data): New type.
	(get_elf_x86_64_backend_data, GET_PLT_ENTRY_SIZE): New macros.
	(elf_x86_64_arch_bed): New variable.
	(elf_backend_arch_data): New macro.
	(elf_x86_64_adjust_dynamic_symbol): Use GET_PLT_ENTRY_SIZE.
	(elf_x86_64_allocate_dynrelocs): Likewise.
	(elf_x86_64_relocate_section): Likewise.
	(elf_x86_64_plt_sym_val): Likewise.
	(elf_x86_64_finish_dynamic_symbol): Use elf_x86_64_backend_data
	parameters for PLT details.
	(elf_x86_64_finish_dynamic_sections): Likewise.

diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 88c47f9..280d6dc 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -585,6 +585,70 @@ static const bfd_byte elf_x86_64_eh_frame_plt[] =
   DW_CFA_nop, DW_CFA_nop, DW_CFA_nop, DW_CFA_nop
 };
 
+/* Architecture-specific backend data for x86-64.  */
+
+struct elf_x86_64_backend_data
+{
+  /* Templates for the initial PLT entry and for subsequent entries.  */
+  const bfd_byte *plt0_entry;
+  const bfd_byte *plt_entry;
+  unsigned int plt_entry_size;          /* Size of each PLT entry.  */
+
+  /* Offsets into plt0_entry that are to be replaced with GOT[1] and GOT[2].  */
+  unsigned int plt0_got1_offset;
+  unsigned int plt0_got2_offset;
+
+  /* Offset of the end of the PC-relative instruction containing
+     plt0_got2_offset.  */
+  unsigned int plt0_got2_insn_end;
+
+  /* Offsets into plt_entry that are to be replaced with...  */
+  unsigned int plt_got_offset;    /* ... address of this symbol in .got. */
+  unsigned int plt_reloc_offset;  /* ... offset into relocation table. */
+  unsigned int plt_plt_offset;    /* ... offset to start of .plt. */
+
+  /* Length of the PC-relative instruction containing plt_got_offset.  */
+  unsigned int plt_got_insn_size;
+
+  /* Offset of the end of the PC-relative jump to plt0_entry.  */
+  unsigned int plt_plt_insn_end;
+
+  /* Offset into plt_entry where the initial value of the GOT entry points.  */
+  unsigned int plt_lazy_offset;
+
+  /* .eh_frame covering the .plt section.  */
+  const bfd_byte *eh_frame_plt;
+  unsigned int eh_frame_plt_size;
+};
+
+#define get_elf_x86_64_backend_data(abfd) \
+  ((const struct elf_x86_64_backend_data *) \
+   get_elf_backend_data (abfd)->arch_data)
+
+#define GET_PLT_ENTRY_SIZE(abfd) \
+  get_elf_x86_64_backend_data (abfd)->plt_entry_size
+
+/* These are the standard parameters.  */
+static const struct elf_x86_64_backend_data elf_x86_64_arch_bed =
+  {
+    elf_x86_64_plt0_entry,              /* plt0_entry */
+    elf_x86_64_plt_entry,               /* plt_entry */
+    sizeof (elf_x86_64_plt_entry),      /* plt_entry_size */
+    2,                                  /* plt0_got1_offset */
+    8,                                  /* plt0_got2_offset */
+    12,                                 /* plt0_got2_insn_end */
+    2,                                  /* plt_got_offset */
+    7,                                  /* plt_reloc_offset */
+    12,                                 /* plt_plt_offset */
+    6,                                  /* plt_got_insn_size */
+    PLT_ENTRY_SIZE,                     /* plt_plt_insn_end */
+    6,                                  /* plt_lazy_offset */
+    elf_x86_64_eh_frame_plt,            /* eh_frame_plt */
+    sizeof (elf_x86_64_eh_frame_plt),   /* eh_frame_plt_size */
+  };
+
+#define	elf_backend_arch_data	&elf_x86_64_arch_bed
+
 /* x86-64 ELF linker hash entry.  */
 
 struct elf_x86_64_link_hash_entry
@@ -2207,6 +2271,7 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
   struct elf_x86_64_link_hash_entry *eh;
   struct elf_dyn_relocs *p;
   const struct elf_backend_data *bed;
+  unsigned int plt_entry_size;
 
   if (h->root.type == bfd_link_hash_indirect)
     return TRUE;
@@ -2218,6 +2283,7 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
   if (htab == NULL)
     return FALSE;
   bed = get_elf_backend_data (info->output_bfd);
+  plt_entry_size = GET_PLT_ENTRY_SIZE (info->output_bfd);
 
   /* Since STT_GNU_IFUNC symbol must go through PLT, we handle it
      here if it is defined and referenced in a non-shared object.  */
@@ -2225,7 +2291,7 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
       && h->def_regular)
     return _bfd_elf_allocate_ifunc_dyn_relocs (info, h,
 					       &eh->dyn_relocs,
-					       PLT_ENTRY_SIZE,
+					       plt_entry_size,
 					       GOT_ENTRY_SIZE);
   else if (htab->elf.dynamic_sections_created
 	   && h->plt.refcount > 0)
@@ -2247,7 +2313,7 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
 	  /* If this is the first .plt entry, make room for the special
 	     first entry.  */
 	  if (s->size == 0)
-	    s->size += PLT_ENTRY_SIZE;
+	    s->size += plt_entry_size;
 
 	  h->plt.offset = s->size;
 
@@ -2264,7 +2330,7 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
 	    }
 
 	  /* Make room for this entry.  */
-	  s->size += PLT_ENTRY_SIZE;
+	  s->size += plt_entry_size;
 
 	  /* We also need to make an entry in the .got.plt section, which
 	     will be placed in the .got section by the linker script.  */
@@ -2688,9 +2754,9 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd,
 	  /* Reserve room for the initial entry.
 	     FIXME: we could probably do away with it in this case.  */
 	  if (htab->elf.splt->size == 0)
-	    htab->elf.splt->size += PLT_ENTRY_SIZE;
+	    htab->elf.splt->size += GET_PLT_ENTRY_SIZE (output_bfd);
 	  htab->tlsdesc_plt = htab->elf.splt->size;
-	  htab->elf.splt->size += PLT_ENTRY_SIZE;
+	  htab->elf.splt->size += GET_PLT_ENTRY_SIZE (output_bfd);
 	}
     }
 
@@ -2981,6 +3047,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
   bfd_vma *local_tlsdesc_gotents;
   Elf_Internal_Rela *rel;
   Elf_Internal_Rela *relend;
+  const unsigned int plt_entry_size = GET_PLT_ENTRY_SIZE (info->output_bfd);
 
   BFD_ASSERT (is_x86_64_elf (input_bfd));
 
@@ -3211,13 +3278,13 @@ elf_x86_64_relocate_section (bfd *output_bfd,
 
 		  if (htab->elf.splt != NULL)
 		    {
-		      plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1;
+		      plt_index = h->plt.offset / plt_entry_size - 1;
 		      off = (plt_index + 3) * GOT_ENTRY_SIZE;
 		      base_got = htab->elf.sgotplt;
 		    }
 		  else
 		    {
-		      plt_index = h->plt.offset / PLT_ENTRY_SIZE;
+		      plt_index = h->plt.offset / plt_entry_size;
 		      off = plt_index * GOT_ENTRY_SIZE;
 		      base_got = htab->elf.igotplt;
 		    }
@@ -3291,7 +3358,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
 		     state, or even just remember the offset, as
 		     finish_dynamic_symbol would use that as offset into
 		     .got.  */
-		  bfd_vma plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1;
+		  bfd_vma plt_index = h->plt.offset / plt_entry_size - 1;
 		  off = (plt_index + 3) * GOT_ENTRY_SIZE;
 		  base_got = htab->elf.sgotplt;
 		}
@@ -4154,6 +4221,8 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
 				  Elf_Internal_Sym *sym)
 {
   struct elf_x86_64_link_hash_table *htab;
+  const struct elf_x86_64_backend_data *const abed
+    = get_elf_x86_64_backend_data (output_bfd);
 
   htab = elf_x86_64_hash_table (info);
   if (htab == NULL)
@@ -4207,24 +4276,23 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
 
       if (plt == htab->elf.splt)
 	{
-	  got_offset = h->plt.offset / PLT_ENTRY_SIZE - 1;
+	  got_offset = h->plt.offset / abed->plt_entry_size - 1;
 	  got_offset = (got_offset + 3) * GOT_ENTRY_SIZE;
 	}
       else
 	{
-	  got_offset = h->plt.offset / PLT_ENTRY_SIZE;
+	  got_offset = h->plt.offset / abed->plt_entry_size;
 	  got_offset = got_offset * GOT_ENTRY_SIZE;
 	}
 
       /* Fill in the entry in the procedure linkage table.  */
-      memcpy (plt->contents + h->plt.offset, elf_x86_64_plt_entry,
-	      PLT_ENTRY_SIZE);
-
-      /* Insert the relocation positions of the plt section.  The magic
-	 numbers at the end of the statements are the positions of the
-	 relocations in the plt section.  */
-      /* Put offset for jmp *name@GOTPCREL(%rip), since the
-	 instruction uses 6 bytes, subtract this value.  */
+      memcpy (plt->contents + h->plt.offset, abed->plt_entry,
+	      abed->plt_entry_size);
+
+      /* Insert the relocation positions of the plt section.  */
+
+      /* Put offset the PC-relative instruction referring to the GOT entry,
+         subtracting the size of that instruction.  */
       bfd_put_32 (output_bfd,
 		      (gotplt->output_section->vma
 		       + gotplt->output_offset
@@ -4232,14 +4300,14 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
 		       - plt->output_section->vma
 		       - plt->output_offset
 		       - h->plt.offset
-		       - 6),
-		  plt->contents + h->plt.offset + 2);
+                   - abed->plt_got_insn_size),
+		  plt->contents + h->plt.offset + abed->plt_got_offset);
 
       /* Fill in the entry in the global offset table, initially this
-	 points to the pushq instruction in the PLT which is at offset 6.  */
+	 points to the second part of the PLT entry.  */
       bfd_put_64 (output_bfd, (plt->output_section->vma
 			       + plt->output_offset
-			       + h->plt.offset + 6),
+			       + h->plt.offset + abed->plt_lazy_offset),
 		  gotplt->contents + got_offset);
 
       /* Fill in the entry in the .rela.plt section.  */
@@ -4273,10 +4341,10 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
 	{
 	  /* Put relocation index.  */
 	  bfd_put_32 (output_bfd, plt_index,
-		      plt->contents + h->plt.offset + 7);
+		      plt->contents + h->plt.offset + abed->plt_reloc_offset);
 	  /* Put offset for jmp .PLT0.  */
-	  bfd_put_32 (output_bfd, - (h->plt.offset + PLT_ENTRY_SIZE),
-		      plt->contents + h->plt.offset + 12);
+	  bfd_put_32 (output_bfd, - (h->plt.offset + abed->plt_plt_insn_end),
+		      plt->contents + h->plt.offset + abed->plt_plt_offset);
 	}
 
       bed = get_elf_backend_data (output_bfd);
@@ -4442,6 +4510,8 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd,
   struct elf_x86_64_link_hash_table *htab;
   bfd *dynobj;
   asection *sdyn;
+  const struct elf_x86_64_backend_data *const abed
+    = get_elf_x86_64_backend_data (output_bfd);
 
   htab = elf_x86_64_hash_table (info);
   if (htab == NULL)
@@ -4524,8 +4594,8 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd,
       if (htab->elf.splt && htab->elf.splt->size > 0)
 	{
 	  /* Fill in the first entry in the procedure linkage table.  */
-	  memcpy (htab->elf.splt->contents, elf_x86_64_plt0_entry,
-		  PLT_ENTRY_SIZE);
+	  memcpy (htab->elf.splt->contents,
+                  abed->plt0_entry, abed->plt_entry_size);
 	  /* Add offset for pushq GOT+8(%rip), since the instruction
 	     uses 6 bytes subtract this value.  */
 	  bfd_put_32 (output_bfd,
@@ -4535,20 +4605,20 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd,
 		       - htab->elf.splt->output_section->vma
 		       - htab->elf.splt->output_offset
 		       - 6),
-		      htab->elf.splt->contents + 2);
-	  /* Add offset for jmp *GOT+16(%rip). The 12 is the offset to
-	     the end of the instruction.  */
+		      htab->elf.splt->contents + abed->plt0_got1_offset);
+	  /* Add offset for the PC-relative instruction accessing GOT+16,
+             subtracting the offset to the end of that instruction.  */
 	  bfd_put_32 (output_bfd,
 		      (htab->elf.sgotplt->output_section->vma
 		       + htab->elf.sgotplt->output_offset
 		       + 16
 		       - htab->elf.splt->output_section->vma
 		       - htab->elf.splt->output_offset
-		       - 12),
-		      htab->elf.splt->contents + 8);
+		       - abed->plt0_got2_insn_end),
+		      htab->elf.splt->contents + abed->plt0_got2_offset);
 
-	  elf_section_data (htab->elf.splt->output_section)->this_hdr.sh_entsize =
-	    PLT_ENTRY_SIZE;
+	  elf_section_data (htab->elf.splt->output_section)
+            ->this_hdr.sh_entsize = abed->plt_entry_size;
 
 	  if (htab->tlsdesc_plt)
 	    {
@@ -4556,8 +4626,7 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd,
 			  htab->elf.sgot->contents + htab->tlsdesc_got);
 
 	      memcpy (htab->elf.splt->contents + htab->tlsdesc_plt,
-		      elf_x86_64_plt0_entry,
-		      PLT_ENTRY_SIZE);
+		      abed->plt0_entry, abed->plt_entry_size);
 
 	      /* Add offset for pushq GOT+8(%rip), since the
 		 instruction uses 6 bytes subtract this value.  */
@@ -4569,10 +4638,11 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd,
 			   - htab->elf.splt->output_offset
 			   - htab->tlsdesc_plt
 			   - 6),
-			  htab->elf.splt->contents + htab->tlsdesc_plt + 2);
-	      /* Add offset for jmp *GOT+TDG(%rip), where TGD stands for
-		 htab->tlsdesc_got. The 12 is the offset to the end of
-		 the instruction.  */
+			  htab->elf.splt->contents
+                          + htab->tlsdesc_plt + abed->plt0_got1_offset);
+	  /* Add offset for the PC-relative instruction accessing GOT+TDG,
+             where TGD stands for htab->tlsdesc_got, subtracting the offset
+             to the end of that instruction.  */
 	      bfd_put_32 (output_bfd,
 			  (htab->elf.sgot->output_section->vma
 			   + htab->elf.sgot->output_offset
@@ -4580,8 +4650,9 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd,
 			   - htab->elf.splt->output_section->vma
 			   - htab->elf.splt->output_offset
 			   - htab->tlsdesc_plt
-			   - 12),
-			  htab->elf.splt->contents + htab->tlsdesc_plt + 8);
+			   - abed->plt0_got2_insn_end),
+			  htab->elf.splt->contents
+                          + htab->tlsdesc_plt + abed->plt0_got2_offset);
 	    }
 	}
     }
@@ -4661,7 +4732,7 @@ static bfd_vma
 elf_x86_64_plt_sym_val (bfd_vma i, const asection *plt,
 			const arelent *rel ATTRIBUTE_UNUSED)
 {
-  return plt->vma + (i + 1) * PLT_ENTRY_SIZE;
+  return plt->vma + (i + 1) * GET_PLT_ENTRY_SIZE (plt->owner);
 }
 
 /* Handle an x86-64 specific section when reading an object file.  This


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]