From 8c5b4e5228ec94923fbdfb0008926b0b2a3f51c2 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Sat, 3 Dec 2016 21:00:01 +1030 Subject: [PATCH] PowerPC64 dot-symbol compatibility bugfixes Lots of fixes for the compatibility code that handles linking of -mcall-aixdesc code (or that generated by 12 year old gcc) with current ELFv1 ABI code. 1) A reference to a dot-symbol in an object file wasn't satisfied by a function descriptor in later object files. 2) The as-needed code had bit-rotted; Shared libs now need a strong reference to be counted as needed. 3) --gc-sections involving dot-symbols was broken, needing func_desc_adjust to be run early and lots of other fixes. bfd/ * elf64-ppc.c (struct ppc_link_hash_entry): Delete "was_undefined". (struct ppc_link_hash_table): Delete "twiddled_syms". Add "need_func_desc_adj". (lookup_fdh): Link direct fdh sym via oh field and set flags. (make_fdh): Make strong and weak undefined function descriptor symbols. (ppc64_elf_merge_symbol): New function. (elf_backend_merge_symbol): Define. (ppc64_elf_archive_symbol_lookup): Don't test undefweak for fake function descriptors. (add_symbol_adjust): Don't twiddle symbols to undefweak. Propagate more ref flags to function descriptor symbol. Make some function descriptor symbols dynamic. (ppc64_elf_before_check_relocs): Only run add_symbol_adjust for ELFv1. Set need_func_desc_adj. Don't fix undefs list. (ppc64_elf_check_relocs): Set non_ir_ref for descriptors. Don't call lookup_fdh here. (ppc64_elf_gc_sections): New function. (bfd_elf64_bfd_gc_sections): Define. (ppc64_elf_gc_mark_hook): Mark descriptor. (func_desc_adjust): Don't make fake function descriptor syms strong here. Exit earlier on non-dotsyms. Take note of elf.dynamic flag when deciding whether a dynamic function descriptor might be needed. Transfer elf.dynamic and set elf.needs_plt. Move plt regardless of visibility. Make descriptor dynamic if entry sym is dynamic, not for other cases. (ppc64_elf_func_desc_adjust): Don't run func_desc_adjust if already done. (ppc64_elf_edit_opd): Use oh field rather than lookup_fdh. (ppc64_elf_size_stubs): Likewise. (ppc_build_one_stub): Don't clear was_undefined. Only set sym undefweak if stub symbol is defined. (undo_symbol_twiddle, ppc64_elf_restore_symbols): Delete. * elf64-ppc.h (ppc64_elf_restore_symbols): Don't declare. ld/ * emultempl/ppc64elf.em (gld${EMULATION_NAME}_finish): Don't call ppc64_elf_restore_symbols. * testsuite/ld-powerpc/dotsym1.d: New. * testsuite/ld-powerpc/dotsym2.d: New. * testsuite/ld-powerpc/dotsym3.d: New. * testsuite/ld-powerpc/dotsym4.d: New. * testsuite/ld-powerpc/dotsymref.s: New. * testsuite/ld-powerpc/nodotsym.s: New. * testsuite/ld-powerpc/powerpc.exp: Run new tests. --- bfd/ChangeLog | 37 ++++ bfd/elf64-ppc.c | 320 ++++++++++++++-------------- bfd/elf64-ppc.h | 2 - ld/ChangeLog | 12 ++ ld/emultempl/ppc64elf.em | 1 - ld/testsuite/ld-powerpc/dotsym1.d | 15 ++ ld/testsuite/ld-powerpc/dotsym2.d | 16 ++ ld/testsuite/ld-powerpc/dotsym3.d | 16 ++ ld/testsuite/ld-powerpc/dotsym4.d | 17 ++ ld/testsuite/ld-powerpc/dotsymref.s | 4 + ld/testsuite/ld-powerpc/nodotsym.s | 11 + ld/testsuite/ld-powerpc/powerpc.exp | 4 + 12 files changed, 295 insertions(+), 160 deletions(-) create mode 100644 ld/testsuite/ld-powerpc/dotsym1.d create mode 100644 ld/testsuite/ld-powerpc/dotsym2.d create mode 100644 ld/testsuite/ld-powerpc/dotsym3.d create mode 100644 ld/testsuite/ld-powerpc/dotsym4.d create mode 100644 ld/testsuite/ld-powerpc/dotsymref.s create mode 100644 ld/testsuite/ld-powerpc/nodotsym.s diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 7721b17407..b0dafb275f 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,40 @@ +2016-12-03 Alan Modra + + * elf64-ppc.c (struct ppc_link_hash_entry): Delete "was_undefined". + (struct ppc_link_hash_table): Delete "twiddled_syms". Add + "need_func_desc_adj". + (lookup_fdh): Link direct fdh sym via oh field and set flags. + (make_fdh): Make strong and weak undefined function descriptor + symbols. + (ppc64_elf_merge_symbol): New function. + (elf_backend_merge_symbol): Define. + (ppc64_elf_archive_symbol_lookup): Don't test undefweak for fake + function descriptors. + (add_symbol_adjust): Don't twiddle symbols to undefweak. + Propagate more ref flags to function descriptor symbol. Make + some function descriptor symbols dynamic. + (ppc64_elf_before_check_relocs): Only run add_symbol_adjust for + ELFv1. Set need_func_desc_adj. Don't fix undefs list. + (ppc64_elf_check_relocs): Set non_ir_ref for descriptors. + Don't call lookup_fdh here. + (ppc64_elf_gc_sections): New function. + (bfd_elf64_bfd_gc_sections): Define. + (ppc64_elf_gc_mark_hook): Mark descriptor. + (func_desc_adjust): Don't make fake function descriptor syms strong + here. Exit earlier on non-dotsyms. Take note of elf.dynamic + flag when deciding whether a dynamic function descriptor might + be needed. Transfer elf.dynamic and set elf.needs_plt. Move + plt regardless of visibility. Make descriptor dynamic if + entry sym is dynamic, not for other cases. + (ppc64_elf_func_desc_adjust): Don't run func_desc_adjust if + already done. + (ppc64_elf_edit_opd): Use oh field rather than lookup_fdh. + (ppc64_elf_size_stubs): Likewise. + (ppc_build_one_stub): Don't clear was_undefined. Only set sym + undefweak if stub symbol is defined. + (undo_symbol_twiddle, ppc64_elf_restore_symbols): Delete. + * elf64-ppc.h (ppc64_elf_restore_symbols): Don't declare. + 2016-12-03 Alan Modra * elf64-ppc.c (ppc64_elf_hide_symbol): Access hash table as diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index 27328ecf58..f624874523 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -87,6 +87,7 @@ static bfd_vma opd_entry_value #define bfd_elf64_bfd_link_hash_table_create ppc64_elf_link_hash_table_create #define bfd_elf64_get_synthetic_symtab ppc64_elf_get_synthetic_symtab #define bfd_elf64_bfd_link_just_syms ppc64_elf_link_just_syms +#define bfd_elf64_bfd_gc_sections ppc64_elf_gc_sections #define elf_backend_object_p ppc64_elf_object_p #define elf_backend_grok_prstatus ppc64_elf_grok_prstatus @@ -118,6 +119,7 @@ static bfd_vma opd_entry_value #define elf_backend_link_output_symbol_hook ppc64_elf_output_symbol_hook #define elf_backend_special_sections ppc64_elf_special_sections #define elf_backend_merge_symbol_attribute ppc64_elf_merge_symbol_attribute +#define elf_backend_merge_symbol ppc64_elf_merge_symbol /* The name of the dynamic interpreter. This is put in the .interp section. */ @@ -3978,9 +3980,6 @@ struct ppc_link_hash_entry should be set for all globals defined in any opd/toc section. */ unsigned int adjust_done:1; - /* Set if we twiddled this symbol to weak at some stage. */ - unsigned int was_undefined:1; - /* Set if this is an out-of-line register save/restore function, with non-standard calling convention. */ unsigned int save_res:1; @@ -4087,8 +4086,8 @@ struct ppc_link_hash_table /* Set on error. */ unsigned int stub_error:1; - /* Temp used by ppc64_elf_before_check_relocs. */ - unsigned int twiddled_syms:1; + /* Whether func_desc_adjust needs to be run over symbols. */ + unsigned int need_func_desc_adj:1; /* Incremented every time we size stubs. */ unsigned int stub_iteration; @@ -4898,32 +4897,29 @@ lookup_fdh (struct ppc_link_hash_entry *fh, struct ppc_link_hash_table *htab) fh->oh = fdh; } - return ppc_follow_link (fdh); + fdh = ppc_follow_link (fdh); + fdh->is_func_descriptor = 1; + fdh->oh = fh; + return fdh; } -/* Make a fake function descriptor sym for the code sym FH. */ +/* Make a fake function descriptor sym for the undefined code sym FH. */ static struct ppc_link_hash_entry * make_fdh (struct bfd_link_info *info, struct ppc_link_hash_entry *fh) { - bfd *abfd; - asymbol *newsym; - struct bfd_link_hash_entry *bh; + bfd *abfd = fh->elf.root.u.undef.abfd; + struct bfd_link_hash_entry *bh = NULL; struct ppc_link_hash_entry *fdh; + flagword flags = (fh->elf.root.type == bfd_link_hash_undefweak + ? BSF_WEAK + : BSF_GLOBAL); - abfd = fh->elf.root.u.undef.abfd; - newsym = bfd_make_empty_symbol (abfd); - newsym->name = fh->elf.root.root.string + 1; - newsym->section = bfd_und_section_ptr; - newsym->value = 0; - newsym->flags = BSF_WEAK; - - bh = NULL; - if (!_bfd_generic_link_add_one_symbol (info, abfd, newsym->name, - newsym->flags, newsym->section, - newsym->value, NULL, FALSE, FALSE, - &bh)) + if (!_bfd_generic_link_add_one_symbol (info, abfd, + fh->elf.root.root.string + 1, + flags, bfd_und_section_ptr, 0, + NULL, FALSE, FALSE, &bh)) return NULL; fdh = (struct ppc_link_hash_entry *) bh; @@ -5012,6 +5008,22 @@ ppc64_elf_merge_symbol_attribute (struct elf_link_hash_entry *h, | ELF_ST_VISIBILITY (h->other)); } +/* Hook called on merging a symbol. We use this to clear "fake" since + we now have a real symbol. */ + +static bfd_boolean +ppc64_elf_merge_symbol (struct elf_link_hash_entry *h, + const Elf_Internal_Sym *isym ATTRIBUTE_UNUSED, + asection **psec ATTRIBUTE_UNUSED, + bfd_boolean newdef ATTRIBUTE_UNUSED, + bfd_boolean olddef ATTRIBUTE_UNUSED, + bfd *oldbfd ATTRIBUTE_UNUSED, + const asection *oldsec ATTRIBUTE_UNUSED) +{ + ((struct ppc_link_hash_entry *) h)->fake = 0; + return TRUE; +} + /* This function makes an old ABI object reference to ".bar" cause the inclusion of a new ABI object archive that defines "bar". NAME is a symbol defined in an archive. Return a symbol in the hash @@ -5030,8 +5042,7 @@ ppc64_elf_archive_symbol_lookup (bfd *abfd, if (h != NULL /* Don't return this sym if it is a fake function descriptor created by add_symbol_adjust. */ - && !(h->root.type == bfd_link_hash_undefweak - && ((struct ppc_link_hash_entry *) h)->fake)) + && !((struct ppc_link_hash_entry *) h)->fake) return h; if (name[0] == '.') @@ -5077,38 +5088,49 @@ add_symbol_adjust (struct ppc_link_hash_entry *eh, struct bfd_link_info *info) return FALSE; fdh = lookup_fdh (eh, htab); - if (fdh == NULL) + if (fdh == NULL + && !bfd_link_relocatable (info) + && (eh->elf.root.type == bfd_link_hash_undefined + || eh->elf.root.type == bfd_link_hash_undefweak) + && eh->elf.ref_regular) { - if (!bfd_link_relocatable (info) - && (eh->elf.root.type == bfd_link_hash_undefined - || eh->elf.root.type == bfd_link_hash_undefweak) - && eh->elf.ref_regular) - { - /* Make an undefweak function descriptor sym, which is enough to - pull in an --as-needed shared lib, but won't cause link - errors. Archives are handled elsewhere. */ - fdh = make_fdh (info, eh); - if (fdh == NULL) - return FALSE; - fdh->elf.ref_regular = 1; - } + /* Make an undefined function descriptor sym, in order to + pull in an --as-needed shared lib. Archives are handled + elsewhere. */ + fdh = make_fdh (info, eh); + if (fdh == NULL) + return FALSE; } - else + + if (fdh != NULL) { unsigned entry_vis = ELF_ST_VISIBILITY (eh->elf.other) - 1; unsigned descr_vis = ELF_ST_VISIBILITY (fdh->elf.other) - 1; + + /* Make both descriptor and entry symbol have the most + constraining visibility of either symbol. */ if (entry_vis < descr_vis) fdh->elf.other += entry_vis - descr_vis; else if (entry_vis > descr_vis) eh->elf.other += descr_vis - entry_vis; - if ((fdh->elf.root.type == bfd_link_hash_defined - || fdh->elf.root.type == bfd_link_hash_defweak) - && eh->elf.root.type == bfd_link_hash_undefined) + /* Propagate reference flags from entry symbol to function + descriptor symbol. */ + fdh->elf.root.non_ir_ref |= eh->elf.root.non_ir_ref; + fdh->elf.ref_regular |= eh->elf.ref_regular; + fdh->elf.ref_regular_nonweak |= eh->elf.ref_regular_nonweak; + + if (!fdh->elf.forced_local + && fdh->elf.dynindx == -1 + && fdh->elf.versioned != versioned_hidden + && (bfd_link_dll (info) + || fdh->elf.def_dynamic + || fdh->elf.ref_dynamic) + && (eh->elf.ref_regular + || eh->elf.def_regular)) { - eh->elf.root.type = bfd_link_hash_undefweak; - eh->was_undefined = 1; - htab->twiddled_syms = 1; + if (! bfd_elf_link_record_dynamic_symbol (info, &fdh->elf)) + return FALSE; } } @@ -5190,18 +5212,14 @@ ppc64_elf_before_check_relocs (bfd *ibfd, struct bfd_link_info *info) 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; + else if (abiversion (ibfd) <= 1) + { + htab->need_func_desc_adj = 1; + if (!add_symbol_adjust (eh, info)) + return FALSE; + } p = &eh->u.next_dot_sym; } - - /* We need to fix the undefs list for any syms we have twiddled to - undefweak. */ - if (htab->twiddled_syms) - { - bfd_link_repair_undef_list (&htab->elf.root); - htab->twiddled_syms = 0; - } return TRUE; } @@ -5394,12 +5412,17 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, h = NULL; else { + struct ppc_link_hash_entry *eh; + h = sym_hashes[r_symndx - symtab_hdr->sh_info]; h = elf_follow_link (h); + eh = (struct ppc_link_hash_entry *) h; /* PR15323, ref flags aren't set for references in the same object. */ h->root.non_ir_ref = 1; + if (eh->is_func && eh->oh != NULL) + eh->oh->elf.root.non_ir_ref = 1; if (h == htab->elf.hgot) sec->has_toc_reloc = 1; @@ -5809,14 +5832,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, && ELF64_R_TYPE ((rel + 1)->r_info) == R_PPC64_TOC) { if (h != NULL) - { - if (h->root.root.string[0] == '.' - && h->root.root.string[1] != 0 - && lookup_fdh ((struct ppc_link_hash_entry *) h, htab)) - ; - else - ((struct ppc_link_hash_entry *) h)->is_func = 1; - } + ((struct ppc_link_hash_entry *) h)->is_func = 1; else { asection *s; @@ -6343,6 +6359,23 @@ defined_func_desc (struct ppc_link_hash_entry *fh) return NULL; } +static bfd_boolean func_desc_adjust (struct elf_link_hash_entry *, void *); + +/* Garbage collect sections, after first dealing with dot-symbols. */ + +static bfd_boolean +ppc64_elf_gc_sections (bfd *abfd, struct bfd_link_info *info) +{ + struct ppc_link_hash_table *htab = ppc_hash_table (info); + + if (htab != NULL && htab->need_func_desc_adj) + { + elf_link_hash_traverse (&htab->elf, func_desc_adjust, info); + htab->need_func_desc_adj = 0; + } + return bfd_elf_gc_sections (abfd, info); +} + /* Mark all our entry sym sections, both opd and code section. */ static void @@ -6477,7 +6510,15 @@ ppc64_elf_gc_mark_hook (asection *sec, eh = (struct ppc_link_hash_entry *) h; fdh = defined_func_desc (eh); if (fdh != NULL) - eh = fdh; + { + /* -mcall-aixdesc code references the dot-symbol on + a call reloc. Mark the function descriptor too + against garbage collection. */ + fdh->elf.mark = 1; + if (fdh->elf.u.weakdef != NULL) + fdh->elf.u.weakdef->mark = 1; + eh = fdh; + } /* Function descriptor syms cause the associated function code sym section to be marked. */ @@ -6956,7 +6997,6 @@ func_desc_adjust (struct elf_link_hash_entry *h, void *inf) { struct bfd_link_info *info; struct ppc_link_hash_table *htab; - struct plt_entry *ent; struct ppc_link_hash_entry *fh; struct ppc_link_hash_entry *fdh; bfd_boolean force_local; @@ -6965,18 +7005,29 @@ func_desc_adjust (struct elf_link_hash_entry *h, void *inf) if (fh->elf.root.type == bfd_link_hash_indirect) return TRUE; + if (!fh->is_func) + return TRUE; + + if (fh->elf.root.root.string[0] != '.' + || fh->elf.root.root.string[1] == '\0') + return TRUE; + info = inf; htab = ppc_hash_table (info); if (htab == NULL) return FALSE; + /* Find the corresponding function descriptor symbol. */ + fdh = lookup_fdh (fh, htab); + /* Resolve undefined references to dot-symbols as the value in the function descriptor, if we have one in a regular object. This is to satisfy cases like ".quad .foo". Calls to functions in dynamic objects are handled elsewhere. */ - if (fh->elf.root.type == bfd_link_hash_undefweak - && fh->was_undefined - && (fdh = defined_func_desc (fh)) != NULL + if ((fh->elf.root.type == bfd_link_hash_undefined + || fh->elf.root.type == bfd_link_hash_undefweak) + && (fdh->elf.root.type == bfd_link_hash_defined + || fdh->elf.root.type == bfd_link_hash_defweak) && get_opd_info (fdh->elf.root.u.def.section) != NULL && opd_entry_value (fdh->elf.root.u.def.section, fdh->elf.root.u.def.value, @@ -6989,23 +7040,18 @@ func_desc_adjust (struct elf_link_hash_entry *h, void *inf) fh->elf.def_dynamic = fdh->elf.def_dynamic; } - /* If this is a function code symbol, transfer dynamic linking - information to the function descriptor symbol. */ - if (!fh->is_func) - return TRUE; + if (!fh->elf.dynamic) + { + struct plt_entry *ent; - for (ent = fh->elf.plt.plist; ent != NULL; ent = ent->next) - if (ent->plt.refcount > 0) - break; - if (ent == NULL - || fh->elf.root.root.string[0] != '.' - || fh->elf.root.root.string[1] == '\0') - return TRUE; + for (ent = fh->elf.plt.plist; ent != NULL; ent = ent->next) + if (ent->plt.refcount > 0) + break; + if (ent == NULL) + return TRUE; + } - /* Find the corresponding function descriptor symbol. Create it - as undefined if necessary. */ - - fdh = lookup_fdh (fh, htab); + /* Create a descriptor as undefined if necessary. */ if (fdh == NULL && !bfd_link_executable (info) && (fh->elf.root.type == bfd_link_hash_undefined @@ -7016,51 +7062,30 @@ func_desc_adjust (struct elf_link_hash_entry *h, void *inf) return FALSE; } - /* Fake function descriptors are made undefweak. If the function - code symbol is strong undefined, make the fake sym the same. - If the function code symbol is defined, then force the fake - descriptor local; We can't support overriding of symbols in a - shared library on a fake descriptor. */ - + /* We can't support overriding of symbols on a fake descriptor. */ if (fdh != NULL && fdh->fake - && fdh->elf.root.type == bfd_link_hash_undefweak) - { - if (fh->elf.root.type == bfd_link_hash_undefined) - { - fdh->elf.root.type = bfd_link_hash_undefined; - bfd_link_add_undef (&htab->elf.root, &fdh->elf.root); - } - else if (fh->elf.root.type == bfd_link_hash_defined - || fh->elf.root.type == bfd_link_hash_defweak) - { - _bfd_elf_link_hash_hide_symbol (info, &fdh->elf, TRUE); - } - } + && (fh->elf.root.type == bfd_link_hash_defined + || fh->elf.root.type == bfd_link_hash_defweak)) + _bfd_elf_link_hash_hide_symbol (info, &fdh->elf, TRUE); - if (fdh != NULL - && !fdh->elf.forced_local - && (!bfd_link_executable (info) - || fdh->elf.def_dynamic - || fdh->elf.ref_dynamic - || (fdh->elf.root.type == bfd_link_hash_undefweak - && ELF_ST_VISIBILITY (fdh->elf.other) == STV_DEFAULT))) + /* Transfer dynamic linking information to the function descriptor. */ + if (fdh != NULL) { - if (fdh->elf.dynindx == -1) - if (! bfd_elf_link_record_dynamic_symbol (info, &fdh->elf)) - return FALSE; fdh->elf.ref_regular |= fh->elf.ref_regular; fdh->elf.ref_dynamic |= fh->elf.ref_dynamic; fdh->elf.ref_regular_nonweak |= fh->elf.ref_regular_nonweak; fdh->elf.non_got_ref |= fh->elf.non_got_ref; - if (ELF_ST_VISIBILITY (fh->elf.other) == STV_DEFAULT) - { - move_plt_plist (fh, fdh); - fdh->elf.needs_plt = 1; - } - fdh->is_func_descriptor = 1; - fdh->oh = fh; - fh->oh = fdh; + fdh->elf.dynamic |= fh->elf.dynamic; + fdh->elf.needs_plt |= (fh->elf.needs_plt + || fh->elf.type == STT_FUNC + || fh->elf.type == STT_GNU_IFUNC); + move_plt_plist (fh, fdh); + + if (!fdh->elf.forced_local + && fh->elf.dynindx != -1) + if (!bfd_elf_link_record_dynamic_symbol (info, &fdh->elf)) + return FALSE; } /* Now that the info is on the function descriptor, clear the @@ -7145,7 +7170,11 @@ ppc64_elf_func_desc_adjust (bfd *obfd ATTRIBUTE_UNUSED, | STV_HIDDEN); } - elf_link_hash_traverse (&htab->elf, func_desc_adjust, info); + if (htab->need_func_desc_adj) + { + elf_link_hash_traverse (&htab->elf, func_desc_adjust, info); + htab->need_func_desc_adj = 0; + } return TRUE; } @@ -8092,11 +8121,14 @@ ppc64_elf_edit_opd (struct bfd_link_info *info) if (h != NULL && h->root.root.string[0] == '.') { - fdh = lookup_fdh ((struct ppc_link_hash_entry *) h, htab); - if (fdh != NULL - && fdh->elf.root.type != bfd_link_hash_defined - && fdh->elf.root.type != bfd_link_hash_defweak) - fdh = NULL; + fdh = ((struct ppc_link_hash_entry *) h)->oh; + if (fdh != NULL) + { + fdh = ppc_follow_link (fdh); + if (fdh->elf.root.type != bfd_link_hash_defined + && fdh->elf.root.type != bfd_link_hash_defweak) + fdh = NULL; + } } skip = (sym_sec->owner != ibfd @@ -11080,10 +11112,10 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) /* If the old-ABI "dot-symbol" is undefined make it weak so we don't get a link error from RELOC_FOR_GLOBAL_SYMBOL. */ - if (fh->elf.root.type == bfd_link_hash_undefined) + if (fh->elf.root.type == bfd_link_hash_undefined + && (stub_entry->h->elf.root.type == bfd_link_hash_defined + || stub_entry->h->elf.root.type == bfd_link_hash_defweak)) fh->elf.root.type = bfd_link_hash_undefweak; - /* Stop undo_symbol_twiddle changing it back to undefined. */ - fh->was_undefined = 0; } /* Now build the stub. */ @@ -12412,8 +12444,9 @@ ppc64_elf_size_stubs (struct bfd_link_info *info) use the func descriptor sym instead if it is defined. */ if (hash->elf.root.root.string[0] == '.' - && (fdh = lookup_fdh (hash, htab)) != NULL) + && hash->oh != NULL) { + fdh = ppc_follow_link (hash->oh); if (fdh->elf.root.type == bfd_link_hash_defined || fdh->elf.root.type == bfd_link_hash_defweak) { @@ -13242,33 +13275,6 @@ ppc64_elf_build_stubs (struct bfd_link_info *info, return TRUE; } -/* This function undoes the changes made by add_symbol_adjust. */ - -static bfd_boolean -undo_symbol_twiddle (struct elf_link_hash_entry *h, void *inf ATTRIBUTE_UNUSED) -{ - struct ppc_link_hash_entry *eh; - - if (h->root.type == bfd_link_hash_indirect) - return TRUE; - - eh = (struct ppc_link_hash_entry *) h; - if (eh->elf.root.type != bfd_link_hash_undefweak || !eh->was_undefined) - return TRUE; - - eh->elf.root.type = bfd_link_hash_undefined; - return TRUE; -} - -void -ppc64_elf_restore_symbols (struct bfd_link_info *info) -{ - struct ppc_link_hash_table *htab = ppc_hash_table (info); - - if (htab != NULL) - elf_link_hash_traverse (&htab->elf, undo_symbol_twiddle, info); -} - /* What to do when ld finds relocations against symbols defined in discarded sections. */ diff --git a/bfd/elf64-ppc.h b/bfd/elf64-ppc.h index 971ba09668..b1ea550ed2 100644 --- a/bfd/elf64-ppc.h +++ b/bfd/elf64-ppc.h @@ -94,5 +94,3 @@ bfd_boolean ppc64_elf_size_stubs (struct bfd_link_info *); bfd_boolean ppc64_elf_build_stubs (struct bfd_link_info *, char **); -void ppc64_elf_restore_symbols - (struct bfd_link_info *info); diff --git a/ld/ChangeLog b/ld/ChangeLog index b1c6b8cd51..90283e3ffd 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,15 @@ +2016-12-03 Alan Modra + + * emultempl/ppc64elf.em (gld${EMULATION_NAME}_finish): Don't call + ppc64_elf_restore_symbols. + * testsuite/ld-powerpc/dotsym1.d: New. + * testsuite/ld-powerpc/dotsym2.d: New. + * testsuite/ld-powerpc/dotsym3.d: New. + * testsuite/ld-powerpc/dotsym4.d: New. + * testsuite/ld-powerpc/dotsymref.s: New. + * testsuite/ld-powerpc/nodotsym.s: New. + * testsuite/ld-powerpc/powerpc.exp: Run new tests. + 2016-12-03 Alan Modra * testsuite/ld-elf/indirect1b.c: Give dot-symbol a version too. diff --git a/ld/emultempl/ppc64elf.em b/ld/emultempl/ppc64elf.em index eaa692db60..b614e07d4e 100644 --- a/ld/emultempl/ppc64elf.em +++ b/ld/emultempl/ppc64elf.em @@ -592,7 +592,6 @@ gld${EMULATION_NAME}_finish (void) if (msg != NULL) free (msg); - ppc64_elf_restore_symbols (&link_info); finish_default (); } diff --git a/ld/testsuite/ld-powerpc/dotsym1.d b/ld/testsuite/ld-powerpc/dotsym1.d new file mode 100644 index 0000000000..1cb93387ba --- /dev/null +++ b/ld/testsuite/ld-powerpc/dotsym1.d @@ -0,0 +1,15 @@ +#source: nodotsym.s +#source: dotsymref.s +#as: -a64 +#ld: -melf64ppc -Ttext=0x10000000 -e foo +#objdump: -d + +.*: file format .* + +Disassembly of section \.text: + +0+10000000 <\.foo>: +.*: (4e 80 00 20|20 00 80 4e) blr +.*: (60 00 00 00|00 00 00 60) nop +.*: (00 00 00 00|00 00 00 10) .* +.*: (10 00 00 00|00 00 00 00) .* diff --git a/ld/testsuite/ld-powerpc/dotsym2.d b/ld/testsuite/ld-powerpc/dotsym2.d new file mode 100644 index 0000000000..7704db731c --- /dev/null +++ b/ld/testsuite/ld-powerpc/dotsym2.d @@ -0,0 +1,16 @@ +#source: dotsymref.s +#source: nodotsym.s +#as: -a64 +#ld: -melf64ppc -Ttext=0x10000000 -e foo +#objdump: -d + +.*: file format .* + +Disassembly of section \.text: + +0+10000000 <\.foo-0x8>: +.*: (00 00 00 00|08 00 00 10) .* +.*: (10 00 00 08|00 00 00 00) .* + +0+10000008 <\.foo>: +.*: (4e 80 00 20|20 00 80 4e) blr diff --git a/ld/testsuite/ld-powerpc/dotsym3.d b/ld/testsuite/ld-powerpc/dotsym3.d new file mode 100644 index 0000000000..fac2f8ec73 --- /dev/null +++ b/ld/testsuite/ld-powerpc/dotsym3.d @@ -0,0 +1,16 @@ +#source: nodotsym.s +#source: dotsymref.s +#as: -a64 +#ld: -melf64ppc -Ttext=0x1000 -shared +#objdump: -dR + +.*: file format .* + +Disassembly of section \.text: + +0+1000 <\.foo>: +.*: (4e 80 00 20|20 00 80 4e) blr +.*: (60 00 00 00|00 00 00 60) nop +.*: (00 00 00 00|00 10 00 00) .* +.*: R_PPC64_RELATIVE \*ABS\*\+0x1000 +.*: (00 00 10 00|00 00 00 00) .* diff --git a/ld/testsuite/ld-powerpc/dotsym4.d b/ld/testsuite/ld-powerpc/dotsym4.d new file mode 100644 index 0000000000..fdd92f3da7 --- /dev/null +++ b/ld/testsuite/ld-powerpc/dotsym4.d @@ -0,0 +1,17 @@ +#source: dotsymref.s +#source: nodotsym.s +#as: -a64 +#ld: -melf64ppc -Ttext=0x1000 -shared +#objdump: -dR + +.*: file format .* + +Disassembly of section \.text: + +0+1000 <\.foo-0x8>: +.*: (00 00 00 00|08 10 00 00) .* +.*: R_PPC64_RELATIVE \*ABS\*\+0x1008 +.*: (00 00 10 08|00 00 00 00) .* + +0+1008 <\.foo>: +.*: (4e 80 00 20|20 00 80 4e) blr diff --git a/ld/testsuite/ld-powerpc/dotsymref.s b/ld/testsuite/ld-powerpc/dotsymref.s new file mode 100644 index 0000000000..54c6f5cea0 --- /dev/null +++ b/ld/testsuite/ld-powerpc/dotsymref.s @@ -0,0 +1,4 @@ + .abiversion 1 + .text + .p2align 3 + .quad .foo diff --git a/ld/testsuite/ld-powerpc/nodotsym.s b/ld/testsuite/ld-powerpc/nodotsym.s new file mode 100644 index 0000000000..dbc44ec83c --- /dev/null +++ b/ld/testsuite/ld-powerpc/nodotsym.s @@ -0,0 +1,11 @@ + .section .opd,"aw" + .p2align 3 + .global foo + .type foo,@function +foo: + .quad .L.foo,.TOC.@tocbase,0 + + .text +.L.foo: + blr + .size foo,.-.L.foo diff --git a/ld/testsuite/ld-powerpc/powerpc.exp b/ld/testsuite/ld-powerpc/powerpc.exp index 07226c63c4..18a8e62c05 100644 --- a/ld/testsuite/ld-powerpc/powerpc.exp +++ b/ld/testsuite/ld-powerpc/powerpc.exp @@ -299,6 +299,10 @@ if [ supports_ppc64 ] then { run_dump_test "tlsld" run_dump_test "relocsort" run_dump_test "addpcis" + run_dump_test "dotsym1" + run_dump_test "dotsym2" + run_dump_test "dotsym3" + run_dump_test "dotsym4" } run_dump_test "tlsld32"