X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=bfd%2Felf64-ppc.c;h=5cbf9acfcd1cb077805fa88ec59d29b57f544d21;hb=abebb03c3af215d7542f5e6b71d78823b15220d5;hp=5f99d4344b7623c8d29c733a5f5d26a935093f5d;hpb=d49e5065ed43ec88627fd8cc6ab9e45fcc0e538a;p=binutils-gdb.git diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index 5f99d4344b7..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; } @@ -3223,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 power10 instructions in linkage stubs. */ - unsigned int power10_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 @@ -3671,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. */ @@ -3715,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; } @@ -4334,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) @@ -4536,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); @@ -4593,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->power10_stubs = 1; + htab->has_power10_relocs = 1; break; default: break; @@ -4644,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; @@ -4680,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; @@ -4688,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; @@ -4696,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; @@ -4706,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; @@ -4915,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; @@ -5191,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; @@ -8024,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. */ @@ -8045,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. */ @@ -8062,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: @@ -10761,7 +10799,7 @@ plt_stub_size (struct ppc_link_hash_table *htab, if (stub_entry->stub_type >= ppc_stub_plt_call_notoc) { - if (htab->power10_stubs) + if (htab->params->power10_stubs != 0) { bfd_vma start = (stub_entry->stub_offset + stub_entry->group->stub_sec->output_offset @@ -11602,7 +11640,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) relp = p; num_rel = 0; - if (htab->power10_stubs) + if (htab->params->power10_stubs != 0) { bfd_boolean load = stub_entry->stub_type >= ppc_stub_plt_call_notoc; p = build_power10_offset (htab->params->stub_bfd, p, off, odd, load); @@ -11641,7 +11679,7 @@ 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->power10_stubs) + if (htab->params->power10_stubs != 0) num_rel += num_relocs_for_power10_offset (off, odd); else { @@ -11651,7 +11689,7 @@ 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->power10_stubs) + 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); @@ -11669,7 +11707,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) } } - if (!htab->power10_stubs + if (htab->params->power10_stubs == 0 && htab->glink_eh_frame != NULL && htab->glink_eh_frame->size != 0) { @@ -12017,7 +12055,7 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) if (info->emitrelocations) { unsigned int num_rel; - if (htab->power10_stubs) + if (htab->params->power10_stubs != 0) num_rel = num_relocs_for_power10_offset (off, odd); else num_rel = num_relocs_for_offset (off - 8); @@ -12025,7 +12063,7 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) stub_entry->group->stub_sec->flags |= SEC_RELOC; } - if (htab->power10_stubs) + if (htab->params->power10_stubs != 0) extra = size_power10_offset (off, odd); else extra = size_offset (off - 8); @@ -12036,7 +12074,7 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) calculated. */ off -= extra; - if (!htab->power10_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. */ @@ -12099,7 +12137,7 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) if (info->emitrelocations) { unsigned int num_rel; - if (htab->power10_stubs) + if (htab->params->power10_stubs != 0) num_rel = num_relocs_for_power10_offset (off, odd); else num_rel = num_relocs_for_offset (off - 8); @@ -12109,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->power10_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. */ @@ -13034,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) @@ -13409,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 @@ -13416,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) { @@ -13874,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 @@ -13928,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); } } @@ -14070,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; } @@ -15028,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) { @@ -15221,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); @@ -15231,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 { @@ -15247,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); @@ -15828,7 +15903,8 @@ 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) + 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 @@ -15847,7 +15923,8 @@ 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) + 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 @@ -15870,34 +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) + 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); @@ -15907,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); } } } @@ -15983,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; @@ -15991,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; @@ -15999,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; @@ -16007,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; @@ -16096,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) @@ -16206,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; @@ -16628,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 (); @@ -17031,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: @@ -17395,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"));