[binutils/f16] Import mainstream elf64-ppc.c in order to fix stub size computation. (BZ 728201)

Nicholas Clifton nickc at fedoraproject.org
Fri Aug 5 12:13:26 UTC 2011


commit fca806956e8f1d744f415657556ff251badba5df
Author: Nick Clifton <nickc at redhat.com>
Date:   Fri Aug 5 13:14:12 2011 +0100

     Import mainstream elf64-ppc.c in order to fix stub size computation.  (BZ 728201)

 binutils-2.21.53.0.1-ppc64-stub-size.patch |  470 ++++++++++++++++++++++++++++
 binutils.spec                              |    7 +-
 2 files changed, 476 insertions(+), 1 deletions(-)
---
diff --git a/binutils-2.21.53.0.1-ppc64-stub-size.patch b/binutils-2.21.53.0.1-ppc64-stub-size.patch
new file mode 100644
index 0000000..04c919d
--- /dev/null
+++ b/binutils-2.21.53.0.1-ppc64-stub-size.patch
@@ -0,0 +1,470 @@
+*** ../binutils-2.21.53.0.1.orig/bfd/elf64-ppc.c	2011-08-05 12:43:25.596878997 +0100
+--- bfd/elf64-ppc.c	2011-08-05 12:44:58.485878988 +0100
+***************
+*** 34,39 ****
+--- 34,40 ----
+  #include "elf-bfd.h"
+  #include "elf/ppc64.h"
+  #include "elf64-ppc.h"
++ #include "dwarf2.h"
+  
+  static bfd_reloc_status_type ppc64_elf_ha_reloc
+    (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
+*************** struct ppc_link_hash_table
+*** 3720,3725 ****
+--- 3721,3727 ----
+    asection *sfpr;
+    asection *brlt;
+    asection *relbrlt;
++   asection *glink_eh_frame;
+  
+    /* Shortcut to .__tls_get_addr and __tls_get_addr.  */
+    struct ppc_link_hash_entry *tls_get_addr;
+*************** create_linkage_sections (bfd *dynobj, st
+*** 4170,4175 ****
+--- 4172,4189 ----
+        || ! bfd_set_section_alignment (dynobj, htab->glink, 3))
+      return FALSE;
+  
++   if (!info->no_ld_generated_unwind_info)
++     {
++       flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_HAS_CONTENTS
++ 	       | SEC_IN_MEMORY | SEC_LINKER_CREATED);
++       htab->glink_eh_frame = bfd_make_section_anyway_with_flags (dynobj,
++ 								 ".eh_frame",
++ 								 flags);
++       if (htab->glink_eh_frame == NULL
++ 	  || !bfd_set_section_alignment (abfd, htab->glink_eh_frame, 2))
++ 	return FALSE;
++     }
++ 
+    flags = SEC_ALLOC | SEC_LINKER_CREATED;
+    htab->iplt = bfd_make_section_anyway_with_flags (dynobj, ".iplt", flags);
+    if (htab->iplt == NULL
+*************** ppc64_elf_size_dynamic_sections (bfd *ou
+*** 9025,9030 ****
+--- 9039,9050 ----
+  	  /* Strip this section if we don't need it; see the
+  	     comment below.  */
+  	}
++       else if (s == htab->glink_eh_frame)
++ 	{
++ 	  if (!bfd_is_abs_section (s->output_section))
++ 	    /* Not sized yet.  */
++ 	    continue;
++ 	}
+        else if (CONST_STRNEQ (s->name, ".rela"))
+  	{
+  	  if (s->size != 0)
+*************** build_plt_stub (bfd *obfd, bfd_byte *p, 
+*** 9271,9277 ****
+  	  r[1].r_offset = r[0].r_offset + 8;
+  	  r[1].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO_DS);
+  	  r[1].r_addend = r[0].r_addend;
+! 	  if (PPC_HA (offset + 16) != PPC_HA (offset))
+  	    {
+  	      r[2].r_offset = r[1].r_offset + 4;
+  	      r[2].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO);
+--- 9291,9297 ----
+  	  r[1].r_offset = r[0].r_offset + 8;
+  	  r[1].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO_DS);
+  	  r[1].r_addend = r[0].r_addend;
+! 	  if (PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
+  	    {
+  	      r[2].r_offset = r[1].r_offset + 4;
+  	      r[2].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO);
+*************** build_plt_stub (bfd *obfd, bfd_byte *p, 
+*** 9282,9290 ****
+  	      r[2].r_offset = r[1].r_offset + 8;
+  	      r[2].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO_DS);
+  	      r[2].r_addend = r[0].r_addend + 8;
+! 	      r[3].r_offset = r[2].r_offset + 4;
+! 	      r[3].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO_DS);
+! 	      r[3].r_addend = r[0].r_addend + 16;
+  	    }
+  	}
+        bfd_put_32 (obfd, ADDIS_R12_R2 | PPC_HA (offset), p),	p += 4;
+--- 9302,9313 ----
+  	      r[2].r_offset = r[1].r_offset + 8;
+  	      r[2].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO_DS);
+  	      r[2].r_addend = r[0].r_addend + 8;
+! 	      if (plt_static_chain)
+! 		{
+! 		  r[3].r_offset = r[2].r_offset + 4;
+! 		  r[3].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO_DS);
+! 		  r[3].r_addend = r[0].r_addend + 16;
+! 		}
+  	    }
+  	}
+        bfd_put_32 (obfd, ADDIS_R12_R2 | PPC_HA (offset), p),	p += 4;
+*************** build_plt_stub (bfd *obfd, bfd_byte *p, 
+*** 9307,9313 ****
+  	{
+  	  r[0].r_offset += 4;
+  	  r[0].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_DS);
+! 	  if (PPC_HA (offset + 16) != PPC_HA (offset))
+  	    {
+  	      r[1].r_offset = r[0].r_offset + 4;
+  	      r[1].r_info = ELF64_R_INFO (0, R_PPC64_TOC16);
+--- 9330,9336 ----
+  	{
+  	  r[0].r_offset += 4;
+  	  r[0].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_DS);
+! 	  if (PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
+  	    {
+  	      r[1].r_offset = r[0].r_offset + 4;
+  	      r[1].r_info = ELF64_R_INFO (0, R_PPC64_TOC16);
+*************** build_plt_stub (bfd *obfd, bfd_byte *p, 
+*** 9317,9326 ****
+  	    {
+  	      r[1].r_offset = r[0].r_offset + 8;
+  	      r[1].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_DS);
+! 	      r[1].r_addend = r[0].r_addend + 16;
+! 	      r[2].r_offset = r[1].r_offset + 4;
+! 	      r[2].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_DS);
+! 	      r[2].r_addend = r[0].r_addend + 8;
+  	    }
+  	}
+        bfd_put_32 (obfd, STD_R2_40R1, p),			p += 4;
+--- 9340,9352 ----
+  	    {
+  	      r[1].r_offset = r[0].r_offset + 8;
+  	      r[1].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_DS);
+! 	      r[1].r_addend = r[0].r_addend + 8 + 8 * plt_static_chain;
+! 	      if (plt_static_chain)
+! 		{
+! 		  r[2].r_offset = r[1].r_offset + 4;
+! 		  r[2].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_DS);
+! 		  r[2].r_addend = r[0].r_addend + 8;
+! 		}
+  	    }
+  	}
+        bfd_put_32 (obfd, STD_R2_40R1, p),			p += 4;
+*************** ppc_build_one_stub (struct bfd_hash_entr
+*** 9788,9795 ****
+        if (info->emitrelocations)
+  	{
+  	  r = get_relocs (stub_entry->stub_sec,
+! 			  (2 + (PPC_HA (off) != 0)
+! 			   + (PPC_HA (off + 16) == PPC_HA (off))));
+  	  if (r == NULL)
+  	    return FALSE;
+  	  r[0].r_offset = loc - stub_entry->stub_sec->contents;
+--- 9814,9823 ----
+        if (info->emitrelocations)
+  	{
+  	  r = get_relocs (stub_entry->stub_sec,
+! 			  (2
+! 			   + (PPC_HA (off) != 0)
+! 			   + (htab->plt_static_chain
+! 			      && PPC_HA (off + 16) == PPC_HA (off))));
+  	  if (r == NULL)
+  	    return FALSE;
+  	  r[0].r_offset = loc - stub_entry->stub_sec->contents;
+*************** ppc_size_one_stub (struct bfd_hash_entry
+*** 9896,9902 ****
+  	size -= 4;
+        if (PPC_HA (off) == 0)
+  	size -= 4;
+!       if (PPC_HA (off + 16) != PPC_HA (off))
+  	size += 4;
+        if (stub_entry->h != NULL
+  	  && (stub_entry->h == htab->tls_get_addr_fd
+--- 9924,9930 ----
+  	size -= 4;
+        if (PPC_HA (off) == 0)
+  	size -= 4;
+!       if (PPC_HA (off + 8 + 8 * htab->plt_static_chain) != PPC_HA (off))
+  	size += 4;
+        if (stub_entry->h != NULL
+  	  && (stub_entry->h == htab->tls_get_addr_fd
+*************** ppc_size_one_stub (struct bfd_hash_entry
+*** 9906,9912 ****
+        if (info->emitrelocations)
+  	{
+  	  stub_entry->stub_sec->reloc_count
+! 	    += 2 + (PPC_HA (off) != 0) + (PPC_HA (off + 16) == PPC_HA (off));
+  	  stub_entry->stub_sec->flags |= SEC_RELOC;
+  	}
+      }
+--- 9934,9943 ----
+        if (info->emitrelocations)
+  	{
+  	  stub_entry->stub_sec->reloc_count
+! 	    += (2
+! 		+ (PPC_HA (off) != 0)
+! 		+ (htab->plt_static_chain
+! 		   && PPC_HA (off + 16) == PPC_HA (off)));
+  	  stub_entry->stub_sec->flags |= SEC_RELOC;
+  	}
+      }
+*************** group_sections (struct ppc_link_hash_tab
+*** 10826,10831 ****
+--- 10857,10896 ----
+  #undef PREV_SEC
+  }
+  
++ static const unsigned char glink_eh_frame_cie[] =
++ {
++   0, 0, 0, 16,				/* length.  */
++   0, 0, 0, 0,				/* id.  */
++   1,					/* CIE version.  */
++   'z', 'R', 0,				/* Augmentation string.  */
++   4,					/* Code alignment.  */
++   0x78,					/* Data alignment.  */
++   65,					/* RA reg.  */
++   1,					/* Augmentation size.  */
++   DW_EH_PE_pcrel | DW_EH_PE_sdata4,	/* FDE encoding.  */
++   DW_CFA_def_cfa, 1, 0			/* def_cfa: r1 offset 0.  */
++ };
++ 
++ /* Stripping output sections is normally done before dynamic section
++    symbols have been allocated.  This function is called later, and
++    handles cases like htab->brlt which is mapped to its own output
++    section.  */
++ 
++ static void
++ maybe_strip_output (struct bfd_link_info *info, asection *isec)
++ {
++   if (isec->size == 0
++       && isec->output_section->size == 0
++       && !bfd_section_removed_from_list (info->output_bfd,
++ 					 isec->output_section)
++       && elf_section_data (isec->output_section)->dynindx == 0)
++     {
++       isec->output_section->flags |= SEC_EXCLUDE;
++       bfd_section_list_remove (info->output_bfd, isec->output_section);
++       info->output_bfd->section_count--;
++     }
++ }
++ 
+  /* Determine and set the size of the stub section for a final link.
+  
+     The basic idea here is to examine all the relocations looking for
+*************** ppc64_elf_size_stubs (struct bfd_link_in
+*** 11169,11174 ****
+--- 11234,11258 ----
+  	  htab->glink->flags |= SEC_RELOC;
+  	}
+  
++       if (htab->glink_eh_frame != NULL
++ 	  && !bfd_is_abs_section (htab->glink_eh_frame->output_section)
++ 	  && (htab->glink_eh_frame->flags & SEC_EXCLUDE) == 0)
++ 	{
++ 	  bfd_size_type size = 0;
++ 
++ 	  for (stub_sec = htab->stub_bfd->sections;
++ 	       stub_sec != NULL;
++ 	       stub_sec = stub_sec->next)
++ 	    if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
++ 	      size += 20;
++ 	  if (htab->glink != NULL && htab->glink->size != 0)
++ 	    size += 24;
++ 	  if (size != 0)
++ 	    size += sizeof (glink_eh_frame_cie);
++ 	  htab->glink_eh_frame->rawsize = htab->glink_eh_frame->size;
++ 	  htab->glink_eh_frame->size = size;
++ 	}
++ 
+        for (stub_sec = htab->stub_bfd->sections;
+  	   stub_sec != NULL;
+  	   stub_sec = stub_sec->next)
+*************** ppc64_elf_size_stubs (struct bfd_link_in
+*** 11178,11194 ****
+  
+        /* Exit from this loop when no stubs have been added, and no stubs
+  	 have changed size.  */
+!       if (stub_sec == NULL)
+  	break;
+  
+        /* Ask the linker to do its stuff.  */
+        (*htab->layout_sections_again) ();
+      }
+  
+!   /* It would be nice to strip htab->brlt from the output if the
+!      section is empty, but it's too late.  If we strip sections here,
+!      the dynamic symbol table is corrupted since the section symbol
+!      for the stripped section isn't written.  */
+  
+    return TRUE;
+  }
+--- 11262,11279 ----
+  
+        /* Exit from this loop when no stubs have been added, and no stubs
+  	 have changed size.  */
+!       if (stub_sec == NULL
+! 	  && (htab->glink_eh_frame == NULL
+! 	      || htab->glink_eh_frame->rawsize == htab->glink_eh_frame->size))
+  	break;
+  
+        /* Ask the linker to do its stuff.  */
+        (*htab->layout_sections_again) ();
+      }
+  
+!   maybe_strip_output (info, htab->brlt);
+!   if (htab->glink_eh_frame != NULL)
+!     maybe_strip_output (info, htab->glink_eh_frame);
+  
+    return TRUE;
+  }
+*************** ppc64_elf_build_stubs (bfd_boolean emit_
+*** 11393,11398 ****
+--- 11478,11577 ----
+  	return FALSE;
+      }
+  
++   if (htab->glink_eh_frame != NULL
++       && htab->glink_eh_frame->size != 0)
++     {
++       bfd_vma val;
++ 
++       p = bfd_zalloc (htab->glink_eh_frame->owner, htab->glink_eh_frame->size);
++       if (p == NULL)
++ 	return FALSE;
++       htab->glink_eh_frame->contents = p;
++ 
++       htab->glink_eh_frame->rawsize = htab->glink_eh_frame->size;
++ 
++       memcpy (p, glink_eh_frame_cie, sizeof (glink_eh_frame_cie));
++       /* CIE length (rewrite in case little-endian).  */
++       bfd_put_32 (htab->elf.dynobj, sizeof (glink_eh_frame_cie) - 4, p);
++       p += sizeof (glink_eh_frame_cie);
++ 
++       for (stub_sec = htab->stub_bfd->sections;
++ 	   stub_sec != NULL;
++ 	   stub_sec = stub_sec->next)
++ 	if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
++ 	  {
++ 	    /* FDE length.  */
++ 	    bfd_put_32 (htab->elf.dynobj, 16, p);
++ 	    p += 4;
++ 	    /* CIE pointer.  */
++ 	    val = p - htab->glink_eh_frame->contents;
++ 	    bfd_put_32 (htab->elf.dynobj, val, p);
++ 	    p += 4;
++ 	    /* Offset to stub section.  */
++ 	    val = (stub_sec->output_section->vma
++ 		   + stub_sec->output_offset);
++ 	    val -= (htab->glink_eh_frame->output_section->vma
++ 		    + htab->glink_eh_frame->output_offset);
++ 	    val -= p - htab->glink_eh_frame->contents;
++ 	    if (val + 0x80000000 > 0xffffffff)
++ 	      {
++ 		info->callbacks->einfo
++ 		  (_("%s offset too large for .eh_frame sdata4 encoding"),
++ 		   stub_sec->name);
++ 		return FALSE;
++ 	      }
++ 	    bfd_put_32 (htab->elf.dynobj, val, p);
++ 	    p += 4;
++ 	    /* stub section size.  */
++ 	    bfd_put_32 (htab->elf.dynobj, stub_sec->rawsize, p);
++ 	    p += 4;
++ 	    /* Augmentation.  */
++ 	    p += 1;
++ 	    /* Pad.  */
++ 	    p += 3;
++ 	  }
++       if (htab->glink != NULL && htab->glink->size != 0)
++ 	{
++ 	  /* FDE length.  */
++ 	  bfd_put_32 (htab->elf.dynobj, 20, p);
++ 	  p += 4;
++ 	  /* CIE pointer.  */
++ 	  val = p - htab->glink_eh_frame->contents;
++ 	  bfd_put_32 (htab->elf.dynobj, val, p);
++ 	  p += 4;
++ 	  /* Offset to .glink.  */
++ 	  val = (htab->glink->output_section->vma
++ 		 + htab->glink->output_offset
++ 		 + 8);
++ 	  val -= (htab->glink_eh_frame->output_section->vma
++ 		  + htab->glink_eh_frame->output_offset);
++ 	  val -= p - htab->glink_eh_frame->contents;
++ 	  if (val + 0x80000000 > 0xffffffff)
++ 	    {
++ 	      info->callbacks->einfo
++ 		(_("%s offset too large for .eh_frame sdata4 encoding"),
++ 		 htab->glink->name);
++ 	      return FALSE;
++ 	    }
++ 	  bfd_put_32 (htab->elf.dynobj, val, p);
++ 	  p += 4;
++ 	  /* .glink size.  */
++ 	  bfd_put_32 (htab->elf.dynobj, htab->glink->rawsize - 8, p);
++ 	  p += 4;
++ 	  /* Augmentation.  */
++ 	  p += 1;
++ 
++ 	  *p++ = DW_CFA_advance_loc + 1;
++ 	  *p++ = DW_CFA_register;
++ 	  *p++ = 65;
++ 	  *p++ = 12;
++ 	  *p++ = DW_CFA_advance_loc + 4;
++ 	  *p++ = DW_CFA_restore_extended;
++ 	  *p++ = 65;
++ 	}
++       htab->glink_eh_frame->size = p - htab->glink_eh_frame->contents;
++     }
++ 
+    /* Build the stubs as directed by the stub hash table.  */
+    bfd_hash_traverse (&htab->stub_hash_table, ppc_build_one_stub, info);
+  
+*************** ppc64_elf_build_stubs (bfd_boolean emit_
+*** 11410,11416 ****
+        }
+  
+    if (stub_sec != NULL
+!       || htab->glink->rawsize != htab->glink->size)
+      {
+        htab->stub_error = TRUE;
+        info->callbacks->einfo (_("stubs don't match calculated size\n"));
+--- 11589,11597 ----
+        }
+  
+    if (stub_sec != NULL
+!       || htab->glink->rawsize != htab->glink->size
+!       || (htab->glink_eh_frame != NULL
+! 	  && htab->glink_eh_frame->rawsize != htab->glink_eh_frame->size))
+      {
+        htab->stub_error = TRUE;
+        info->callbacks->einfo (_("stubs don't match calculated size\n"));
+*************** ppc64_elf_relocate_section (bfd *output_
+*** 12842,12853 ****
+  	      else if (!SYMBOL_CALLS_LOCAL (info, &h->elf)
+  		       && !is_opd
+  		       && r_type != R_PPC64_TOC)
+! 		{
+! 		  outrel.r_info = ELF64_R_INFO (h->elf.dynindx, r_type);
+! 		  if (h->elf.dynindx == -1
+! 		      && h->elf.root.type == bfd_link_hash_undefweak)
+! 		    memset (&outrel, 0, sizeof outrel);
+! 		}
+  	      else
+  		{
+  		  /* This symbol is local, or marked to become local,
+--- 13021,13027 ----
+  	      else if (!SYMBOL_CALLS_LOCAL (info, &h->elf)
+  		       && !is_opd
+  		       && r_type != R_PPC64_TOC)
+! 		outrel.r_info = ELF64_R_INFO (h->elf.dynindx, r_type);
+  	      else
+  		{
+  		  /* This symbol is local, or marked to become local,
+*************** ppc64_elf_finish_dynamic_sections (bfd *
+*** 13566,13571 ****
+--- 13740,13753 ----
+  				       NULL))
+      return FALSE;
+  
++ 
++   if (htab->glink_eh_frame != NULL
++       && htab->glink_eh_frame->sec_info_type == ELF_INFO_TYPE_EH_FRAME
++       && !_bfd_elf_write_section_eh_frame (output_bfd, info,
++ 					   htab->glink_eh_frame,
++ 					   htab->glink_eh_frame->contents))
++     return FALSE;
++ 
+    /* We need to handle writing out multiple GOT sections ourselves,
+       since we didn't add them to DYNOBJ.  We know dynobj is the first
+       bfd.  */
diff --git a/binutils.spec b/binutils.spec
index c95f9a9..7d9a201 100644
--- a/binutils.spec
+++ b/binutils.spec
@@ -17,7 +17,7 @@
 Summary: A GNU collection of binary utilities
 Name: %{?cross}binutils%{?_with_debug:-debug}
 Version: 2.21.53.0.1
-Release: 2%{?dist}
+Release: 3%{?dist}
 License: GPLv3+
 Group: Development/Tools
 URL: http://sources.redhat.com/binutils
@@ -32,6 +32,7 @@ Patch06: binutils-2.20.51.0.10-copy-osabi.patch
 Patch07: binutils-2.20.51.0.10-sec-merge-emit.patch
 Patch08: binutils-2.20.51.0.2-build-id.patch
 Patch09: binutils-2.21.53.0.1-debug_macro.patch
+Patch10: binutils-2.21.53.0.1-ppc64-stub-size.patch
 
 %define gold_arches %ix86 x86_64
 
@@ -131,6 +132,7 @@ using libelf instead of BFD.
 %patch07 -p0 -b .sec-merge-emit~
 %patch08 -p0 -b .build-id~
 %patch09 -p0 -b .debug_macro~
+%patch10 -p0 -b .stub_size~
 
 # We cannot run autotools as there is an exact requirement of autoconf-2.59.
 
@@ -420,6 +422,9 @@ exit 0
 %endif # %{isnative}
 
 %changelog
+* Fri Aug  05 2011 Nick Clifton <nickc at redhat.com> - 2.21.53.0.1-3
+- Import mainstream elf64-ppc.c in order to fix stub size computation.  (BZ 728201)
+
 * Wed Jul  27 2011 Nick Clifton <nickc at redhat.com> - 2.21.53.0.1-2
 - Import Jakub Jelinek's patch to add support for displaying the contents of .debug_macro sections.
 


More information about the scm-commits mailing list