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 - 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 - 2.21.53.0.1-2 - Import Jakub Jelinek's patch to add support for displaying the contents of .debug_macro sections.