From 406b4ada55b2957c10fedaeaada801e77912d976 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Sat, 19 Jun 2021 20:20:52 -0700 Subject: [PATCH] x86: Count PLT for GOTOFF relocation against IFUNC symbol Since GOTOFF relocations against IFUNC symbols must go through PLT, set PLT reference count to 1 for GOTOFF relocation. bfd/ PR ld/27998 * elfxx-x86.c (elf_x86_allocate_dynrelocs): Count PLT for GOTOFF relocation against IFUNC symbols. (_bfd_x86_elf_adjust_dynamic_symbol): Likewise. ld/ PR ld/27998 * testsuite/ld-i386/i386.exp: Run PR ld/27998 tests. * testsuite/ld-i386/pr27998a.d: New file. * testsuite/ld-i386/pr27998a.s: Likewise. * testsuite/ld-i386/pr27998b.d: Likewise. * testsuite/ld-i386/pr27998b.s: Likewise. --- bfd/ChangeLog | 7 +++++++ bfd/elfxx-x86.c | 12 ++++++++++-- ld/ChangeLog | 9 +++++++++ ld/testsuite/ld-i386/i386.exp | 2 ++ ld/testsuite/ld-i386/pr27998a.d | 7 +++++++ ld/testsuite/ld-i386/pr27998a.s | 22 ++++++++++++++++++++++ ld/testsuite/ld-i386/pr27998b.d | 7 +++++++ ld/testsuite/ld-i386/pr27998b.s | 20 ++++++++++++++++++++ 8 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 ld/testsuite/ld-i386/pr27998a.d create mode 100644 ld/testsuite/ld-i386/pr27998a.s create mode 100644 ld/testsuite/ld-i386/pr27998b.d create mode 100644 ld/testsuite/ld-i386/pr27998b.s diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 5211e98e111..212fe332e2d 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,10 @@ +2021-06-19 H.J. Lu + + PR ld/27998 + * elfxx-x86.c (elf_x86_allocate_dynrelocs): Count PLT for GOTOFF + relocation against IFUNC symbols. + (_bfd_x86_elf_adjust_dynamic_symbol): Likewise. + 2021-06-19 H.J. Lu * elflink.c (bfd_elf_final_link): Correct DT_TEXTREL warning in diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c index 62d516aab8d..088f6e5c536 100644 --- a/bfd/elfxx-x86.c +++ b/bfd/elfxx-x86.c @@ -131,6 +131,10 @@ elf_x86_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) if (h->type == STT_GNU_IFUNC && h->def_regular) { + /* GOTOFF relocation needs PLT. */ + if (eh->gotoff_ref) + h->plt.refcount = 1; + if (_bfd_elf_allocate_ifunc_dyn_relocs (info, h, &h->dyn_relocs, plt_entry_size, (htab->plt.has_plt0 @@ -1818,6 +1822,8 @@ _bfd_x86_elf_adjust_dynamic_symbol (struct bfd_link_info *info, const struct elf_backend_data *bed = get_elf_backend_data (info->output_bfd); + eh = (struct elf_x86_link_hash_entry *) h; + /* STT_GNU_IFUNC symbol must go through PLT. */ if (h->type == STT_GNU_IFUNC) { @@ -1856,6 +1862,10 @@ _bfd_x86_elf_adjust_dynamic_symbol (struct bfd_link_info *info, h->plt.refcount += 1; } } + + /* GOTOFF relocation needs PLT. */ + if (eh->gotoff_ref) + h->plt.refcount = 1; } if (h->plt.refcount <= 0) @@ -1896,8 +1906,6 @@ _bfd_x86_elf_adjust_dynamic_symbol (struct bfd_link_info *info, the link may change h->type. So fix it now. */ h->plt.offset = (bfd_vma) -1; - eh = (struct elf_x86_link_hash_entry *) h; - /* If this is a weak symbol, and there is a real definition, the processor independent code will have arranged for us to see the real definition first, and we can just use the same value. */ diff --git a/ld/ChangeLog b/ld/ChangeLog index 36f8d4b5268..dc08ec9f0a0 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,12 @@ +2021-06-19 H.J. Lu + + PR ld/27998 + * testsuite/ld-i386/i386.exp: Run PR ld/27998 tests. + * testsuite/ld-i386/pr27998a.d: New file. + * testsuite/ld-i386/pr27998a.s: Likewise. + * testsuite/ld-i386/pr27998b.d: Likewise. + * testsuite/ld-i386/pr27998b.s: Likewise. + 2021-06-19 H.J. Lu * testsuite/ld-x86-64/textrel-1.err: New file. diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp index 3d6047b790d..ceb60002d13 100644 --- a/ld/testsuite/ld-i386/i386.exp +++ b/ld/testsuite/ld-i386/i386.exp @@ -519,6 +519,8 @@ run_dump_test "pr19939a" run_dump_test "pr19939b" run_dump_test "tlsdesc2" run_dump_test "report-reloc-1" +run_dump_test "pr27998a" +run_dump_test "pr27998b" proc undefined_weak {cflags ldflags} { set testname "Undefined weak symbol" diff --git a/ld/testsuite/ld-i386/pr27998a.d b/ld/testsuite/ld-i386/pr27998a.d new file mode 100644 index 00000000000..ca3c9205fa6 --- /dev/null +++ b/ld/testsuite/ld-i386/pr27998a.d @@ -0,0 +1,7 @@ +#as: --32 +#ld: -shared -melf_i386 +#readelf: -r --wide + +Relocation section '.rel.plt' at offset 0x[0-9a-f]+ contains 1 entry: + Offset Info Type Sym. Value Symbol's Name +[0-9a-f]+ +[0-9a-f]+ +R_386_IRELATIVE + diff --git a/ld/testsuite/ld-i386/pr27998a.s b/ld/testsuite/ld-i386/pr27998a.s new file mode 100644 index 00000000000..ec55cd6948a --- /dev/null +++ b/ld/testsuite/ld-i386/pr27998a.s @@ -0,0 +1,22 @@ + .text + .p2align 4 + .type my_foo, @function +my_foo: + ret + .size my_foo, .-my_foo + .p2align 4 + .type resolve_foo, @function +resolve_foo: + leal my_foo@GOTOFF(%eax), %eax + ret + .size resolve_foo, .-resolve_foo + .globl foo + .hidden foo + .type foo, @gnu_indirect_function + .set foo,resolve_foo + .p2align 4 + .globl bar + .type bar, @function +bar: + leal foo@GOTOFF(%eax), %eax + ret diff --git a/ld/testsuite/ld-i386/pr27998b.d b/ld/testsuite/ld-i386/pr27998b.d new file mode 100644 index 00000000000..ca3c9205fa6 --- /dev/null +++ b/ld/testsuite/ld-i386/pr27998b.d @@ -0,0 +1,7 @@ +#as: --32 +#ld: -shared -melf_i386 +#readelf: -r --wide + +Relocation section '.rel.plt' at offset 0x[0-9a-f]+ contains 1 entry: + Offset Info Type Sym. Value Symbol's Name +[0-9a-f]+ +[0-9a-f]+ +R_386_IRELATIVE + diff --git a/ld/testsuite/ld-i386/pr27998b.s b/ld/testsuite/ld-i386/pr27998b.s new file mode 100644 index 00000000000..8b023e9b12d --- /dev/null +++ b/ld/testsuite/ld-i386/pr27998b.s @@ -0,0 +1,20 @@ + .text + .p2align 4 + .type my_foo, @function +my_foo: + ret + .size my_foo, .-my_foo + .p2align 4 + .type resolve_foo, @function +resolve_foo: + leal my_foo@GOTOFF(%eax), %eax + ret + .size resolve_foo, .-resolve_foo + .type foo, @gnu_indirect_function + .set foo,resolve_foo + .p2align 4 + .globl bar + .type bar, @function +bar: + leal foo@GOTOFF(%eax), %eax + ret -- 2.30.2