X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=bfd%2Felf64-ppc.c;h=5cbf9acfcd1cb077805fa88ec59d29b57f544d21;hb=abebb03c3af215d7542f5e6b71d78823b15220d5;hp=945f83c7e614d356a45ebee8b53b34724892707d;hpb=988b7300bc990abafd982bdcd217c58bc1e0679a;p=binutils-gdb.git diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index 945f83c7e61..5cbf9acfcd1 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -930,16 +930,16 @@ static reloc_howto_type ppc64_elf_howto_raw[] = HOW (R_PPC64_DTPREL34, 4, 34, 0x3ffff0000ffffULL, 0, FALSE, signed, ppc64_elf_unhandled_reloc), - HOW (R_PPC64_GOT_TLSGD34, 4, 34, 0x3ffff0000ffffULL, 0, TRUE, signed, + HOW (R_PPC64_GOT_TLSGD_PCREL34, 4, 34, 0x3ffff0000ffffULL, 0, TRUE, signed, ppc64_elf_unhandled_reloc), - HOW (R_PPC64_GOT_TLSLD34, 4, 34, 0x3ffff0000ffffULL, 0, TRUE, signed, + HOW (R_PPC64_GOT_TLSLD_PCREL34, 4, 34, 0x3ffff0000ffffULL, 0, TRUE, signed, ppc64_elf_unhandled_reloc), - HOW (R_PPC64_GOT_TPREL34, 4, 34, 0x3ffff0000ffffULL, 0, TRUE, signed, + HOW (R_PPC64_GOT_TPREL_PCREL34, 4, 34, 0x3ffff0000ffffULL, 0, TRUE, signed, ppc64_elf_unhandled_reloc), - HOW (R_PPC64_GOT_DTPREL34, 4, 34, 0x3ffff0000ffffULL, 0, TRUE, signed, + HOW (R_PPC64_GOT_DTPREL_PCREL34, 4, 34, 0x3ffff0000ffffULL, 0, TRUE, signed, ppc64_elf_unhandled_reloc), HOW (R_PPC64_ADDR16_HIGHER34, 1, 16, 0xffff, 34, FALSE, dont, @@ -999,8 +999,7 @@ ppc_howto_init (void) } static reloc_howto_type * -ppc64_elf_reloc_type_lookup (bfd *abfd, - bfd_reloc_code_real_type code) +ppc64_elf_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code) { enum elf_ppc64_reloc_type r = R_PPC64_NONE; @@ -1280,13 +1279,13 @@ ppc64_elf_reloc_type_lookup (bfd *abfd, break; case BFD_RELOC_PPC64_DTPREL34: r = R_PPC64_DTPREL34; break; - case BFD_RELOC_PPC64_GOT_TLSGD34: r = R_PPC64_GOT_TLSGD34; + case BFD_RELOC_PPC64_GOT_TLSGD_PCREL34: r = R_PPC64_GOT_TLSGD_PCREL34; break; - case BFD_RELOC_PPC64_GOT_TLSLD34: r = R_PPC64_GOT_TLSLD34; + case BFD_RELOC_PPC64_GOT_TLSLD_PCREL34: r = R_PPC64_GOT_TLSLD_PCREL34; break; - case BFD_RELOC_PPC64_GOT_TPREL34: r = R_PPC64_GOT_TPREL34; + case BFD_RELOC_PPC64_GOT_TPREL_PCREL34: r = R_PPC64_GOT_TPREL_PCREL34; break; - case BFD_RELOC_PPC64_GOT_DTPREL34: r = R_PPC64_GOT_DTPREL34; + case BFD_RELOC_PPC64_GOT_DTPREL_PCREL34: r = R_PPC64_GOT_DTPREL_PCREL34; break; case BFD_RELOC_PPC64_ADDR16_HIGHER34: r = R_PPC64_ADDR16_HIGHER34; break; @@ -1318,16 +1317,33 @@ ppc64_elf_reloc_type_lookup (bfd *abfd, }; static reloc_howto_type * -ppc64_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, - const char *r_name) +ppc64_elf_reloc_name_lookup (bfd *abfd, const char *r_name) { unsigned int i; + static char *compat_map[][2] = { + { "R_PPC64_GOT_TLSGD34", "R_PPC64_GOT_TLSGD_PCREL34" }, + { "R_PPC64_GOT_TLSLD34", "R_PPC64_GOT_TLSLD_PCREL34" }, + { "R_PPC64_GOT_TPREL34", "R_PPC64_GOT_TPREL_PCREL34" }, + { "R_PPC64_GOT_DTPREL34", "R_PPC64_GOT_DTPREL_PCREL34" } + }; for (i = 0; i < ARRAY_SIZE (ppc64_elf_howto_raw); i++) if (ppc64_elf_howto_raw[i].name != NULL && strcasecmp (ppc64_elf_howto_raw[i].name, r_name) == 0) return &ppc64_elf_howto_raw[i]; + /* Handle old names of relocations in case they were used by + .reloc directives. + FIXME: Remove this soon. Mapping the reloc names is very likely + completely unnecessary. */ + for (i = 0; i < ARRAY_SIZE (compat_map); i++) + if (strcasecmp (compat_map[i][0], r_name) == 0) + { + _bfd_error_handler (_("warning: %s should be used rather than %s"), + compat_map[i][1], compat_map[i][0]); + return ppc64_elf_reloc_name_lookup (abfd, compat_map[i][1]); + } + return NULL; } @@ -2422,8 +2438,7 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd, free_contents_and_exit_err: count = -1; free_contents_and_exit: - if (contents) - free (contents); + free (contents); goto done; } @@ -2914,7 +2929,7 @@ must_be_dyn_reloc (struct bfd_link_info *info, . mtctr %r12 . bctr - There are also ELFv1 powerxx variants of these stubs. + There are also ELFv1 power10 variants of these stubs. ppc_stub_long_branch_notoc: . pla %r12,dest@pcrel . b dest @@ -2937,7 +2952,7 @@ must_be_dyn_reloc (struct bfd_link_info *info, In cases where the high instructions would add zero, they are omitted and following instructions modified in some cases. - For example, a powerxx ppc_stub_plt_call_notoc might simplify down + For example, a power10 ppc_stub_plt_call_notoc might simplify down to . pld %r12,xxx@pcrel . mtctr %r12 @@ -3076,9 +3091,6 @@ struct ppc_link_hash_entry struct ppc_link_hash_entry *next_dot_sym; } u; - /* Track dynamic relocs copied for this symbol. */ - struct elf_dyn_relocs *dyn_relocs; - /* Link between function code and descriptor symbols. */ struct ppc_link_hash_entry *oh; @@ -3227,25 +3239,17 @@ struct ppc_link_hash_table /* Whether func_desc_adjust needs to be run over symbols. */ unsigned int need_func_desc_adj:1; - /* Whether there exist local gnu indirect function resolvers, - referenced by dynamic relocations. */ - unsigned int local_ifunc_resolver:1; - unsigned int maybe_local_ifunc_resolver:1; - /* Whether plt calls for ELFv2 localentry:0 funcs have been optimized. */ unsigned int has_plt_localentry0:1; /* Whether calls are made via the PLT from NOTOC functions. */ unsigned int notoc_plt:1; - /* Whether to use powerxx instructions in linkage stubs. */ - unsigned int powerxx_stubs:1; + /* Whether any code linked seems to be Power10. */ + unsigned int has_power10_relocs:1; /* Incremented every time we size stubs. */ unsigned int stub_iteration; - - /* Small local sym cache. */ - struct sym_cache sym_cache; }; /* Rename some of the generic section flags to better document how they @@ -3675,6 +3679,37 @@ ppc_stub_name (const asection *input_section, return stub_name; } +/* If mixing power10 with non-power10 code and --power10-stubs is not + specified (or is auto) then calls using @notoc relocations that + need a stub will utilize power10 instructions in the stub, and + calls without @notoc relocations will not use power10 instructions. + The two classes of stubs are stored in separate stub_hash_table + entries having the same key string. The two entries will always be + adjacent on entry->root.next chain, even if hash table resizing + occurs. This function selects the correct entry to use. */ + +static struct ppc_stub_hash_entry * +select_alt_stub (struct ppc_stub_hash_entry *entry, bfd_boolean notoc) +{ + bfd_boolean have_notoc; + + have_notoc = (entry->stub_type == ppc_stub_plt_call_notoc + || entry->stub_type == ppc_stub_plt_branch_notoc + || entry->stub_type == ppc_stub_long_branch_notoc); + + if (have_notoc != notoc) + { + const char *stub_name = entry->root.string; + + entry = (struct ppc_stub_hash_entry *) entry->root.next; + if (entry != NULL + && entry->root.string != stub_name) + entry = NULL; + } + + return entry; +} + /* Look up an entry in the stub hash. Stub entries are cached because creating the stub name takes a bit of time. */ @@ -3719,6 +3754,13 @@ ppc_get_stub_entry (const asection *input_section, free (stub_name); } + if (stub_entry != NULL && htab->params->power10_stubs == -1) + { + bfd_boolean notoc = ELF64_R_TYPE (rel->r_info) == R_PPC64_REL24_NOTOC; + + stub_entry = select_alt_stub (stub_entry, notoc); + } + return stub_entry; } @@ -3907,20 +3949,20 @@ ppc64_elf_copy_indirect_symbol (struct bfd_link_info *info, return; /* Copy over any dynamic relocs we may have on the indirect sym. */ - if (eind->dyn_relocs != NULL) + if (ind->dyn_relocs != NULL) { - if (edir->dyn_relocs != NULL) + if (dir->dyn_relocs != NULL) { struct elf_dyn_relocs **pp; struct elf_dyn_relocs *p; /* Add reloc counts against the indirect sym to the direct sym list. Merge any entries against the same section. */ - for (pp = &eind->dyn_relocs; (p = *pp) != NULL; ) + for (pp = &ind->dyn_relocs; (p = *pp) != NULL; ) { struct elf_dyn_relocs *q; - for (q = edir->dyn_relocs; q != NULL; q = q->next) + for (q = dir->dyn_relocs; q != NULL; q = q->next) if (q->sec == p->sec) { q->pc_count += p->pc_count; @@ -3931,11 +3973,11 @@ ppc64_elf_copy_indirect_symbol (struct bfd_link_info *info, if (q == NULL) pp = &p->next; } - *pp = edir->dyn_relocs; + *pp = dir->dyn_relocs; } - edir->dyn_relocs = eind->dyn_relocs; - eind->dyn_relocs = NULL; + dir->dyn_relocs = ind->dyn_relocs; + ind->dyn_relocs = NULL; } /* Copy over got entries that we may have already seen to the @@ -4338,7 +4380,8 @@ ppc64_elf_before_check_relocs (bfd *ibfd, struct bfd_link_info *info) Elf_Internal_Sym *isym; asection *s; - isym = bfd_sym_from_r_symndx (&htab->sym_cache, ibfd, r_symndx); + isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache, ibfd, + r_symndx); if (isym == NULL) { if (elf_section_data (opd)->relocs != relocs) @@ -4540,15 +4583,6 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, if (bfd_link_relocatable (info)) return TRUE; - /* Don't do anything special with non-loaded, non-alloced sections. - In particular, any relocs in such sections should not affect GOT - and PLT reference counting (ie. we don't allow them to create GOT - or PLT entries), there's no possibility or desire to optimize TLS - relocs, and there's not much point in propagating relocs to shared - libs that the dynamic linker won't relocate. */ - if ((sec->flags & SEC_ALLOC) == 0) - return TRUE; - BFD_ASSERT (is_ppc64_elf (abfd)); htab = ppc_hash_table (info); @@ -4597,14 +4631,14 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_PPC64_DTPREL34: case R_PPC64_PCREL34: case R_PPC64_GOT_PCREL34: - case R_PPC64_GOT_TLSGD34: - case R_PPC64_GOT_TLSLD34: - case R_PPC64_GOT_TPREL34: - case R_PPC64_GOT_DTPREL34: + case R_PPC64_GOT_TLSGD_PCREL34: + case R_PPC64_GOT_TLSLD_PCREL34: + case R_PPC64_GOT_TPREL_PCREL34: + case R_PPC64_GOT_DTPREL_PCREL34: case R_PPC64_PLT_PCREL34: case R_PPC64_PLT_PCREL34_NOTOC: case R_PPC64_PCREL28: - htab->powerxx_stubs = 1; + htab->has_power10_relocs = 1; break; default: break; @@ -4648,7 +4682,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, } else { - Elf_Internal_Sym *isym = bfd_sym_from_r_symndx (&htab->sym_cache, + Elf_Internal_Sym *isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache, abfd, r_symndx); if (isym == NULL) return FALSE; @@ -4684,7 +4718,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_PPC64_GOT_TLSLD16_LO: case R_PPC64_GOT_TLSLD16_HI: case R_PPC64_GOT_TLSLD16_HA: - case R_PPC64_GOT_TLSLD34: + case R_PPC64_GOT_TLSLD_PCREL34: tls_type = TLS_TLS | TLS_LD; goto dogottls; @@ -4692,7 +4726,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_PPC64_GOT_TLSGD16_LO: case R_PPC64_GOT_TLSGD16_HI: case R_PPC64_GOT_TLSGD16_HA: - case R_PPC64_GOT_TLSGD34: + case R_PPC64_GOT_TLSGD_PCREL34: tls_type = TLS_TLS | TLS_GD; goto dogottls; @@ -4700,7 +4734,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_PPC64_GOT_TPREL16_LO_DS: case R_PPC64_GOT_TPREL16_HI: case R_PPC64_GOT_TPREL16_HA: - case R_PPC64_GOT_TPREL34: + case R_PPC64_GOT_TPREL_PCREL34: if (bfd_link_dll (info)) info->flags |= DF_STATIC_TLS; tls_type = TLS_TLS | TLS_TPREL; @@ -4710,7 +4744,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_PPC64_GOT_DTPREL16_LO_DS: case R_PPC64_GOT_DTPREL16_HI: case R_PPC64_GOT_DTPREL16_HA: - case R_PPC64_GOT_DTPREL34: + case R_PPC64_GOT_DTPREL_PCREL34: tls_type = TLS_TLS | TLS_DTPREL; dogottls: sec->has_tls_reloc = 1; @@ -4774,14 +4808,6 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, if (!update_local_sym_info (abfd, symtab_hdr, r_symndx, rel->r_addend, tls_type)) return FALSE; - - /* We may also need a plt entry if the symbol turns out to be - an ifunc. */ - if (h != NULL && !bfd_link_pic (info) && abiversion (abfd) != 1) - { - if (!update_plt_info (abfd, &h->plt.plist, rel->r_addend)) - return FALSE; - } break; case R_PPC64_PLT16_HA: @@ -4927,7 +4953,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, { Elf_Internal_Sym *isym; - isym = bfd_sym_from_r_symndx (&htab->sym_cache, + isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache, abfd, r_symndx); if (isym == NULL) return FALSE; @@ -5174,7 +5200,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, struct elf_dyn_relocs *p; struct elf_dyn_relocs **head; - head = &ppc_elf_hash_entry (h)->dyn_relocs; + head = &h->dyn_relocs; p = *head; if (p == NULL || p->sec != sec) { @@ -5203,7 +5229,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, void *vpp; Elf_Internal_Sym *isym; - isym = bfd_sym_from_r_symndx (&htab->sym_cache, + isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache, abfd, r_symndx); if (isym == NULL) return FALSE; @@ -6368,24 +6394,6 @@ ppc64_elf_func_desc_adjust (bfd *obfd ATTRIBUTE_UNUSED, return TRUE; } -/* Find dynamic relocs for H that apply to read-only sections. */ - -static asection * -readonly_dynrelocs (struct elf_link_hash_entry *h) -{ - struct ppc_link_hash_entry *eh = ppc_elf_hash_entry (h); - struct elf_dyn_relocs *p; - - for (p = eh->dyn_relocs; p != NULL; p = p->next) - { - asection *s = p->sec->output_section; - - if (s != NULL && (s->flags & SEC_READONLY) != 0) - return p->sec; - } - return NULL; -} - /* Return true if we have dynamic relocs against H or any of its weak aliases, that apply to read-only sections. Cannot be used after size_dynamic_sections. */ @@ -6396,7 +6404,7 @@ alias_readonly_dynrelocs (struct elf_link_hash_entry *h) struct ppc_link_hash_entry *eh = ppc_elf_hash_entry (h); do { - if (readonly_dynrelocs (&eh->elf)) + if (_bfd_elf_readonly_dynrelocs (&eh->elf)) return TRUE; eh = ppc_elf_hash_entry (eh->elf.u.alias); } @@ -6412,7 +6420,7 @@ pc_dynrelocs (struct ppc_link_hash_entry *eh) { struct elf_dyn_relocs *p; - for (p = eh->dyn_relocs; p != NULL; p = p->next) + for (p = eh->elf.dyn_relocs; p != NULL; p = p->next) if (p->pc_count != 0) return TRUE; return FALSE; @@ -6475,7 +6483,7 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info, if (!bfd_link_pic (info) && h->type != STT_GNU_IFUNC && local) - ppc_elf_hash_entry (h)->dyn_relocs = NULL; + h->dyn_relocs = NULL; /* Clear procedure linkage table information for any symbol that won't need a .plt entry. */ @@ -6505,7 +6513,7 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info, extra work in ld.so when resolving these symbols. */ if (global_entry_stub (h)) { - if (!readonly_dynrelocs (h)) + if (!_bfd_elf_readonly_dynrelocs (h)) { h->pointer_equality_needed = 0; /* If we haven't seen a branch reloc and the symbol @@ -6516,14 +6524,14 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info, else if (!bfd_link_pic (info)) /* We are going to be defining the function symbol on the plt stub, so no dyn_relocs needed when non-pic. */ - ppc_elf_hash_entry (h)->dyn_relocs = NULL; + h->dyn_relocs = NULL; } /* ELFv2 function symbols can't have copy relocs. */ return TRUE; } else if (!h->needs_plt - && !readonly_dynrelocs (h)) + && !_bfd_elf_readonly_dynrelocs (h)) { /* If we haven't seen a branch reloc and the symbol isn't an ifunc then we don't need a plt entry. */ @@ -6546,7 +6554,7 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info, h->root.u.def.value = def->root.u.def.value; if (def->root.u.def.section == htab->elf.sdynbss || def->root.u.def.section == htab->elf.sdynrelro) - ppc_elf_hash_entry (h)->dyn_relocs = NULL; + h->dyn_relocs = NULL; return TRUE; } @@ -6636,7 +6644,7 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info, } /* We no longer want dyn_relocs. */ - ppc_elf_hash_entry (h)->dyn_relocs = NULL; + h->dyn_relocs = NULL; return _bfd_elf_adjust_dynamic_copy (info, h, s); } @@ -7058,7 +7066,7 @@ dec_dynrel_count (bfd_vma r_info, { struct elf_dyn_relocs *p; struct elf_dyn_relocs **pp; - pp = &ppc_elf_hash_entry (h)->dyn_relocs; + pp = &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 @@ -7311,11 +7319,9 @@ ppc64_elf_edit_opd (struct bfd_link_info *info) bfd_byte *loc; if (!bfd_malloc_and_get_section (ibfd, sec, &loc)) { - if (loc != NULL) - free (loc); + free (loc); error_ret: - if (local_syms != NULL - && symtab_hdr->contents != (unsigned char *) local_syms) + if (symtab_hdr->contents != (unsigned char *) local_syms) free (local_syms); if (elf_section_data (sec)->relocs != relstart) free (relstart); @@ -7641,8 +7647,7 @@ ppc64_elf_inline_plt (struct bfd_link_info *info) { if (elf_section_data (sec)->relocs != relstart) free (relstart); - if (local_syms != NULL - && symtab_hdr->contents != (bfd_byte *) local_syms) + if (symtab_hdr->contents != (bfd_byte *) local_syms) free (local_syms); return FALSE; } @@ -7983,11 +7988,9 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info) err_free_rel: if (elf_section_data (sec)->relocs != relstart) free (relstart); - if (toc_ref != NULL) - free (toc_ref); - if (locsyms != NULL - && (elf_symtab_hdr (ibfd).contents - != (unsigned char *) locsyms)) + free (toc_ref); + if (elf_symtab_hdr (ibfd).contents + != (unsigned char *) locsyms) free (locsyms); return ret; } @@ -8059,7 +8062,7 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info) { case R_PPC64_GOT_TLSLD16: case R_PPC64_GOT_TLSLD16_LO: - case R_PPC64_GOT_TLSLD34: + case R_PPC64_GOT_TLSLD_PCREL34: expecting_tls_get_addr = 1; found_tls_get_addr_arg = 1; /* Fall through. */ @@ -8080,7 +8083,7 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info) case R_PPC64_GOT_TLSGD16: case R_PPC64_GOT_TLSGD16_LO: - case R_PPC64_GOT_TLSGD34: + case R_PPC64_GOT_TLSGD_PCREL34: expecting_tls_get_addr = 1; found_tls_get_addr_arg = 1; /* Fall through. */ @@ -8097,7 +8100,7 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info) tls_type = TLS_TLS | TLS_GD; break; - case R_PPC64_GOT_TPREL34: + case R_PPC64_GOT_TPREL_PCREL34: case R_PPC64_GOT_TPREL16_DS: case R_PPC64_GOT_TPREL16_LO_DS: case R_PPC64_GOT_TPREL16_HI: @@ -8402,8 +8405,7 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info) } } - if (toc_ref != NULL) - free (toc_ref); + free (toc_ref); htab->do_tls_opt = 1; return TRUE; } @@ -8613,6 +8615,15 @@ xlate_pcrel_opt (uint64_t *pinsn1, uint64_t *pinsn2, bfd_signed_vma *poff) off = insn2 & 0xffff; break; + case 6: /* lxvp, stxvp */ + if ((insn2 & 0xe) != 0) + return FALSE; + insn1 = ((1ULL << 58) | (1ULL << 52) + | ((insn2 & 1) == 0 ? 58ULL << 26 : 62ULL << 26) + | (insn2 & (31ULL << 21))); + off = insn2 & 0xfff0; + break; + case 62: /* std, stq */ if ((insn2 & 1) != 0) return FALSE; @@ -8834,18 +8845,14 @@ ppc64_elf_edit_toc (struct bfd_link_info *info) if (used == NULL) { error_ret: - if (local_syms != NULL - && symtab_hdr->contents != (unsigned char *) local_syms) + if (symtab_hdr->contents != (unsigned char *) local_syms) free (local_syms); if (sec != NULL - && relstart != NULL && elf_section_data (sec)->relocs != relstart) free (relstart); - if (toc_relocs != NULL - && elf_section_data (toc)->relocs != toc_relocs) + if (elf_section_data (toc)->relocs != toc_relocs) free (toc_relocs); - if (skip != NULL) - free (skip); + free (skip); return FALSE; } @@ -9212,8 +9219,7 @@ ppc64_elf_edit_toc (struct bfd_link_info *info) rel_hdr->sh_size = toc->reloc_count * sz; } } - else if (toc_relocs != NULL - && elf_section_data (toc)->relocs != toc_relocs) + else if (elf_section_data (toc)->relocs != toc_relocs) free (toc_relocs); if (local_syms != NULL @@ -9264,11 +9270,9 @@ ppc64_elf_edit_toc (struct bfd_link_info *info) if (relstart == NULL) { got_error_ret: - if (local_syms != NULL - && symtab_hdr->contents != (unsigned char *) local_syms) + if (symtab_hdr->contents != (unsigned char *) local_syms) free (local_syms); if (sec != NULL - && relstart != NULL && elf_section_data (sec)->relocs != relstart) free (relstart); return FALSE; @@ -9371,6 +9375,9 @@ ppc64_elf_edit_toc (struct bfd_link_info *info) || discarded_section (sym_sec)) continue; + if ((h ? h->type : ELF_ST_TYPE (sym->st_info)) == STT_GNU_IFUNC) + continue; + if (!SYMBOL_REFERENCES_LOCAL (info, h)) continue; @@ -9640,19 +9647,19 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) IFUNCs which are handled even in static executables. */ if (!htab->elf.dynamic_sections_created && h->type != STT_GNU_IFUNC) - eh->dyn_relocs = NULL; + h->dyn_relocs = NULL; /* Discard relocs on undefined symbols that must be local. */ else if (h->root.type == bfd_link_hash_undefined && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT) - eh->dyn_relocs = NULL; + h->dyn_relocs = NULL; /* Also discard relocs on undefined weak syms with non-default visibility, or when dynamic_undefined_weak says so. */ else if (UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)) - eh->dyn_relocs = NULL; + h->dyn_relocs = NULL; - if (eh->dyn_relocs != NULL) + if (h->dyn_relocs != NULL) { struct elf_dyn_relocs *p, **pp; @@ -9672,7 +9679,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) avoid writing weird assembly. */ if (SYMBOL_CALLS_LOCAL (info, h)) { - for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) + for (pp = &h->dyn_relocs; (p = *pp) != NULL; ) { p->count -= p->pc_count; p->pc_count = 0; @@ -9683,7 +9690,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) } } - if (eh->dyn_relocs != NULL) + if (h->dyn_relocs != NULL) { /* Ensure we catch all the cases where this symbol should be made dynamic. */ @@ -9707,14 +9714,14 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) /* But if that didn't work out, discard dynamic relocs. */ if (h->dynindx == -1) - eh->dyn_relocs = NULL; + h->dyn_relocs = NULL; } else - eh->dyn_relocs = NULL; + h->dyn_relocs = NULL; } /* Finally, allocate space. */ - for (p = eh->dyn_relocs; p != NULL; p = p->next) + for (p = h->dyn_relocs; p != NULL; p = p->next) { asection *sreloc = elf_section_data (p->sec)->sreloc; if (eh->elf.type == STT_GNU_IFUNC) @@ -9893,33 +9900,6 @@ size_global_entry_stubs (struct elf_link_hash_entry *h, void *inf) return TRUE; } -/* Set DF_TEXTREL if we find any dynamic relocs that apply to - read-only sections. */ - -static bfd_boolean -maybe_set_textrel (struct elf_link_hash_entry *h, void *inf) -{ - asection *sec; - - if (h->root.type == bfd_link_hash_indirect) - return TRUE; - - sec = readonly_dynrelocs (h); - if (sec != NULL) - { - struct bfd_link_info *info = (struct bfd_link_info *) inf; - - info->flags |= DF_TEXTREL; - info->callbacks->minfo (_("%pB: dynamic relocation against `%pT'" - " in read-only section `%pA'\n"), - sec->owner, h->root.root.string, sec); - - /* Not an error, just cut short the traversal. */ - return FALSE; - } - return TRUE; -} - /* Set the sizes of the dynamic sections. */ static bfd_boolean @@ -10295,7 +10275,8 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd, /* If any dynamic relocs apply to a read-only section, then we need a DT_TEXTREL entry. */ if ((info->flags & DF_TEXTREL) == 0) - elf_link_hash_traverse (&htab->elf, maybe_set_textrel, info); + elf_link_hash_traverse (&htab->elf, + _bfd_elf_maybe_set_textrel, info); if ((info->flags & DF_TEXTREL) != 0) { @@ -10602,7 +10583,7 @@ emit_relocs_for_offset (struct bfd_link_info *info, Elf_Internal_Rela *r, } static bfd_byte * -build_powerxx_offset (bfd *abfd, bfd_byte *p, bfd_vma off, int odd, +build_power10_offset (bfd *abfd, bfd_byte *p, bfd_vma off, int odd, bfd_boolean load) { uint64_t insn; @@ -10684,7 +10665,7 @@ build_powerxx_offset (bfd *abfd, bfd_byte *p, bfd_vma off, int odd, } static unsigned int -size_powerxx_offset (bfd_vma off, int odd) +size_power10_offset (bfd_vma off, int odd) { if (off - odd + (1ULL << 33) < 1ULL << 34) return odd + 8; @@ -10695,7 +10676,7 @@ size_powerxx_offset (bfd_vma off, int odd) } static unsigned int -num_relocs_for_powerxx_offset (bfd_vma off, int odd) +num_relocs_for_power10_offset (bfd_vma off, int odd) { if (off - odd + (1ULL << 33) < 1ULL << 34) return 1; @@ -10706,7 +10687,7 @@ num_relocs_for_powerxx_offset (bfd_vma off, int odd) } static Elf_Internal_Rela * -emit_relocs_for_powerxx_offset (struct bfd_link_info *info, +emit_relocs_for_power10_offset (struct bfd_link_info *info, Elf_Internal_Rela *r, bfd_vma roff, bfd_vma targ, bfd_vma off, int odd) { @@ -10818,14 +10799,14 @@ plt_stub_size (struct ppc_link_hash_table *htab, if (stub_entry->stub_type >= ppc_stub_plt_call_notoc) { - if (htab->powerxx_stubs) + if (htab->params->power10_stubs != 0) { bfd_vma start = (stub_entry->stub_offset + stub_entry->group->stub_sec->output_offset + stub_entry->group->stub_sec->output_section->vma); if (stub_entry->stub_type > ppc_stub_plt_call_notoc) start += 4; - size = 8 + size_powerxx_offset (off, start & 4); + size = 8 + size_power10_offset (off, start & 4); } else size = 8 + size_offset (off - 8); @@ -11659,10 +11640,10 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) relp = p; num_rel = 0; - if (htab->powerxx_stubs) + if (htab->params->power10_stubs != 0) { bfd_boolean load = stub_entry->stub_type >= ppc_stub_plt_call_notoc; - p = build_powerxx_offset (htab->params->stub_bfd, p, off, odd, load); + p = build_power10_offset (htab->params->stub_bfd, p, off, odd, load); } else { @@ -11698,8 +11679,8 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) if (info->emitrelocations) { bfd_vma roff = relp - stub_entry->group->stub_sec->contents; - if (htab->powerxx_stubs) - num_rel += num_relocs_for_powerxx_offset (off, odd); + if (htab->params->power10_stubs != 0) + num_rel += num_relocs_for_power10_offset (off, odd); else { num_rel += num_relocs_for_offset (off); @@ -11708,8 +11689,8 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) r = get_relocs (stub_entry->group->stub_sec, num_rel); if (r == NULL) return FALSE; - if (htab->powerxx_stubs) - r = emit_relocs_for_powerxx_offset (info, r, roff, targ, off, odd); + if (htab->params->power10_stubs != 0) + r = emit_relocs_for_power10_offset (info, r, roff, targ, off, odd); else r = emit_relocs_for_offset (info, r, roff, targ, off); if (stub_entry->stub_type == ppc_stub_long_branch_notoc @@ -11726,7 +11707,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) } } - if (!htab->powerxx_stubs + if (htab->params->power10_stubs == 0 && htab->glink_eh_frame != NULL && htab->glink_eh_frame->size != 0) { @@ -12074,16 +12055,16 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) if (info->emitrelocations) { unsigned int num_rel; - if (htab->powerxx_stubs) - num_rel = num_relocs_for_powerxx_offset (off, odd); + if (htab->params->power10_stubs != 0) + num_rel = num_relocs_for_power10_offset (off, odd); else num_rel = num_relocs_for_offset (off - 8); stub_entry->group->stub_sec->reloc_count += num_rel; stub_entry->group->stub_sec->flags |= SEC_RELOC; } - if (htab->powerxx_stubs) - extra = size_powerxx_offset (off, odd); + if (htab->params->power10_stubs != 0) + extra = size_power10_offset (off, odd); else extra = size_offset (off - 8); /* Include branch insn plus those in the offset sequence. */ @@ -12093,7 +12074,7 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) calculated. */ off -= extra; - if (!htab->powerxx_stubs) + if (htab->params->power10_stubs == 0) { /* After the bcl, lr has been modified so we need to emit .eh_frame info saying the return address is in r12. */ @@ -12156,8 +12137,8 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) if (info->emitrelocations) { unsigned int num_rel; - if (htab->powerxx_stubs) - num_rel = num_relocs_for_powerxx_offset (off, odd); + if (htab->params->power10_stubs != 0) + num_rel = num_relocs_for_power10_offset (off, odd); else num_rel = num_relocs_for_offset (off - 8); stub_entry->group->stub_sec->reloc_count += num_rel; @@ -12166,7 +12147,7 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) size = plt_stub_size (htab, stub_entry, off); - if (!htab->powerxx_stubs) + if (htab->params->power10_stubs == 0) { /* After the bcl, lr has been modified so we need to emit .eh_frame info saying the return address is in r12. */ @@ -12788,9 +12769,8 @@ toc_adjusting_stub_needed (struct bfd_link_info *info, asection *isec) } } - if (local_syms != NULL - && (elf_symtab_hdr (isec->owner).contents - != (unsigned char *) local_syms)) + if (elf_symtab_hdr (isec->owner).contents + != (unsigned char *) local_syms) free (local_syms); if (elf_section_data (isec)->relocs != relstart) free (relstart); @@ -13092,6 +13072,9 @@ ppc64_elf_size_stubs (struct bfd_link_info *info) if (htab == NULL) return FALSE; + if (htab->params->power10_stubs == -1 && !htab->has_power10_relocs) + htab->params->power10_stubs = 0; + if (htab->params->plt_thread_safe == -1 && !bfd_link_executable (info)) htab->params->plt_thread_safe = 1; if (!htab->opd_abi) @@ -13467,6 +13450,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info) if (stub_entry != NULL) { enum ppc_stub_type old_type; + /* A stub has already been created, but it may not be the required type. We shouldn't be transitioning from plt_call to long_branch @@ -13474,6 +13458,39 @@ ppc64_elf_size_stubs (struct bfd_link_info *info) upgrading from plt_call to plt_call_r2save or from long_branch to long_branch_r2off. */ free (stub_name); + if (htab->params->power10_stubs == -1) + { + /* For --power10-stubs=auto, don't merge _notoc + and other varieties of stubs. (The _both + variety won't be created.) */ + bfd_boolean notoc = r_type == R_PPC64_REL24_NOTOC; + struct ppc_stub_hash_entry *alt_stub + = select_alt_stub (stub_entry, notoc); + + if (alt_stub == NULL) + { + alt_stub = (struct ppc_stub_hash_entry *) + stub_hash_newfunc (NULL, + &htab->stub_hash_table, + stub_entry->root.string); + if (alt_stub == NULL) + { + /* xgettext:c-format */ + _bfd_error_handler + (_("%pB: cannot create stub entry %s"), + section->owner, stub_entry->root.string); + goto error_ret_free_internal; + } + *alt_stub = *stub_entry; + stub_entry->root.next = &alt_stub->root; + if (notoc) + /* Sort notoc stubs first, for no good + reason. */ + alt_stub = stub_entry; + alt_stub->stub_type = stub_type; + } + stub_entry = alt_stub; + } old_type = stub_entry->stub_type; switch (old_type) { @@ -13543,9 +13560,8 @@ ppc64_elf_size_stubs (struct bfd_link_info *info) if (elf_section_data (section)->relocs == NULL) free (internal_relocs); error_ret_free_local: - if (local_syms != NULL - && (symtab_hdr->contents - != (unsigned char *) local_syms)) + if (symtab_hdr->contents + != (unsigned char *) local_syms) free (local_syms); return FALSE; } @@ -13777,6 +13793,8 @@ ppc64_elf_size_stubs (struct bfd_link_info *info) } maybe_strip_output (info, htab->brlt); + if (htab->relbrlt != NULL) + maybe_strip_output (info, htab->relbrlt); if (htab->glink_eh_frame != NULL) maybe_strip_output (info, htab->glink_eh_frame); @@ -13931,7 +13949,7 @@ build_global_entry_stubs_and_plt (struct elf_link_hash_entry *h, void *inf) { plt = htab->elf.iplt; relplt = htab->elf.irelplt; - htab->local_ifunc_resolver = 1; + htab->elf.ifunc_resolvers = TRUE; if (htab->opd_abi) rela.r_info = ELF64_R_INFO (0, R_PPC64_JMP_IREL); else @@ -13985,7 +14003,7 @@ build_global_entry_stubs_and_plt (struct elf_link_hash_entry *h, void *inf) + ((ent->plt.offset - PLT_INITIAL_ENTRY_SIZE (htab)) / PLT_ENTRY_SIZE (htab) * sizeof (Elf64_External_Rela))); if (h->type == STT_GNU_IFUNC && is_static_defined (h)) - htab->maybe_local_ifunc_resolver = 1; + htab->elf.ifunc_resolvers = TRUE; bfd_elf64_swap_reloca_out (info->output_bfd, &rela, loc); } } @@ -14114,8 +14132,7 @@ write_plt_relocs_for_local_syms (struct bfd_link_info *info) if (!get_sym_h (NULL, &sym, &sym_sec, NULL, &local_syms, lplt - local_plt, ibfd)) { - if (local_syms != NULL - && symtab_hdr->contents != (unsigned char *) local_syms) + if (symtab_hdr->contents != (unsigned char *) local_syms) free (local_syms); return FALSE; } @@ -14128,7 +14145,7 @@ write_plt_relocs_for_local_syms (struct bfd_link_info *info) if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC) { - htab->local_ifunc_resolver = 1; + htab->elf.ifunc_resolvers = TRUE; plt = htab->elf.iplt; relplt = htab->elf.irelplt; } @@ -15086,7 +15103,7 @@ ppc64_elf_relocate_section (bfd *output_bfd, } break; - case R_PPC64_GOT_TPREL34: + case R_PPC64_GOT_TPREL_PCREL34: if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_TPREL) == 0) { @@ -15279,7 +15296,7 @@ ppc64_elf_relocate_section (bfd *output_bfd, } break; - case R_PPC64_GOT_TLSGD34: + case R_PPC64_GOT_TLSGD_PCREL34: if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_GD) == 0) { pinsn = bfd_get_32 (input_bfd, contents + rel->r_offset); @@ -15289,7 +15306,7 @@ ppc64_elf_relocate_section (bfd *output_bfd, { /* IE, pla -> pld */ pinsn += (-2ULL << 56) + (57ULL << 26) - (14ULL << 26); - r_type = R_PPC64_GOT_TPREL34; + r_type = R_PPC64_GOT_TPREL_PCREL34; } else { @@ -15305,7 +15322,7 @@ ppc64_elf_relocate_section (bfd *output_bfd, } break; - case R_PPC64_GOT_TLSLD34: + case R_PPC64_GOT_TLSLD_PCREL34: if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_LD) == 0) { pinsn = bfd_get_32 (input_bfd, contents + rel->r_offset); @@ -15886,6 +15903,9 @@ ppc64_elf_relocate_section (bfd *output_bfd, break; case R_PPC64_GOT16_DS: + if ((h ? h->elf.type : ELF_ST_TYPE (sym->st_info)) == STT_GNU_IFUNC + || !htab->do_toc_opt) + break; from = TOCstart + htab->sec_info[input_section->id].toc_off; if (relocation + addend - from + 0x8000 < 0x10000 && SYMBOL_REFERENCES_LOCAL (info, &h->elf)) @@ -15903,6 +15923,9 @@ ppc64_elf_relocate_section (bfd *output_bfd, case R_PPC64_GOT16_LO_DS: case R_PPC64_GOT16_HA: + if ((h ? h->elf.type : ELF_ST_TYPE (sym->st_info)) == STT_GNU_IFUNC + || !htab->do_toc_opt) + break; from = TOCstart + htab->sec_info[input_section->id].toc_off; if (relocation + addend - from + 0x80008000ULL < 0x100000000ULL && SYMBOL_REFERENCES_LOCAL (info, &h->elf)) @@ -15924,32 +15947,38 @@ ppc64_elf_relocate_section (bfd *output_bfd, break; case R_PPC64_GOT_PCREL34: + if ((h ? h->elf.type : ELF_ST_TYPE (sym->st_info)) == STT_GNU_IFUNC + || !htab->do_toc_opt) + break; from = (rel->r_offset + input_section->output_section->vma + input_section->output_offset); - if (relocation - from + (1ULL << 33) < 1ULL << 34 - && SYMBOL_REFERENCES_LOCAL (info, &h->elf)) - { - offset = rel->r_offset; - pinsn = bfd_get_32 (input_bfd, contents + offset); - pinsn <<= 32; - pinsn |= bfd_get_32 (input_bfd, contents + offset + 4); - if ((pinsn & ((-1ULL << 50) | (63ULL << 26))) - == ((1ULL << 58) | (1ULL << 52) | (57ULL << 26) /* pld */)) - { - /* Replace with paddi. */ - pinsn += (2ULL << 56) + (14ULL << 26) - (57ULL << 26); - r_type = R_PPC64_PCREL34; - rel->r_info = ELF64_R_INFO (r_symndx, r_type); - bfd_put_32 (input_bfd, pinsn >> 32, contents + offset); - bfd_put_32 (input_bfd, pinsn, contents + offset + 4); - goto pcrelopt; - } - } - break; + if (!(relocation - from + (1ULL << 33) < 1ULL << 34 + && SYMBOL_REFERENCES_LOCAL (info, &h->elf))) + break; + + offset = rel->r_offset; + pinsn = bfd_get_32 (input_bfd, contents + offset); + pinsn <<= 32; + pinsn |= bfd_get_32 (input_bfd, contents + offset + 4); + if ((pinsn & ((-1ULL << 50) | (63ULL << 26))) + != ((1ULL << 58) | (1ULL << 52) | (57ULL << 26) /* pld */)) + break; + + /* Replace with paddi. */ + pinsn += (2ULL << 56) + (14ULL << 26) - (57ULL << 26); + r_type = R_PPC64_PCREL34; + rel->r_info = ELF64_R_INFO (r_symndx, r_type); + bfd_put_32 (input_bfd, pinsn >> 32, contents + offset); + bfd_put_32 (input_bfd, pinsn, contents + offset + 4); + /* Fall through. */ case R_PPC64_PCREL34: - if (SYMBOL_REFERENCES_LOCAL (info, &h->elf)) + if (!htab->params->no_pcrel_opt + && rel + 1 < relend + && rel[1].r_offset == rel->r_offset + && rel[1].r_info == ELF64_R_INFO (0, R_PPC64_PCREL_OPT) + && SYMBOL_REFERENCES_LOCAL (info, &h->elf)) { offset = rel->r_offset; pinsn = bfd_get_32 (input_bfd, contents + offset); @@ -15959,43 +15988,37 @@ ppc64_elf_relocate_section (bfd *output_bfd, == ((1ULL << 58) | (2ULL << 56) | (1ULL << 52) | (14ULL << 26) /* paddi */)) { - pcrelopt: - if (rel + 1 < relend - && rel[1].r_offset == offset - && rel[1].r_info == ELF64_R_INFO (0, R_PPC64_PCREL_OPT)) + bfd_vma off2 = rel[1].r_addend; + if (off2 == 0) + /* zero means next insn. */ + off2 = 8; + off2 += offset; + if (off2 + 4 <= input_section->size) { - bfd_vma off2 = rel[1].r_addend; - if (off2 == 0) - /* zero means next insn. */ - off2 = 8; - off2 += offset; - if (off2 + 4 <= input_section->size) + uint64_t pinsn2; + bfd_signed_vma addend_off; + pinsn2 = bfd_get_32 (input_bfd, contents + off2); + pinsn2 <<= 32; + if ((pinsn2 & (63ULL << 58)) == 1ULL << 58) { - uint64_t pinsn2; - bfd_signed_vma addend_off; - pinsn2 = bfd_get_32 (input_bfd, contents + off2); - pinsn2 <<= 32; + if (off2 + 8 > input_section->size) + break; + pinsn2 |= bfd_get_32 (input_bfd, + contents + off2 + 4); + } + if (xlate_pcrel_opt (&pinsn, &pinsn2, &addend_off)) + { + addend += addend_off; + rel->r_addend = addend; + bfd_put_32 (input_bfd, pinsn >> 32, + contents + offset); + bfd_put_32 (input_bfd, pinsn, + contents + offset + 4); + bfd_put_32 (input_bfd, pinsn2 >> 32, + contents + off2); if ((pinsn2 & (63ULL << 58)) == 1ULL << 58) - { - if (off2 + 8 > input_section->size) - break; - pinsn2 |= bfd_get_32 (input_bfd, - contents + off2 + 4); - } - if (xlate_pcrel_opt (&pinsn, &pinsn2, &addend_off)) - { - addend += addend_off; - rel->r_addend = addend; - bfd_put_32 (input_bfd, pinsn >> 32, - contents + offset); - bfd_put_32 (input_bfd, pinsn, - contents + offset + 4); - bfd_put_32 (input_bfd, pinsn2 >> 32, - contents + off2); - if ((pinsn2 & (63ULL << 58)) == 1ULL << 58) - bfd_put_32 (input_bfd, pinsn2, - contents + off2 + 4); - } + bfd_put_32 (input_bfd, pinsn2, + contents + off2 + 4); } } } @@ -16035,7 +16058,7 @@ ppc64_elf_relocate_section (bfd *output_bfd, case R_PPC64_GOT_TLSGD16_LO: case R_PPC64_GOT_TLSGD16_HI: case R_PPC64_GOT_TLSGD16_HA: - case R_PPC64_GOT_TLSGD34: + case R_PPC64_GOT_TLSGD_PCREL34: tls_type = TLS_TLS | TLS_GD; goto dogot; @@ -16043,7 +16066,7 @@ ppc64_elf_relocate_section (bfd *output_bfd, case R_PPC64_GOT_TLSLD16_LO: case R_PPC64_GOT_TLSLD16_HI: case R_PPC64_GOT_TLSLD16_HA: - case R_PPC64_GOT_TLSLD34: + case R_PPC64_GOT_TLSLD_PCREL34: tls_type = TLS_TLS | TLS_LD; goto dogot; @@ -16051,7 +16074,7 @@ ppc64_elf_relocate_section (bfd *output_bfd, case R_PPC64_GOT_TPREL16_LO_DS: case R_PPC64_GOT_TPREL16_HI: case R_PPC64_GOT_TPREL16_HA: - case R_PPC64_GOT_TPREL34: + case R_PPC64_GOT_TPREL_PCREL34: tls_type = TLS_TLS | TLS_TPREL; goto dogot; @@ -16059,7 +16082,7 @@ ppc64_elf_relocate_section (bfd *output_bfd, case R_PPC64_GOT_DTPREL16_LO_DS: case R_PPC64_GOT_DTPREL16_HI: case R_PPC64_GOT_DTPREL16_HA: - case R_PPC64_GOT_DTPREL34: + case R_PPC64_GOT_DTPREL_PCREL34: tls_type = TLS_TLS | TLS_DTPREL; goto dogot; @@ -16148,10 +16171,8 @@ ppc64_elf_relocate_section (bfd *output_bfd, if (ifunc) { relgot = htab->elf.irelplt; - if (indx == 0) - htab->local_ifunc_resolver = 1; - else if (is_static_defined (&h->elf)) - htab->maybe_local_ifunc_resolver = 1; + if (indx == 0 || is_static_defined (&h->elf)) + htab->elf.ifunc_resolvers = TRUE; } else if (indx != 0 || (bfd_link_pic (info) @@ -16258,10 +16279,10 @@ ppc64_elf_relocate_section (bfd *output_bfd, relocation = got->output_section->vma + got->output_offset + off; addend = 0; if (!(r_type == R_PPC64_GOT_PCREL34 - || r_type == R_PPC64_GOT_TLSGD34 - || r_type == R_PPC64_GOT_TLSLD34 - || r_type == R_PPC64_GOT_TPREL34 - || r_type == R_PPC64_GOT_DTPREL34)) + || r_type == R_PPC64_GOT_TLSGD_PCREL34 + || r_type == R_PPC64_GOT_TLSLD_PCREL34 + || r_type == R_PPC64_GOT_TPREL_PCREL34 + || r_type == R_PPC64_GOT_DTPREL_PCREL34)) addend = -(TOCstart + htab->sec_info[input_section->id].toc_off); } break; @@ -16515,11 +16536,11 @@ ppc64_elf_relocate_section (bfd *output_bfd, if (bfd_link_pic (info) ? ((h == NULL - || h->dyn_relocs != NULL) + || h->elf.dyn_relocs != NULL) && ((h != NULL && pc_dynrelocs (h)) || must_be_dyn_reloc (info, r_type))) : (h != NULL - ? h->dyn_relocs != NULL + ? h->elf.dyn_relocs != NULL : ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)) { bfd_boolean skip, relocate; @@ -16680,10 +16701,8 @@ ppc64_elf_relocate_section (bfd *output_bfd, : ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC) { sreloc = htab->elf.irelplt; - if (indx == 0) - htab->local_ifunc_resolver = 1; - else if (is_static_defined (&h->elf)) - htab->maybe_local_ifunc_resolver = 1; + if (indx == 0 || is_static_defined (&h->elf)) + htab->elf.ifunc_resolvers = TRUE; } if (sreloc == NULL) abort (); @@ -17083,10 +17102,10 @@ ppc64_elf_relocate_section (bfd *output_bfd, case R_PPC64_GOT_PCREL34: case R_PPC64_TPREL34: case R_PPC64_DTPREL34: - case R_PPC64_GOT_TLSGD34: - case R_PPC64_GOT_TLSLD34: - case R_PPC64_GOT_TPREL34: - case R_PPC64_GOT_DTPREL34: + case R_PPC64_GOT_TLSGD_PCREL34: + case R_PPC64_GOT_TLSLD_PCREL34: + case R_PPC64_GOT_TPREL_PCREL34: + case R_PPC64_GOT_DTPREL_PCREL34: case R_PPC64_PLT_PCREL34: case R_PPC64_PLT_PCREL34_NOTOC: case R_PPC64_D28: @@ -17187,8 +17206,7 @@ ppc64_elf_relocate_section (bfd *output_bfd, reloc_name, sym_name, (int) r); ret = FALSE; } - if (more_info != NULL) - free (more_info); + free (more_info); } copy_reloc: if (wrel != rel) @@ -17448,11 +17466,7 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd, break; case DT_TEXTREL: - if (htab->local_ifunc_resolver) - info->callbacks->einfo - (_("%X%P: text relocations and GNU indirect " - "functions will result in a segfault at runtime\n")); - else if (htab->maybe_local_ifunc_resolver) + if (htab->elf.ifunc_resolvers) info->callbacks->einfo (_("%P: warning: text relocations and GNU indirect " "functions may result in a segfault at runtime\n"));