diff options
author | Alan Modra <amodra@gmail.com> | 2009-09-18 03:30:34 +0000 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2009-09-18 03:30:34 +0000 |
commit | b31867b61af05a84ae1faabfd602ebe69b689cc3 (patch) | |
tree | 093180d0d1d9fac2abc3eac987dd7038b2956fbe /bfd | |
parent | 20e6d0d602ee8907dd3b97bc1ffdeb9441a2314a (diff) | |
download | gdb-b31867b61af05a84ae1faabfd602ebe69b689cc3.zip gdb-b31867b61af05a84ae1faabfd602ebe69b689cc3.tar.gz gdb-b31867b61af05a84ae1faabfd602ebe69b689cc3.tar.bz2 |
bfd/
* elf64-ppc.c (follow_link, elf_follow_link, ppc_follow_link): New
functions. Use throughout.
(ppc64_elf_copy_indirect_symbol): Set direct symbol "oh" field
from indirect symbol.
(lookup_fdh): Rename from get_fdh. Follow indirect sym links.
(add_symbol_adjust): Simplify.
(defined_code_entry, defined_func_desc): New functions.
(ppc64_elf_gc_keep): Follow indirect sym links. Use defined_code_entry.
(ppc64_elf_gc_mark_dynamic_ref): Use defined_func_desc and
defined_code_entry to follow indirect sym links.
(ppc64_elf_gc_mark_hook, func_desc_adjust): Likewise.
(ppc_type_of_stub): Follow indirect sym links.
(toc_adjusting_stub_needed): Likewise.
(ppc_build_one_stub): Likewise. Make undefined dot-symbols weak
rather than defining them at stub.
(ppc64_elf_relocate_section): Rewrite call test to avoid multiple
assignments in test.
ld/testsuite/
* ld-powerpc/tlsso.d: Update.
* ld-powerpc/tlsso.r: Update.
* ld-powerpc/tlstocso.d: Update.
* ld-powerpc/tlstocso.r: Update.
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/ChangeLog | 20 | ||||
-rw-r--r-- | bfd/elf64-ppc.c | 253 |
2 files changed, 167 insertions, 106 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 6d91f05..5bdd8fd 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,23 @@ +2009-09-18 Alan Modra <amodra@bigpond.net.au> + + * elf64-ppc.c (follow_link, elf_follow_link, ppc_follow_link): New + functions. Use throughout. + (ppc64_elf_copy_indirect_symbol): Set direct symbol "oh" field + from indirect symbol. + (lookup_fdh): Rename from get_fdh. Follow indirect sym links. + (add_symbol_adjust): Simplify. + (defined_code_entry, defined_func_desc): New functions. + (ppc64_elf_gc_keep): Follow indirect sym links. Use defined_code_entry. + (ppc64_elf_gc_mark_dynamic_ref): Use defined_func_desc and + defined_code_entry to follow indirect sym links. + (ppc64_elf_gc_mark_hook, func_desc_adjust): Likewise. + (ppc_type_of_stub): Follow indirect sym links. + (toc_adjusting_stub_needed): Likewise. + (ppc_build_one_stub): Likewise. Make undefined dot-symbols weak + rather than defining them at stub. + (ppc64_elf_relocate_section): Rewrite call test to avoid multiple + assignments in test. + 2009-09-16 Tristan Gingold <gingold@adacore.com> * mach-o.h (bfd_mach_o_filetype): Add new constants from darwin10. diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index f154658..99bfec2 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -4282,6 +4282,29 @@ ppc64_elf_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info) return TRUE; } +/* Follow indirect and warning symbol links. */ + +static inline struct bfd_link_hash_entry * +follow_link (struct bfd_link_hash_entry *h) +{ + while (h->type == bfd_link_hash_indirect + || h->type == bfd_link_hash_warning) + h = h->u.i.link; + return h; +} + +static inline struct elf_link_hash_entry * +elf_follow_link (struct elf_link_hash_entry *h) +{ + return (struct elf_link_hash_entry *) follow_link (&h->root); +} + +static inline struct ppc_link_hash_entry * +ppc_follow_link (struct ppc_link_hash_entry *h) +{ + return (struct ppc_link_hash_entry *) follow_link (&h->elf.root); +} + /* Merge PLT info on FROM with that on TO. */ static void @@ -4364,6 +4387,8 @@ ppc64_elf_copy_indirect_symbol (struct bfd_link_info *info, edir->is_func |= eind->is_func; edir->is_func_descriptor |= eind->is_func_descriptor; edir->tls_mask |= eind->tls_mask; + if (eind->oh != NULL) + edir->oh = ppc_follow_link (eind->oh); /* If called to transfer flags for a weakdef during processing of elf_adjust_dynamic_symbol, don't copy NON_GOT_REF. @@ -4433,7 +4458,7 @@ ppc64_elf_copy_indirect_symbol (struct bfd_link_info *info, hash entry FH. Link the entries via their OH fields. */ static struct ppc_link_hash_entry * -get_fdh (struct ppc_link_hash_entry *fh, struct ppc_link_hash_table *htab) +lookup_fdh (struct ppc_link_hash_entry *fh, struct ppc_link_hash_table *htab) { struct ppc_link_hash_entry *fdh = fh->oh; @@ -4443,16 +4468,16 @@ get_fdh (struct ppc_link_hash_entry *fh, struct ppc_link_hash_table *htab) fdh = (struct ppc_link_hash_entry *) elf_link_hash_lookup (&htab->elf, fd_name, FALSE, FALSE, FALSE); - if (fdh != NULL) - { - fdh->is_func_descriptor = 1; - fdh->oh = fh; - fh->is_func = 1; - fh->oh = fdh; - } + if (fdh == NULL) + return fdh; + + fdh->is_func_descriptor = 1; + fdh->oh = fh; + fh->is_func = 1; + fh->oh = fdh; } - return fdh; + return ppc_follow_link (fdh); } /* Make a fake function descriptor sym for the code sym FH. */ @@ -4574,23 +4599,24 @@ add_symbol_adjust (struct ppc_link_hash_entry *eh, struct bfd_link_info *info) abort (); htab = ppc_hash_table (info); - fdh = get_fdh (eh, htab); - if (fdh == NULL - && !info->relocatable - && (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; - else - fdh->elf.ref_regular = 1; + fdh = lookup_fdh (eh, htab); + if (fdh == NULL) + { + if (!info->relocatable + && (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; + } } - else if (fdh != NULL) + else { unsigned entry_vis = ELF_ST_VISIBILITY (eh->elf.other) - 1; unsigned descr_vis = ELF_ST_VISIBILITY (fdh->elf.other) - 1; @@ -4839,9 +4865,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, else { h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - while (h->root.type == bfd_link_hash_indirect - || h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; + h = elf_follow_link (h); } tls_type = 0; @@ -5199,7 +5223,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, { if (h->root.root.string[0] == '.' && h->root.root.string[1] != 0 - && get_fdh ((struct ppc_link_hash_entry *) h, htab)) + && lookup_fdh ((struct ppc_link_hash_entry *) h, htab)) ; else ((struct ppc_link_hash_entry *) h)->is_func = 1; @@ -5452,9 +5476,7 @@ opd_entry_value (asection *opd_sec, sym_hashes = elf_sym_hashes (opd_bfd); rh = sym_hashes[symndx - symtab_hdr->sh_info]; - while (rh->root.type == bfd_link_hash_indirect - || rh->root.type == bfd_link_hash_warning) - rh = ((struct elf_link_hash_entry *) rh->root.u.i.link); + 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; @@ -5475,6 +5497,39 @@ opd_entry_value (asection *opd_sec, return val; } +/* If FDH is a function descriptor symbol, return the associated code + entry symbol if it is defined. Return NULL otherwise. */ + +static struct ppc_link_hash_entry * +defined_code_entry (struct ppc_link_hash_entry *fdh) +{ + if (fdh->is_func_descriptor) + { + struct ppc_link_hash_entry *fh = ppc_follow_link (fdh->oh); + if (fh->elf.root.type == bfd_link_hash_defined + || fh->elf.root.type == bfd_link_hash_defweak) + return fh; + } + return NULL; +} + +/* If FH is a function code entry symbol, return the associated + function descriptor symbol if it is defined. Return NULL otherwise. */ + +static struct ppc_link_hash_entry * +defined_func_desc (struct ppc_link_hash_entry *fh) +{ + if (fh->oh != NULL + && fh->oh->is_func_descriptor) + { + struct ppc_link_hash_entry *fdh = ppc_follow_link (fh->oh); + if (fdh->elf.root.type == bfd_link_hash_defined + || fdh->elf.root.type == bfd_link_hash_defweak) + return fdh; + } + return NULL; +} + /* Mark all our entry sym sections, both opd and code section. */ static void @@ -5485,22 +5540,21 @@ ppc64_elf_gc_keep (struct bfd_link_info *info) for (sym = info->gc_sym_list; sym != NULL; sym = sym->next) { - struct ppc_link_hash_entry *eh; + struct ppc_link_hash_entry *eh, *fh; asection *sec; eh = (struct ppc_link_hash_entry *) - elf_link_hash_lookup (&htab->elf, sym->name, FALSE, FALSE, FALSE); + elf_link_hash_lookup (&htab->elf, sym->name, FALSE, FALSE, TRUE); if (eh == NULL) continue; if (eh->elf.root.type != bfd_link_hash_defined && eh->elf.root.type != bfd_link_hash_defweak) continue; - if (eh->is_func_descriptor - && (eh->oh->elf.root.type == bfd_link_hash_defined - || eh->oh->elf.root.type == bfd_link_hash_defweak)) + fh = defined_code_entry (eh); + if (fh != NULL) { - sec = eh->oh->elf.root.u.def.section; + sec = fh->elf.root.u.def.section; sec->flags |= SEC_KEEP; } else if (get_opd_info (eh->elf.root.u.def.section) != NULL @@ -5523,16 +5577,15 @@ ppc64_elf_gc_mark_dynamic_ref (struct elf_link_hash_entry *h, void *inf) { struct bfd_link_info *info = (struct bfd_link_info *) inf; struct ppc_link_hash_entry *eh = (struct ppc_link_hash_entry *) h; + struct ppc_link_hash_entry *fdh; if (eh->elf.root.type == bfd_link_hash_warning) eh = (struct ppc_link_hash_entry *) eh->elf.root.u.i.link; /* Dynamic linking info is on the func descriptor sym. */ - if (eh->oh != NULL - && eh->oh->is_func_descriptor - && (eh->oh->elf.root.type == bfd_link_hash_defined - || eh->oh->elf.root.type == bfd_link_hash_defweak)) - eh = eh->oh; + fdh = defined_func_desc (eh); + if (fdh != NULL) + eh = fdh; if ((eh->elf.root.type == bfd_link_hash_defined || eh->elf.root.type == bfd_link_hash_defweak) @@ -5543,15 +5596,18 @@ ppc64_elf_gc_mark_dynamic_ref (struct elf_link_hash_entry *h, void *inf) && ELF_ST_VISIBILITY (eh->elf.other) != STV_HIDDEN))) { asection *code_sec; + struct ppc_link_hash_entry *fh; eh->elf.root.u.def.section->flags |= SEC_KEEP; /* Function descriptor syms cause the associated function code sym section to be marked. */ - if (eh->is_func_descriptor - && (eh->oh->elf.root.type == bfd_link_hash_defined - || eh->oh->elf.root.type == bfd_link_hash_defweak)) - eh->oh->elf.root.u.def.section->flags |= SEC_KEEP; + fh = defined_code_entry (eh); + if (fh != NULL) + { + code_sec = fh->elf.root.u.def.section; + code_sec->flags |= SEC_KEEP; + } else if (get_opd_info (eh->elf.root.u.def.section) != NULL && opd_entry_value (eh->elf.root.u.def.section, eh->elf.root.u.def.value, @@ -5583,7 +5639,7 @@ ppc64_elf_gc_mark_hook (asection *sec, if (h != NULL) { enum elf_ppc64_reloc_type r_type; - struct ppc_link_hash_entry *eh; + struct ppc_link_hash_entry *eh, *fh, *fdh; r_type = ELF64_R_TYPE (rel->r_info); switch (r_type) @@ -5598,22 +5654,19 @@ ppc64_elf_gc_mark_hook (asection *sec, case bfd_link_hash_defined: case bfd_link_hash_defweak: eh = (struct ppc_link_hash_entry *) h; - if (eh->oh != NULL - && eh->oh->is_func_descriptor - && (eh->oh->elf.root.type == bfd_link_hash_defined - || eh->oh->elf.root.type == bfd_link_hash_defweak)) - eh = eh->oh; + fdh = defined_func_desc (eh); + if (fdh != NULL) + eh = fdh; /* Function descriptor syms cause the associated function code sym section to be marked. */ - if (eh->is_func_descriptor - && (eh->oh->elf.root.type == bfd_link_hash_defined - || eh->oh->elf.root.type == bfd_link_hash_defweak)) + fh = defined_code_entry (eh); + if (fh != NULL) { /* They also mark their opd section. */ eh->elf.root.u.def.section->gc_mark = 1; - rsec = eh->oh->elf.root.u.def.section; + rsec = fh->elf.root.u.def.section; } else if (get_opd_info (eh->elf.root.u.def.section) != NULL && opd_entry_value (eh->elf.root.u.def.section, @@ -5693,9 +5746,7 @@ ppc64_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info, struct ppc_dyn_relocs *p; h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - while (h->root.type == bfd_link_hash_indirect - || h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; + h = elf_follow_link (h); eh = (struct ppc_link_hash_entry *) h; for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) @@ -6081,18 +6132,17 @@ func_desc_adjust (struct elf_link_hash_entry *h, void *inf) in dynamic objects are handled elsewhere. */ if (fh->elf.root.type == bfd_link_hash_undefweak && fh->was_undefined - && (fh->oh->elf.root.type == bfd_link_hash_defined - || fh->oh->elf.root.type == bfd_link_hash_defweak) - && get_opd_info (fh->oh->elf.root.u.def.section) != NULL - && opd_entry_value (fh->oh->elf.root.u.def.section, - fh->oh->elf.root.u.def.value, + && (fdh = defined_func_desc (fh)) != NULL + && 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, &fh->elf.root.u.def.section, &fh->elf.root.u.def.value) != (bfd_vma) -1) { - fh->elf.root.type = fh->oh->elf.root.type; + fh->elf.root.type = fdh->elf.root.type; fh->elf.forced_local = 1; - fh->elf.def_regular = fh->oh->elf.def_regular; - fh->elf.def_dynamic = fh->oh->elf.def_dynamic; + fh->elf.def_regular = fdh->elf.def_regular; + fh->elf.def_dynamic = fdh->elf.def_dynamic; } /* If this is a function code symbol, transfer dynamic linking @@ -6111,12 +6161,7 @@ func_desc_adjust (struct elf_link_hash_entry *h, void *inf) /* Find the corresponding function descriptor symbol. Create it as undefined if necessary. */ - fdh = get_fdh (fh, htab); - if (fdh != NULL) - while (fdh->elf.root.type == bfd_link_hash_indirect - || fdh->elf.root.type == bfd_link_hash_warning) - fdh = (struct ppc_link_hash_entry *) fdh->elf.root.u.i.link; - + fdh = lookup_fdh (fh, htab); if (fdh == NULL && !info->executable && (fh->elf.root.type == bfd_link_hash_undefined @@ -6454,9 +6499,7 @@ get_sym_h (struct elf_link_hash_entry **hp, struct elf_link_hash_entry *h; h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - while (h->root.type == bfd_link_hash_indirect - || h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; + h = elf_follow_link (h); if (hp != NULL) *hp = h; @@ -7024,8 +7067,8 @@ ppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info, if (h != NULL && h->root.root.string[0] == '.') { - fdh = get_fdh ((struct ppc_link_hash_entry *) h, - ppc_hash_table (info)); + fdh = lookup_fdh ((struct ppc_link_hash_entry *) h, + ppc_hash_table (info)); if (fdh != NULL && fdh->elf.root.type != bfd_link_hash_defined && fdh->elf.root.type != bfd_link_hash_defweak) @@ -7208,9 +7251,7 @@ branch_reloc_hash_match (const bfd *ibfd, struct elf_link_hash_entry *h; h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - while (h->root.type == bfd_link_hash_indirect - || h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; + h = elf_follow_link (h); if (h == &hash1->elf || h == &hash2->elf) return TRUE; } @@ -8668,9 +8709,9 @@ ppc_type_of_stub (asection *input_sec, { struct plt_entry *ent; struct ppc_link_hash_entry *fdh = h; - if (fdh->oh != NULL - && fdh->oh->is_func_descriptor) - fdh = fdh->oh; + if (h->oh != NULL + && h->oh->is_func_descriptor) + fdh = ppc_follow_link (h->oh); for (ent = fdh->elf.plt.plist; ent != NULL; ent = ent->next) if (ent->addend == rel->r_addend @@ -8944,7 +8985,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) hashes[symndx] = &h->elf; r->r_info = ELF64_R_INFO (symndx, R_PPC64_REL24); if (h->oh != NULL && h->oh->is_func) - h = h->oh; + h = ppc_follow_link (h->oh); if (h->elf.root.u.def.section != stub_entry->target_section) /* H is an opd symbol. The addend must be zero. */ r->r_addend = 0; @@ -9109,22 +9150,20 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) break; case ppc_stub_plt_call: - /* Do the best we can for shared libraries built without - exporting ".foo" for each "foo". This can happen when symbol - versioning scripts strip all bar a subset of symbols. */ if (stub_entry->h != NULL - && stub_entry->h->oh != NULL - && stub_entry->h->oh->elf.root.type != bfd_link_hash_defined - && stub_entry->h->oh->elf.root.type != bfd_link_hash_defweak) + && stub_entry->h->is_func_descriptor + && stub_entry->h->oh != NULL) { - /* Point the symbol at the stub. There may be multiple stubs, - we don't really care; The main thing is to make this sym - defined somewhere. Maybe defining the symbol in the stub - section is a silly idea. If we didn't do this, htab->top_id - could disappear. */ - stub_entry->h->oh->elf.root.type = bfd_link_hash_defined; - stub_entry->h->oh->elf.root.u.def.section = stub_entry->stub_sec; - stub_entry->h->oh->elf.root.u.def.value = stub_entry->stub_offset; + struct ppc_link_hash_entry *fh = ppc_follow_link (stub_entry->h->oh); + + /* If the old-ABI "dot-symbol" is undefined make it weak so + we don't get a link error from RELOC_FOR_GLOBAL_SYMBOL. + FIXME: We used to define the symbol on one of the call + stubs instead, which is why we test symbol section id + against htab->top_id in various places. Likely all + these checks could now disappear. */ + if (fh->elf.root.type == bfd_link_hash_undefined) + fh->elf.root.type = bfd_link_hash_undefweak; } /* Now build the stub. */ @@ -9561,7 +9600,7 @@ toc_adjusting_stub_needed (struct bfd_link_info *info, asection *isec) if (eh != NULL && (eh->elf.plt.plist != NULL || (eh->oh != NULL - && eh->oh->elf.plt.plist != NULL))) + && ppc_follow_link (eh->oh)->elf.plt.plist != NULL))) { ret = 1; break; @@ -10000,7 +10039,7 @@ ppc64_elf_size_stubs (bfd *output_bfd, use the func descriptor sym instead if it is defined. */ if (hash->elf.root.root.string[0] == '.' - && (fdh = get_fdh (hash, htab)) != NULL) + && (fdh = lookup_fdh (hash, htab)) != NULL) { if (fdh->elf.root.type == bfd_link_hash_defined || fdh->elf.root.type == bfd_link_hash_defweak) @@ -11188,10 +11227,12 @@ ppc64_elf_relocate_section (bfd *output_bfd, base pointer. */ stub_entry = NULL; fdh = h; - if (((h != NULL - && (((fdh = h->oh) != NULL - && fdh->elf.plt.plist != NULL) - || (fdh = h)->elf.plt.plist != NULL)) + if (h != NULL + && h->oh != NULL + && h->oh->is_func_descriptor) + fdh = ppc_follow_link (h->oh); + if (((fdh != NULL + && fdh->elf.plt.plist != NULL) || (sec != NULL && sec->output_section != NULL && sec->id <= htab->top_id |