diff options
24 files changed, 179 insertions, 44 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 146045b..8f9e69c 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,26 @@ +2020-06-09 H.J. Lu <hongjiu.lu@intel.com> + + PR ld/18801 + * elf-bfd.h (elf_link_hash_table): Add ifunc_resolvers. + (_bfd_elf_allocate_ifunc_dyn_relocs): Remove the + bfd_boolean * argument. Set ifunc_resolvers if there are IFUNC + resolvers. + * elf-ifunc.c (_bfd_elf_allocate_ifunc_dyn_relocs): Updated. + Set ifunc_resolvers if there are FUNC resolvers. + * elf64-ppc.c (ppc_link_hash_table): Remove local_ifunc_resolver. + (build_global_entry_stubs_and_plt): Replace local_ifunc_resolver + with elf.ifunc_resolvers. + (write_plt_relocs_for_local_syms): Likewise. + (ppc64_elf_relocate_section): Likewise. + (ppc64_elf_finish_dynamic_sections): Likewise. + * elfnn-aarch64.c (elfNN_aarch64_allocate_ifunc_dynrelocs): + Updated. + * elfxx-x86.c (elf_x86_allocate_dynrelocs): Likewise. + (_bfd_x86_elf_size_dynamic_sections): Check elf.ifunc_resolvers + instead of readonly_dynrelocs_against_ifunc. + * elfxx-x86.h (elf_x86_link_hash_table): Remove + readonly_dynrelocs_against_ifunc. + 2020-06-09 Alan Modra <amodra@gmail.com> * elf64-ppc.c (struct ppc_link_hash_table): Delete diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index 0e31ed1..242750f 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -570,6 +570,9 @@ struct elf_link_hash_table section symbols. */ bfd_boolean is_relocatable_executable; + /* TRUE if there are IFUNC resolvers. */ + bfd_boolean ifunc_resolvers; + /* The BFD used to hold special sections created by the linker. This will be the first BFD found which requires these sections to be created. */ @@ -2875,8 +2878,8 @@ extern bfd_boolean _bfd_elf_create_ifunc_sections (bfd *, struct bfd_link_info *); extern bfd_boolean _bfd_elf_allocate_ifunc_dyn_relocs (struct bfd_link_info *, struct elf_link_hash_entry *, - struct elf_dyn_relocs **, bfd_boolean *, unsigned int, - unsigned int, unsigned int, bfd_boolean); + struct elf_dyn_relocs **, unsigned int, unsigned int, + unsigned int, bfd_boolean); extern void elf_append_rela (bfd *, asection *, Elf_Internal_Rela *); extern void elf_append_rel (bfd *, asection *, Elf_Internal_Rela *); diff --git a/bfd/elf-ifunc.c b/bfd/elf-ifunc.c index b044164..904950c 100644 --- a/bfd/elf-ifunc.c +++ b/bfd/elf-ifunc.c @@ -107,7 +107,6 @@ bfd_boolean _bfd_elf_allocate_ifunc_dyn_relocs (struct bfd_link_info *info, struct elf_link_hash_entry *h, struct elf_dyn_relocs **head, - bfd_boolean *readonly_dynrelocs_against_ifunc_p, unsigned int plt_entry_size, unsigned int plt_header_size, unsigned int got_entry_size, @@ -118,7 +117,6 @@ _bfd_elf_allocate_ifunc_dyn_relocs (struct bfd_link_info *info, unsigned int sizeof_reloc; const struct elf_backend_data *bed; struct elf_link_hash_table *htab; - bfd_boolean readonly_dynrelocs_against_ifunc; /* If AVOID_PLT is TRUE, don't use PLT if possible. */ bfd_boolean use_plt = !avoid_plt || h->plt.refcount > 0; bfd_boolean need_dynreloc = !use_plt || bfd_link_pic (info); @@ -255,8 +253,6 @@ _bfd_elf_allocate_ifunc_dyn_relocs (struct bfd_link_info *info, if (!need_dynreloc || !h->non_got_ref) *head = NULL; - readonly_dynrelocs_against_ifunc = FALSE; - /* Finally, allocate space. */ p = *head; if (p != NULL) @@ -264,17 +260,13 @@ _bfd_elf_allocate_ifunc_dyn_relocs (struct bfd_link_info *info, bfd_size_type count = 0; do { - if (!readonly_dynrelocs_against_ifunc) - { - asection *s = p->sec->output_section; - if (s != NULL && (s->flags & SEC_READONLY) != 0) - readonly_dynrelocs_against_ifunc = TRUE; - } count += p->count; p = p->next; } while (p != NULL); + htab->ifunc_resolvers = count != 0; + /* Dynamic relocations are stored in 1. .rel[a].ifunc section in PIC object. 2. .rel[a].got section in dynamic executable. @@ -290,9 +282,6 @@ _bfd_elf_allocate_ifunc_dyn_relocs (struct bfd_link_info *info, } } - if (readonly_dynrelocs_against_ifunc_p) - *readonly_dynrelocs_against_ifunc_p = readonly_dynrelocs_against_ifunc; - /* For STT_GNU_IFUNC symbol, .got.plt has the real function address and .got has the PLT entry adddress. We will load the GOT entry with the PLT entry in finish_dynamic_symbol if it is used. For diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index 9868f6a..8d71084 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -3239,10 +3239,6 @@ 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; - /* Whether plt calls for ELFv2 localentry:0 funcs have been optimized. */ unsigned int has_plt_localentry0:1; @@ -13880,7 +13876,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 @@ -13934,7 +13930,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->local_ifunc_resolver = 1; + htab->elf.ifunc_resolvers = TRUE; bfd_elf64_swap_reloca_out (info->output_bfd, &rela, loc); } } @@ -14076,7 +14072,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; } @@ -16103,7 +16099,7 @@ ppc64_elf_relocate_section (bfd *output_bfd, { relgot = htab->elf.irelplt; if (indx == 0 || is_static_defined (&h->elf)) - htab->local_ifunc_resolver = 1; + htab->elf.ifunc_resolvers = TRUE; } else if (indx != 0 || (bfd_link_pic (info) @@ -16633,7 +16629,7 @@ ppc64_elf_relocate_section (bfd *output_bfd, { sreloc = htab->elf.irelplt; if (indx == 0 || is_static_defined (&h->elf)) - htab->local_ifunc_resolver = 1; + htab->elf.ifunc_resolvers = TRUE; } if (sreloc == NULL) abort (); @@ -17397,7 +17393,7 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd, break; case DT_TEXTREL: - if (htab->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")); diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c index 6857c4c..eff27f6 100644 --- a/bfd/elfnn-aarch64.c +++ b/bfd/elfnn-aarch64.c @@ -8818,7 +8818,6 @@ elfNN_aarch64_allocate_ifunc_dynrelocs (struct elf_link_hash_entry *h, && h->def_regular) return _bfd_elf_allocate_ifunc_dyn_relocs (info, h, &h->dyn_relocs, - NULL, htab->plt_entry_size, htab->plt_header_size, GOT_ENTRY_SIZE, diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c index f020240..29b0204 100644 --- a/bfd/elfxx-x86.c +++ b/bfd/elfxx-x86.c @@ -132,7 +132,6 @@ elf_x86_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) && h->def_regular) { if (_bfd_elf_allocate_ifunc_dyn_relocs (info, h, &h->dyn_relocs, - &htab->readonly_dynrelocs_against_ifunc, plt_entry_size, (htab->plt.has_plt0 * plt_entry_size), @@ -1416,15 +1415,11 @@ _bfd_x86_elf_size_dynamic_sections (bfd *output_bfd, if ((info->flags & DF_TEXTREL) != 0) { - if (htab->readonly_dynrelocs_against_ifunc) - { - info->callbacks->einfo - (_("%P%X: read-only segment has dynamic IFUNC relocations;" - " recompile with %s\n"), - bfd_link_dll (info) ? "-fPIC" : "-fPIE"); - bfd_set_error (bfd_error_bad_value); - return FALSE; - } + if (htab->elf.ifunc_resolvers) + info->callbacks->einfo + (_("%P: warning: GNU indirect functions with DT_TEXTREL " + "may result in a segfault at runtime; recompile with %s\n"), + bfd_link_dll (info) ? "-fPIC" : "-fPIE"); if (!add_dynamic_entry (DT_TEXTREL, 0)) return FALSE; diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h index dc7e6be..915cd4d 100644 --- a/bfd/elfxx-x86.h +++ b/bfd/elfxx-x86.h @@ -483,10 +483,6 @@ struct elf_x86_link_hash_table /* The index of the next R_X86_64_IRELATIVE entry in .rela.plt. */ bfd_vma next_irelative_index; - /* TRUE if there are dynamic relocs against IFUNC symbols that apply - to read-only sections. */ - bfd_boolean readonly_dynrelocs_against_ifunc; - /* The (unloaded but important) .rel.plt.unloaded section on VxWorks. This is used for i386 only. */ asection *srelplt2; diff --git a/ld/ChangeLog b/ld/ChangeLog index b0336b7..ba4151e 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,25 @@ +2020-06-09 H.J. Lu <hongjiu.lu@intel.com> + + PR ld/18801 + * testsuite/ld-i386/i386.exp: Run ifunc-textrel-1a, + ifunc-textrel-1b, ifunc-textrel-2a and ifunc-textrel-2b. + * testsuite/ld-x86-64/x86-64.exp: Likewise. + * testsuite/ld-i386/ifunc-textrel-1a.d: Likewise. + * testsuite/ld-i386/ifunc-textrel-1b.d: Likewise. + * testsuite/ld-i386/ifunc-textrel-2a.d: Likewise. + * testsuite/ld-i386/ifunc-textrel-2b.d: Likewise. + * testsuite/ld-x86-64/ifunc-textrel-1.s: Likewise. + * testsuite/ld-x86-64/ifunc-textrel-1a.d: Likewise. + * testsuite/ld-x86-64/ifunc-textrel-1b.d: Likewise. + * testsuite/ld-x86-64/ifunc-textrel-2.s: Likewise. + * testsuite/ld-x86-64/ifunc-textrel-2a.d: Likewise. + * testsuite/ld-x86-64/ifunc-textrel-2b.d: Likewise. + * testsuite/ld-i386/pr18801a.d: Expect warning for IFUNC + resolvers. + * testsuite/ld-i386/pr18801b.d: Likewise. + * estsuite/ld-x86-64/pr18801a.d: Likewise. + * estsuite/ld-x86-64/pr18801b.d: Likewise. + 2020-06-09 Alan Modra <amodra@gmail.com> PR 26065 diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp index e1bbcdd..891ebce 100644 --- a/ld/testsuite/ld-i386/i386.exp +++ b/ld/testsuite/ld-i386/i386.exp @@ -519,6 +519,10 @@ run_dump_test "pr17935-1" run_dump_test "pr17935-2" run_dump_test "pr18801a" run_dump_test "pr18801b" +run_dump_test "ifunc-textrel-1a" +run_dump_test "ifunc-textrel-1b" +run_dump_test "ifunc-textrel-2a" +run_dump_test "ifunc-textrel-2b" run_dump_test "pr18815" run_dump_test "pr19939a" run_dump_test "pr19939b" diff --git a/ld/testsuite/ld-i386/ifunc-textrel-1a.d b/ld/testsuite/ld-i386/ifunc-textrel-1a.d new file mode 100644 index 0000000..15f545d --- /dev/null +++ b/ld/testsuite/ld-i386/ifunc-textrel-1a.d @@ -0,0 +1,4 @@ +#source: ../ld-x86-64/ifunc-textrel-1.s +#as: --32 +#ld: -m elf_i386 -pie +#warning: GNU indirect functions with DT_TEXTREL may result in a segfault at runtime; recompile with -fPIE diff --git a/ld/testsuite/ld-i386/ifunc-textrel-1b.d b/ld/testsuite/ld-i386/ifunc-textrel-1b.d new file mode 100644 index 0000000..6e4a67c --- /dev/null +++ b/ld/testsuite/ld-i386/ifunc-textrel-1b.d @@ -0,0 +1,4 @@ +#source: ../ld-x86-64/ifunc-textrel-1.s +#as: --32 +#ld: -m elf_i386 -shared +#warning: GNU indirect functions with DT_TEXTREL may result in a segfault at runtime; recompile with -fPIC diff --git a/ld/testsuite/ld-i386/ifunc-textrel-2a.d b/ld/testsuite/ld-i386/ifunc-textrel-2a.d new file mode 100644 index 0000000..7195912 --- /dev/null +++ b/ld/testsuite/ld-i386/ifunc-textrel-2a.d @@ -0,0 +1,8 @@ +#source: ../ld-x86-64/ifunc-textrel-2.s +#as: --32 +#ld: -m elf_i386 -pie -z notext +#readelf: -r --wide + +#failif +[0-9a-f]+ +[0-9a-f]+ +R_386_IRELATIVE + +#.. diff --git a/ld/testsuite/ld-i386/ifunc-textrel-2b.d b/ld/testsuite/ld-i386/ifunc-textrel-2b.d new file mode 100644 index 0000000..7d51e68 --- /dev/null +++ b/ld/testsuite/ld-i386/ifunc-textrel-2b.d @@ -0,0 +1,8 @@ +#source: ../ld-x86-64/ifunc-textrel-2.s +#as: --32 +#ld: -m elf_i386 -shared -z notext +#readelf: -r --wide + +#failif +[0-9a-f]+ +[0-9a-f]+ +R_386_IRELATIVE + +#.. diff --git a/ld/testsuite/ld-i386/pr18801a.d b/ld/testsuite/ld-i386/pr18801a.d index f8dc3f1..73cb5d1 100644 --- a/ld/testsuite/ld-i386/pr18801a.d +++ b/ld/testsuite/ld-i386/pr18801a.d @@ -1,4 +1,4 @@ #source: pr18801.s #as: --32 #ld: -m elf_i386 -pie -#error: read-only segment has dynamic IFUNC relocations; recompile with -fPIE +#warning: GNU indirect functions with DT_TEXTREL may result in a segfault at runtime; recompile with -fPIE diff --git a/ld/testsuite/ld-i386/pr18801b.d b/ld/testsuite/ld-i386/pr18801b.d index f1d5c8d..0bf7fb7 100644 --- a/ld/testsuite/ld-i386/pr18801b.d +++ b/ld/testsuite/ld-i386/pr18801b.d @@ -1,4 +1,4 @@ #source: pr18801.s #as: --32 #ld: -m elf_i386 -shared -#error: read-only segment has dynamic IFUNC relocations; recompile with -fPIC +#warning: GNU indirect functions with DT_TEXTREL may result in a segfault at runtime; recompile with -fPIC diff --git a/ld/testsuite/ld-x86-64/ifunc-textrel-1.s b/ld/testsuite/ld-x86-64/ifunc-textrel-1.s new file mode 100644 index 0000000..373e15f --- /dev/null +++ b/ld/testsuite/ld-x86-64/ifunc-textrel-1.s @@ -0,0 +1,28 @@ + .text + .type selector, %function +foo: + movl $0, %eax + ret +selector: +.ifdef __x86_64__ + leaq foo(%rip), %rax +.else + leal foo@GOTOFF(%eax), %eax +.endif + ret + .type selector, %gnu_indirect_function + .globl _start +_start: +.ifdef __x86_64__ + movabs ptr, %rax + call *%rax +.else + mov ptr, %eax + call *%eax +.endif + ret + .data + .type ptr, @object +ptr: + .dc.a selector + .section .note.GNU-stack,"",@progbits diff --git a/ld/testsuite/ld-x86-64/ifunc-textrel-1a.d b/ld/testsuite/ld-x86-64/ifunc-textrel-1a.d new file mode 100644 index 0000000..64a1e70 --- /dev/null +++ b/ld/testsuite/ld-x86-64/ifunc-textrel-1a.d @@ -0,0 +1,4 @@ +#source: ifunc-textrel-1.s +#as: --64 -defsym __x86_64__=1 +#ld: -m elf_x86_64 -pie +#warning: GNU indirect functions with DT_TEXTREL may result in a segfault at runtime; recompile with -fPIE diff --git a/ld/testsuite/ld-x86-64/ifunc-textrel-1b.d b/ld/testsuite/ld-x86-64/ifunc-textrel-1b.d new file mode 100644 index 0000000..aeb31fd --- /dev/null +++ b/ld/testsuite/ld-x86-64/ifunc-textrel-1b.d @@ -0,0 +1,4 @@ +#source: ifunc-textrel-1.s +#as: --64 -defsym __x86_64__=1 +#ld: -m elf_x86_64 -shared +#warning: GNU indirect functions with DT_TEXTREL may result in a segfault at runtime; recompile with -fPIC diff --git a/ld/testsuite/ld-x86-64/ifunc-textrel-2.s b/ld/testsuite/ld-x86-64/ifunc-textrel-2.s new file mode 100644 index 0000000..5c8f271 --- /dev/null +++ b/ld/testsuite/ld-x86-64/ifunc-textrel-2.s @@ -0,0 +1,28 @@ + .text + .type selector, %function +foo: + movl $0, %eax + ret +selector: +.ifdef __x86_64__ + leaq foo(%rip), %rax +.else + leal foo@GOTOFF(%eax), %eax +.endif + ret + .type selector, %gnu_indirect_function + .globl _start +_start: +.ifdef __x86_64__ + movabs ptr, %rax + call *%rax +.else + mov ptr, %eax + call *%eax +.endif + ret + .data + .type ptr, @object +ptr: + .dc.a foo + .section .note.GNU-stack,"",@progbits diff --git a/ld/testsuite/ld-x86-64/ifunc-textrel-2a.d b/ld/testsuite/ld-x86-64/ifunc-textrel-2a.d new file mode 100644 index 0000000..7bef52e --- /dev/null +++ b/ld/testsuite/ld-x86-64/ifunc-textrel-2a.d @@ -0,0 +1,8 @@ +#source: ifunc-textrel-2.s +#as: --64 -defsym __x86_64__=1 +#ld: -m elf_x86_64 -pie -z notext +#readelf: -r --wide + +#failif +[0-9a-f]+ +[0-9a-f]+ +R_X86_64_IRELATIVE +[0-9a-f]+ +#.. diff --git a/ld/testsuite/ld-x86-64/ifunc-textrel-2b.d b/ld/testsuite/ld-x86-64/ifunc-textrel-2b.d new file mode 100644 index 0000000..629ecc8 --- /dev/null +++ b/ld/testsuite/ld-x86-64/ifunc-textrel-2b.d @@ -0,0 +1,8 @@ +#source: ifunc-textrel-2.s +#as: --64 -defsym __x86_64__=1 +#ld: -m elf_x86_64 -shared -z notext +#readelf: -r --wide + +#failif +[0-9a-f]+ +[0-9a-f]+ +R_X86_64_IRELATIVE +[0-9a-f]+ +#.. diff --git a/ld/testsuite/ld-x86-64/pr18801a.d b/ld/testsuite/ld-x86-64/pr18801a.d index b527f04..2b4159d 100644 --- a/ld/testsuite/ld-x86-64/pr18801a.d +++ b/ld/testsuite/ld-x86-64/pr18801a.d @@ -1,4 +1,4 @@ #source: pr18801.s #as: --64 #ld: -melf_x86_64 -pie -#error: read-only segment has dynamic IFUNC relocations; recompile with -fPIE +#warning: GNU indirect functions with DT_TEXTREL may result in a segfault at runtime; recompile with -fPIE diff --git a/ld/testsuite/ld-x86-64/pr18801b.d b/ld/testsuite/ld-x86-64/pr18801b.d index 7cdb2cd..34dab1a 100644 --- a/ld/testsuite/ld-x86-64/pr18801b.d +++ b/ld/testsuite/ld-x86-64/pr18801b.d @@ -1,4 +1,4 @@ #source: pr18801.s #as: --64 #ld: -melf_x86_64 -shared -#error: read-only segment has dynamic IFUNC relocations; recompile with -fPIC +#warning: GNU indirect functions with DT_TEXTREL may result in a segfault at runtime; recompile with -fPIC diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp index fd8fd34..69548f2 100644 --- a/ld/testsuite/ld-x86-64/x86-64.exp +++ b/ld/testsuite/ld-x86-64/x86-64.exp @@ -581,6 +581,10 @@ run_dump_test "pr18160" run_dump_test "pr18176" run_dump_test "pr18801a" run_dump_test "pr18801b" +run_dump_test "ifunc-textrel-1a" +run_dump_test "ifunc-textrel-1b" +run_dump_test "ifunc-textrel-2a" +run_dump_test "ifunc-textrel-2b" run_dump_test "pr18815" run_dump_test "pr19013" run_dump_test "pr19013-x32" |