diff -rup ../binutils-2.19.51.0.14.original/bfd/ChangeLog bfd/ChangeLog --- ../binutils-2.19.51.0.14.original/bfd/ChangeLog 2010-02-08 15:39:17.000000000 +0000 +++ bfd/ChangeLog 2010-02-08 15:40:38.000000000 +0000 @@ -1,3 +1,30 @@ +2010-02-08 Nick Clifton + + BZ 562249 + Import this patch from the mainline: + + 2009-12-17 Alan Modra + + PR ld/11088 + * elf64-ppc.c (ppc64_elf_gc_sweep_hook): Don't abort if symbol + hiding has nulled out plt.plist. + + PR ld/11088 + * elf32-ppc.c (update_plt_info): Clear sec here when addend is + less than 32768.. + (ppc_elf_check_relocs): ..rather than doing so here. Ignore new + relax relocs. + (ppc_elf_gc_sweep_hook): Don't segfault when symbol hiding has + removed plt_entry records. + (ppc_elf_tls_setup): Handle PIE calls to __tls_get_addr correctly. + (ppc_elf_tls_optimize): Likewise. Also dec __tls_get_addr refcount + when optimizing code using new tlsgd and tlsld marker relocs. + (ppc_elf_relax_section): Differentiate relaxed PLTREL24 relocs + from ADDR24 relocs using plt or glink. Don't clear the addend + for R_PPC_RELAX_PLTREL24. + (ppc_elf_relocate_section): Correctly handle addends on relaxed + PLTREL24 relocs. + 2009-07-22 H.J. Lu PR ld/10433 diff -rup ../binutils-2.19.51.0.14.original/bfd/elf32-ppc.c bfd/elf32-ppc.c --- ../binutils-2.19.51.0.14.original/bfd/elf32-ppc.c 2010-02-08 15:39:17.000000000 +0000 +++ bfd/elf32-ppc.c 2010-02-08 16:01:59.000000000 +0000 @@ -3309,9 +3309,13 @@ update_plt_info (bfd *abfd, struct plt_e { struct plt_entry *ent; + if (addend < 32768) + sec = NULL; + for (ent = *plist; ent != NULL; ent = ent->next) if (ent->sec == sec && ent->addend == addend) break; + if (ent == NULL) { bfd_size_type amt = sizeof (*ent); @@ -3500,8 +3504,7 @@ ppc_elf_check_relocs (bfd *abfd, ppc_elf_tdata (abfd)->makes_plt_call = 1; addend = rel->r_addend; } - if (!update_plt_info (abfd, ifunc, - addend < 32768 ? NULL : got2, addend)) + if (!update_plt_info (abfd, ifunc, got2, addend)) return FALSE; if (htab->glink == NULL) @@ -3727,8 +3730,7 @@ ppc_elf_check_relocs (bfd *abfd, addend = rel->r_addend; } h->needs_plt = 1; - if (!update_plt_info (abfd, &h->plt.plist, - addend < 32768 ? NULL : got2, addend)) + if (!update_plt_info (abfd, &h->plt.plist, got2, addend)) return FALSE; } break; @@ -3759,10 +3761,9 @@ ppc_elf_check_relocs (bfd *abfd, case R_PPC_EMB_MRKREF: case R_PPC_NONE: case R_PPC_max: - case R_PPC_RELAX32: - case R_PPC_RELAX32PC: - case R_PPC_RELAX32_PLT: - case R_PPC_RELAX32PC_PLT: + case R_PPC_RELAX: + case R_PPC_RELAX_PLT: + case R_PPC_RELAX_PLTREL24: break; /* These should only appear in dynamic objects. */ @@ -4431,7 +4432,8 @@ ppc_elf_gc_sweep_hook (bfd *abfd, { bfd_vma addend = r_type == R_PPC_PLTREL24 ? rel->r_addend : 0; struct plt_entry *ent = find_plt_ent (ifunc, got2, addend); - if (ent->plt.refcount > 0) + + if (ent != NULL && ent->plt.refcount > 0) ent->plt.refcount -= 1; continue; } @@ -4505,7 +4507,8 @@ ppc_elf_gc_sweep_hook (bfd *abfd, bfd_vma addend = r_type == R_PPC_PLTREL24 ? rel->r_addend : 0; struct plt_entry *ent = find_plt_ent (&h->plt.plist, got2, addend); - if (ent->plt.refcount > 0) + + if (ent != NULL && ent->plt.refcount > 0) ent->plt.refcount -= 1; } break; @@ -4591,6 +4594,7 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUT { Elf_Internal_Sym *locsyms = NULL; Elf_Internal_Shdr *symtab_hdr = &elf_symtab_hdr (ibfd); + asection *got2 = bfd_get_section_by_name (ibfd, ".got2"); for (sec = ibfd->sections; sec != NULL; sec = sec->next) if (sec->has_tls_reloc && !bfd_is_abs_section (sec->output_section)) @@ -4684,6 +4688,13 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUT else continue; + case R_PPC_TLSGD: + case R_PPC_TLSLD: + expecting_tls_get_addr = 2; + tls_set = 0; + tls_clear = 0; + break; + default: continue; } @@ -4691,7 +4702,8 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUT if (pass == 0) { if (!expecting_tls_get_addr - || !sec->has_tls_get_addr_call) + || (expecting_tls_get_addr == 1 + && ! sec->has_tls_get_addr_call)) continue; if (rel + 1 < relend @@ -4707,6 +4719,23 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUT break; } + if (expecting_tls_get_addr) + { + struct plt_entry *ent; + bfd_vma addend = 0; + + if (info->shared + && ELF32_R_TYPE (rel[1].r_info) == R_PPC_PLTREL24) + addend = rel[1].r_addend; + ent = find_plt_ent (&htab->tls_get_addr->plt.plist, + got2, addend); + if (ent != NULL && ent->plt.refcount > 0) + ent->plt.refcount -= 1; + + if (expecting_tls_get_addr == 2) + continue; + } + if (h != NULL) { tls_mask = &ppc_elf_hash_entry (h)->tls_mask; @@ -4751,16 +4780,6 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUT *got_count -= 1; } - if (expecting_tls_get_addr) - { - struct plt_entry *ent; - - ent = find_plt_ent (&htab->tls_get_addr->plt.plist, - NULL, 0); - if (ent != NULL && ent->plt.refcount > 0) - ent->plt.refcount -= 1; - } - *tls_mask |= tls_set; *tls_mask &= ~tls_clear; } @@ -6098,28 +6117,29 @@ ppc_elf_relax_section (bfd *abfd, { size = 4 * ARRAY_SIZE (shared_stub_entry); insn_offset = 12; - stub_rtype = R_PPC_RELAX32PC; } else { size = 4 * ARRAY_SIZE (stub_entry); insn_offset = 0; - stub_rtype = R_PPC_RELAX32; } - if (R_PPC_RELAX32_PLT - R_PPC_RELAX32 - != R_PPC_RELAX32PC_PLT - R_PPC_RELAX32PC) - abort (); + stub_rtype = R_PPC_RELAX; if (tsec == htab->plt || tsec == htab->glink) - stub_rtype += R_PPC_RELAX32_PLT - R_PPC_RELAX32; + { + stub_rtype = R_PPC_RELAX_PLT; + if (r_type == R_PPC_PLTREL24) + stub_rtype = R_PPC_RELAX_PLTREL24; + } /* Hijack the old relocation. Since we need two relocations for this use a "composite" reloc. */ irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), stub_rtype); irel->r_offset = trampoff + insn_offset; - if (r_type == R_PPC_PLTREL24) + if (r_type == R_PPC_PLTREL24 + && stub_rtype != R_PPC_RELAX_PLTREL24) irel->r_addend = 0; /* Record the fixup so we don't do it again this section. */ @@ -6289,7 +6309,7 @@ ppc_elf_relax_section (bfd *abfd, { /* Convert the internal relax relocs to external form. */ for (irel = internal_relocs; irel < irelend; irel++) - if (ELF32_R_TYPE (irel->r_info) == R_PPC_RELAX32) + if (ELF32_R_TYPE (irel->r_info) == R_PPC_RELAX) { unsigned long r_symndx = ELF32_R_SYM (irel->r_info); @@ -7461,32 +7481,36 @@ ppc_elf_relocate_section (bfd *output_bf } break; - case R_PPC_RELAX32PC_PLT: - case R_PPC_RELAX32_PLT: - { - struct plt_entry *ent = find_plt_ent (&h->plt.plist, got2, addend); - - if (htab->plt_type == PLT_NEW) - relocation = (htab->glink->output_section->vma - + htab->glink->output_offset - + ent->glink_offset); - else - relocation = (htab->plt->output_section->vma - + htab->plt->output_offset - + ent->plt.offset); - } - if (r_type == R_PPC_RELAX32_PLT) - goto relax32; - /* Fall thru */ + case R_PPC_RELAX_PLT: + case R_PPC_RELAX_PLTREL24: + if (h != NULL) + { + struct plt_entry *ent; + bfd_vma got2_addend = 0; - case R_PPC_RELAX32PC: - relocation -= (input_section->output_section->vma - + input_section->output_offset - + rel->r_offset - 4); + if (r_type == R_PPC_RELAX_PLTREL24) + { + if (info->shared) + got2_addend = addend; + addend = 0; + } + ent = find_plt_ent (&h->plt.plist, got2, got2_addend); + if (htab->plt_type == PLT_NEW) + relocation = (htab->glink->output_section->vma + + htab->glink->output_offset + + ent->glink_offset); + else + relocation = (htab->plt->output_section->vma + + htab->plt->output_offset + + ent->plt.offset); + } /* Fall thru */ - case R_PPC_RELAX32: - relax32: + case R_PPC_RELAX: + if (info->shared) + relocation -= (input_section->output_section->vma + + input_section->output_offset + + rel->r_offset - 4); { unsigned long t0; unsigned long t1; diff -rup ../binutils-2.19.51.0.14.original/include/elf/ppc.h include/elf/ppc.h --- ../binutils-2.19.51.0.14.original/include/elf/ppc.h 2010-02-08 15:39:06.000000000 +0000 +++ include/elf/ppc.h 2010-02-08 16:47:05.000000000 +0000 @@ -73,10 +73,9 @@ START_RELOC_NUMBERS (elf_ppc_reloc_type) #ifndef RELOC_MACROS_GEN_FUNC /* Fake relocations for branch stubs, only used internally by ld. */ - RELOC_NUMBER (R_PPC_RELAX32, 48) - RELOC_NUMBER (R_PPC_RELAX32PC, 49) - RELOC_NUMBER (R_PPC_RELAX32_PLT, 50) - RELOC_NUMBER (R_PPC_RELAX32PC_PLT, 51) + RELOC_NUMBER (R_PPC_RELAX, 48) + RELOC_NUMBER (R_PPC_RELAX_PLT, 49) + RELOC_NUMBER (R_PPC_RELAX_PLTREL24, 50) #endif /* Relocs added to support TLS. */ --- ../binutils-2.19.51.0.14.original/bfd/elf64-ppc.c 2010-02-08 15:39:17.000000000 +0000 +++ bfd/elf64-ppc.c 2010-02-09 15:36:43.000000000 +0000 @@ -5640,9 +5640,7 @@ ppc64_elf_gc_sweep_hook (bfd *abfd, stru for (ent = *ifunc; ent != NULL; ent = ent->next) if (ent->addend == rel->r_addend) break; - if (ent == NULL) - abort (); - if (ent->plt.refcount > 0) + if (ent != NULL && ent->plt.refcount > 0) ent->plt.refcount -= 1; continue; } @@ -5721,9 +5719,7 @@ ppc64_elf_gc_sweep_hook (bfd *abfd, stru for (ent = h->plt.plist; ent != NULL; ent = ent->next) if (ent->addend == rel->r_addend) break; - if (ent == NULL) - abort (); - if (ent->plt.refcount > 0) + if (ent != NULL && ent->plt.refcount > 0) ent->plt.refcount -= 1; } break;