2014-03-12 Aldy Hernandez Copy over bfd/elf64-ppc.c from upstream binutils-2_24-branch. Additional supporting changes to get elf64-ppc.c to build (tests, header files, etc). diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index 4688ddd..34ad362 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -643,7 +643,8 @@ enum elf_reloc_type_class { reloc_class_normal, reloc_class_relative, reloc_class_plt, - reloc_class_copy + reloc_class_copy, + reloc_class_ifunc }; struct elf_reloc_cookie @@ -1130,7 +1131,7 @@ struct elf_backend_data /* This function returns class of a reloc type. */ enum elf_reloc_type_class (*elf_backend_reloc_type_class) - (const Elf_Internal_Rela *); + (const struct bfd_link_info *, const asection *, const Elf_Internal_Rela *); /* This function, if defined, removes information about discarded functions from other sections which mention them. */ @@ -1788,7 +1789,8 @@ extern bfd_boolean _bfd_elf_can_make_relative (bfd *input_bfd, struct bfd_link_info *info, asection *eh_frame_section); extern enum elf_reloc_type_class _bfd_elf_reloc_type_class - (const Elf_Internal_Rela *); + (const struct bfd_link_info *, const asection *, + const Elf_Internal_Rela *); extern bfd_vma _bfd_elf_rela_local_sym (bfd *, Elf_Internal_Sym *, asection **, Elf_Internal_Rela *); extern bfd_vma _bfd_elf_rel_local_sym @@ -2156,6 +2158,8 @@ extern bfd_boolean _bfd_elf_default_relocs_compatible extern bfd_boolean _bfd_elf_relocs_compatible (const bfd_target *, const bfd_target *); +extern bfd_boolean _bfd_elf_notice_as_needed +(bfd *, struct bfd_link_info *, enum notice_asneeded_action); extern struct elf_link_hash_entry *_bfd_elf_archive_symbol_lookup (bfd *, struct bfd_link_info *, const char *); diff --git a/bfd/elf.c b/bfd/elf.c index dcbd50a..661fcc4 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -9877,7 +9877,9 @@ bfd_get_elf_phdrs (bfd *abfd, void *phdrs) } enum elf_reloc_type_class -_bfd_elf_reloc_type_class (const Elf_Internal_Rela *rela ATTRIBUTE_UNUSED) +_bfd_elf_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED, + const asection *rel_sec ATTRIBUTE_UNUSED, + const Elf_Internal_Rela *rela ATTRIBUTE_UNUSED) { return reloc_class_normal; } diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index a3680f2..2082441 100644 --- a/bfd/elf32-ppc.c +++ b/bfd/elf32-ppc.c @@ -9349,8 +9349,15 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd, } static enum elf_reloc_type_class -ppc_elf_reloc_type_class (const Elf_Internal_Rela *rela) +ppc_elf_reloc_type_class (const struct bfd_link_info *info, + const asection *rel_sec, + const Elf_Internal_Rela *rela) { + struct ppc_elf_link_hash_table *htab = ppc_elf_hash_table (info); + + if (rel_sec == htab->reliplt) + return reloc_class_ifunc; + switch (ELF32_R_TYPE (rela->r_info)) { case R_PPC_RELATIVE: diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index 80c2a4d..6ae78f3 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -97,7 +97,7 @@ static bfd_vma opd_entry_value #define elf_backend_copy_indirect_symbol ppc64_elf_copy_indirect_symbol #define elf_backend_add_symbol_hook ppc64_elf_add_symbol_hook #define elf_backend_check_directives ppc64_elf_process_dot_syms -#define elf_backend_as_needed_cleanup ppc64_elf_as_needed_cleanup +#define elf_backend_notice_as_needed ppc64_elf_notice_as_needed #define elf_backend_archive_symbol_lookup ppc64_elf_archive_symbol_lookup #define elf_backend_check_relocs ppc64_elf_check_relocs #define elf_backend_gc_keep ppc64_elf_gc_keep @@ -134,7 +134,7 @@ static bfd_vma opd_entry_value /* Offsets to some stack save slots. */ #define STK_LR 16 #define STK_TOC(htab) (htab->opd_abi ? 40 : 24) -/* This one is dodgy. ABIv2 does not have a linker word, so use the +/* This one is dodgy. ELFv2 does not have a linker word, so use the CR save slot. Used only by optimised __tls_get_addr call stub, relying on __tls_get_addr_opt not saving CR.. */ #define STK_LINKER(htab) (htab->opd_abi ? 32 : 8) @@ -2592,7 +2592,7 @@ ppc64_elf_toc_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, TOCstart = _bfd_get_gp_value (input_section->output_section->owner); if (TOCstart == 0) - TOCstart = ppc64_elf_toc (input_section->output_section->owner); + TOCstart = ppc64_elf_set_toc (NULL, input_section->output_section->owner); /* Subtract the TOC base address. */ reloc_entry->addend -= TOCstart + TOC_BASE_OFF; @@ -2615,7 +2615,7 @@ ppc64_elf_toc_ha_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, TOCstart = _bfd_get_gp_value (input_section->output_section->owner); if (TOCstart == 0) - TOCstart = ppc64_elf_toc (input_section->output_section->owner); + TOCstart = ppc64_elf_set_toc (NULL, input_section->output_section->owner); /* Subtract the TOC base address. */ reloc_entry->addend -= TOCstart + TOC_BASE_OFF; @@ -2642,7 +2642,7 @@ ppc64_elf_toc64_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, TOCstart = _bfd_get_gp_value (input_section->output_section->owner); if (TOCstart == 0) - TOCstart = ppc64_elf_toc (input_section->output_section->owner); + TOCstart = ppc64_elf_set_toc (NULL, input_section->output_section->owner); octets = reloc_entry->address * bfd_octets_per_byte (abfd); bfd_put_64 (abfd, TOCstart + TOC_BASE_OFF, (bfd_byte *) data + octets); @@ -2735,8 +2735,13 @@ struct ppc64_elf_obj_tdata sections means we potentially need one of these for each input bfd. */ struct got_entry tlsld_got; - /* A copy of relocs before they are modified for --emit-relocs. */ - Elf_Internal_Rela *opd_relocs; + union { + /* A copy of relocs before they are modified for --emit-relocs. */ + Elf_Internal_Rela *relocs; + + /* Section contents. */ + bfd_byte *contents; + } opd; /* Nonzero if this bfd has small toc/got relocs, ie. that expect the reloc to be in the range -32768 to 32767. */ @@ -3768,9 +3773,6 @@ struct ppc_stub_hash_entry { struct ppc_link_hash_entry *h; struct plt_entry *plt_ent; - /* And the reloc addend that this was derived from. */ - bfd_vma addend; - /* Where this stub is being called from, or, in the case of combined stub sections, the first input section in the group. */ asection *id_sec; @@ -3791,6 +3793,21 @@ struct ppc_branch_hash_entry { unsigned int iter; }; +/* Used to track dynamic relocations for local symbols. */ +struct ppc_dyn_relocs +{ + struct ppc_dyn_relocs *next; + + /* The input section of the reloc. */ + asection *sec; + + /* Total number of relocs copied for the input section. */ + unsigned int count : 31; + + /* Whether this entry is for STT_GNU_IFUNC symbols. */ + unsigned int ifunc : 1; +}; + struct ppc_link_hash_entry { struct elf_link_hash_entry elf; @@ -3892,12 +3909,7 @@ struct ppc_link_hash_table /* List of input sections for each output section. */ asection **input_list; - /* Short-cuts to get to dynamic linker sections. */ - asection *got; - asection *plt; - asection *relplt; - asection *iplt; - asection *reliplt; + /* Shortcuts to get to dynamic linker sections. */ asection *dynbss; asection *relbss; asection *glink; @@ -3910,9 +3922,6 @@ struct ppc_link_hash_table struct ppc_link_hash_entry *tls_get_addr; struct ppc_link_hash_entry *tls_get_addr_fd; - /* The special .TOC. symbol. */ - struct ppc_link_hash_entry *dot_toc_dot; - /* The size of reliplt used by got entry relocs. */ bfd_size_type got_reli_size; @@ -4204,9 +4213,85 @@ ppc64_elf_link_hash_table_free (struct bfd_link_hash_table *hash) _bfd_elf_link_hash_table_free (hash); } +/* Create sections for linker generated code. */ + +static bfd_boolean +create_linkage_sections (bfd *dynobj, struct bfd_link_info *info) +{ + struct ppc_link_hash_table *htab; + flagword flags; + + htab = ppc_hash_table (info); + + /* Create .sfpr for code to save and restore fp regs. */ + flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_READONLY + | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED); + htab->sfpr = bfd_make_section_anyway_with_flags (dynobj, ".sfpr", + flags); + if (htab->sfpr == NULL + || ! bfd_set_section_alignment (dynobj, htab->sfpr, 2)) + return FALSE; + + /* Create .glink for lazy dynamic linking support. */ + htab->glink = bfd_make_section_anyway_with_flags (dynobj, ".glink", + flags); + if (htab->glink == NULL + || ! 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 (dynobj, htab->glink_eh_frame, 2)) + return FALSE; + } + + flags = SEC_ALLOC | SEC_LINKER_CREATED; + htab->elf.iplt = bfd_make_section_anyway_with_flags (dynobj, ".iplt", flags); + if (htab->elf.iplt == NULL + || ! bfd_set_section_alignment (dynobj, htab->elf.iplt, 3)) + return FALSE; + + flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY + | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED); + htab->elf.irelplt + = bfd_make_section_anyway_with_flags (dynobj, ".rela.iplt", flags); + if (htab->elf.irelplt == NULL + || ! bfd_set_section_alignment (dynobj, htab->elf.irelplt, 3)) + return FALSE; + + /* Create branch lookup table for plt_branch stubs. */ + flags = (SEC_ALLOC | SEC_LOAD + | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED); + htab->brlt = bfd_make_section_anyway_with_flags (dynobj, ".branch_lt", + flags); + if (htab->brlt == NULL + || ! bfd_set_section_alignment (dynobj, htab->brlt, 3)) + return FALSE; + + if (!info->shared) + return TRUE; + + flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY + | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED); + htab->relbrlt = bfd_make_section_anyway_with_flags (dynobj, + ".rela.branch_lt", + flags); + if (htab->relbrlt == NULL + || ! bfd_set_section_alignment (dynobj, htab->relbrlt, 3)) + return FALSE; + + return TRUE; +} + /* Satisfy the ELF linker by filling in some fields in our fake bfd. */ -void +bfd_boolean ppc64_elf_init_stub_bfd (bfd *abfd, struct bfd_link_info *info) { struct ppc_link_hash_table *htab; @@ -4218,9 +4303,14 @@ ppc64_elf_init_stub_bfd (bfd *abfd, struct bfd_link_info *info) the start of the output TOC section. */ htab = ppc_hash_table (info); if (htab == NULL) - return; + return FALSE; htab->stub_bfd = abfd; htab->elf.dynobj = abfd; + + if (info->relocatable) + return TRUE; + + return create_linkage_sections (htab->elf.dynobj, info); } /* Build a name for an entry in the stub hash table. */ @@ -4370,85 +4460,6 @@ ppc_add_stub (const char *stub_name, return stub_entry; } -/* Create sections for linker generated code. */ - -static bfd_boolean -create_linkage_sections (bfd *dynobj, struct bfd_link_info *info) -{ - struct ppc_link_hash_table *htab; - flagword flags; - - htab = ppc_hash_table (info); - if (htab == NULL) - return FALSE; - - /* Create .sfpr for code to save and restore fp regs. */ - flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_READONLY - | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED); - htab->sfpr = bfd_make_section_anyway_with_flags (dynobj, ".sfpr", - flags); - if (htab->sfpr == NULL - || ! bfd_set_section_alignment (dynobj, htab->sfpr, 2)) - return FALSE; - - /* Create .glink for lazy dynamic linking support. */ - htab->glink = bfd_make_section_anyway_with_flags (dynobj, ".glink", - flags); - if (htab->glink == NULL - || ! 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 (dynobj, 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 - || ! bfd_set_section_alignment (dynobj, htab->iplt, 3)) - return FALSE; - - flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY - | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED); - htab->reliplt = bfd_make_section_anyway_with_flags (dynobj, - ".rela.iplt", - flags); - if (htab->reliplt == NULL - || ! bfd_set_section_alignment (dynobj, htab->reliplt, 3)) - return FALSE; - - /* Create branch lookup table for plt_branch stubs. */ - flags = (SEC_ALLOC | SEC_LOAD - | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED); - htab->brlt = bfd_make_section_anyway_with_flags (dynobj, ".branch_lt", - flags); - if (htab->brlt == NULL - || ! bfd_set_section_alignment (dynobj, htab->brlt, 3)) - return FALSE; - - if (!info->shared) - return TRUE; - - flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY - | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED); - htab->relbrlt = bfd_make_section_anyway_with_flags (dynobj, - ".rela.branch_lt", - flags); - if (htab->relbrlt == NULL - || ! bfd_set_section_alignment (dynobj, htab->relbrlt, 3)) - return FALSE; - - return TRUE; -} - /* Create .got and .rela.got sections in ABFD, and .got in dynobj if not already done. */ @@ -4464,15 +4475,9 @@ create_got_section (bfd *abfd, struct bfd_link_info *info) if (htab == NULL) return FALSE; - if (!htab->got) - { - if (! _bfd_elf_create_got_section (htab->elf.dynobj, info)) - return FALSE; - - htab->got = bfd_get_linker_section (htab->elf.dynobj, ".got"); - if (!htab->got) - abort (); - } + if (!htab->elf.sgot + && !_bfd_elf_create_got_section (htab->elf.dynobj, info)) + return FALSE; flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED); @@ -4507,15 +4512,11 @@ ppc64_elf_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info) if (htab == NULL) return FALSE; - if (!htab->got) - htab->got = bfd_get_linker_section (dynobj, ".got"); - htab->plt = bfd_get_linker_section (dynobj, ".plt"); - htab->relplt = bfd_get_linker_section (dynobj, ".rela.plt"); htab->dynbss = bfd_get_linker_section (dynobj, ".dynbss"); if (!info->shared) htab->relbss = bfd_get_linker_section (dynobj, ".rela.bss"); - if (!htab->got || !htab->plt || !htab->relplt || !htab->dynbss + if (!htab->elf.sgot || !htab->elf.splt || !htab->elf.srelplt || !htab->dynbss || (!info->shared && !htab->relbss)) abort (); @@ -4941,7 +4942,12 @@ ppc64_elf_process_dot_syms (bfd *ibfd, struct bfd_link_info *info) while ((eh = *p) != NULL) { *p = NULL; - if (!add_symbol_adjust (eh, info)) + if (&eh->elf == htab->elf.hgot) + ; + else if (htab->elf.hgot == NULL + && strcmp (eh->elf.root.root.string, ".TOC.") == 0) + htab->elf.hgot = &eh->elf; + else if (!add_symbol_adjust (eh, info)) return FALSE; p = &eh->u.next_dot_sym; } @@ -4968,17 +4974,22 @@ ppc64_elf_process_dot_syms (bfd *ibfd, struct bfd_link_info *info) /* Undo hash table changes when an --as-needed input file is determined not to be needed. */ +__attribute__((unused)) static bfd_boolean -ppc64_elf_as_needed_cleanup (bfd *ibfd ATTRIBUTE_UNUSED, - struct bfd_link_info *info) +ppc64_elf_notice_as_needed (bfd *ibfd, + struct bfd_link_info *info, + enum notice_asneeded_action act) { - struct ppc_link_hash_table *htab = ppc_hash_table (info); + if (act == notice_not_needed) + { + struct ppc_link_hash_table *htab = ppc_hash_table (info); - if (htab == NULL) - return FALSE; + if (htab == NULL) + return FALSE; - htab->dot_syms = NULL; - return TRUE; + htab->dot_syms = NULL; + } + return _bfd_elf_notice_as_needed (ibfd, info, act); } /* If --just-symbols against a final linked binary, then assume we need @@ -4991,10 +5002,8 @@ ppc64_elf_link_just_syms (asection *sec, struct bfd_link_info *info) && (sec->owner->flags & (EXEC_P | DYNAMIC)) != 0 && is_ppc64_elf (sec->owner)) { - asection *got = bfd_get_section_by_name (sec->owner, ".got"); - if (got != NULL - && got->size >= elf_backend_got_header_size - && bfd_get_section_by_name (sec->owner, ".opd") != NULL) + if (abiversion (sec->owner) >= 2 + || bfd_get_section_by_name (sec->owner, ".opd") != NULL) sec->has_toc_reloc = 1; } _bfd_elf_link_just_syms (sec, info); @@ -5162,10 +5171,6 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, ppc64_elf_section_data (sec)->sec_type = sec_opd; } - if (htab->sfpr == NULL - && !create_linkage_sections (htab->elf.dynobj, info)) - return FALSE; - rel_end = relocs + sec->reloc_count; for (rel = relocs; rel < rel_end; rel++) { @@ -5183,6 +5188,13 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, { h = sym_hashes[r_symndx - symtab_hdr->sh_info]; h = elf_follow_link (h); + + /* PR15323, ref flags aren't set for references in the same + object. */ + h->root.non_ir_ref = 1; + + if (h == htab->elf.hgot) + sec->has_toc_reloc = 1; } tls_type = 0; @@ -5656,7 +5668,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, if ((info->shared && (must_be_dyn_reloc (info, r_type) || (h != NULL - && (! info->symbolic + && (!SYMBOLIC_BIND (info, h) || h->root.type == bfd_link_hash_defweak || !h->def_regular)))) || (ELIMINATE_COPY_RELOCS @@ -5667,9 +5679,6 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, || (!info->shared && ifunc != NULL)) { - struct elf_dyn_relocs *p; - struct elf_dyn_relocs **head; - /* We must copy these reloc types into the output file. Create a reloc section in dynobj and make room for this reloc. */ @@ -5686,13 +5695,34 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, relocations we need for this symbol. */ if (h != NULL) { + struct elf_dyn_relocs *p; + struct elf_dyn_relocs **head; + head = &((struct ppc_link_hash_entry *) h)->dyn_relocs; + p = *head; + if (p == NULL || p->sec != sec) + { + p = bfd_alloc (htab->elf.dynobj, sizeof *p); + if (p == NULL) + return FALSE; + p->next = *head; + *head = p; + p->sec = sec; + p->count = 0; + p->pc_count = 0; + } + p->count += 1; + if (!must_be_dyn_reloc (info, r_type)) + p->pc_count += 1; } else { /* Track dynamic relocs needed for local syms too. We really need local syms available to do this easily. Oh well. */ + struct ppc_dyn_relocs *p; + struct ppc_dyn_relocs **head; + bfd_boolean is_ifunc; asection *s; void *vpp; Elf_Internal_Sym *isym; @@ -5707,25 +5737,24 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, s = sec; vpp = &elf_section_data (s)->local_dynrel; - head = (struct elf_dyn_relocs **) vpp; - } - - p = *head; - if (p == NULL || p->sec != sec) - { - p = bfd_alloc (htab->elf.dynobj, sizeof *p); - if (p == NULL) - return FALSE; - p->next = *head; - *head = p; - p->sec = sec; - p->count = 0; - p->pc_count = 0; + head = (struct ppc_dyn_relocs **) vpp; + is_ifunc = ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC; + p = *head; + if (p != NULL && p->sec == sec && p->ifunc != is_ifunc) + p = p->next; + if (p == NULL || p->sec != sec || p->ifunc != is_ifunc) + { + p = bfd_alloc (htab->elf.dynobj, sizeof *p); + if (p == NULL) + return FALSE; + p->next = *head; + *head = p; + p->sec = sec; + p->ifunc = is_ifunc; + p->count = 0; + } + p->count += 1; } - - p->count += 1; - if (!must_be_dyn_reloc (info, r_type)) - p->pc_count += 1; } break; @@ -5828,12 +5857,16 @@ opd_entry_value (asection *opd_sec, at a final linked executable with addr2line or somesuch. */ if (opd_sec->reloc_count == 0) { - char buf[8]; + bfd_byte *contents = ppc64_elf_tdata (opd_bfd)->opd.contents; - if (!bfd_get_section_contents (opd_bfd, opd_sec, buf, offset, 8)) - return (bfd_vma) -1; + if (contents == NULL) + { + if (!bfd_malloc_and_get_section (opd_bfd, opd_sec, &contents)) + return (bfd_vma) -1; + ppc64_elf_tdata (opd_bfd)->opd.contents = contents; + } - val = bfd_get_64 (opd_bfd, buf); + val = bfd_get_64 (opd_bfd, contents + offset); if (code_sec != NULL) { asection *sec, *likely = NULL; @@ -5865,7 +5898,7 @@ opd_entry_value (asection *opd_sec, BFD_ASSERT (is_ppc64_elf (opd_bfd)); - relocs = ppc64_elf_tdata (opd_bfd)->opd_relocs; + relocs = ppc64_elf_tdata (opd_bfd)->opd.relocs; if (relocs == NULL) relocs = _bfd_elf_link_read_relocs (opd_bfd, opd_sec, NULL, NULL, TRUE); @@ -5921,11 +5954,30 @@ opd_entry_value (asection *opd_sec, sym_hashes = elf_sym_hashes (opd_bfd); rh = sym_hashes[symndx - symtab_hdr->sh_info]; - rh = elf_follow_link (rh); - BFD_ASSERT (rh->root.type == bfd_link_hash_defined - || rh->root.type == bfd_link_hash_defweak); - val = rh->root.u.def.value; - sec = rh->root.u.def.section; + if (rh != NULL) + { + rh = elf_follow_link (rh); + BFD_ASSERT (rh->root.type == bfd_link_hash_defined + || rh->root.type == bfd_link_hash_defweak); + val = rh->root.u.def.value; + sec = rh->root.u.def.section; + } + else + { + /* Handle the odd case where we can be called + during bfd_elf_link_add_symbols before the + symbol hashes have been fully populated. */ + Elf_Internal_Sym *sym; + + sym = bfd_elf_get_elf_syms (opd_bfd, symtab_hdr, 1, + symndx, NULL, NULL, NULL); + if (sym == NULL) + break; + + val = sym->st_value; + sec = bfd_section_from_elf_index (opd_bfd, sym->st_shndx); + free (sym); + } } val += look->r_addend; if (code_off != NULL) @@ -6782,6 +6834,21 @@ ppc64_elf_func_desc_adjust (bfd *obfd ATTRIBUTE_UNUSED, if (htab == NULL) return FALSE; + if (!info->relocatable + && htab->elf.hgot != NULL) + { + _bfd_elf_link_hash_hide_symbol (info, htab->elf.hgot, TRUE); + /* Make .TOC. defined so as to prevent it being made dynamic. + The wrong value here is fixed later in ppc64_elf_set_toc. */ + htab->elf.hgot->type = STT_OBJECT; + htab->elf.hgot->root.type = bfd_link_hash_defined; + htab->elf.hgot->root.u.def.value = 0; + htab->elf.hgot->root.u.def.section = bfd_abs_section_ptr; + htab->elf.hgot->def_regular = 1; + htab->elf.hgot->other = ((htab->elf.hgot->other & ~ELF_ST_VISIBILITY (-1)) + | STV_HIDDEN); + } + if (htab->sfpr == NULL) /* We don't have any relocs. */ return TRUE; @@ -7267,7 +7334,7 @@ adjust_opd_syms (struct elf_link_hash_entry *h, void *inf ATTRIBUTE_UNUSED) } /* Handles decrementing dynamic reloc counts for the reloc specified by - R_INFO in section SEC. If LOCAL_SYMS is NULL, then H and SYM_SEC + R_INFO in section SEC. If LOCAL_SYMS is NULL, then H and SYM have already been determined. */ static bfd_boolean @@ -7276,11 +7343,10 @@ dec_dynrel_count (bfd_vma r_info, struct bfd_link_info *info, Elf_Internal_Sym **local_syms, struct elf_link_hash_entry *h, - asection *sym_sec) + Elf_Internal_Sym *sym) { enum elf_ppc64_reloc_type r_type; - struct elf_dyn_relocs *p; - struct elf_dyn_relocs **pp; + asection *sym_sec = NULL; /* Can this reloc be dynamic? This switch, and later tests here should be kept in sync with the code in check_relocs. */ @@ -7339,7 +7405,6 @@ dec_dynrel_count (bfd_vma r_info, if (local_syms != NULL) { unsigned long r_symndx; - Elf_Internal_Sym *sym; bfd *ibfd = sec->owner; r_symndx = ELF64_R_SYM (r_info); @@ -7350,7 +7415,7 @@ dec_dynrel_count (bfd_vma r_info, if ((info->shared && (must_be_dyn_reloc (info, r_type) || (h != NULL - && (!info->symbolic + && (!SYMBOLIC_BIND (info, h) || h->root.type == bfd_link_hash_defweak || !h->def_regular)))) || (ELIMINATE_COPY_RELOCS @@ -7363,40 +7428,62 @@ dec_dynrel_count (bfd_vma r_info, return TRUE; if (h != NULL) - pp = &((struct ppc_link_hash_entry *) h)->dyn_relocs; - else { - if (sym_sec != NULL) - { - void *vpp = &elf_section_data (sym_sec)->local_dynrel; - pp = (struct elf_dyn_relocs **) vpp; - } - else + struct elf_dyn_relocs *p; + struct elf_dyn_relocs **pp; + pp = &((struct ppc_link_hash_entry *) h)->dyn_relocs; + + /* elf_gc_sweep may have already removed all dyn relocs associated + with local syms for a given section. Also, symbol flags are + changed by elf_gc_sweep_symbol, confusing the test above. Don't + report a dynreloc miscount. */ + if (*pp == NULL && info->gc_sections) + return TRUE; + + while ((p = *pp) != NULL) { - void *vpp = &elf_section_data (sec)->local_dynrel; - pp = (struct elf_dyn_relocs **) vpp; + if (p->sec == sec) + { + if (!must_be_dyn_reloc (info, r_type)) + p->pc_count -= 1; + p->count -= 1; + if (p->count == 0) + *pp = p->next; + return TRUE; + } + pp = &p->next; } } + else + { + struct ppc_dyn_relocs *p; + struct ppc_dyn_relocs **pp; + void *vpp; + bfd_boolean is_ifunc; - /* elf_gc_sweep may have already removed all dyn relocs associated - with local syms for a given section. Also, symbol flags are - changed by elf_gc_sweep_symbol, confusing the test above. Don't - report a dynreloc miscount. */ - if (*pp == NULL && info->gc_sections) - return TRUE; + if (local_syms == NULL) + sym_sec = bfd_section_from_elf_index (sec->owner, sym->st_shndx); + if (sym_sec == NULL) + sym_sec = sec; - while ((p = *pp) != NULL) - { - if (p->sec == sec) + vpp = &elf_section_data (sym_sec)->local_dynrel; + pp = (struct ppc_dyn_relocs **) vpp; + + if (*pp == NULL && info->gc_sections) + return TRUE; + + is_ifunc = ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC; + while ((p = *pp) != NULL) { - if (!must_be_dyn_reloc (info, r_type)) - p->pc_count -= 1; - p->count -= 1; - if (p->count == 0) - *pp = p->next; - return TRUE; + if (p->sec == sec && p->ifunc == is_ifunc) + { + p->count -= 1; + if (p->count == 0) + *pp = p->next; + return TRUE; + } + pp = &p->next; } - pp = &p->next; } info->callbacks->einfo (_("%P: dynreloc miscount for %B, section %A\n"), @@ -7729,7 +7816,7 @@ ppc64_elf_edit_opd (struct bfd_link_info *info, bfd_boolean non_overlapping) if (!NO_OPD_RELOCS && !info->relocatable && !dec_dynrel_count (rel->r_info, sec, info, - NULL, h, sym_sec)) + NULL, h, sym)) goto error_ret; } else @@ -8339,13 +8426,13 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info) /* If we got rid of a DTPMOD/DTPREL reloc pair then we'll lose one or two dyn relocs. */ if (!dec_dynrel_count (rel->r_info, sec, info, - NULL, h, sym_sec)) + NULL, h, sym)) return FALSE; if (tls_set == (TLS_EXPLICIT | TLS_GD)) { if (!dec_dynrel_count ((rel + 1)->r_info, sec, info, - NULL, h, sym_sec)) + NULL, h, sym)) return FALSE; } } @@ -9137,19 +9224,18 @@ allocate_got (struct elf_link_hash_entry *h, got->size += entsize; dyn = htab->elf.dynamic_sections_created; - if ((info->shared - || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)) - && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT - || h->root.type != bfd_link_hash_undefweak)) + if (h->type == STT_GNU_IFUNC) { - asection *relgot = ppc64_elf_tdata (gent->owner)->relgot; - relgot->size += rentsize; + htab->elf.irelplt->size += rentsize; + htab->got_reli_size += rentsize; } - else if (h->type == STT_GNU_IFUNC) + else if ((info->shared + || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)) + && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT + || h->root.type != bfd_link_hash_undefweak)) { - asection *relgot = htab->reliplt; + asection *relgot = ppc64_elf_tdata (gent->owner)->relgot; relgot->size += rentsize; - htab->got_reli_size += rentsize; } } @@ -9207,16 +9293,16 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) if (!htab->elf.dynamic_sections_created || h->dynindx == -1) { - s = htab->iplt; + s = htab->elf.iplt; pent->plt.offset = s->size; s->size += PLT_ENTRY_SIZE (htab); - s = htab->reliplt; + s = htab->elf.irelplt; } else { /* If this is the first .plt entry, make room for the special first entry. */ - s = htab->plt; + s = htab->elf.splt; if (s->size == 0) s->size += PLT_INITIAL_ENTRY_SIZE (htab); @@ -9240,7 +9326,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) s->size += 4; /* We also need to make an entry in the .rela.plt section. */ - s = htab->relplt; + s = htab->elf.srelplt; } s->size += sizeof (Elf64_External_Rela); doneone = TRUE; @@ -9330,8 +9416,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) if (eh->dyn_relocs == NULL || (!htab->elf.dynamic_sections_created - && (h->type != STT_GNU_IFUNC - || !htab->opd_abi))) + && h->type != STT_GNU_IFUNC)) return TRUE; /* In the shared -Bsymbolic case, discard space allocated for @@ -9419,8 +9504,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) for (p = eh->dyn_relocs; p != NULL; p = p->next) { asection *sreloc = elf_section_data (p->sec)->sreloc; - if (!htab->elf.dynamic_sections_created) - sreloc = htab->reliplt; + if (eh->elf.type == STT_GNU_IFUNC) + sreloc = htab->elf.irelplt; sreloc->size += p->count * sizeof (Elf64_External_Rela); } @@ -9535,14 +9620,13 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd, unsigned char *lgot_masks; bfd_size_type locsymcount; Elf_Internal_Shdr *symtab_hdr; - asection *srel; if (!is_ppc64_elf (ibfd)) continue; for (s = ibfd->sections; s != NULL; s = s->next) { - struct elf_dyn_relocs *p; + struct ppc_dyn_relocs *p; for (p = elf_section_data (s)->local_dynrel; p != NULL; p = p->next) { @@ -9556,9 +9640,9 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd, } else if (p->count != 0) { - srel = elf_section_data (p->sec)->sreloc; - if (!htab->elf.dynamic_sections_created) - srel = htab->reliplt; + asection *srel = elf_section_data (p->sec)->sreloc; + if (p->ifunc) + srel = htab->elf.irelplt; srel->size += p->count * sizeof (Elf64_External_Rela); if ((p->sec->output_section->flags & SEC_READONLY) != 0) info->flags |= DF_TEXTREL; @@ -9577,7 +9661,6 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd, end_local_plt = local_plt + locsymcount; lgot_masks = (unsigned char *) end_local_plt; s = ppc64_elf_tdata (ibfd)->got; - srel = ppc64_elf_tdata (ibfd)->relgot; for (; lgot_ents < end_lgot_ents; ++lgot_ents, ++lgot_masks) { struct got_entry **pent, *ent; @@ -9593,19 +9676,25 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd, } else { - unsigned int num = 1; + unsigned int ent_size = 8; + unsigned int rel_size = sizeof (Elf64_External_Rela); + ent->got.offset = s->size; if ((ent->tls_type & *lgot_masks & TLS_GD) != 0) - num = 2; - s->size += num * 8; - if (info->shared) - srel->size += num * sizeof (Elf64_External_Rela); - else if ((*lgot_masks & PLT_IFUNC) != 0) { - htab->reliplt->size - += num * sizeof (Elf64_External_Rela); - htab->got_reli_size - += num * sizeof (Elf64_External_Rela); + ent_size *= 2; + rel_size *= 2; + } + s->size += ent_size; + if ((*lgot_masks & PLT_IFUNC) != 0) + { + htab->elf.irelplt->size += rel_size; + htab->got_reli_size += rel_size; + } + else if (info->shared) + { + asection *srel = ppc64_elf_tdata (ibfd)->relgot; + srel->size += rel_size; } pent = &ent->next; } @@ -9622,11 +9711,11 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd, for (ent = *local_plt; ent != NULL; ent = ent->next) if (ent->plt.refcount > 0) { - s = htab->iplt; + s = htab->elf.iplt; ent->plt.offset = s->size; s->size += PLT_ENTRY_SIZE (htab); - htab->reliplt->size += sizeof (Elf64_External_Rela); + htab->elf.irelplt->size += sizeof (Elf64_External_Rela); } else ent->plt.offset = (bfd_vma) -1; @@ -9689,9 +9778,9 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd, if (s == htab->brlt || s == htab->relbrlt) /* These haven't been allocated yet; don't strip. */ continue; - else if (s == htab->got - || s == htab->plt - || s == htab->iplt + else if (s == htab->elf.sgot + || s == htab->elf.splt + || s == htab->elf.iplt || s == htab->glink || s == htab->dynbss) { @@ -9708,7 +9797,7 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd, { if (s->size != 0) { - if (s != htab->relplt) + if (s != htab->elf.srelplt) relocs = TRUE; /* We use the reloc_count field as a counter if we need @@ -9758,7 +9847,7 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd, continue; s = ppc64_elf_tdata (ibfd)->got; - if (s != NULL && s != htab->got) + if (s != NULL && s != htab->elf.sgot) { if (s->size == 0) s->flags |= SEC_EXCLUDE; @@ -9803,7 +9892,7 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd, return FALSE; } - if (htab->plt != NULL && htab->plt->size != 0) + if (htab->elf.splt != NULL && htab->elf.splt->size != 0) { if (!add_dynamic_entry (DT_PLTGOT, 0) || !add_dynamic_entry (DT_PLTRELSZ, 0) @@ -10509,8 +10598,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) r[0].r_offset = loc - stub_entry->stub_sec->contents; if (bfd_big_endian (info->output_bfd)) r[0].r_offset += 2; - if (stub_entry->stub_type == ppc_stub_plt_branch_r2off - && htab->opd_abi) + if (stub_entry->stub_type == ppc_stub_plt_branch_r2off) r[0].r_offset += 4; r[0].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_DS); r[0].r_addend = dest; @@ -10523,8 +10611,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) } } - if (stub_entry->stub_type != ppc_stub_plt_branch_r2off - || !htab->opd_abi) + if (stub_entry->stub_type != ppc_stub_plt_branch_r2off) { if (PPC_HA (off) != 0) { @@ -10543,7 +10630,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) { bfd_vma r2off = get_r2off (info, stub_entry); - if (r2off == 0) + if (r2off == 0 && htab->opd_abi) { htab->stub_error = TRUE; return FALSE; @@ -10551,28 +10638,29 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) bfd_put_32 (htab->stub_bfd, STD_R2_0R1 + STK_TOC (htab), loc); loc += 4; - size = 20; + size = 16; if (PPC_HA (off) != 0) { size += 4; bfd_put_32 (htab->stub_bfd, ADDIS_R11_R2 | PPC_HA (off), loc); loc += 4; bfd_put_32 (htab->stub_bfd, LD_R12_0R11 | PPC_LO (off), loc); - loc += 4; } else - { - bfd_put_32 (htab->stub_bfd, LD_R12_0R2 | PPC_LO (off), loc); - loc += 4; - } + bfd_put_32 (htab->stub_bfd, LD_R12_0R2 | PPC_LO (off), loc); if (PPC_HA (r2off) != 0) { size += 4; + loc += 4; bfd_put_32 (htab->stub_bfd, ADDIS_R2_R2 | PPC_HA (r2off), loc); + } + if (PPC_LO (r2off) != 0) + { + size += 4; loc += 4; + bfd_put_32 (htab->stub_bfd, ADDI_R2_R2 | PPC_LO (r2off), loc); } - bfd_put_32 (htab->stub_bfd, ADDI_R2_R2 | PPC_LO (r2off), loc); } loc += 4; bfd_put_32 (htab->stub_bfd, MTCTR_R12, loc); @@ -10605,11 +10693,11 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) if (dest >= (bfd_vma) -2) abort (); - plt = htab->plt; + plt = htab->elf.splt; if (!htab->elf.dynamic_sections_created || stub_entry->h == NULL || stub_entry->h->elf.dynindx == -1) - plt = htab->iplt; + plt = htab->elf.iplt; dest += plt->output_offset + plt->output_section->vma; @@ -10628,8 +10716,8 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) + stub_entry->target_section->output_offset + stub_entry->target_section->output_section->vma); - rl = (htab->reliplt->contents - + (htab->reliplt->reloc_count++ + rl = (htab->elf.irelplt->contents + + (htab->elf.irelplt->reloc_count++ * sizeof (Elf64_External_Rela))); bfd_elf64_swap_reloca_out (info->output_bfd, &rela, rl); stub_entry->plt_ent->plt.offset |= 1; @@ -10664,10 +10752,11 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) 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)))); + ((PPC_HA (off) != 0) + + (htab->opd_abi + ? 2 + (htab->plt_static_chain + && PPC_HA (off + 16) == PPC_HA (off)) + : 1))); if (r == NULL) return FALSE; r[0].r_offset = loc - stub_entry->stub_sec->contents; @@ -10759,11 +10848,11 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) off = stub_entry->plt_ent->plt.offset & ~(bfd_vma) 1; if (off >= (bfd_vma) -2) abort (); - plt = htab->plt; + plt = htab->elf.splt; if (!htab->elf.dynamic_sections_created || stub_entry->h == NULL || stub_entry->h->elf.dynindx == -1) - plt = htab->iplt; + plt = htab->elf.iplt; off += (plt->output_offset + plt->output_section->vma - elf_gp (plt->output_section->owner) @@ -10866,8 +10955,7 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) stub_entry->stub_sec->flags |= SEC_RELOC; } - if (stub_entry->stub_type != ppc_stub_plt_branch_r2off - || !htab->opd_abi) + if (stub_entry->stub_type != ppc_stub_plt_branch_r2off) { size = 12; if (PPC_HA (off) != 0) @@ -10875,12 +10963,14 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) } else { - size = 20; + size = 16; if (PPC_HA (off) != 0) size += 4; if (PPC_HA (r2off) != 0) size += 4; + if (PPC_LO (r2off) != 0) + size += 4; } } else if (info->emitrelocations) @@ -10917,9 +11007,6 @@ ppc64_elf_setup_section_lists htab->add_stub_section = add_stub_section; htab->layout_sections_again = layout_sections_again; - if (htab->brlt == NULL) - return 0; - /* Find the top input section id. */ for (input_bfd = info->input_bfds, top_id = 3; input_bfd != NULL; @@ -10972,8 +11059,7 @@ ppc64_elf_start_multitoc_partition (struct bfd_link_info *info) { struct ppc_link_hash_table *htab = ppc_hash_table (info); - elf_gp (info->output_bfd) = ppc64_elf_toc (info->output_bfd); - htab->toc_curr = elf_gp (info->output_bfd); + htab->toc_curr = ppc64_elf_set_toc (info, info->output_bfd); htab->toc_bfd = NULL; htab->toc_first_sec = NULL; } @@ -11134,8 +11220,8 @@ ppc64_elf_layout_multitoc (struct bfd_link_info *info) } /* Zap sizes of got sections. */ - htab->reliplt->rawsize = htab->reliplt->size; - htab->reliplt->size -= htab->got_reli_size; + htab->elf.irelplt->rawsize = htab->elf.irelplt->size; + htab->elf.irelplt->size -= htab->got_reli_size; htab->got_reli_size = 0; for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) @@ -11167,7 +11253,7 @@ ppc64_elf_layout_multitoc (struct bfd_link_info *info) unsigned char *lgot_masks; bfd_size_type locsymcount; Elf_Internal_Shdr *symtab_hdr; - asection *s, *srel; + asection *s; if (!is_ppc64_elf (ibfd)) continue; @@ -11183,26 +11269,31 @@ ppc64_elf_layout_multitoc (struct bfd_link_info *info) end_local_plt = local_plt + locsymcount; lgot_masks = (unsigned char *) end_local_plt; s = ppc64_elf_tdata (ibfd)->got; - srel = ppc64_elf_tdata (ibfd)->relgot; for (; lgot_ents < end_lgot_ents; ++lgot_ents, ++lgot_masks) { struct got_entry *ent; for (ent = *lgot_ents; ent != NULL; ent = ent->next) { - unsigned int num = 1; + unsigned int ent_size = 8; + unsigned int rel_size = sizeof (Elf64_External_Rela); + ent->got.offset = s->size; if ((ent->tls_type & *lgot_masks & TLS_GD) != 0) - num = 2; - s->size += num * 8; - if (info->shared) - srel->size += num * sizeof (Elf64_External_Rela); - else if ((*lgot_masks & PLT_IFUNC) != 0) { - htab->reliplt->size - += num * sizeof (Elf64_External_Rela); - htab->got_reli_size - += num * sizeof (Elf64_External_Rela); + ent_size *= 2; + rel_size *= 2; + } + s->size += ent_size; + if ((*lgot_masks & PLT_IFUNC) != 0) + { + htab->elf.irelplt->size += rel_size; + htab->got_reli_size += rel_size; + } + else if (info->shared) + { + asection *srel = ppc64_elf_tdata (ibfd)->relgot; + srel->size += rel_size; } } } @@ -11232,7 +11323,7 @@ ppc64_elf_layout_multitoc (struct bfd_link_info *info) } } - done_something = htab->reliplt->rawsize != htab->reliplt->size; + done_something = htab->elf.irelplt->rawsize != htab->elf.irelplt->size; if (!done_something) for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) { @@ -11517,42 +11608,25 @@ ppc64_elf_next_input_section (struct bfd_link_info *info, asection *isec) if (htab->multi_toc_needed) { - /* If a code section has a function that uses the TOC then we need - to use the right TOC (obviously). Also, make sure that .opd gets - the correct TOC value for R_PPC64_TOC relocs that don't have or - can't find their function symbol (shouldn't ever happen now). - Also specially treat .fixup for the linux kernel. .fixup - contains branches, but only back to the function that hit an - exception. */ - if (isec->has_toc_reloc - || (isec->flags & SEC_CODE) == 0 - || strcmp (isec->name, ".fixup") == 0) + /* Analyse sections that aren't already flagged as needing a + valid toc pointer. Exclude .fixup for the linux kernel. + .fixup contains branches, but only back to the function that + hit an exception. */ + if (!(isec->has_toc_reloc + || (isec->flags & SEC_CODE) == 0 + || strcmp (isec->name, ".fixup") == 0 + || isec->call_check_done)) { - if (elf_gp (isec->owner) != 0) - htab->toc_curr = elf_gp (isec->owner); - } - else - { - if (!isec->call_check_done - && toc_adjusting_stub_needed (info, isec) < 0) + if (toc_adjusting_stub_needed (info, isec) < 0) return FALSE; - /* If we make a local call from this section, ie. a branch - without a following nop, then we have no place to put a - toc restoring insn. We must use the same toc group as - the callee. - Testing makes_toc_func_call actually tests for *any* - calls to functions that need a good toc pointer. A more - precise test would be better, as this one will set - incorrect values for pasted .init/.fini fragments. - (Fixed later in check_pasted_section.) */ - if (isec->makes_toc_func_call - && elf_gp (isec->owner) != 0) - htab->toc_curr = elf_gp (isec->owner); - } - } - - /* Functions that don't use the TOC can belong in any TOC group. - Use the last TOC base. */ + } + /* Make all sections use the TOC assigned for this object file. + This will be wrong for pasted sections; We fix that in + check_pasted_section(). */ + if (elf_gp (isec->owner) != 0) + htab->toc_curr = elf_gp (isec->owner); + } + htab->stub_group[isec->id].toc_off = htab->toc_curr; return TRUE; } @@ -11805,9 +11879,6 @@ ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size, } } htab->plt_thread_safe = plt_thread_safe; - htab->dot_toc_dot = ((struct ppc_link_hash_entry *) - elf_link_hash_lookup (&htab->elf, ".TOC.", - FALSE, FALSE, TRUE)); stubs_always_before_branch = group_size < 0; if (group_size < 0) stub_group_size = -group_size; @@ -12105,7 +12176,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size, } stub_entry->h = hash; stub_entry->plt_ent = plt_ent; - stub_entry->addend = irela->r_addend; + stub_entry->other = hash ? hash->elf.other : sym->st_other; if (stub_entry->h != NULL) htab->stub_globals += 1; @@ -12214,7 +12285,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size, move, we'll be called again. Provide a value for TOCstart. */ bfd_vma -ppc64_elf_toc (bfd *obfd) +ppc64_elf_set_toc (struct bfd_link_info *info, bfd *obfd) { asection *s; bfd_vma TOCstart; @@ -12265,6 +12336,19 @@ ppc64_elf_toc (bfd *obfd) if (s != NULL) TOCstart = s->output_section->vma + s->output_offset; + _bfd_set_gp_value (obfd, TOCstart); + + if (info != NULL && s != NULL && is_ppc64_elf (obfd)) + { + struct ppc_link_hash_table *htab = ppc_hash_table (info); + + if (htab != NULL + && htab->elf.hgot != NULL) + { + htab->elf.hgot->root.u.def.value = TOC_BASE_OFF; + htab->elf.hgot->root.u.def.section = s; + } + } return TOCstart; } @@ -12303,10 +12387,10 @@ build_global_entry_stubs (struct elf_link_hash_entry *h, void *inf) bfd_vma off; p = s->contents + h->root.u.def.value; - plt = htab->plt; + plt = htab->elf.splt; if (!htab->elf.dynamic_sections_created || h->dynindx == -1) - plt = htab->iplt; + plt = htab->elf.iplt; off = pent->plt.offset + plt->output_offset + plt->output_section->vma; off -= h->root.u.def.value + s->output_offset + s->output_section->vma; @@ -12394,7 +12478,9 @@ ppc64_elf_build_stubs (bfd_boolean emit_stub_syms, h->non_elf = 0; } } - plt0 = htab->plt->output_section->vma + htab->plt->output_offset - 16; + plt0 = (htab->elf.splt->output_section->vma + + htab->elf.splt->output_offset + - 16); if (info->emitrelocations) { Elf_Internal_Rela *r = get_relocs (htab->glink, 1); @@ -12882,8 +12968,7 @@ ppc64_elf_relocate_section (bfd *output_bfd, } else { - bfd_boolean ignored; - + int ignored; RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, r_symndx, symtab_hdr, sym_hashes, h_elf, sec, relocation, @@ -12917,13 +13002,6 @@ ppc64_elf_relocate_section (bfd *output_bfd, } } } - if (h_elf == &htab->dot_toc_dot->elf) - { - relocation = (TOCstart - + htab->stub_group[input_section->id].toc_off); - sec = bfd_abs_section_ptr; - unresolved_reloc = FALSE; - } } h = (struct ppc_link_hash_entry *) h_elf; @@ -12936,6 +13014,14 @@ ppc64_elf_relocate_section (bfd *output_bfd, if (info->relocatable) continue; + if (h != NULL && &h->elf == htab->elf.hgot) + { + relocation = (TOCstart + + htab->stub_group[input_section->id].toc_off); + sec = bfd_abs_section_ptr; + unresolved_reloc = FALSE; + } + /* TLS optimizations. Replace instruction sequences and relocs based on information we collected in tls_optimize. We edit RELOCS so that --emit-relocs will output something sensible @@ -13491,60 +13577,90 @@ ppc64_elf_relocate_section (bfd *output_bfd, { bfd_boolean can_plt_call = FALSE; + /* All of these stubs will modify r2, so there must be a + branch and link followed by a nop. The nop is + replaced by an insn to restore r2. */ if (rel->r_offset + 8 <= input_section->size) { - unsigned long nop; - nop = bfd_get_32 (input_bfd, contents + rel->r_offset + 4); - if (nop == NOP - || nop == CROR_151515 || nop == CROR_313131) + unsigned long br; + + br = bfd_get_32 (input_bfd, + contents + rel->r_offset); + if ((br & 1) != 0) { - if (h != NULL - && (h == htab->tls_get_addr_fd - || h == htab->tls_get_addr) - && !htab->no_tls_get_addr_opt) + unsigned long nop; + + nop = bfd_get_32 (input_bfd, + contents + rel->r_offset + 4); + if (nop == NOP + || nop == CROR_151515 || nop == CROR_313131) { - /* Special stub used, leave nop alone. */ + if (h != NULL + && (h == htab->tls_get_addr_fd + || h == htab->tls_get_addr) + && !htab->no_tls_get_addr_opt) + { + /* Special stub used, leave nop alone. */ + } + else + bfd_put_32 (input_bfd, + LD_R2_0R1 + STK_TOC (htab), + contents + rel->r_offset + 4); + can_plt_call = TRUE; } - else - bfd_put_32 (input_bfd, LD_R2_40R1, - contents + rel->r_offset + 4); - can_plt_call = TRUE; } } - if (!can_plt_call) + if (!can_plt_call && h != NULL) { - if (stub_entry->stub_type == ppc_stub_plt_call - || stub_entry->stub_type == ppc_stub_plt_call_r2save) - { - /* If this is a plain branch rather than a branch - and link, don't require a nop. However, don't - allow tail calls in a shared library as they - will result in r2 being corrupted. */ - unsigned long br; - br = bfd_get_32 (input_bfd, contents + rel->r_offset); - if (info->executable && (br & 1) == 0) - can_plt_call = TRUE; - else - stub_entry = NULL; - } - else if (h != NULL - && strcmp (h->elf.root.root.string, - ".__libc_start_main") == 0) + const char *name = h->elf.root.root.string; + + if (*name == '.') + ++name; + + if (strncmp (name, "__libc_start_main", 17) == 0 + && (name[17] == 0 || name[17] == '@')) { - /* Allow crt1 branch to go via a toc adjusting stub. */ + /* Allow crt1 branch to go via a toc adjusting + stub. Other calls that never return could do + the same, if we could detect such. */ can_plt_call = TRUE; } - else + } + + if (!can_plt_call) + { + /* g++ as of 20130507 emits self-calls without a + following nop. This is arguably wrong since we + have conflicting information. On the one hand a + global symbol and on the other a local call + sequence, but don't error for this special case. + It isn't possible to cheaply verify we have + exactly such a call. Allow all calls to the same + section. */ + asection *code_sec = sec; + + if (get_opd_info (sec) != NULL) { - info->callbacks->einfo - (_("%P: %H: call to `%T' lacks nop, can't restore toc; " - "recompile with -fPIC"), - input_bfd, input_section, rel->r_offset, sym_name); + bfd_vma off = (relocation + addend + - sec->output_section->vma + - sec->output_offset); - bfd_set_error (bfd_error_bad_value); - ret = FALSE; + opd_entry_value (sec, off, &code_sec, NULL, FALSE); } + if (code_sec == input_section) + can_plt_call = TRUE; + } + + if (!can_plt_call) + { + info->callbacks->einfo + (_("%P: %H: call to `%T' lacks nop, can't restore toc; " + "recompile with -fPIC\n"), + input_bfd, input_section, rel->r_offset, sym_name); + + bfd_set_error (bfd_error_bad_value); + ret = FALSE; } if (can_plt_call @@ -13790,15 +13906,15 @@ ppc64_elf_relocate_section (bfd *output_bfd, ifunc = (h != NULL ? h->elf.type == STT_GNU_IFUNC : ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC); - if ((info->shared || indx != 0) - && (h == NULL - || (tls_type == (TLS_TLS | TLS_LD) - && !h->elf.def_dynamic) - || ELF_ST_VISIBILITY (h->elf.other) == STV_DEFAULT - || h->elf.root.type != bfd_link_hash_undefweak)) + if (ifunc) + relgot = htab->elf.irelplt; + else if ((info->shared || indx != 0) + && (h == NULL + || (tls_type == (TLS_TLS | TLS_LD) + && !h->elf.def_dynamic) + || ELF_ST_VISIBILITY (h->elf.other) == STV_DEFAULT + || h->elf.root.type != bfd_link_hash_undefweak)) relgot = ppc64_elf_tdata (ent->owner)->relgot; - else if (ifunc) - relgot = htab->reliplt; if (relgot != NULL) { outrel.r_offset = (got->output_section->vma @@ -13905,15 +14021,15 @@ ppc64_elf_relocate_section (bfd *output_bfd, symbol. This happens when statically linking PIC code, or when using -Bsymbolic. Go find a match if there is a PLT entry. */ - if (htab->plt != NULL) + if (htab->elf.splt != NULL) { struct plt_entry *ent; for (ent = h->elf.plt.plist; ent != NULL; ent = ent->next) if (ent->plt.offset != (bfd_vma) -1 && ent->addend == orig_rel.r_addend) { - relocation = (htab->plt->output_section->vma - + htab->plt->output_offset + relocation = (htab->elf.splt->output_section->vma + + htab->elf.splt->output_offset + ent->plt.offset); unresolved_reloc = FALSE; break; @@ -14125,9 +14241,6 @@ ppc64_elf_relocate_section (bfd *output_bfd, { BFD_ASSERT (h->elf.dynindx != -1); 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 { @@ -14222,8 +14335,10 @@ ppc64_elf_relocate_section (bfd *output_bfd, } sreloc = elf_section_data (input_section)->sreloc; - if (!htab->elf.dynamic_sections_created) - sreloc = htab->reliplt; + if (h != NULL + ? h->elf.type == STT_GNU_IFUNC + : ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC) + sreloc = htab->elf.irelplt; if (sreloc == NULL) abort (); @@ -14529,8 +14644,8 @@ ppc64_elf_relocate_section (bfd *output_bfd, bfd_size_type amt; amt = input_section->reloc_count * sizeof (Elf_Internal_Rela); rel = bfd_alloc (input_bfd, amt); - BFD_ASSERT (ppc64_elf_tdata (input_bfd)->opd_relocs == NULL); - ppc64_elf_tdata (input_bfd)->opd_relocs = rel; + BFD_ASSERT (ppc64_elf_tdata (input_bfd)->opd.relocs == NULL); + ppc64_elf_tdata (input_bfd)->opd.relocs = rel; if (rel == NULL) return FALSE; memcpy (rel, relocs, amt); @@ -14600,8 +14715,8 @@ ppc64_elf_finish_dynamic_symbol (bfd *output_bfd, && h->def_regular && (h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak)); - rela.r_offset = (htab->iplt->output_section->vma - + htab->iplt->output_offset + rela.r_offset = (htab->elf.iplt->output_section->vma + + htab->elf.iplt->output_offset + ent->plt.offset); if (htab->opd_abi) rela.r_info = ELF64_R_INFO (0, R_PPC64_JMP_IREL); @@ -14611,18 +14726,18 @@ ppc64_elf_finish_dynamic_symbol (bfd *output_bfd, + h->root.u.def.section->output_offset + h->root.u.def.section->output_section->vma + ent->addend); - loc = (htab->reliplt->contents - + (htab->reliplt->reloc_count++ + loc = (htab->elf.irelplt->contents + + (htab->elf.irelplt->reloc_count++ * sizeof (Elf64_External_Rela))); } else { - rela.r_offset = (htab->plt->output_section->vma - + htab->plt->output_offset + rela.r_offset = (htab->elf.splt->output_section->vma + + htab->elf.splt->output_offset + ent->plt.offset); rela.r_info = ELF64_R_INFO (h->dynindx, R_PPC64_JMP_SLOT); rela.r_addend = ent->addend; - loc = (htab->relplt->contents + loc = (htab->elf.srelplt->contents + ((ent->plt.offset - PLT_INITIAL_ENTRY_SIZE (htab)) / PLT_ENTRY_SIZE (htab) * sizeof (Elf64_External_Rela))); } @@ -14680,9 +14795,15 @@ ppc64_elf_finish_dynamic_symbol (bfd *output_bfd, dynamic linker, before writing them out. */ static enum elf_reloc_type_class -ppc64_elf_reloc_type_class (const Elf_Internal_Rela *rela) +ppc64_elf_reloc_type_class (const struct bfd_link_info *info, + const asection *rel_sec, + const Elf_Internal_Rela *rela) { enum elf_ppc64_reloc_type r_type; + struct ppc_link_hash_table *htab = ppc_hash_table (info); + + if (rel_sec == htab->elf.irelplt) + return reloc_class_ifunc; r_type = ELF64_R_TYPE (rela->r_info); switch (r_type) @@ -14719,7 +14840,7 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd, { Elf64_External_Dyn *dyncon, *dynconend; - if (sdyn == NULL || htab->got == NULL) + if (sdyn == NULL || htab->elf.sgot == NULL) abort (); dyncon = (Elf64_External_Dyn *) sdyn->contents; @@ -14766,23 +14887,23 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd, break; case DT_PLTGOT: - s = htab->plt; + s = htab->elf.splt; dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; break; case DT_JMPREL: - s = htab->relplt; + s = htab->elf.srelplt; dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; break; case DT_PLTRELSZ: - dyn.d_un.d_val = htab->relplt->size; + dyn.d_un.d_val = htab->elf.srelplt->size; break; case DT_RELASZ: /* Don't count procedure linkage table relocs in the overall reloc count. */ - s = htab->relplt; + s = htab->elf.srelplt; if (s == NULL) continue; dyn.d_un.d_val -= s->size; @@ -14792,7 +14913,7 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd, /* We may not be using the standard ELF linker script. If .rela.plt is the first .rela section, we adjust DT_RELA to not include it. */ - s = htab->relplt; + s = htab->elf.srelplt; if (s == NULL) continue; if (dyn.d_un.d_ptr != s->output_section->vma + s->output_offset) @@ -14805,22 +14926,22 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd, } } - if (htab->got != NULL && htab->got->size != 0) + if (htab->elf.sgot != NULL && htab->elf.sgot->size != 0) { /* Fill in the first entry in the global offset table. We use it to hold the link-time TOCbase. */ bfd_put_64 (output_bfd, elf_gp (output_bfd) + TOC_BASE_OFF, - htab->got->contents); + htab->elf.sgot->contents); /* Set .got entry size. */ - elf_section_data (htab->got->output_section)->this_hdr.sh_entsize = 8; + elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize = 8; } - if (htab->plt != NULL && htab->plt->size != 0) + if (htab->elf.splt != NULL && htab->elf.splt->size != 0) { /* Set .plt entry size. */ - elf_section_data (htab->plt->output_section)->this_hdr.sh_entsize + elf_section_data (htab->elf.splt->output_section)->this_hdr.sh_entsize = PLT_ENTRY_SIZE (htab); } diff --git a/bfd/elf64-ppc.h b/bfd/elf64-ppc.h index 2728b27..06c655f 100644 --- a/bfd/elf64-ppc.h +++ b/bfd/elf64-ppc.h @@ -19,7 +19,7 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ -void ppc64_elf_init_stub_bfd +bfd_boolean ppc64_elf_init_stub_bfd (bfd *, struct bfd_link_info *); bfd_boolean ppc64_elf_edit_opd (struct bfd_link_info *, bfd_boolean); @@ -31,8 +31,8 @@ bfd_boolean ppc64_elf_edit_toc (struct bfd_link_info *); bfd_boolean ppc64_elf_has_small_toc_reloc (asection *); -bfd_vma ppc64_elf_toc - (bfd *); +bfd_vma ppc64_elf_set_toc + (struct bfd_link_info *, bfd *); int ppc64_elf_setup_section_lists (struct bfd_link_info *, asection *(*) (const char *, asection *), void (*) (void)); diff --git a/bfd/elflink.c b/bfd/elflink.c index c319183..0c963e1 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -8493,7 +8493,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) struct elf_link_sort_rela *s = (struct elf_link_sort_rela *) p; (*swap_in) (abfd, erel, s->rela); - s->type = (*bed->elf_backend_reloc_type_class) (s->rela); + s->type = (*bed->elf_backend_reloc_type_class) (info, o, s->rela); s->u.sym_mask = r_sym_mask; p += sort_elt; erel += ext_size; diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h index 86c9b1b..97e0918 100644 --- a/bfd/elfxx-target.h +++ b/bfd/elfxx-target.h @@ -424,6 +424,9 @@ #ifndef elf_backend_check_directives #define elf_backend_check_directives 0 #endif +#ifndef elf_backend_notice_as_needed +#define elf_backend_notice_as_needed _bfd_elf_notice_as_needed +#endif #ifndef elf_backend_as_needed_cleanup #define elf_backend_as_needed_cleanup 0 #endif diff --git a/ld/emultempl/ppc64elf.em b/ld/emultempl/ppc64elf.em index bad3e2c..4239f90 100644 --- a/ld/emultempl/ppc64elf.em +++ b/ld/emultempl/ppc64elf.em @@ -423,7 +423,7 @@ ppc_layout_sections_again (void) if (!link_info.relocatable) _bfd_set_gp_value (link_info.output_bfd, - ppc64_elf_toc (link_info.output_bfd)); + ppc64_elf_set_toc (&link_info, link_info.output_bfd)); need_laying_out = -1; } @@ -525,7 +525,7 @@ gld${EMULATION_NAME}_after_allocation (void) if (!link_info.relocatable) _bfd_set_gp_value (link_info.output_bfd, - ppc64_elf_toc (link_info.output_bfd)); + ppc64_elf_set_toc (&link_info, link_info.output_bfd)); } } diff --git a/ld/testsuite/ld-powerpc/powerpc.exp b/ld/testsuite/ld-powerpc/powerpc.exp index 837ad64..87e4ea8 100644 --- a/ld/testsuite/ld-powerpc/powerpc.exp +++ b/ld/testsuite/ld-powerpc/powerpc.exp @@ -82,7 +82,7 @@ proc supports_ppc64 { } { global ld catch "exec $ld --help | grep emulations" tmp - if [ string match "*elf64ppc*" $tmp ] then { + if [ regexp "elf64l?ppc" $tmp ] then { return 1 } else { return 0 @@ -243,7 +243,7 @@ set ppceabitests { } if [istarget "powerpc*le*-*-*"] then { - set options_regsub(ld) {-melf32ppc -melf32lppc} + set options_regsub(ld) {{-melf([3264]*)ppc} {-melf\1lppc}} for {set i 0} {$i < [llength $ppcelftests]} {incr i} { set line [lindex $ppcelftests $i] @@ -255,7 +255,7 @@ if [istarget "powerpc*le*-*-*"] then { if [ supports_ppc64 ] then { for {set i 0} {$i < [llength $ppc64elftests]} {incr i} { - set line [lindex $ppcelftests $i] + set line [lindex $ppc64elftests $i] set ld_options [lindex $line 1] regsub -all elf64ppc $ld_options elf64lppc ld_options set line [lreplace $line 1 1 $ld_options] diff --git a/ld/testsuite/ld-powerpc/tlsexe.d b/ld/testsuite/ld-powerpc/tlsexe.d index 0d5ee40..747b5e1 100644 --- a/ld/testsuite/ld-powerpc/tlsexe.d +++ b/ld/testsuite/ld-powerpc/tlsexe.d @@ -8,13 +8,13 @@ Disassembly of section \.text: -.* <00000010\.plt_call\.__tls_get_addr(|_opt)>: +.* <.*plt_call\.__tls_get_addr(|_opt)>: .* (e9 63 00 00|00 00 63 e9) ld r11,0\(r3\) .* (e9 83 00 08|08 00 83 e9) ld r12,8\(r3\) .* (7c 60 1b 78|78 1b 60 7c) mr r0,r3 .* (2c 2b 00 00|00 00 2b 2c) cmpdi r11,0 .* (7c 6c 6a 14|14 6a 6c 7c) add r3,r12,r13 -.* (4d 82 00 20|20 00 82 4d) beqlr +.* (4d 82 00 20|20 00 82 4d) beqlr * .* (7c 03 03 78|78 03 03 7c) mr r3,r0 .* (7d 68 02 a6|a6 02 68 7d) mflr r11 .* (f9 61 00 20|20 00 61 f9) std r11,32\(r1\) diff --git a/ld/testsuite/ld-powerpc/tlsexe.r b/ld/testsuite/ld-powerpc/tlsexe.r index 72ef3f4..f78f300 100644 --- a/ld/testsuite/ld-powerpc/tlsexe.r +++ b/ld/testsuite/ld-powerpc/tlsexe.r @@ -1,7 +1,7 @@ #source: tls.s #source: tlslib.s #as: -a64 -#ld: +#ld: #readelf: -WSsrl #target: powerpc64*-*-* @@ -45,11 +45,11 @@ Program Headers: Section to Segment mapping: +Segment Sections\.\.\. +0+ + - +01 +\.interp - +02 +\.interp \.hash \.dynsym \.dynstr \.rela\.dyn \.rela\.plt \.text - +03 +\.tdata \.dynamic \.opd \.got \.plt - +04 +\.dynamic - +05 +\.tdata \.tbss + +01 +\.interp * + +02 +\.interp \.hash \.dynsym \.dynstr \.rela\.dyn \.rela\.plt \.text * + +03 +\.tdata \.dynamic \.opd \.got \.plt * + +04 +\.dynamic * + +05 +\.tdata \.tbss * Relocation section '\.rela\.dyn' at offset .* contains 3 entries: +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend @@ -63,7 +63,7 @@ Relocation section '\.rela\.plt' at offset .* contains 1 entries: Symbol table '\.dynsym' contains [0-9]+ entries: +Num: +Value +Size +Type +Bind +Vis +Ndx +Name -.* NOTYPE +LOCAL +DEFAULT +UND +.* NOTYPE +LOCAL +DEFAULT +UND * .* TLS +GLOBAL +DEFAULT +UND gd .* TLS +GLOBAL +DEFAULT +UND ld .* TLS +GLOBAL +DEFAULT +9 ld2 @@ -74,20 +74,20 @@ Symbol table '\.dynsym' contains [0-9]+ entries: Symbol table '\.symtab' contains [0-9]+ entries: +Num: +Value +Size +Type +Bind +Vis +Ndx +Name -.* 0+ +0 +NOTYPE +LOCAL +DEFAULT +UND -.* SECTION +LOCAL +DEFAULT +1 -.* SECTION +LOCAL +DEFAULT +2 -.* SECTION +LOCAL +DEFAULT +3 -.* SECTION +LOCAL +DEFAULT +4 -.* SECTION +LOCAL +DEFAULT +5 -.* SECTION +LOCAL +DEFAULT +6 -.* SECTION +LOCAL +DEFAULT +7 -.* SECTION +LOCAL +DEFAULT +8 -.* SECTION +LOCAL +DEFAULT +9 -.* SECTION +LOCAL +DEFAULT +10 -.* SECTION +LOCAL +DEFAULT +11 -.* SECTION +LOCAL +DEFAULT +12 -.* SECTION +LOCAL +DEFAULT +13 +.* 0+ +0 +NOTYPE +LOCAL +DEFAULT +UND * +.* SECTION +LOCAL +DEFAULT +1 * +.* SECTION +LOCAL +DEFAULT +2 * +.* SECTION +LOCAL +DEFAULT +3 * +.* SECTION +LOCAL +DEFAULT +4 * +.* SECTION +LOCAL +DEFAULT +5 * +.* SECTION +LOCAL +DEFAULT +6 * +.* SECTION +LOCAL +DEFAULT +7 * +.* SECTION +LOCAL +DEFAULT +8 * +.* SECTION +LOCAL +DEFAULT +9 * +.* SECTION +LOCAL +DEFAULT +10 * +.* SECTION +LOCAL +DEFAULT +11 * +.* SECTION +LOCAL +DEFAULT +12 * +.* SECTION +LOCAL +DEFAULT +13 * .* FILE +LOCAL +DEFAULT +ABS .* .* TLS +LOCAL +DEFAULT +8 gd4 .* TLS +LOCAL +DEFAULT +8 ld4 @@ -98,9 +98,9 @@ Symbol table '\.symtab' contains [0-9]+ entries: .* TLS +LOCAL +DEFAULT +8 le5 .* (FUNC|NOTYPE) +LOCAL +DEFAULT +UND \.__tls_get_addr(|_opt) .* FILE +LOCAL +DEFAULT +ABS .* -.* NOTYPE +LOCAL +DEFAULT +7 00000010\.plt_call\.__tls_get_addr(|_opt) .* OBJECT +LOCAL +DEFAULT +10 _DYNAMIC .* NOTYPE +LOCAL +DEFAULT +7 __glink_PLTresolve +.* NOTYPE +LOCAL +DEFAULT +7 .*\.plt_call\.__tls_get_addr(|_opt) .* GLOBAL +DEFAULT +UND gd .* GLOBAL +DEFAULT +9 le0 .* GLOBAL +DEFAULT +9 ld0 diff --git a/ld/testsuite/ld-powerpc/tlsexetoc.d b/ld/testsuite/ld-powerpc/tlsexetoc.d index ee0f3b2..f38ca9c 100644 --- a/ld/testsuite/ld-powerpc/tlsexetoc.d +++ b/ld/testsuite/ld-powerpc/tlsexetoc.d @@ -8,13 +8,13 @@ Disassembly of section \.text: -.* <00000010\.plt_call\.__tls_get_addr(|_opt)>: +.* <.*plt_call\.__tls_get_addr(|_opt)>: .* (e9 63 00 00|00 00 63 e9) ld r11,0\(r3\) .* (e9 83 00 08|08 00 83 e9) ld r12,8\(r3\) .* (7c 60 1b 78|78 1b 60 7c) mr r0,r3 .* (2c 2b 00 00|00 00 2b 2c) cmpdi r11,0 .* (7c 6c 6a 14|14 6a 6c 7c) add r3,r12,r13 -.* (4d 82 00 20|20 00 82 4d) beqlr +.* (4d 82 00 20|20 00 82 4d) beqlr * .* (7c 03 03 78|78 03 03 7c) mr r3,r0 .* (7d 68 02 a6|a6 02 68 7d) mflr r11 .* (f9 61 00 20|20 00 61 f9) std r11,32\(r1\) diff --git a/ld/testsuite/ld-powerpc/tlsexetoc.g b/ld/testsuite/ld-powerpc/tlsexetoc.g index dc563ad..b75c8e6 100644 --- a/ld/testsuite/ld-powerpc/tlsexetoc.g +++ b/ld/testsuite/ld-powerpc/tlsexetoc.g @@ -4,7 +4,7 @@ #objdump: -sj.got #target: powerpc64*-*-* -.*: +file format elf64-powerpc +.* Contents of section \.got: .* (00000000|d8850110) (100185d8|00000000) 00000000 00000000 .* diff --git a/ld/testsuite/ld-powerpc/tlsexetoc.r b/ld/testsuite/ld-powerpc/tlsexetoc.r index e6f606b..d238f26 100644 --- a/ld/testsuite/ld-powerpc/tlsexetoc.r +++ b/ld/testsuite/ld-powerpc/tlsexetoc.r @@ -1,7 +1,7 @@ #source: tlslib.s #source: tlstoc.s #as: -a64 -#ld: +#ld: #readelf: -WSsrl #target: powerpc64*-*-* @@ -45,11 +45,11 @@ Program Headers: Section to Segment mapping: +Segment Sections\.\.\. +0+ + - +01 +\.interp - +02 +\.interp \.hash \.dynsym \.dynstr \.rela\.dyn \.rela\.plt \.text - +03 +\.tdata \.dynamic \.opd \.got \.plt - +04 +\.dynamic - +05 +\.tdata \.tbss + +01 +\.interp * + +02 +\.interp \.hash \.dynsym \.dynstr \.rela\.dyn \.rela\.plt \.text * + +03 +\.tdata \.dynamic \.opd \.got \.plt * + +04 +\.dynamic * + +05 +\.tdata \.tbss * Relocation section '\.rela\.dyn' at offset .* contains 3 entries: +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend @@ -63,7 +63,7 @@ Relocation section '\.rela\.plt' at offset .* contains 1 entries: Symbol table '\.dynsym' contains [0-9]+ entries: +Num: +Value +Size +Type +Bind +Vis +Ndx +Name -.* NOTYPE +LOCAL +DEFAULT +UND +.* NOTYPE +LOCAL +DEFAULT +UND * .* TLS +GLOBAL +DEFAULT +UND gd .* TLS +GLOBAL +DEFAULT +UND ld .* NOTYPE +GLOBAL +DEFAULT +13 __bss_start @@ -73,20 +73,20 @@ Symbol table '\.dynsym' contains [0-9]+ entries: Symbol table '\.symtab' contains [0-9]+ entries: +Num: +Value +Size +Type +Bind +Vis +Ndx +Name -.* NOTYPE +LOCAL +DEFAULT +UND -.* SECTION +LOCAL +DEFAULT +1 -.* SECTION +LOCAL +DEFAULT +2 -.* SECTION +LOCAL +DEFAULT +3 -.* SECTION +LOCAL +DEFAULT +4 -.* SECTION +LOCAL +DEFAULT +5 -.* SECTION +LOCAL +DEFAULT +6 -.* SECTION +LOCAL +DEFAULT +7 -.* SECTION +LOCAL +DEFAULT +8 -.* SECTION +LOCAL +DEFAULT +9 -.* SECTION +LOCAL +DEFAULT +10 -.* SECTION +LOCAL +DEFAULT +11 -.* SECTION +LOCAL +DEFAULT +12 -.* SECTION +LOCAL +DEFAULT +13 +.* NOTYPE +LOCAL +DEFAULT +UND * +.* SECTION +LOCAL +DEFAULT +1 * +.* SECTION +LOCAL +DEFAULT +2 * +.* SECTION +LOCAL +DEFAULT +3 * +.* SECTION +LOCAL +DEFAULT +4 * +.* SECTION +LOCAL +DEFAULT +5 * +.* SECTION +LOCAL +DEFAULT +6 * +.* SECTION +LOCAL +DEFAULT +7 * +.* SECTION +LOCAL +DEFAULT +8 * +.* SECTION +LOCAL +DEFAULT +9 * +.* SECTION +LOCAL +DEFAULT +10 * +.* SECTION +LOCAL +DEFAULT +11 * +.* SECTION +LOCAL +DEFAULT +12 * +.* SECTION +LOCAL +DEFAULT +13 * .* FILE +LOCAL +DEFAULT +ABS .* .* TLS +LOCAL +DEFAULT +8 gd4 .* TLS +LOCAL +DEFAULT +8 ld4 @@ -98,9 +98,9 @@ Symbol table '\.symtab' contains [0-9]+ entries: .* NOTYPE +LOCAL +DEFAULT +12 \.Lie0 .* (FUNC|NOTYPE) +LOCAL +DEFAULT +UND \.__tls_get_addr(|_opt) .* FILE +LOCAL +DEFAULT +ABS .* -.* NOTYPE +LOCAL +DEFAULT +7 00000010\.plt_call\.__tls_get_addr(|_opt) .* OBJECT +LOCAL +DEFAULT +10 _DYNAMIC .* NOTYPE +LOCAL +DEFAULT +7 __glink_PLTresolve +.* NOTYPE +LOCAL +DEFAULT +7 .*\.plt_call\.__tls_get_addr(|_opt) .* TLS +GLOBAL +DEFAULT +UND gd .* TLS +GLOBAL +DEFAULT +9 le0 .* TLS +GLOBAL +DEFAULT +9 ld0 diff --git a/ld/testsuite/ld-powerpc/tlsso.d b/ld/testsuite/ld-powerpc/tlsso.d index e64184d..7fe7e87 100644 --- a/ld/testsuite/ld-powerpc/tlsso.d +++ b/ld/testsuite/ld-powerpc/tlsso.d @@ -4,17 +4,17 @@ #objdump: -dr #target: powerpc64*-*-* -.*: +file format elf64-powerpc +.* Disassembly of section \.text: -.* <00000010\.plt_call\.__tls_get_addr(|_opt)>: +.* <.*plt_call\.__tls_get_addr(|_opt)>: .* (f8 41 00 28|28 00 41 f8) std r2,40\(r1\) .* (e9 82 80 78|78 80 82 e9) ld r12,-32648\(r2\) .* (7d 89 03 a6|a6 03 89 7d) mtctr r12 .* (e8 42 80 80|80 80 42 e8) ld r2,-32640\(r2\) .* (28 22 00 00|00 00 22 28) cmpldi r2,0 -.* (4c e2 04 20|20 04 e2 4c) bnectr\+ +.* (4c e2 04 20|20 04 e2 4c) bnectr\+ * .* (48 00 00 ..|.. 00 00 48) b .* <__tls_get_addr@plt> .* <\._start>: diff --git a/ld/testsuite/ld-powerpc/tlsso.g b/ld/testsuite/ld-powerpc/tlsso.g index 8fd3ce0..0ba9fda 100644 --- a/ld/testsuite/ld-powerpc/tlsso.g +++ b/ld/testsuite/ld-powerpc/tlsso.g @@ -4,7 +4,7 @@ #objdump: -sj.got #target: powerpc64*-*-* -.*: +file format elf64-powerpc +.* Contents of section \.got: 107e0 (00000000|e0870100) (000187e0|00000000) 00000000 00000000 .* diff --git a/ld/testsuite/ld-powerpc/tlsso.r b/ld/testsuite/ld-powerpc/tlsso.r index 6464be0..ddaaebc 100644 --- a/ld/testsuite/ld-powerpc/tlsso.r +++ b/ld/testsuite/ld-powerpc/tlsso.r @@ -39,10 +39,10 @@ Program Headers: Section to Segment mapping: +Segment Sections\.\.\. - +0+ +\.hash \.dynsym \.dynstr \.rela\.dyn \.rela\.plt \.text - +01 +\.tdata \.dynamic \.opd \.got \.plt - +02 +\.dynamic - +03 +\.tdata \.tbss + +0+ +\.hash \.dynsym \.dynstr \.rela\.dyn \.rela\.plt \.text * + +01 +\.tdata \.dynamic \.opd \.got \.plt * + +02 +\.dynamic * + +03 +\.tdata \.tbss * Relocation section '\.rela\.dyn' at offset .* contains 18 entries: +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend @@ -71,9 +71,9 @@ Relocation section '\.rela\.plt' at offset .* contains 1 entries: Symbol table '\.dynsym' contains [0-9]+ entries: +Num: +Value +Size +Type +Bind +Vis +Ndx +Name -.* NOTYPE +LOCAL +DEFAULT +UND -.* SECTION +LOCAL +DEFAULT +6 -.* SECTION +LOCAL +DEFAULT +7 +.* NOTYPE +LOCAL +DEFAULT +UND * +.* SECTION +LOCAL +DEFAULT +6 * +.* SECTION +LOCAL +DEFAULT +7 * .* TLS +GLOBAL +DEFAULT +UND gd .* TLS +GLOBAL +DEFAULT +8 le0 .* NOTYPE +GLOBAL +DEFAULT +UND __tls_get_addr @@ -91,19 +91,19 @@ Symbol table '\.dynsym' contains [0-9]+ entries: Symbol table '\.symtab' contains [0-9]+ entries: +Num: +Value +Size +Type +Bind +Vis +Ndx +Name -.* NOTYPE +LOCAL +DEFAULT +UND -.* SECTION +LOCAL +DEFAULT +1 -.* SECTION +LOCAL +DEFAULT +2 -.* SECTION +LOCAL +DEFAULT +3 -.* SECTION +LOCAL +DEFAULT +4 -.* SECTION +LOCAL +DEFAULT +5 -.* SECTION +LOCAL +DEFAULT +6 -.* SECTION +LOCAL +DEFAULT +7 -.* SECTION +LOCAL +DEFAULT +8 -.* SECTION +LOCAL +DEFAULT +9 -.* SECTION +LOCAL +DEFAULT +10 -.* SECTION +LOCAL +DEFAULT +11 -.* SECTION +LOCAL +DEFAULT +12 +.* NOTYPE +LOCAL +DEFAULT +UND * +.* SECTION +LOCAL +DEFAULT +1 * +.* SECTION +LOCAL +DEFAULT +2 * +.* SECTION +LOCAL +DEFAULT +3 * +.* SECTION +LOCAL +DEFAULT +4 * +.* SECTION +LOCAL +DEFAULT +5 * +.* SECTION +LOCAL +DEFAULT +6 * +.* SECTION +LOCAL +DEFAULT +7 * +.* SECTION +LOCAL +DEFAULT +8 * +.* SECTION +LOCAL +DEFAULT +9 * +.* SECTION +LOCAL +DEFAULT +10 * +.* SECTION +LOCAL +DEFAULT +11 * +.* SECTION +LOCAL +DEFAULT +12 * .* FILE +LOCAL +DEFAULT +ABS .* .* TLS +LOCAL +DEFAULT +7 gd4 .* TLS +LOCAL +DEFAULT +7 ld4 @@ -115,7 +115,7 @@ Symbol table '\.symtab' contains [0-9]+ entries: .* NOTYPE +LOCAL +DEFAULT +UND \.__tls_get_addr .* FILE +LOCAL +DEFAULT +ABS .* .* OBJECT +LOCAL +DEFAULT +9 _DYNAMIC -.* NOTYPE +LOCAL +DEFAULT +6 00000010\.plt_call\.__tls_get_addr +.* NOTYPE +LOCAL +DEFAULT +6 .*\.plt_call\.__tls_get_addr .* NOTYPE +LOCAL +DEFAULT +6 __glink_PLTresolve .* TLS +GLOBAL +DEFAULT +UND gd .* TLS +GLOBAL +DEFAULT +8 le0 diff --git a/ld/testsuite/ld-powerpc/tlstocso.d b/ld/testsuite/ld-powerpc/tlstocso.d index fa3b77a..6aa1056 100644 --- a/ld/testsuite/ld-powerpc/tlstocso.d +++ b/ld/testsuite/ld-powerpc/tlstocso.d @@ -4,17 +4,17 @@ #objdump: -dr #target: powerpc64*-*-* -.*: +file format elf64-powerpc +.* Disassembly of section \.text: -.* <00000010\.plt_call\.__tls_get_addr(|_opt)>: +.* <.*plt_call\.__tls_get_addr(|_opt)>: .* (f8 41 00 28|28 00 41 f8) std r2,40\(r1\) .* (e9 82 80 70|70 80 82 e9) ld r12,-32656\(r2\) .* (7d 89 03 a6|a6 03 89 7d) mtctr r12 .* (e8 42 80 78|78 80 42 e8) ld r2,-32648\(r2\) .* (28 22 00 00|00 00 22 28) cmpldi r2,0 -.* (4c e2 04 20|20 04 e2 4c) bnectr\+ +.* (4c e2 04 20|20 04 e2 4c) bnectr\+ * .* (48 00 00 ..|.. 00 00 48) b .* <__tls_get_addr@plt> .* <\._start>: diff --git a/ld/testsuite/ld-powerpc/tlstocso.g b/ld/testsuite/ld-powerpc/tlstocso.g index a22497d..9da93ec 100644 --- a/ld/testsuite/ld-powerpc/tlstocso.g +++ b/ld/testsuite/ld-powerpc/tlstocso.g @@ -7,7 +7,7 @@ .* Contents of section \.got: - 106c8 00000000 (000186c8|c8860100) 00000000 00000000 .* + 10720 (00000000|20870100) (00018720|00000000) 00000000 00000000 .* .* 00000000 00000000 00000000 00000000 .* .* 00000000 00000000 00000000 00000000 .* .* 00000000 00000000 00000000 00000000 .* diff --git a/ld/testsuite/ld-powerpc/tlstocso.r b/ld/testsuite/ld-powerpc/tlstocso.r index f397915..f5bdfe3 100644 --- a/ld/testsuite/ld-powerpc/tlstocso.r +++ b/ld/testsuite/ld-powerpc/tlstocso.r @@ -39,10 +39,10 @@ Program Headers: Section to Segment mapping: +Segment Sections\.\.\. - +0+ +\.hash \.dynsym \.dynstr \.rela\.dyn \.rela\.plt \.text - +01 +\.tdata \.dynamic \.opd \.got \.plt - +02 +\.dynamic - +03 +\.tdata \.tbss + +0+ +\.hash \.dynsym \.dynstr \.rela\.dyn \.rela\.plt \.text * + +01 +\.tdata \.dynamic \.opd \.got \.plt * + +02 +\.dynamic * + +03 +\.tdata \.tbss * Relocation section '\.rela\.dyn' at offset .* contains 13 entries: +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend @@ -66,9 +66,9 @@ Relocation section '\.rela\.plt' at offset .* contains 1 entries: Symbol table '\.dynsym' contains [0-9]+ entries: +Num: +Value +Size +Type +Bind +Vis +Ndx +Name -.* NOTYPE +LOCAL +DEFAULT +UND -.* SECTION +LOCAL +DEFAULT +6 -.* SECTION +LOCAL +DEFAULT +7 +.* NOTYPE +LOCAL +DEFAULT +UND * +.* SECTION +LOCAL +DEFAULT +6 * +.* SECTION +LOCAL +DEFAULT +7 * .* TLS +GLOBAL +DEFAULT +UND gd .* TLS +GLOBAL +DEFAULT +8 le0 .* NOTYPE +GLOBAL +DEFAULT +UND __tls_get_addr @@ -86,19 +86,19 @@ Symbol table '\.dynsym' contains [0-9]+ entries: Symbol table '\.symtab' contains [0-9]+ entries: +Num: +Value +Size +Type +Bind +Vis +Ndx +Name -.* NOTYPE +LOCAL +DEFAULT +UND -.* SECTION +LOCAL +DEFAULT +1 -.* SECTION +LOCAL +DEFAULT +2 -.* SECTION +LOCAL +DEFAULT +3 -.* SECTION +LOCAL +DEFAULT +4 -.* SECTION +LOCAL +DEFAULT +5 -.* SECTION +LOCAL +DEFAULT +6 -.* SECTION +LOCAL +DEFAULT +7 -.* SECTION +LOCAL +DEFAULT +8 -.* SECTION +LOCAL +DEFAULT +9 -.* SECTION +LOCAL +DEFAULT +10 -.* SECTION +LOCAL +DEFAULT +11 -.* SECTION +LOCAL +DEFAULT +12 +.* NOTYPE +LOCAL +DEFAULT +UND * +.* SECTION +LOCAL +DEFAULT +1 * +.* SECTION +LOCAL +DEFAULT +2 * +.* SECTION +LOCAL +DEFAULT +3 * +.* SECTION +LOCAL +DEFAULT +4 * +.* SECTION +LOCAL +DEFAULT +5 * +.* SECTION +LOCAL +DEFAULT +6 * +.* SECTION +LOCAL +DEFAULT +7 * +.* SECTION +LOCAL +DEFAULT +8 * +.* SECTION +LOCAL +DEFAULT +9 * +.* SECTION +LOCAL +DEFAULT +10 * +.* SECTION +LOCAL +DEFAULT +11 * +.* SECTION +LOCAL +DEFAULT +12 * .* FILE +LOCAL +DEFAULT +ABS .* .* TLS +LOCAL +DEFAULT +7 gd4 .* TLS +LOCAL +DEFAULT +7 ld4 @@ -111,7 +111,7 @@ Symbol table '\.symtab' contains [0-9]+ entries: .* NOTYPE +LOCAL +DEFAULT +UND \.__tls_get_addr .* FILE +LOCAL +DEFAULT +ABS .* .* OBJECT +LOCAL +DEFAULT +9 _DYNAMIC -.* NOTYPE +LOCAL +DEFAULT +6 00000010\.plt_call\.__tls_get_addr +.* NOTYPE +LOCAL +DEFAULT +6 .*\.plt_call\.__tls_get_addr .* NOTYPE +LOCAL +DEFAULT +6 __glink_PLTresolve .* TLS +GLOBAL +DEFAULT +UND gd .* TLS +GLOBAL +DEFAULT +8 le0 diff --git a/ld/testsuite/ld-powerpc/tlstocso.t b/ld/testsuite/ld-powerpc/tlstocso.t index ce4f44a..408d2a5 100644 --- a/ld/testsuite/ld-powerpc/tlstocso.t +++ b/ld/testsuite/ld-powerpc/tlstocso.t @@ -7,7 +7,7 @@ .* Contents of section \.tdata: -.* (12345678|78563412) (9abcdef0|f0debc9a) (23456789|89674523) (abcdef01|01efcdab) .* -.* (3456789a|9a785634) (bcdef012|12f0debc) (456789ab|ab896745) (cdef0123|2301efcd) .* -.* (56789abc|bc9a7856) (def01234|3412f0de) (6789abcd|cdab8967) (ef012345|452301ef) .* -.* (789abcde|debc9a78) (f0123456|563412f0) .* +.* (12345678|f0debc9a) (9abcdef0|78563412) (23456789|01efcdab) (abcdef01|89674523) .* +.* (3456789a|12f0debc) (bcdef012|9a785634) (456789ab|2301efcd) (cdef0123|ab896745) .* +.* (56789abc|3412f0de) (def01234|bc9a7856) (6789abcd|452301ef) (ef012345|cdab8967) .* +.* (789abcde|563412f0) (f0123456|debc9a78) .*