aboutsummaryrefslogtreecommitdiff
path: root/ld
diff options
context:
space:
mode:
authorXi Ruoyao <xry111@xry111.site>2024-06-30 15:18:22 +0800
committerliuzhensong <liuzhensong@loongson.cn>2024-07-05 12:11:11 +0800
commit41ef0bff2033bb7b30a2792417aa946503492ce0 (patch)
tree9c18ea35d658259c1fe5315e98997207e2c9f831 /ld
parent1c31db21fe6555e1a9b2a33b95a0125250c517d8 (diff)
downloadfsf-binutils-gdb-41ef0bff2033bb7b30a2792417aa946503492ce0.zip
fsf-binutils-gdb-41ef0bff2033bb7b30a2792417aa946503492ce0.tar.gz
fsf-binutils-gdb-41ef0bff2033bb7b30a2792417aa946503492ce0.tar.bz2
LoongArch: Fix bad reloc with mixed visibility ifunc symbols in shared libraries
With a simple test case: .globl ifunc .globl ifunc_hidden .hidden ifunc_hidden .type ifunc, %gnu_indirect_function .type ifunc_hidden, %gnu_indirect_function .text .align 2 ifunc: ret ifunc_hidden: ret test: bl ifunc bl ifunc_hidden "ld -shared" produces a shared object with one R_LARCH_NONE (instead of R_LARCH_JUMP_SLOT as we expect) to relocate the GOT entry of "ifunc". It's because the indices in .plt and .rela.plt mismatches for STV_DEFAULT STT_IFUNC symbols when another PLT entry exists for a STV_HIDDEN STT_IFUNC symbol, and such a mismatch breaks the logic of loongarch_elf_finish_dynamic_symbol. Fix the issue by reordering .plt so the indices no longer mismatch. Signed-off-by: Xi Ruoyao <xry111@xry111.site>
Diffstat (limited to 'ld')
-rw-r--r--ld/testsuite/ld-loongarch-elf/ifunc-reloc.d19
-rw-r--r--ld/testsuite/ld-loongarch-elf/ifunc-reloc.s55
-rw-r--r--ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp1
3 files changed, 75 insertions, 0 deletions
diff --git a/ld/testsuite/ld-loongarch-elf/ifunc-reloc.d b/ld/testsuite/ld-loongarch-elf/ifunc-reloc.d
new file mode 100644
index 0000000..cb59287
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/ifunc-reloc.d
@@ -0,0 +1,19 @@
+#ld: -shared
+#readelf: -Wr
+
+#...
+.*'\.rela\.dyn'.*
+#...
+.* R_LARCH_RELATIVE .*
+.* R_LARCH_IRELATIVE .*
+.* R_LARCH_IRELATIVE .*
+.* R_LARCH_IRELATIVE .*
+#...
+.*'\.rela\.plt'.*
+#...
+.* R_LARCH_JUMP_SLOT .*
+.* R_LARCH_JUMP_SLOT .*
+.* R_LARCH_JUMP_SLOT .*
+.* R_LARCH_JUMP_SLOT .*
+.* R_LARCH_JUMP_SLOT .*
+.* R_LARCH_JUMP_SLOT .*
diff --git a/ld/testsuite/ld-loongarch-elf/ifunc-reloc.s b/ld/testsuite/ld-loongarch-elf/ifunc-reloc.s
new file mode 100644
index 0000000..e59f2b2
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/ifunc-reloc.s
@@ -0,0 +1,55 @@
+.globl foo
+.globl foo_hidden1
+.globl foo_hidden2
+.globl foo_protected
+
+.type foo, %gnu_indirect_function
+.type foo_hidden1, %gnu_indirect_function
+.type foo_hidden2, %gnu_indirect_function
+.type foo_protected, %gnu_indirect_function
+.type foo_internal, %gnu_indirect_function
+
+.hidden foo_hidden1
+.hidden foo_hidden2
+
+.protected foo_protected
+
+.globl ext_ifunc1
+.globl ext_ifunc2
+.type ext_ifunc1, %gnu_indirect_function
+.type ext_ifunc2, %gnu_indirect_function
+
+.text
+.align 2
+foo:
+ ret
+
+foo_hidden1:
+ ret
+
+foo_hidden2:
+ ret
+
+foo_protected:
+ ret
+
+foo_internal:
+ ret
+
+test:
+ la.got $a0, num
+ # The order is deliberately shuffled.
+ bl ext_ifunc1
+ bl foo
+ bl foo_hidden1
+ bl ext_func1
+ bl foo_protected
+ bl foo_internal
+ bl foo_hidden2
+ bl ext_func2
+ bl ext_ifunc2
+
+.data
+.align 3
+num:
+ .quad 114514
diff --git a/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp b/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp
index 4d9f4ae..6cff117 100644
--- a/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp
+++ b/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp
@@ -133,6 +133,7 @@ if [istarget "loongarch64-*-*"] {
run_dump_test "reloc_ler_with_shared"
run_dump_test "reloc_abs_with_shared"
run_dump_test "r_larch_32_elf64"
+ run_dump_test "ifunc-reloc"
}
if [check_pie_support] {