X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Felf64-ppc.c;h=9a9374fab1a002bf323ff7c5db286224a007160d;hb=e46d79a76ea748165a3ecd1102dd10498d089a49;hp=d5a46dbf21f55f1f7d3ae3a1efcd32ec19f99c4c;hpb=ec73ddcd43b588924c95f1a997351314ddf84e39;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index d5a46dbf21..9a9374fab1 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -35,6 +35,9 @@ #include "elf64-ppc.h" #include "dwarf2.h" +/* All users of this file have bfd_octets_per_byte (abfd, sec) == 1. */ +#define OCTETS_PER_BYTE(ABFD, SEC) 1 + static bfd_reloc_status_type ppc64_elf_ha_reloc (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); static bfd_reloc_status_type ppc64_elf_branch_reloc @@ -1405,7 +1408,7 @@ ppc64_elf_ha_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, + input_section->output_section->vma); value = (bfd_signed_vma) value >> 16; - octets = reloc_entry->address * bfd_octets_per_byte (abfd); + octets = reloc_entry->address * OCTETS_PER_BYTE (abfd, input_section); insn = bfd_get_32 (abfd, (bfd_byte *) data + octets); insn &= ~0x1fffc1; insn |= (value & 0xffc1) | ((value & 0x3e) << 15); @@ -1480,7 +1483,7 @@ ppc64_elf_brtaken_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message); - octets = reloc_entry->address * bfd_octets_per_byte (abfd); + octets = reloc_entry->address * OCTETS_PER_BYTE (abfd, input_section); insn = bfd_get_32 (abfd, (bfd_byte *) data + octets); insn &= ~(0x01 << 21); r_type = reloc_entry->howto->type; @@ -1630,7 +1633,7 @@ ppc64_elf_toc64_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, if (TOCstart == 0) TOCstart = ppc64_elf_set_toc (NULL, input_section->output_section->owner); - octets = reloc_entry->address * bfd_octets_per_byte (abfd); + octets = reloc_entry->address * OCTETS_PER_BYTE (abfd, input_section); bfd_put_64 (abfd, TOCstart + TOC_BASE_OFF, (bfd_byte *) data + octets); return bfd_reloc_ok; } @@ -2101,7 +2104,17 @@ compare_symbols (const void *ap, const void *bp) if ((a->flags & BSF_DYNAMIC) == 0 && (b->flags & BSF_DYNAMIC) != 0) return 1; - return a > b; + /* Finally, sort on where the symbol is in memory. The symbols will + be in at most two malloc'd blocks, one for static syms, one for + dynamic syms, and we distinguish the two blocks above by testing + BSF_DYNAMIC. Since we are sorting the symbol pointers which were + originally in the same order as the symbols (and we're not + sorting the symbols themselves), this ensures a stable sort. */ + if (a < b) + return -1; + if (a > b) + return 1; + return 0; } /* Search SYMS for a symbol of the given VALUE. */ @@ -3218,8 +3231,9 @@ struct ppc_link_hash_table /* Nonzero if this section has TLS related relocations. */ #define has_tls_reloc sec_flg0 -/* Nonzero if this section has an old-style call to __tls_get_addr. */ -#define has_tls_get_addr_call sec_flg1 +/* Nonzero if this section has a call to __tls_get_addr lacking marker + relocations. */ +#define nomark_tls_get_addr sec_flg1 /* Nonzero if this section has any toc or got relocs. */ #define has_toc_reloc sec_flg2 @@ -4543,8 +4557,6 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, sec->has_toc_reloc = 1; } - tls_type = 0; - ifunc = NULL; r_type = ELF64_R_TYPE (rel->r_info); switch (r_type) { @@ -4597,6 +4609,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, break; } + ifunc = NULL; if (h != NULL) { if (h->type == STT_GNU_IFUNC) @@ -4622,6 +4635,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, } } + tls_type = 0; switch (r_type) { case R_PPC64_TLSGD: @@ -4925,7 +4939,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, ; else /* Mark this section as having an old-style call. */ - sec->has_tls_get_addr_call = 1; + sec->nomark_tls_get_addr = 1; } plt_list = &h->plt.plist; } @@ -5826,9 +5840,7 @@ sfpr_define (struct bfd_link_info *info, s = elf_link_hash_lookup (&htab->elf, buf, TRUE, TRUE, FALSE); if (s == NULL) return FALSE; - if (s->root.type == bfd_link_hash_new - || (s->root.type = bfd_link_hash_defined - && s->root.u.def.section == stub_sec)) + if (s->root.type == bfd_link_hash_new) { s->root.type = bfd_link_hash_defined; s->root.u.def.section = stub_sec; @@ -7803,11 +7815,9 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info) value = sym->st_value; ok_tprel = FALSE; - is_local = FALSE; - if (h == NULL - || !h->def_dynamic) + is_local = SYMBOL_REFERENCES_LOCAL (info, h); + if (is_local) { - is_local = TRUE; if (h != NULL && h->root.type == bfd_link_hash_undefweak) ok_tprel = TRUE; @@ -7835,7 +7845,7 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info) setup insn. If we don't find matching arg setup relocs, don't do any tls optimization. */ if (pass == 0 - && sec->has_tls_get_addr_call + && sec->nomark_tls_get_addr && h != NULL && (h == &htab->tls_get_addr->elf || h == &htab->tls_get_addr_fd->elf) @@ -7907,8 +7917,11 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info) } continue; - case R_PPC64_TLSGD: case R_PPC64_TLSLD: + if (!is_local) + continue; + /* Fall through. */ + case R_PPC64_TLSGD: if (rel + 1 < relend && is_plt_seq_reloc (ELF64_R_TYPE (rel[1].r_info))) { @@ -8036,7 +8049,7 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info) if (pass == 0) { if (!expecting_tls_get_addr - || !sec->has_tls_get_addr_call) + || !sec->nomark_tls_get_addr) continue; if (rel + 1 < relend @@ -8088,12 +8101,12 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info) Disable optimization in this case. */ if ((tls_clear & (TLS_GD | TLS_LD)) != 0 && (tls_set & TLS_EXPLICIT) == 0 - && !sec->has_tls_get_addr_call + && !sec->nomark_tls_get_addr && ((*tls_mask & (TLS_TLS | TLS_MARK)) != (TLS_TLS | TLS_MARK))) continue; - if (expecting_tls_get_addr) + if (expecting_tls_get_addr == 1 + !sec->nomark_tls_get_addr) { struct plt_entry *ent = NULL; @@ -9278,7 +9291,7 @@ allocate_got (struct elf_link_hash_entry *h, htab->got_reli_size += rentsize; } else if (((bfd_link_pic (info) - && !((gent->tls_type & TLS_TPREL) != 0 + && !(gent->tls_type != 0 && bfd_link_executable (info) && SYMBOL_REFERENCES_LOCAL (info, h))) || (htab->elf.dynamic_sections_created @@ -9384,7 +9397,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) if (gent->got.refcount > 0) { if ((gent->tls_type & TLS_LD) != 0 - && !h->def_dynamic) + && SYMBOL_REFERENCES_LOCAL (info, h)) { ppc64_tlsld_got (gent->owner)->got.refcount += 1; *pgent = gent->next; @@ -9813,7 +9826,7 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd, htab->got_reli_size += rel_size; } else if (bfd_link_pic (info) - && !((ent->tls_type & TLS_TPREL) != 0 + && !(ent->tls_type != 0 && bfd_link_executable (info))) { asection *srel = ppc64_elf_tdata (ibfd)->relgot; @@ -9890,7 +9903,7 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd, ent->got.offset = s->size; ent->owner = ibfd; s->size += 16; - if (bfd_link_pic (info)) + if (bfd_link_dll (info)) { asection *srel = ppc64_elf_tdata (ibfd)->relgot; srel->size += sizeof (Elf64_External_Rela); @@ -12185,7 +12198,7 @@ ppc64_elf_layout_multitoc (struct bfd_link_info *info) htab->got_reli_size += rel_size; } else if (bfd_link_pic (info) - && !((ent->tls_type & TLS_TPREL) != 0 + && !(ent->tls_type != 0 && bfd_link_executable (info))) { asection *srel = ppc64_elf_tdata (ibfd)->relgot; @@ -12211,7 +12224,7 @@ ppc64_elf_layout_multitoc (struct bfd_link_info *info) asection *s = ppc64_elf_tdata (ibfd)->got; ent->got.offset = s->size; s->size += 16; - if (bfd_link_pic (info)) + if (bfd_link_dll (info)) { asection *srel = ppc64_elf_tdata (ibfd)->relgot; srel->size += sizeof (Elf64_External_Rela); @@ -14730,7 +14743,7 @@ ppc64_elf_relocate_section (bfd *output_bfd, stays with its arg setup insns, ie. that the next reloc is the __tls_get_addr call associated with the current reloc. Edit both insns. */ - if (input_section->has_tls_get_addr_call + if (input_section->nomark_tls_get_addr && rel + 1 < relend && branch_reloc_hash_match (input_bfd, rel + 1, htab->tls_get_addr, @@ -15611,8 +15624,7 @@ ppc64_elf_relocate_section (bfd *output_bfd, struct got_entry *ent; if (tls_type == (TLS_TLS | TLS_LD) - && (h == NULL - || !h->elf.def_dynamic)) + && SYMBOL_REFERENCES_LOCAL (info, &h->elf)) ent = ppc64_tlsld_got (input_bfd); else { @@ -15687,10 +15699,8 @@ ppc64_elf_relocate_section (bfd *output_bfd, else if (indx != 0 || (bfd_link_pic (info) && (h == NULL - || !UNDEFWEAK_NO_DYNAMIC_RELOC (info, &h->elf) - || (tls_type == (TLS_TLS | TLS_LD) - && !h->elf.def_dynamic)) - && !(tls_type == (TLS_TLS | TLS_TPREL) + || !UNDEFWEAK_NO_DYNAMIC_RELOC (info, &h->elf)) + && !(tls_type != 0 && bfd_link_executable (info) && SYMBOL_REFERENCES_LOCAL (info, &h->elf)))) relgot = ppc64_elf_tdata (ent->owner)->relgot;