[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