Browse Source
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.binutils-2_36-branch
7 changed files with 79 additions and 14 deletions
@ -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]+ |
|||
@ -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 |
|||
Loading…
Reference in new issue