aboutsummaryrefslogtreecommitdiff
path: root/ld
diff options
context:
space:
mode:
authorNelson Chu <nelson.chu@sifive.com>2020-11-17 19:39:52 -0800
committerNelson Chu <nelson.chu@sifive.com>2020-11-21 09:41:58 +0800
commitabd20cb637008da9d32018b4b03973e119388a0a (patch)
treead7714c9a527ae258996c30a1f4dc0ee61039073 /ld
parentd4087e81506bb8c7dc50cfdf318f4343f89002f9 (diff)
downloadfsf-binutils-gdb-abd20cb637008da9d32018b4b03973e119388a0a.zip
fsf-binutils-gdb-abd20cb637008da9d32018b4b03973e119388a0a.tar.gz
fsf-binutils-gdb-abd20cb637008da9d32018b4b03973e119388a0a.tar.bz2
RISC-V: Relax PCREL to GPREL while doing other relaxations is dangerous.
I get the feedback recently that enable linker relaxations may fail to build some program. Consider the following case, .text foo: addi a0, a0, %pcrel_lo(.L2) call foo .L1: auipc a1, %pcrel_hi(data_g) addi a1, a1, %pcrel_lo(.L1) lui a2, %hi(data_g) addi a2, a2, %lo(data_g) lui a3, %tprel_hi(data_t) add a3, a3, tp, %tprel_add(data_t) addi a3, a3, %tprel_lo(data_t) .L2: auipc a0, %pcrel_hi(data_g) .data .word 0x0 .global data_g data_g: .word 0x1 .section .tbss data_t: .word 0x0 The current ld reports `dangerous relocation error` when doing the pcgp relaxation, test.o: in function `foo': (.text+0x0): dangerous relocation: %pcrel_lo missing matching %pcrel_hi The .L2 auipc should not be removed since it is behind the corresponding addi, so we record the information in the pcgp_relocs table to avoid removing the auipc later. But current ld still remove it since we do not update the pcgp_relocs table while doing other relaxations. I have two solutions to fix the problem, 1. Update the pcgp_relocs table once we actually delete the code. 2. Add new relax pass to do the pcgp relaxations At first I tried to do the first solution, and we need to update at least three information - hi_sec_off of riscv_pcgp_lo_reloc, hi_sec_off and hi_addr (symbol value) of riscv_pcgp_hi_reloc. Update the hi_sec_off is simple, but it is more complicate to update the symbol value, since we almost have to do parts the same works of _bfd_riscv_relax_call again in the riscv_relax_delete_bytes to get the correct symbol value. Compared with the first solution, the second one is more intuitive and simple. We add a new relax pass to do the pcgp relaxations later, so we will get all the information correctly in the _bfd_riscv_relax_call, including the symbol value, without changing so much code. I do not see any penalty by adding a new relax pass for now, so it should be fine to delay the pcgp relaxations. Besides, I have pass all riscv-gnu-toolchain regressions for this patch. bfd/ * elfnn-riscv.c (_bfd_riscv_relax_section): Add a new relax pass to do the pcgp relaxation later, after the lui and call relaxations, but before the delete and alignment relaxations. ld/ * emultempl/riscvelf.em (riscv_elf_before_allocation): Change link_info.relax_pass from 3 to 4. * testsuite/ld-riscv-elf/pcgp-relax.d: New testcase. * testsuite/ld-riscv-elf/pcgp-relax.s: Likewise. * testsuite/ld-riscv-elf/ld-riscv-elf.exp: Updated.
Diffstat (limited to 'ld')
-rw-r--r--ld/ChangeLog8
-rw-r--r--ld/emultempl/riscvelf.em2
-rw-r--r--ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp1
-rw-r--r--ld/testsuite/ld-riscv-elf/pcgp-relax.d16
-rw-r--r--ld/testsuite/ld-riscv-elf/pcgp-relax.s29
5 files changed, 55 insertions, 1 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 5e81fa2..4686c59 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,11 @@
+2020-11-21 Nelson Chu <nelson.chu@sifive.com>
+
+ * emultempl/riscvelf.em (riscv_elf_before_allocation): Change
+ link_info.relax_pass from 3 to 4.
+ * testsuite/ld-riscv-elf/pcgp-relax.d: New testcase.
+ * testsuite/ld-riscv-elf/pcgp-relax.s: Likewise.
+ * testsuite/ld-riscv-elf/ld-riscv-elf.exp: Updated.
+
2020-11-20 Nick Alcock <nick.alcock@oracle.com>
* testsuite/ld-ctf/data-func-conflicted.d: Shrink the expected
diff --git a/ld/emultempl/riscvelf.em b/ld/emultempl/riscvelf.em
index da5c934..077f976 100644
--- a/ld/emultempl/riscvelf.em
+++ b/ld/emultempl/riscvelf.em
@@ -42,7 +42,7 @@ riscv_elf_before_allocation (void)
ENABLE_RELAXATION;
}
- link_info.relax_pass = 3;
+ link_info.relax_pass = 4;
}
static void
diff --git a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
index 9834041..86910e6 100644
--- a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
+++ b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
@@ -62,6 +62,7 @@ proc run_dump_test_ifunc { name target output} {
if [istarget "riscv*-*-*"] {
run_dump_test "call-relax"
+ run_dump_test "pcgp-relax"
run_dump_test "c-lui"
run_dump_test "c-lui-2"
run_dump_test "disas-jalr"
diff --git a/ld/testsuite/ld-riscv-elf/pcgp-relax.d b/ld/testsuite/ld-riscv-elf/pcgp-relax.d
new file mode 100644
index 0000000..dae2b62
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/pcgp-relax.d
@@ -0,0 +1,16 @@
+#source: pcgp-relax.s
+#ld: --relax
+#objdump: -d -Mno-aliases
+
+.*:[ ]+file format .*
+
+
+Disassembly of section \.text:
+
+0+[0-9a-f]+ <_start>:
+.*:[ ]+[0-9a-f]+[ ]+addi[ ]+a0,a0,[0-9]+
+.*:[ ]+[0-9a-f]+[ ]+jal[ ]+ra,[0-9a-f]+ <_start>
+.*:[ ]+[0-9a-f]+[ ]+addi[ ]+a1,gp,\-[0-9]+ # [0-9a-f]+ <data_g>
+.*:[ ]+[0-9a-f]+[ ]+addi[ ]+a2,gp,\-[0-9]+ # [0-9a-f]+ <data_g>
+.*:[ ]+[0-9a-f]+[ ]+addi[ ]+a3,tp,0 # 0 <data_t>
+.*:[ ]+[0-9a-f]+[ ]+auipc[ ]+a0,0x[0-9a-f]+
diff --git a/ld/testsuite/ld-riscv-elf/pcgp-relax.s b/ld/testsuite/ld-riscv-elf/pcgp-relax.s
new file mode 100644
index 0000000..fab6a5b
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/pcgp-relax.s
@@ -0,0 +1,29 @@
+ .text
+ .globl _start
+_start:
+ addi a0, a0, %pcrel_lo(.L2)
+
+ call _start
+.L1:
+ auipc a1, %pcrel_hi(data_g)
+ addi a1, a1, %pcrel_lo(.L1)
+
+ lui a2, %hi(data_g)
+ addi a2, a2, %lo(data_g)
+
+ lui a3, %tprel_hi(data_t)
+ add a3, a3, tp, %tprel_add(data_t)
+ addi a3, a3, %tprel_lo(data_t)
+
+.L2:
+ auipc a0, %pcrel_hi(data_g)
+
+ .data
+ .word 0x0
+ .globl data_g
+data_g:
+ .word 0x1
+
+ .section .tbss
+data_t:
+ .word 0x0