From: Alan Modra Date: Tue, 10 May 2005 00:42:00 +0000 (+0000) Subject: Apply from mainline. X-Git-Tag: binutils-2_16_1~55 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b04fa8f23252ec134667817f51126dad9008252f;p=thirdparty%2Fbinutils-gdb.git Apply from mainline. 2005-05-09 Alan Modra * elf64-ppc.c (struct ppc64_elf_obj_tdata): Add has_dotsym. (ppc64_elf_add_symbol_hook): Set has_dotsym. (ppc64_elf_check_directives): Only process syms when has_dotsym. (func_desc_adjust): Hide fake function descriptors when function code entry is defined. (adjust_opd_syms): Adjust for deleted_section becoming union field. 2005-04-05 Alan Modra * elf64-ppc.c (dec_dynrel_count): New function split out from ppc64_elf_edit_toc, with additional code from ppc64_elf_edit_opd. (ppc64_elf_edit_toc, ppc64_elf_edit_opd): Use it. (ppc64_elf_tls_optimize): Likewise. 2005-04-01 Alan Modra * elf64-ppc.c (ppc64_elf_edit_toc): Account for dynamic relocs that we no longer need. --- diff --git a/bfd/ChangeLog b/bfd/ChangeLog index afa80b2e944..15dc99ee98f 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,24 @@ +2005-05-10 Alan Modra + + Apply from mainline. + 2005-05-09 Alan Modra + * elf64-ppc.c (struct ppc64_elf_obj_tdata): Add has_dotsym. + (ppc64_elf_add_symbol_hook): Set has_dotsym. + (ppc64_elf_check_directives): Only process syms when has_dotsym. + (func_desc_adjust): Hide fake function descriptors when function + code entry is defined. + (adjust_opd_syms): Adjust for deleted_section becoming union field. + + 2005-04-05 Alan Modra + * elf64-ppc.c (dec_dynrel_count): New function split out from + ppc64_elf_edit_toc, with additional code from ppc64_elf_edit_opd. + (ppc64_elf_edit_toc, ppc64_elf_edit_opd): Use it. + (ppc64_elf_tls_optimize): Likewise. + + 2005-04-01 Alan Modra + * elf64-ppc.c (ppc64_elf_edit_toc): Account for dynamic relocs + that we no longer need. + 2005-05-02 Daniel Jacobowitz * Makefile.am: Clear RELEASE. diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index 9377564b1e2..69afd3a65f7 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -2370,9 +2370,14 @@ struct ppc64_elf_obj_tdata asection *got; asection *relgot; - /* Used during garbage collection. We attach global symbols defined - on removed .opd entries to this section so that the sym is removed. */ - asection *deleted_section; + union { + /* Used during garbage collection. We attach global symbols defined + on removed .opd entries to this section so that the sym is removed. */ + asection *deleted_section; + + /* Used when adding symbols. */ + bfd_boolean has_dotsym; + } u; /* TLS local dynamic got entry handling. Suppose for multiple GOT sections means we potentially need one of these for each input bfd. */ @@ -2709,7 +2714,7 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd, long j; /* Trim duplicate syms, since we may have merged the normal and dynamic symbols. Actually, we only care about syms that have - different values, so trim any with the same value. */ + different values, so trim any with the same value. */ for (i = 1, j = 1; i < symcount; ++i) if (syms[i - 1]->value + syms[i - 1]->section->vma != syms[i]->value + syms[i]->section->vma) @@ -3998,10 +4003,10 @@ make_fdh (struct bfd_link_info *info, function type. */ static bfd_boolean -ppc64_elf_add_symbol_hook (bfd *ibfd ATTRIBUTE_UNUSED, +ppc64_elf_add_symbol_hook (bfd *ibfd, struct bfd_link_info *info ATTRIBUTE_UNUSED, Elf_Internal_Sym *isym, - const char **name ATTRIBUTE_UNUSED, + const char **name, flagword *flags ATTRIBUTE_UNUSED, asection **sec, bfd_vma *value ATTRIBUTE_UNUSED) @@ -4009,6 +4014,13 @@ ppc64_elf_add_symbol_hook (bfd *ibfd ATTRIBUTE_UNUSED, if (*sec != NULL && strcmp (bfd_get_section_name (ibfd, *sec), ".opd") == 0) isym->st_info = ELF_ST_INFO (ELF_ST_BIND (isym->st_info), STT_FUNC); + + if ((*name)[0] == '.' + && ELF_ST_BIND (isym->st_info) == STB_GLOBAL + && ELF_ST_TYPE (isym->st_info) < STT_SECTION + && is_ppc64_elf_target (ibfd->xvec)) + ppc64_elf_tdata (ibfd)->u.has_dotsym = 1; + return TRUE; } @@ -4122,12 +4134,18 @@ add_symbol_adjust (struct elf_link_hash_entry *h, void *inf) } static bfd_boolean -ppc64_elf_check_directives (bfd *abfd ATTRIBUTE_UNUSED, - struct bfd_link_info *info) +ppc64_elf_check_directives (bfd *abfd, struct bfd_link_info *info) { struct ppc_link_hash_table *htab; struct add_symbol_adjust_data data; + if (!is_ppc64_elf_target (abfd->xvec)) + return TRUE; + + if (!ppc64_elf_tdata (abfd)->u.has_dotsym) + return TRUE; + ppc64_elf_tdata (abfd)->u.deleted_section = NULL; + htab = ppc_hash_table (info); if (!is_ppc64_elf_target (htab->elf.root.creator)) return TRUE; @@ -4768,7 +4786,7 @@ opd_entry_value (asection *opd_sec, if (!bfd_get_section_contents (opd_bfd, opd_sec, &val, offset, 8)) return (bfd_vma) -1; - + if (code_sec != NULL) { asection *sec, *likely = NULL; @@ -5446,15 +5464,25 @@ func_desc_adjust (struct elf_link_hash_entry *h, void *inf) } /* Fake function descriptors are made undefweak. If the function - code symbol is strong undefined, make the fake sym the same. */ + 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. */ if (fdh != NULL && fdh->fake - && fdh->elf.root.type == bfd_link_hash_undefweak - && fh->elf.root.type == bfd_link_hash_undefined) + && fdh->elf.root.type == bfd_link_hash_undefweak) { - fdh->elf.root.type = bfd_link_hash_undefined; - bfd_link_add_undef (&htab->elf.root, &fdh->elf.root); + 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); + } } if (fdh != NULL @@ -5931,13 +5959,13 @@ adjust_opd_syms (struct elf_link_hash_entry *h, void *inf ATTRIBUTE_UNUSED) if (adjust == -1) { /* This entry has been deleted. */ - asection *dsec = ppc64_elf_tdata (sym_sec->owner)->deleted_section; + asection *dsec = ppc64_elf_tdata (sym_sec->owner)->u.deleted_section; if (dsec == NULL) { for (dsec = sym_sec->owner->sections; dsec; dsec = dsec->next) if (elf_discarded_section (dsec)) { - ppc64_elf_tdata (sym_sec->owner)->deleted_section = dsec; + ppc64_elf_tdata (sym_sec->owner)->u.deleted_section = dsec; break; } } @@ -5951,6 +5979,125 @@ adjust_opd_syms (struct elf_link_hash_entry *h, void *inf ATTRIBUTE_UNUSED) return TRUE; } +/* 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 + have already been determined. */ + +static bfd_boolean +dec_dynrel_count (bfd_vma r_info, + asection *sec, + struct bfd_link_info *info, + Elf_Internal_Sym **local_syms, + struct elf_link_hash_entry *h, + asection *sym_sec) +{ + enum elf_ppc64_reloc_type r_type; + struct ppc_dyn_relocs *p; + struct ppc_dyn_relocs **pp; + + /* Can this reloc be dynamic? This switch, and later tests here + should be kept in sync with the code in check_relocs. */ + r_type = ELF64_R_TYPE (r_info); + switch (r_type) + { + default: + return TRUE; + + case R_PPC64_TPREL16: + case R_PPC64_TPREL16_LO: + case R_PPC64_TPREL16_HI: + case R_PPC64_TPREL16_HA: + case R_PPC64_TPREL16_DS: + case R_PPC64_TPREL16_LO_DS: + case R_PPC64_TPREL16_HIGHER: + case R_PPC64_TPREL16_HIGHERA: + case R_PPC64_TPREL16_HIGHEST: + case R_PPC64_TPREL16_HIGHESTA: + if (!info->shared) + return TRUE; + + case R_PPC64_TPREL64: + case R_PPC64_DTPMOD64: + case R_PPC64_DTPREL64: + case R_PPC64_ADDR64: + case R_PPC64_REL30: + case R_PPC64_REL32: + case R_PPC64_REL64: + case R_PPC64_ADDR14: + case R_PPC64_ADDR14_BRNTAKEN: + case R_PPC64_ADDR14_BRTAKEN: + case R_PPC64_ADDR16: + case R_PPC64_ADDR16_DS: + case R_PPC64_ADDR16_HA: + case R_PPC64_ADDR16_HI: + case R_PPC64_ADDR16_HIGHER: + case R_PPC64_ADDR16_HIGHERA: + case R_PPC64_ADDR16_HIGHEST: + case R_PPC64_ADDR16_HIGHESTA: + case R_PPC64_ADDR16_LO: + case R_PPC64_ADDR16_LO_DS: + case R_PPC64_ADDR24: + case R_PPC64_ADDR32: + case R_PPC64_UADDR16: + case R_PPC64_UADDR32: + case R_PPC64_UADDR64: + case R_PPC64_TOC: + break; + } + + if (local_syms != NULL) + { + unsigned long r_symndx; + Elf_Internal_Sym *sym; + bfd *ibfd = sec->owner; + + r_symndx = ELF64_R_SYM (r_info); + if (!get_sym_h (&h, &sym, &sym_sec, NULL, local_syms, r_symndx, ibfd)) + return FALSE; + } + + if ((info->shared + && (MUST_BE_DYN_RELOC (r_type) + || (h != NULL + && (!info->symbolic + || h->root.type == bfd_link_hash_defweak + || !h->def_regular)))) + || (ELIMINATE_COPY_RELOCS + && !info->shared + && h != NULL + && (h->root.type == bfd_link_hash_defweak + || !h->def_regular))) + ; + else + return TRUE; + + if (h != NULL) + pp = &((struct ppc_link_hash_entry *) h)->dyn_relocs; + else if (sym_sec != NULL) + pp = (struct ppc_dyn_relocs **) &elf_section_data (sym_sec)->local_dynrel; + else + pp = (struct ppc_dyn_relocs **) &elf_section_data (sec)->local_dynrel; + + while ((p = *pp) != NULL) + { + if (p->sec == sec) + { + if (!MUST_BE_DYN_RELOC (r_type)) + p->pc_count -= 1; + p->count -= 1; + if (p->count == 0) + *pp = p->next; + return TRUE; + } + pp = &p->next; + } + + (*_bfd_error_handler) (_("dynreloc miscount for %B, section %A"), + sec->owner, sec); + bfd_set_error (bfd_error_bad_value); + return FALSE; +} + /* Remove unused Official Procedure Descriptor entries. Currently we only remove those associated with functions in discarded link-once sections, or weakly defined functions that have been overridden. It @@ -6271,33 +6418,9 @@ ppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info, if (skip) { - BFD_ASSERT (MUST_BE_DYN_RELOC (ELF64_R_TYPE (rel->r_info))); - if (info->shared) - { - /* We won't be needing dynamic relocs here. */ - struct ppc_dyn_relocs **pp; - struct ppc_dyn_relocs *p; - - if (h != NULL) - pp = &((struct ppc_link_hash_entry *) h)->dyn_relocs; - else if (sym_sec != NULL) - pp = ((struct ppc_dyn_relocs **) - &elf_section_data (sym_sec)->local_dynrel); - else - pp = ((struct ppc_dyn_relocs **) - &elf_section_data (sec)->local_dynrel); - while ((p = *pp) != NULL) - { - if (p->sec == sec) - { - p->count -= 1; - if (p->count == 0) - *pp = p->next; - break; - } - pp = &p->next; - } - } + if (!dec_dynrel_count (rel->r_info, sec, info, + NULL, h, sym_sec)) + goto error_ret; } else { @@ -6668,29 +6791,20 @@ ppc64_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info) ent->got.refcount -= 1; } } - else if (h != NULL) + else { - struct ppc_link_hash_entry * eh; - struct ppc_dyn_relocs **pp; - struct ppc_dyn_relocs *p; - - /* Adjust dynamic relocs. */ - eh = (struct ppc_link_hash_entry *) h; - for (pp = &eh->dyn_relocs; - (p = *pp) != NULL; - pp = &p->next) - if (p->sec == sec) - { - /* If we got rid of a DTPMOD/DTPREL reloc - pair then we'll lose one or two dyn - relocs. */ - if (tls_set == (TLS_EXPLICIT | TLS_GD)) - p->count -= 1; - p->count -= 1; - if (p->count == 0) - *pp = p->next; - break; - } + /* 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)) + return FALSE; + + if (tls_set == (TLS_EXPLICIT | TLS_GD)) + { + if (!dec_dynrel_count ((rel + 1)->r_info, sec, info, + NULL, h, sym_sec)) + return FALSE; + } } *tls_mask |= tls_set; @@ -7056,6 +7170,10 @@ ppc64_elf_edit_toc (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info) wrel->r_addend = rel->r_addend; ++wrel; } + else if (!dec_dynrel_count (rel->r_info, toc, info, + &local_syms, NULL, NULL)) + goto error_ret; + toc->reloc_count = wrel - relstart; sz = elf_section_data (toc)->rel_hdr.sh_entsize; elf_section_data (toc)->rel_hdr.sh_size = toc->reloc_count * sz;