X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=bfd%2Felf64-ppc.c;h=7f959183a30e7245f91f6999c4a3108dbaf89b90;hb=60124e18308ef9e55661efd268dfbda72ff03f91;hp=3f219fa9d725b33b752cd19ec450251d2935ecfe;hpb=909272ee76c4915692763a3dde6b4b1dc21fc166;p=binutils-gdb.git diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index 3f219fa9d72..7f959183a30 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -95,6 +95,7 @@ static bfd_vma opd_entry_value #define elf_backend_hide_symbol ppc64_elf_hide_symbol #define elf_backend_always_size_sections ppc64_elf_func_desc_adjust #define elf_backend_size_dynamic_sections ppc64_elf_size_dynamic_sections +#define elf_backend_action_discarded ppc64_elf_action_discarded #define elf_backend_relocate_section ppc64_elf_relocate_section #define elf_backend_finish_dynamic_symbol ppc64_elf_finish_dynamic_symbol #define elf_backend_reloc_type_class ppc64_elf_reloc_type_class @@ -4767,13 +4768,15 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, easily. Oh well. */ asection *s; + void *vpp; + s = bfd_section_from_r_symndx (abfd, &htab->sym_sec, sec, r_symndx); if (s == NULL) return FALSE; - head = ((struct ppc_dyn_relocs **) - &elf_section_data (s)->local_dynrel); + vpp = &elf_section_data (s)->local_dynrel; + head = (struct ppc_dyn_relocs **) vpp; } p = *head; @@ -6118,10 +6121,25 @@ dec_dynrel_count (bfd_vma r_info, 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; + { + if (sym_sec != NULL) + { + void *vpp = &elf_section_data (sym_sec)->local_dynrel; + pp = (struct ppc_dyn_relocs **) vpp; + } + else + { + void *vpp = &elf_section_data (sec)->local_dynrel; + pp = (struct ppc_dyn_relocs **) vpp; + } + + /* elf_gc_sweep may have already removed all dyn relocs associated + with local syms for a given section. Don't report a dynreloc + miscount. */ + if (*pp == NULL) + return TRUE; + } while ((p = *pp) != NULL) { @@ -6468,7 +6486,8 @@ ppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info, if (skip) { - if (!info->relocatable + if (!NO_OPD_RELOCS + && !info->relocatable && !dec_dynrel_count (rel->r_info, sec, info, NULL, h, sym_sec)) goto error_ret; @@ -7638,10 +7657,7 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, { struct ppc_dyn_relocs *p; - for (p = *((struct ppc_dyn_relocs **) - &elf_section_data (s)->local_dynrel); - p != NULL; - p = p->next) + for (p = elf_section_data (s)->local_dynrel; p != NULL; p = p->next) { if (!bfd_is_abs_section (p->sec) && bfd_is_abs_section (p->sec->output_section)) @@ -7888,26 +7904,34 @@ ppc_type_of_stub (asection *input_sec, if (h != NULL) { - if (h->oh != NULL - && h->oh->is_func_descriptor) - h = h->oh; + struct ppc_link_hash_entry *fdh = h; + if (fdh->oh != NULL + && fdh->oh->is_func_descriptor) + fdh = fdh->oh; - if (h->elf.dynindx != -1) + if (fdh->elf.dynindx != -1) { struct plt_entry *ent; - for (ent = h->elf.plt.plist; ent != NULL; ent = ent->next) + for (ent = fdh->elf.plt.plist; ent != NULL; ent = ent->next) if (ent->addend == rel->r_addend && ent->plt.offset != (bfd_vma) -1) { - *hash = h; + *hash = fdh; return ppc_stub_plt_call; } } - if (!(h->elf.root.type == bfd_link_hash_defined - || h->elf.root.type == bfd_link_hash_defweak) - || h->elf.root.u.def.section->output_section == NULL) + /* Here, we know we don't have a plt entry. If we don't have a + either a defined function descriptor or a defined entry symbol + in a regular object file, then it is pointless trying to make + any other type of stub. */ + if (!((fdh->elf.root.type == bfd_link_hash_defined + || fdh->elf.root.type == bfd_link_hash_defweak) + && fdh->elf.root.u.def.section->output_section != NULL) + && !((h->elf.root.type == bfd_link_hash_defined + || h->elf.root.type == bfd_link_hash_defweak) + && h->elf.root.u.def.section->output_section != NULL)) return ppc_stub_none; } @@ -8015,7 +8039,13 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) } bfd_put_32 (htab->stub_bfd, B_DOT | (off & 0x3fffffc), loc); - BFD_ASSERT (off + (1 << 25) < (bfd_vma) (1 << 26)); + if (off + (1 << 25) >= (bfd_vma) (1 << 26)) + { + (*_bfd_error_handler) (_("long branch stub `%s' offset overflow"), + stub_entry->root.string); + htab->stub_error = TRUE; + return FALSE; + } if (info->emitrelocations) { @@ -8087,7 +8117,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) if (br_entry == NULL) { (*_bfd_error_handler) (_("can't find branch stub `%s'"), - stub_entry->root.string + 9); + stub_entry->root.string); htab->stub_error = TRUE; return FALSE; } @@ -8331,7 +8361,7 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) if (br_entry == NULL) { (*_bfd_error_handler) (_("can't build branch stub `%s'"), - stub_entry->root.string + 9); + stub_entry->root.string); htab->stub_error = TRUE; return FALSE; } @@ -8752,7 +8782,10 @@ group_sections (struct ppc_link_hash_table *htab, curr = tail; total = tail->size; - big_sec = total >= stub_group_size; + big_sec = total > stub_group_size; + if (big_sec) + (*_bfd_error_handler) (_("%B section %A exceeds stub group size"), + tail->owner, tail); curr_toc = htab->stub_group[tail->id].toc_off; while ((prev = PREV_SEC (curr)) != NULL @@ -8854,10 +8887,8 @@ ppc64_elf_size_stubs (bfd *output_bfd, bfd *input_bfd; unsigned int bfd_indx; asection *stub_sec; - bfd_boolean stub_changed; htab->stub_iteration += 1; - stub_changed = FALSE; for (input_bfd = info->input_bfds, bfd_indx = 0; input_bfd != NULL; @@ -8944,16 +8975,25 @@ ppc64_elf_size_stubs (bfd *output_bfd, ok_dest = FALSE; fdh = NULL; + sym_value = 0; if (hash == NULL) { sym_value = sym->st_value; ok_dest = TRUE; } - else + else if (hash->elf.root.type == bfd_link_hash_defined + || hash->elf.root.type == bfd_link_hash_defweak) + { + sym_value = hash->elf.root.u.def.value; + if (sym_sec->output_section != NULL) + ok_dest = TRUE; + } + else if (hash->elf.root.type == bfd_link_hash_undefweak + || hash->elf.root.type == bfd_link_hash_undefined) { - sym_value = 0; /* Recognise an old ABI func code entry sym, and - use the func descriptor sym instead. */ + use the func descriptor sym instead if it is + defined. */ if (hash->elf.root.root.string[0] == '.' && (fdh = get_fdh (hash, htab)) != NULL) { @@ -8968,22 +9008,11 @@ ppc64_elf_size_stubs (bfd *output_bfd, else fdh = NULL; } - else if (hash->elf.root.type == bfd_link_hash_defined - || hash->elf.root.type == bfd_link_hash_defweak) - { - sym_value = hash->elf.root.u.def.value; - if (sym_sec->output_section != NULL) - ok_dest = TRUE; - } - else if (hash->elf.root.type == bfd_link_hash_undefweak) - ; - else if (hash->elf.root.type == bfd_link_hash_undefined) - ; - else - { - bfd_set_error (bfd_error_bad_value); - goto error_ret_free_internal; - } + } + else + { + bfd_set_error (bfd_error_bad_value); + goto error_ret_free_internal; } destination = 0; @@ -9106,8 +9135,6 @@ ppc64_elf_size_stubs (bfd *output_bfd, if (stub_entry->h != NULL) htab->stub_globals += 1; - - stub_changed = TRUE; } /* We're done with the internal relocs, free them. */ @@ -9125,16 +9152,14 @@ ppc64_elf_size_stubs (bfd *output_bfd, } } - if (!stub_changed) - break; - - /* OK, we've added some stubs. Find out the new size of the + /* We may have added some stubs. Find out the new size of the stub sections. */ for (stub_sec = htab->stub_bfd->sections; stub_sec != NULL; stub_sec = stub_sec->next) if ((stub_sec->flags & SEC_LINKER_CREATED) == 0) { + stub_sec->rawsize = stub_sec->size; stub_sec->size = 0; stub_sec->reloc_count = 0; } @@ -9145,6 +9170,18 @@ ppc64_elf_size_stubs (bfd *output_bfd, bfd_hash_traverse (&htab->stub_hash_table, ppc_size_one_stub, info); + for (stub_sec = htab->stub_bfd->sections; + stub_sec != NULL; + stub_sec = stub_sec->next) + if ((stub_sec->flags & SEC_LINKER_CREATED) == 0 + && stub_sec->rawsize != stub_sec->size) + break; + + /* Exit from this loop when no stubs have been added, and no stubs + have changed size. */ + if (stub_sec == NULL) + break; + /* Ask the linker to do its stuff. */ (*htab->layout_sections_again) (); } @@ -9428,6 +9465,21 @@ ppc64_elf_restore_symbols (struct bfd_link_info *info) elf_link_hash_traverse (&htab->elf, undo_symbol_twiddle, info); } +/* What to do when ld finds relocations against symbols defined in + discarded sections. */ + +static unsigned int +ppc64_elf_action_discarded (asection *sec) +{ + if (strcmp (".opd", sec->name) == 0) + return 0; + + if (strcmp (".toc", sec->name) == 0) + return 0; + + return _bfd_elf_default_action_discarded (sec); +} + /* The RELOCATE_SECTION function is called by the ELF backend linker to handle the relocations for a section.