This is the mail archive of the binutils-cvs@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]

[binutils-gdb] x86: Add _bfd_x86_elf_finish_dynamic_sections


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=9577f60b5a19ce93536f49cba3af4be39e39c327

commit 9577f60b5a19ce93536f49cba3af4be39e39c327
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Sat Oct 14 11:29:58 2017 -0700

    x86: Add _bfd_x86_elf_finish_dynamic_sections
    
    Extract the common parts of elf_i386_finish_dynamic_sections and
    elf_x86_64_finish_dynamic_sections into a separate function in
    elfxx-x86.c.
    
    	* elf32-i386.c (elf_i386_finish_dynamic_sections): Call
    	_bfd_x86_elf_finish_dynamic_sections.
    	* elf64-x86-64.c (elf_x86_64_finish_dynamic_sections): Likewise.
    	* elfxx-x86.c (_bfd_x86_elf_finish_dynamic_sections): New
    	function.
    	* elfxx-x86.h (_bfd_x86_elf_finish_dynamic_sections): New
    	prototype.

Diff:
---
 bfd/ChangeLog      |  10 ++
 bfd/elf32-i386.c   | 308 ++++++++++++--------------------------------------
 bfd/elf64-x86-64.c | 324 ++++++++++++-----------------------------------------
 bfd/elfxx-x86.c    | 218 +++++++++++++++++++++++++++++++++++
 bfd/elfxx-x86.h    |   3 +
 5 files changed, 376 insertions(+), 487 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 5f3fb8c..474572f 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,15 @@
 2017-10-14  H.J. Lu  <hongjiu.lu@intel.com>
 
+	* elf32-i386.c (elf_i386_finish_dynamic_sections): Call
+	_bfd_x86_elf_finish_dynamic_sections.
+	* elf64-x86-64.c (elf_x86_64_finish_dynamic_sections): Likewise.
+	* elfxx-x86.c (_bfd_x86_elf_finish_dynamic_sections): New
+	function.
+	* elfxx-x86.h (_bfd_x86_elf_finish_dynamic_sections): New
+	prototype.
+
+2017-10-14  H.J. Lu  <hongjiu.lu@intel.com>
+
 	PR ld/21384
 	* elf32-cris.c (elf_cris_discard_excess_program_dynamics): Don't
 	hide symbol which was forced to be dynamic.
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index cf2e43f..166ca9d 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -4012,262 +4012,102 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd,
 				  struct bfd_link_info *info)
 {
   struct elf_x86_link_hash_table *htab;
-  bfd *dynobj;
-  asection *sdyn;
-  const struct elf_i386_backend_data *abed;
 
-  htab = elf_x86_hash_table (info, I386_ELF_DATA);
+  htab = _bfd_x86_elf_finish_dynamic_sections (output_bfd, info);
   if (htab == NULL)
     return FALSE;
 
-  dynobj = htab->elf.dynobj;
-  sdyn = bfd_get_linker_section (dynobj, ".dynamic");
-  abed = get_elf_i386_backend_data (output_bfd);
+  if (!htab->elf.dynamic_sections_created)
+    return TRUE;
 
-  if (htab->elf.dynamic_sections_created)
+  if (htab->elf.splt && htab->elf.splt->size > 0)
     {
-      Elf32_External_Dyn *dyncon, *dynconend;
+      /* UnixWare sets the entsize of .plt to 4, although that doesn't
+	 really seem like the right value.  */
+      elf_section_data (htab->elf.splt->output_section)
+	->this_hdr.sh_entsize = 4;
 
-      if (sdyn == NULL || htab->elf.sgot == NULL)
-	abort ();
-
-      dyncon = (Elf32_External_Dyn *) sdyn->contents;
-      dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size);
-      for (; dyncon < dynconend; dyncon++)
+      if (htab->plt.has_plt0)
 	{
-	  Elf_Internal_Dyn dyn;
-	  asection *s;
-
-	  bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
-
-	  switch (dyn.d_tag)
+	  /* Fill in the special first entry in the procedure linkage
+	     table.  */
+	  const struct elf_i386_backend_data *abed
+	    = get_elf_i386_backend_data (output_bfd);
+
+	  memcpy (htab->elf.splt->contents, htab->plt.plt0_entry,
+		  htab->lazy_plt->plt0_entry_size);
+	  memset (htab->elf.splt->contents + htab->lazy_plt->plt0_entry_size,
+		  abed->plt0_pad_byte,
+		  htab->plt.plt_entry_size - htab->lazy_plt->plt0_entry_size);
+	  if (!bfd_link_pic (info))
 	    {
-	    default:
-	      if (htab->is_vxworks
-                  && elf_vxworks_finish_dynamic_entry (output_bfd, &dyn))
-		break;
-	      continue;
-
-	    case DT_PLTGOT:
-	      s = htab->elf.sgotplt;
-	      dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
-	      break;
-
-	    case DT_JMPREL:
-	      s = htab->elf.srelplt;
-	      dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
-	      break;
-
-	    case DT_PLTRELSZ:
-	      s = htab->elf.srelplt;
-	      dyn.d_un.d_val = s->size;
-	      break;
-	    }
-
-	  bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
-	}
-
-      if (htab->elf.splt && htab->elf.splt->size > 0)
-	{
-	  /* UnixWare sets the entsize of .plt to 4, although that doesn't
-	     really seem like the right value.  */
-	  elf_section_data (htab->elf.splt->output_section)
-	    ->this_hdr.sh_entsize = 4;
+	      bfd_put_32 (output_bfd,
+			  (htab->elf.sgotplt->output_section->vma
+			   + htab->elf.sgotplt->output_offset
+			   + 4),
+			  htab->elf.splt->contents
+			  + htab->lazy_plt->plt0_got1_offset);
+	      bfd_put_32 (output_bfd,
+			  (htab->elf.sgotplt->output_section->vma
+			   + htab->elf.sgotplt->output_offset
+			   + 8),
+			  htab->elf.splt->contents
+			  + htab->lazy_plt->plt0_got2_offset);
 
-	  if (htab->plt.has_plt0)
-	    {
-	      /* Fill in the special first entry in the procedure linkage
-		 table.  */
-	      memcpy (htab->elf.splt->contents, htab->plt.plt0_entry,
-		      htab->lazy_plt->plt0_entry_size);
-	      memset (htab->elf.splt->contents + htab->lazy_plt->plt0_entry_size,
-		      abed->plt0_pad_byte,
-		      htab->plt.plt_entry_size - htab->lazy_plt->plt0_entry_size);
-	      if (!bfd_link_pic (info))
+	      if (htab->is_vxworks)
 		{
-		  bfd_put_32 (output_bfd,
-			      (htab->elf.sgotplt->output_section->vma
-			       + htab->elf.sgotplt->output_offset
-			       + 4),
-			      htab->elf.splt->contents
-			      + htab->lazy_plt->plt0_got1_offset);
-		  bfd_put_32 (output_bfd,
-			      (htab->elf.sgotplt->output_section->vma
-			       + htab->elf.sgotplt->output_offset
-			       + 8),
-			      htab->elf.splt->contents
-			      + htab->lazy_plt->plt0_got2_offset);
+		  Elf_Internal_Rela rel;
+		  int num_plts = (htab->elf.splt->size
+				  / htab->plt.plt_entry_size) - 1;
+		  unsigned char *p;
+		  asection *srelplt2 = htab->srelplt2;
+
+		  /* Generate a relocation for _GLOBAL_OFFSET_TABLE_
+		     + 4.  On IA32 we use REL relocations so the
+		     addend goes in the PLT directly.  */
+		  rel.r_offset = (htab->elf.splt->output_section->vma
+				  + htab->elf.splt->output_offset
+				  + htab->lazy_plt->plt0_got1_offset);
+		  rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx,
+					     R_386_32);
+		  bfd_elf32_swap_reloc_out (output_bfd, &rel,
+					    srelplt2->contents);
+		  /* Generate a relocation for _GLOBAL_OFFSET_TABLE_
+		     + 8.  */
+		  rel.r_offset = (htab->elf.splt->output_section->vma
+				  + htab->elf.splt->output_offset
+				  + htab->lazy_plt->plt0_got2_offset);
+		  rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx,
+					     R_386_32);
+		  bfd_elf32_swap_reloc_out (output_bfd, &rel,
+					    srelplt2->contents +
+					    sizeof (Elf32_External_Rel));
+		  /* Correct the .rel.plt.unloaded relocations.  */
+		  p = srelplt2->contents;
+		  if (bfd_link_pic (info))
+		    p += PLTRESOLVE_RELOCS_SHLIB * sizeof (Elf32_External_Rel);
+		  else
+		    p += PLTRESOLVE_RELOCS * sizeof (Elf32_External_Rel);
 
-		  if (htab->is_vxworks)
+		  for (; num_plts; num_plts--)
 		    {
-		      Elf_Internal_Rela rel;
-		      int num_plts = (htab->elf.splt->size
-				      / htab->plt.plt_entry_size) - 1;
-		      unsigned char *p;
-		      asection *srelplt2 = htab->srelplt2;
-
-		      /* Generate a relocation for _GLOBAL_OFFSET_TABLE_
-			 + 4.  On IA32 we use REL relocations so the
-			 addend goes in the PLT directly.  */
-		      rel.r_offset = (htab->elf.splt->output_section->vma
-				      + htab->elf.splt->output_offset
-				      + htab->lazy_plt->plt0_got1_offset);
-		      rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx,
-						 R_386_32);
-		      bfd_elf32_swap_reloc_out (output_bfd, &rel,
-						srelplt2->contents);
-		      /* Generate a relocation for _GLOBAL_OFFSET_TABLE_
-			 + 8.  */
-		      rel.r_offset = (htab->elf.splt->output_section->vma
-				      + htab->elf.splt->output_offset
-				      + htab->lazy_plt->plt0_got2_offset);
+		      bfd_elf32_swap_reloc_in (output_bfd, p, &rel);
 		      rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx,
 						 R_386_32);
-		      bfd_elf32_swap_reloc_out (output_bfd, &rel,
-						srelplt2->contents +
-						sizeof (Elf32_External_Rel));
-		      /* Correct the .rel.plt.unloaded relocations.  */
-		      p = srelplt2->contents;
-		      if (bfd_link_pic (info))
-			p += PLTRESOLVE_RELOCS_SHLIB * sizeof (Elf32_External_Rel);
-		      else
-			p += PLTRESOLVE_RELOCS * sizeof (Elf32_External_Rel);
+		      bfd_elf32_swap_reloc_out (output_bfd, &rel, p);
+		      p += sizeof (Elf32_External_Rel);
 
-		      for (; num_plts; num_plts--)
-			{
-			  bfd_elf32_swap_reloc_in (output_bfd, p, &rel);
-			  rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx,
-						     R_386_32);
-			  bfd_elf32_swap_reloc_out (output_bfd, &rel, p);
-			  p += sizeof (Elf32_External_Rel);
-
-			  bfd_elf32_swap_reloc_in (output_bfd, p, &rel);
-			  rel.r_info = ELF32_R_INFO (htab->elf.hplt->indx,
-						     R_386_32);
-			  bfd_elf32_swap_reloc_out (output_bfd, &rel, p);
-			  p += sizeof (Elf32_External_Rel);
-			}
+		      bfd_elf32_swap_reloc_in (output_bfd, p, &rel);
+		      rel.r_info = ELF32_R_INFO (htab->elf.hplt->indx,
+						 R_386_32);
+		      bfd_elf32_swap_reloc_out (output_bfd, &rel, p);
+		      p += sizeof (Elf32_External_Rel);
 		    }
 		}
 	    }
 	}
-
-      if (htab->plt_got != NULL && htab->plt_got->size > 0)
-	elf_section_data (htab->plt_got->output_section)
-	  ->this_hdr.sh_entsize = htab->non_lazy_plt->plt_entry_size;
-
-      if (htab->plt_second != NULL && htab->plt_second->size > 0)
-	elf_section_data (htab->plt_second->output_section)
-	  ->this_hdr.sh_entsize = htab->non_lazy_plt->plt_entry_size;
-    }
-
-  /* Fill in the first three entries in the global offset table.  */
-  if (htab->elf.sgotplt && htab->elf.sgotplt->size > 0)
-    {
-      if (bfd_is_abs_section (htab->elf.sgotplt->output_section))
-	{
-	  _bfd_error_handler
-	    (_("discarded output section: `%A'"), htab->elf.sgotplt);
-	  return FALSE;
-	}
-
-      bfd_put_32 (output_bfd,
-		  (sdyn == NULL ? 0
-		   : sdyn->output_section->vma + sdyn->output_offset),
-		  htab->elf.sgotplt->contents);
-      bfd_put_32 (output_bfd, 0, htab->elf.sgotplt->contents + 4);
-      bfd_put_32 (output_bfd, 0, htab->elf.sgotplt->contents + 8);
-
-      elf_section_data (htab->elf.sgotplt->output_section)->this_hdr.sh_entsize = 4;
-    }
-
-  /* Adjust .eh_frame for .plt section.  */
-  if (htab->plt_eh_frame != NULL
-      && htab->plt_eh_frame->contents != NULL)
-    {
-      if (htab->elf.splt != NULL
-	  && htab->elf.splt->size != 0
-	  && (htab->elf.splt->flags & SEC_EXCLUDE) == 0
-	  && htab->elf.splt->output_section != NULL
-	  && htab->plt_eh_frame->output_section != NULL)
-	{
-	  bfd_vma plt_start = htab->elf.splt->output_section->vma;
-	  bfd_vma eh_frame_start = htab->plt_eh_frame->output_section->vma
-				   + htab->plt_eh_frame->output_offset
-				   + PLT_FDE_START_OFFSET;
-	  bfd_put_signed_32 (dynobj, plt_start - eh_frame_start,
-			     htab->plt_eh_frame->contents
-			     + PLT_FDE_START_OFFSET);
-	}
-      if (htab->plt_eh_frame->sec_info_type
-	  == SEC_INFO_TYPE_EH_FRAME)
-	{
-	  if (! _bfd_elf_write_section_eh_frame (output_bfd, info,
-						 htab->plt_eh_frame,
-						 htab->plt_eh_frame->contents))
-	    return FALSE;
-	}
-    }
-
-  /* Adjust .eh_frame for .plt.got section.  */
-  if (htab->plt_got_eh_frame != NULL
-      && htab->plt_got_eh_frame->contents != NULL)
-    {
-      if (htab->plt_got != NULL
-	  && htab->plt_got->size != 0
-	  && (htab->plt_got->flags & SEC_EXCLUDE) == 0
-	  && htab->plt_got->output_section != NULL
-	  && htab->plt_got_eh_frame->output_section != NULL)
-	{
-	  bfd_vma plt_start = htab->plt_got->output_section->vma;
-	  bfd_vma eh_frame_start = htab->plt_got_eh_frame->output_section->vma
-				   + htab->plt_got_eh_frame->output_offset
-				   + PLT_FDE_START_OFFSET;
-	  bfd_put_signed_32 (dynobj, plt_start - eh_frame_start,
-			     htab->plt_got_eh_frame->contents
-			     + PLT_FDE_START_OFFSET);
-	}
-      if (htab->plt_got_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME)
-	{
-	  if (! _bfd_elf_write_section_eh_frame (output_bfd, info,
-						 htab->plt_got_eh_frame,
-						 htab->plt_got_eh_frame->contents))
-	    return FALSE;
-	}
     }
 
-  /* Adjust .eh_frame for the second PLT section.  */
-  if (htab->plt_second_eh_frame != NULL
-      && htab->plt_second_eh_frame->contents != NULL)
-    {
-      if (htab->plt_second != NULL
-	  && htab->plt_second->size != 0
-	  && (htab->plt_second->flags & SEC_EXCLUDE) == 0
-	  && htab->plt_second->output_section != NULL
-	  && htab->plt_second_eh_frame->output_section != NULL)
-	{
-	  bfd_vma plt_start = htab->plt_second->output_section->vma;
-	  bfd_vma eh_frame_start
-	    = (htab->plt_second_eh_frame->output_section->vma
-	       + htab->plt_second_eh_frame->output_offset
-	       + PLT_FDE_START_OFFSET);
-	  bfd_put_signed_32 (dynobj, plt_start - eh_frame_start,
-			     htab->plt_second_eh_frame->contents
-			     + PLT_FDE_START_OFFSET);
-	}
-      if (htab->plt_second_eh_frame->sec_info_type
-	  == SEC_INFO_TYPE_EH_FRAME)
-	{
-	  if (! _bfd_elf_write_section_eh_frame (output_bfd, info,
-						 htab->plt_second_eh_frame,
-						 htab->plt_second_eh_frame->contents))
-	    return FALSE;
-	}
-    }
-
-  if (htab->elf.sgot && htab->elf.sgot->size > 0)
-    elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize = 4;
-
   /* Fill PLT entries for undefined weak symbols in PIE.  */
   if (bfd_link_pie (info))
     bfd_hash_traverse (&info->hash->table,
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index b970146..047e78a 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -4360,273 +4360,91 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd,
 				    struct bfd_link_info *info)
 {
   struct elf_x86_link_hash_table *htab;
-  bfd *dynobj;
-  asection *sdyn;
 
-  htab = elf_x86_hash_table (info, X86_64_ELF_DATA);
+  htab = _bfd_x86_elf_finish_dynamic_sections (output_bfd, info);
   if (htab == NULL)
     return FALSE;
 
-  dynobj = htab->elf.dynobj;
-  sdyn = bfd_get_linker_section (dynobj, ".dynamic");
-
-  if (htab->elf.dynamic_sections_created)
-    {
-      bfd_byte *dyncon, *dynconend;
-      const struct elf_backend_data *bed;
-      bfd_size_type sizeof_dyn;
-
-      if (sdyn == NULL || htab->elf.sgot == NULL)
-	abort ();
-
-      bed = get_elf_backend_data (dynobj);
-      sizeof_dyn = bed->s->sizeof_dyn;
-      dyncon = sdyn->contents;
-      dynconend = sdyn->contents + sdyn->size;
-      for (; dyncon < dynconend; dyncon += sizeof_dyn)
-	{
-	  Elf_Internal_Dyn dyn;
-	  asection *s;
-
-	  (*bed->s->swap_dyn_in) (dynobj, dyncon, &dyn);
-
-	  switch (dyn.d_tag)
-	    {
-	    default:
-	      continue;
-
-	    case DT_PLTGOT:
-	      s = htab->elf.sgotplt;
-	      dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
-	      break;
-
-	    case DT_JMPREL:
-	      dyn.d_un.d_ptr = htab->elf.srelplt->output_section->vma;
-	      break;
-
-	    case DT_PLTRELSZ:
-	      s = htab->elf.srelplt->output_section;
-	      dyn.d_un.d_val = s->size;
-	      break;
-
-	    case DT_TLSDESC_PLT:
-	      s = htab->elf.splt;
-	      dyn.d_un.d_ptr = s->output_section->vma + s->output_offset
-		+ htab->tlsdesc_plt;
-	      break;
-
-	    case DT_TLSDESC_GOT:
-	      s = htab->elf.sgot;
-	      dyn.d_un.d_ptr = s->output_section->vma + s->output_offset
-		+ htab->tlsdesc_got;
-	      break;
-	    }
-
-	  (*bed->s->swap_dyn_out) (output_bfd, &dyn, dyncon);
-	}
-
-      if (htab->elf.splt && htab->elf.splt->size > 0)
-	{
-	  elf_section_data (htab->elf.splt->output_section)
-	    ->this_hdr.sh_entsize = htab->plt.plt_entry_size;
-
-	  if (htab->plt.has_plt0)
-	    {
-	      /* Fill in the special first entry in the procedure linkage
-		 table.  */
-	      memcpy (htab->elf.splt->contents,
-		      htab->lazy_plt->plt0_entry,
-		      htab->lazy_plt->plt0_entry_size);
-	      /* Add offset for pushq GOT+8(%rip), since the instruction
-		 uses 6 bytes subtract this value.  */
-	      bfd_put_32 (output_bfd,
-			  (htab->elf.sgotplt->output_section->vma
-			   + htab->elf.sgotplt->output_offset
-			   + 8
-			   - htab->elf.splt->output_section->vma
-			   - htab->elf.splt->output_offset
-			   - 6),
-			  (htab->elf.splt->contents
-			   + htab->lazy_plt->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
-			   - htab->lazy_plt->plt0_got2_insn_end),
-			  (htab->elf.splt->contents
-			   + htab->lazy_plt->plt0_got2_offset));
-
-	      if (htab->tlsdesc_plt)
-		{
-		  bfd_put_64 (output_bfd, (bfd_vma) 0,
-			      htab->elf.sgot->contents + htab->tlsdesc_got);
-
-		  memcpy (htab->elf.splt->contents + htab->tlsdesc_plt,
-			  htab->lazy_plt->plt0_entry,
-			  htab->lazy_plt->plt0_entry_size);
-
-		  /* Add offset for pushq GOT+8(%rip), since the
-		     instruction uses 6 bytes subtract this value.  */
-		  bfd_put_32 (output_bfd,
-			      (htab->elf.sgotplt->output_section->vma
-			       + htab->elf.sgotplt->output_offset
-			       + 8
-			       - htab->elf.splt->output_section->vma
-			       - htab->elf.splt->output_offset
-			       - htab->tlsdesc_plt
-			       - 6),
-			      (htab->elf.splt->contents
-			       + htab->tlsdesc_plt
-			       + htab->lazy_plt->plt0_got1_offset));
-		  /* Add offset for the PC-relative instruction accessing
-		     GOT+TDG, where TDG 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
-			       + htab->tlsdesc_got
-			       - htab->elf.splt->output_section->vma
-			       - htab->elf.splt->output_offset
-			       - htab->tlsdesc_plt
-			       - htab->lazy_plt->plt0_got2_insn_end),
-			      (htab->elf.splt->contents
-			       + htab->tlsdesc_plt
-			       + htab->lazy_plt->plt0_got2_offset));
-		}
-	    }
-	}
-
-      if (htab->plt_got != NULL && htab->plt_got->size > 0)
-	elf_section_data (htab->plt_got->output_section)
-	  ->this_hdr.sh_entsize = htab->non_lazy_plt->plt_entry_size;
-
-      if (htab->plt_second != NULL && htab->plt_second->size > 0)
-	elf_section_data (htab->plt_second->output_section)
-	  ->this_hdr.sh_entsize = htab->non_lazy_plt->plt_entry_size;
-    }
-
-  /* GOT is always created in setup_gnu_properties.  But it may not be
-     needed.  */
-  if (htab->elf.sgotplt && htab->elf.sgotplt->size > 0)
-    {
-      if (bfd_is_abs_section (htab->elf.sgotplt->output_section))
-	{
-	  _bfd_error_handler
-	    (_("discarded output section: `%A'"), htab->elf.sgotplt);
-	  return FALSE;
-	}
-
-      /* Set the first entry in the global offset table to the address of
-	 the dynamic section.  */
-      if (sdyn == NULL)
-	bfd_put_64 (output_bfd, (bfd_vma) 0, htab->elf.sgotplt->contents);
-      else
-	bfd_put_64 (output_bfd,
-		    sdyn->output_section->vma + sdyn->output_offset,
-		    htab->elf.sgotplt->contents);
-      /* Write GOT[1] and GOT[2], needed for the dynamic linker.  */
-      bfd_put_64 (output_bfd, (bfd_vma) 0,
-		  htab->elf.sgotplt->contents + GOT_ENTRY_SIZE);
-      bfd_put_64 (output_bfd, (bfd_vma) 0,
-		  htab->elf.sgotplt->contents + GOT_ENTRY_SIZE*2);
-
-      elf_section_data (htab->elf.sgotplt->output_section)->this_hdr.sh_entsize
-	= GOT_ENTRY_SIZE;
-    }
+  if (! htab->elf.dynamic_sections_created)
+    return TRUE;
 
-  /* Adjust .eh_frame for .plt section.  */
-  if (htab->plt_eh_frame != NULL
-      && htab->plt_eh_frame->contents != NULL)
+  if (htab->elf.splt && htab->elf.splt->size > 0)
     {
-      if (htab->elf.splt != NULL
-	  && htab->elf.splt->size != 0
-	  && (htab->elf.splt->flags & SEC_EXCLUDE) == 0
-	  && htab->elf.splt->output_section != NULL
-	  && htab->plt_eh_frame->output_section != NULL)
-	{
-	  bfd_vma plt_start = htab->elf.splt->output_section->vma;
-	  bfd_vma eh_frame_start = htab->plt_eh_frame->output_section->vma
-				   + htab->plt_eh_frame->output_offset
-				   + PLT_FDE_START_OFFSET;
-	  bfd_put_signed_32 (dynobj, plt_start - eh_frame_start,
-			     htab->plt_eh_frame->contents
-			     + PLT_FDE_START_OFFSET);
-	}
-      if (htab->plt_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME)
-	{
-	  if (! _bfd_elf_write_section_eh_frame (output_bfd, info,
-						 htab->plt_eh_frame,
-						 htab->plt_eh_frame->contents))
-	    return FALSE;
-	}
-    }
+      elf_section_data (htab->elf.splt->output_section)
+	->this_hdr.sh_entsize = htab->plt.plt_entry_size;
 
-  /* Adjust .eh_frame for .plt.got section.  */
-  if (htab->plt_got_eh_frame != NULL
-      && htab->plt_got_eh_frame->contents != NULL)
-    {
-      if (htab->plt_got != NULL
-	  && htab->plt_got->size != 0
-	  && (htab->plt_got->flags & SEC_EXCLUDE) == 0
-	  && htab->plt_got->output_section != NULL
-	  && htab->plt_got_eh_frame->output_section != NULL)
+      if (htab->plt.has_plt0)
 	{
-	  bfd_vma plt_start = htab->plt_got->output_section->vma;
-	  bfd_vma eh_frame_start = htab->plt_got_eh_frame->output_section->vma
-				   + htab->plt_got_eh_frame->output_offset
-				   + PLT_FDE_START_OFFSET;
-	  bfd_put_signed_32 (dynobj, plt_start - eh_frame_start,
-			     htab->plt_got_eh_frame->contents
-			     + PLT_FDE_START_OFFSET);
-	}
-      if (htab->plt_got_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME)
-	{
-	  if (! _bfd_elf_write_section_eh_frame (output_bfd, info,
-						 htab->plt_got_eh_frame,
-						 htab->plt_got_eh_frame->contents))
-	    return FALSE;
+	  /* Fill in the special first entry in the procedure linkage
+	     table.  */
+	  memcpy (htab->elf.splt->contents,
+		  htab->lazy_plt->plt0_entry,
+		  htab->lazy_plt->plt0_entry_size);
+	  /* Add offset for pushq GOT+8(%rip), since the instruction
+	     uses 6 bytes subtract this value.  */
+	  bfd_put_32 (output_bfd,
+		      (htab->elf.sgotplt->output_section->vma
+		       + htab->elf.sgotplt->output_offset
+		       + 8
+		       - htab->elf.splt->output_section->vma
+		       - htab->elf.splt->output_offset
+		       - 6),
+		      (htab->elf.splt->contents
+		       + htab->lazy_plt->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
+		       - htab->lazy_plt->plt0_got2_insn_end),
+		      (htab->elf.splt->contents
+		       + htab->lazy_plt->plt0_got2_offset));
 	}
-    }
 
-  /* Adjust .eh_frame for the second PLT section.  */
-  if (htab->plt_second_eh_frame != NULL
-      && htab->plt_second_eh_frame->contents != NULL)
-    {
-      if (htab->plt_second != NULL
-	  && htab->plt_second->size != 0
-	  && (htab->plt_second->flags & SEC_EXCLUDE) == 0
-	  && htab->plt_second->output_section != NULL
-	  && htab->plt_second_eh_frame->output_section != NULL)
-	{
-	  bfd_vma plt_start = htab->plt_second->output_section->vma;
-	  bfd_vma eh_frame_start
-	    = (htab->plt_second_eh_frame->output_section->vma
-	       + htab->plt_second_eh_frame->output_offset
-	       + PLT_FDE_START_OFFSET);
-	  bfd_put_signed_32 (dynobj, plt_start - eh_frame_start,
-			     htab->plt_second_eh_frame->contents
-			     + PLT_FDE_START_OFFSET);
-	}
-      if (htab->plt_second_eh_frame->sec_info_type
-	  == SEC_INFO_TYPE_EH_FRAME)
+      if (htab->tlsdesc_plt)
 	{
-	  if (! _bfd_elf_write_section_eh_frame (output_bfd, info,
-						 htab->plt_second_eh_frame,
-						 htab->plt_second_eh_frame->contents))
-	    return FALSE;
+	  bfd_put_64 (output_bfd, (bfd_vma) 0,
+		      htab->elf.sgot->contents + htab->tlsdesc_got);
+
+	  memcpy (htab->elf.splt->contents + htab->tlsdesc_plt,
+		  htab->lazy_plt->plt0_entry,
+		  htab->lazy_plt->plt0_entry_size);
+
+	  /* Add offset for pushq GOT+8(%rip), since the
+	     instruction uses 6 bytes subtract this value.  */
+	  bfd_put_32 (output_bfd,
+		      (htab->elf.sgotplt->output_section->vma
+		       + htab->elf.sgotplt->output_offset
+		       + 8
+		       - htab->elf.splt->output_section->vma
+		       - htab->elf.splt->output_offset
+		       - htab->tlsdesc_plt
+		       - 6),
+		      (htab->elf.splt->contents
+		       + htab->tlsdesc_plt
+		       + htab->lazy_plt->plt0_got1_offset));
+	  /* Add offset for the PC-relative instruction accessing
+	     GOT+TDG, where TDG 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
+		       + htab->tlsdesc_got
+		       - htab->elf.splt->output_section->vma
+		       - htab->elf.splt->output_offset
+		       - htab->tlsdesc_plt
+		       - htab->lazy_plt->plt0_got2_insn_end),
+		      (htab->elf.splt->contents
+		       + htab->tlsdesc_plt
+		       + htab->lazy_plt->plt0_got2_offset));
 	}
     }
 
-  if (htab->elf.sgot && htab->elf.sgot->size > 0)
-    elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize
-      = GOT_ENTRY_SIZE;
-
   /* Fill PLT entries for undefined weak symbols in PIE.  */
   if (bfd_link_pie (info))
     bfd_hash_traverse (&info->hash->table,
diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c
index dd139ca..1aad33f 100644
--- a/bfd/elfxx-x86.c
+++ b/bfd/elfxx-x86.c
@@ -1294,6 +1294,224 @@ _bfd_x86_elf_size_dynamic_sections (bfd *output_bfd,
   return TRUE;
 }
 
+/* Finish up the x86 dynamic sections.  */
+
+struct elf_x86_link_hash_table *
+_bfd_x86_elf_finish_dynamic_sections (bfd *output_bfd,
+				      struct bfd_link_info *info)
+{
+  struct elf_x86_link_hash_table *htab;
+  const struct elf_backend_data *bed;
+  bfd *dynobj;
+  asection *sdyn;
+  bfd_byte *dyncon, *dynconend;
+  bfd_size_type sizeof_dyn;
+
+  bed = get_elf_backend_data (output_bfd);
+  htab = elf_x86_hash_table (info, bed->target_id);
+  if (htab == NULL)
+    return htab;
+
+  dynobj = htab->elf.dynobj;
+  sdyn = bfd_get_linker_section (dynobj, ".dynamic");
+
+  /* GOT is always created in setup_gnu_properties.  But it may not be
+     needed.  .got.plt section may be needed for static IFUNC.  */
+  if (htab->elf.sgotplt && htab->elf.sgotplt->size > 0)
+    {
+      bfd_vma dynamic_addr;
+
+      if (bfd_is_abs_section (htab->elf.sgotplt->output_section))
+	{
+	  _bfd_error_handler
+	    (_("discarded output section: `%A'"), htab->elf.sgotplt);
+	  return NULL;
+	}
+
+      elf_section_data (htab->elf.sgotplt->output_section)->this_hdr.sh_entsize
+	= htab->got_entry_size;
+
+      dynamic_addr = (sdyn == NULL
+		      ? (bfd_vma) 0
+		      : sdyn->output_section->vma + sdyn->output_offset);
+
+      /* Set the first entry in the global offset table to the address
+         of the dynamic section.  Write GOT[1] and GOT[2], needed for
+	 the dynamic linker.  */
+      if (htab->got_entry_size == 8)
+	{
+	  bfd_put_64 (output_bfd, dynamic_addr,
+		      htab->elf.sgotplt->contents);
+	  bfd_put_64 (output_bfd, (bfd_vma) 0,
+		      htab->elf.sgotplt->contents + 8);
+	  bfd_put_64 (output_bfd, (bfd_vma) 0,
+		      htab->elf.sgotplt->contents + 8*2);
+	}
+      else
+	{
+	  bfd_put_32 (output_bfd, dynamic_addr,
+		      htab->elf.sgotplt->contents);
+	  bfd_put_32 (output_bfd, 0,
+		      htab->elf.sgotplt->contents + 4);
+	  bfd_put_32 (output_bfd, 0,
+		      htab->elf.sgotplt->contents + 4*2);
+	}
+    }
+
+  if (!htab->elf.dynamic_sections_created)
+    return htab;
+
+  if (sdyn == NULL || htab->elf.sgot == NULL)
+    abort ();
+
+  sizeof_dyn = bed->s->sizeof_dyn;
+  dyncon = sdyn->contents;
+  dynconend = sdyn->contents + sdyn->size;
+  for (; dyncon < dynconend; dyncon += sizeof_dyn)
+    {
+      Elf_Internal_Dyn dyn;
+      asection *s;
+
+      (*bed->s->swap_dyn_in) (dynobj, dyncon, &dyn);
+
+      switch (dyn.d_tag)
+	{
+	default:
+	  if (htab->is_vxworks
+	      && elf_vxworks_finish_dynamic_entry (output_bfd, &dyn))
+	    break;
+	  continue;
+
+	case DT_PLTGOT:
+	  s = htab->elf.sgotplt;
+	  dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
+	  break;
+
+	case DT_JMPREL:
+	  dyn.d_un.d_ptr = htab->elf.srelplt->output_section->vma;
+	  break;
+
+	case DT_PLTRELSZ:
+	  s = htab->elf.srelplt->output_section;
+	  dyn.d_un.d_val = s->size;
+	  break;
+
+	case DT_TLSDESC_PLT:
+	  s = htab->elf.splt;
+	  dyn.d_un.d_ptr = s->output_section->vma + s->output_offset
+	    + htab->tlsdesc_plt;
+	  break;
+
+	case DT_TLSDESC_GOT:
+	  s = htab->elf.sgot;
+	  dyn.d_un.d_ptr = s->output_section->vma + s->output_offset
+	    + htab->tlsdesc_got;
+	  break;
+	}
+
+      (*bed->s->swap_dyn_out) (output_bfd, &dyn, dyncon);
+    }
+
+  if (htab->plt_got != NULL && htab->plt_got->size > 0)
+    elf_section_data (htab->plt_got->output_section)
+      ->this_hdr.sh_entsize = htab->non_lazy_plt->plt_entry_size;
+
+  if (htab->plt_second != NULL && htab->plt_second->size > 0)
+    elf_section_data (htab->plt_second->output_section)
+      ->this_hdr.sh_entsize = htab->non_lazy_plt->plt_entry_size;
+
+  /* Adjust .eh_frame for .plt section.  */
+  if (htab->plt_eh_frame != NULL
+      && htab->plt_eh_frame->contents != NULL)
+    {
+      if (htab->elf.splt != NULL
+	  && htab->elf.splt->size != 0
+	  && (htab->elf.splt->flags & SEC_EXCLUDE) == 0
+	  && htab->elf.splt->output_section != NULL
+	  && htab->plt_eh_frame->output_section != NULL)
+	{
+	  bfd_vma plt_start = htab->elf.splt->output_section->vma;
+	  bfd_vma eh_frame_start = htab->plt_eh_frame->output_section->vma
+				   + htab->plt_eh_frame->output_offset
+				   + PLT_FDE_START_OFFSET;
+	  bfd_put_signed_32 (dynobj, plt_start - eh_frame_start,
+			     htab->plt_eh_frame->contents
+			     + PLT_FDE_START_OFFSET);
+	}
+
+      if (htab->plt_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME)
+	{
+	  if (! _bfd_elf_write_section_eh_frame (output_bfd, info,
+						 htab->plt_eh_frame,
+						 htab->plt_eh_frame->contents))
+	    return NULL;
+	}
+    }
+
+  /* Adjust .eh_frame for .plt.got section.  */
+  if (htab->plt_got_eh_frame != NULL
+      && htab->plt_got_eh_frame->contents != NULL)
+    {
+      if (htab->plt_got != NULL
+	  && htab->plt_got->size != 0
+	  && (htab->plt_got->flags & SEC_EXCLUDE) == 0
+	  && htab->plt_got->output_section != NULL
+	  && htab->plt_got_eh_frame->output_section != NULL)
+	{
+	  bfd_vma plt_start = htab->plt_got->output_section->vma;
+	  bfd_vma eh_frame_start = htab->plt_got_eh_frame->output_section->vma
+				   + htab->plt_got_eh_frame->output_offset
+				   + PLT_FDE_START_OFFSET;
+	  bfd_put_signed_32 (dynobj, plt_start - eh_frame_start,
+			     htab->plt_got_eh_frame->contents
+			     + PLT_FDE_START_OFFSET);
+	}
+      if (htab->plt_got_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME)
+	{
+	  if (! _bfd_elf_write_section_eh_frame (output_bfd, info,
+						 htab->plt_got_eh_frame,
+						 htab->plt_got_eh_frame->contents))
+	    return NULL;
+	}
+    }
+
+  /* Adjust .eh_frame for the second PLT section.  */
+  if (htab->plt_second_eh_frame != NULL
+      && htab->plt_second_eh_frame->contents != NULL)
+    {
+      if (htab->plt_second != NULL
+	  && htab->plt_second->size != 0
+	  && (htab->plt_second->flags & SEC_EXCLUDE) == 0
+	  && htab->plt_second->output_section != NULL
+	  && htab->plt_second_eh_frame->output_section != NULL)
+	{
+	  bfd_vma plt_start = htab->plt_second->output_section->vma;
+	  bfd_vma eh_frame_start
+	    = (htab->plt_second_eh_frame->output_section->vma
+	       + htab->plt_second_eh_frame->output_offset
+	       + PLT_FDE_START_OFFSET);
+	  bfd_put_signed_32 (dynobj, plt_start - eh_frame_start,
+			     htab->plt_second_eh_frame->contents
+			     + PLT_FDE_START_OFFSET);
+	}
+      if (htab->plt_second_eh_frame->sec_info_type
+	  == SEC_INFO_TYPE_EH_FRAME)
+	{
+	  if (! _bfd_elf_write_section_eh_frame (output_bfd, info,
+						 htab->plt_second_eh_frame,
+						 htab->plt_second_eh_frame->contents))
+	    return NULL;
+	}
+    }
+
+  if (htab->elf.sgot && htab->elf.sgot->size > 0)
+    elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize
+      = htab->got_entry_size;
+
+  return htab;
+}
+
+
 bfd_boolean
 _bfd_x86_elf_always_size_sections (bfd *output_bfd,
 				   struct bfd_link_info *info)
diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h
index 542439c..a6a8455 100644
--- a/bfd/elfxx-x86.h
+++ b/bfd/elfxx-x86.h
@@ -601,6 +601,9 @@ extern bfd_boolean _bfd_x86_elf_link_check_relocs
 extern bfd_boolean _bfd_x86_elf_size_dynamic_sections
   (bfd *, struct bfd_link_info *);
 
+extern struct elf_x86_link_hash_table *_bfd_x86_elf_finish_dynamic_sections
+  (bfd *, struct bfd_link_info *);
+
 extern bfd_boolean _bfd_x86_elf_always_size_sections
   (bfd *, struct bfd_link_info *);


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