RISC-V: Fix wrongly inserted IRELATIVE relocs
Checks
Commit Message
For ifun symbols that are referenced by global pointer (and will be put
in .data.rel section), the linker overwrites their entris in .rela.iplt.
The issue is similar to commit 51a8a7c2e3cc0730831963651a55d23d1fae624d.
This patch uses the variable `last_iplt_index` added in the previous
commit to insert ifunc reloactions .rela.iplt.
---
bfd/elfnn-riscv.c | 12 ++++--
.../ifunc-plt-got-overwrite-02-exe.rd | 4 ++
.../ld-riscv-elf/ifunc-plt-got-overwrite-02.d | 12 ++++++
.../ld-riscv-elf/ifunc-plt-got-overwrite-02.s | 37 +++++++++++++++++++
ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp | 2 +
5 files changed, 64 insertions(+), 3 deletions(-)
create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-plt-got-overwrite-02-exe.rd
create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-plt-got-overwrite-02.d
create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-plt-got-overwrite-02.s
@@ -3118,16 +3118,22 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd,
/* Calculate the address of the PLT header. */
header_address = sec_addr (plt);
- /* Calculate the index of the entry and the offset of .got.plt entry.
- For static executables, we don't reserve anything. */
+ /* Calculate the index of the entry and the offset of .got.plt entry.*/
if (plt == htab->elf.splt)
{
+ /* Reserve PLT header. */
plt_idx = (h->plt.offset - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE;
got_offset = GOTPLT_HEADER_SIZE + (plt_idx * GOT_ENTRY_SIZE);
}
else
{
- plt_idx = h->plt.offset / PLT_ENTRY_SIZE;
+ /* For static executables, we don't reserve anything.
+ And we add relocs in backward order to fix wrong relocation indexing.
+ See:
+ https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=51a8a7c2e3cc0730831963651a55d23d1fae624d
+ */
+
+ plt_idx = htab->last_iplt_index--;
got_offset = plt_idx * GOT_ENTRY_SIZE;
}
new file mode 100644
@@ -0,0 +1,4 @@
+Relocation section '.rela.plt' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_IRELATIVE[ ]+[0-9a-f]*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_IRELATIVE[ ]+[0-9a-f]*
new file mode 100644
@@ -0,0 +1,12 @@
+#...
+Disassembly of section .text:
+#...
+0+[0-9a-f]+ <resolver1>:
+#...
+0+[0-9a-f]+ <resolver2>:
+#...
+0+[0-9a-f]+ <main>:
+.*:[ ]+[0-9a-f]+[ ]+auipc[ ]+.*
+.*:[ ]+[0-9a-f]+[ ]+jalr[ ]+.*<(.*plt.*)>
+.*:[ ]+[0-9a-f]+[ ]+ret
+#...
new file mode 100644
@@ -0,0 +1,37 @@
+ .text
+
+ .type resolver1, @function
+resolver1:
+ ret
+ .size resolver1, .-resolver1
+
+ .type resolver2, @function
+resolver2:
+ ret
+ .size resolver2, .-resolver2
+
+ .globl ifunc1
+ .type ifunc1, %gnu_indirect_function
+ .set ifunc1, resolver1
+
+ .globl ifunc2
+ .type ifunc2, %gnu_indirect_function
+ .set ifunc2, resolver2
+
+
+ .globl ifunc2_ptr
+ .section .data.rel,"aw"
+ .align 3
+ .type ifunc2_ptr, @object
+ .size ifunc2_ptr, 8
+ifunc2_ptr:
+ .dword ifunc2
+ .text
+ .align 1
+
+ .globl main
+ .type main, @function
+main:
+ call ifunc1@plt
+ ret
+ .size main, .-main
@@ -281,6 +281,8 @@ if [istarget "riscv*-*-*"] {
run_dump_test_ifunc "ifunc-plt-got-overwrite" rv64 exe
run_dump_test_ifunc "ifunc-plt-got-overwrite" rv64 pie
run_dump_test_ifunc "ifunc-plt-got-overwrite" rv64 pic
+ run_dump_test_ifunc "ifunc-plt-got-overwrite-02" rv32 exe
+ run_dump_test_ifunc "ifunc-plt-got-overwrite-02" rv64 exe
# TODO: Make the following tests work under RV32.
if [istarget "riscv32-*-*"] {