aboutsummaryrefslogtreecommitdiff
path: root/ld
diff options
context:
space:
mode:
authorLewis Revill <lewis.revill@embecosm.com>2021-10-21 11:15:47 +0800
committerNelson Chu <nelson.chu@sifive.com>2021-10-22 16:44:37 +0800
commit9abcdc10b21ed9f98e218ead7ac9d91612f9ed0f (patch)
treee0c51e3c37a1e462dec834b0a334a1ae2aa38f73 /ld
parent66cc044255f805fd052b9cb9352915cbdf3040b5 (diff)
downloadgdb-9abcdc10b21ed9f98e218ead7ac9d91612f9ed0f.zip
gdb-9abcdc10b21ed9f98e218ead7ac9d91612f9ed0f.tar.gz
gdb-9abcdc10b21ed9f98e218ead7ac9d91612f9ed0f.tar.bz2
RISC-V: Don't separate pcgp relaxation to another relax pass.
Commit abd20cb637008da9d32018b4b03973e119388a0a and ebdcad3fddf6ec21f6d4dcc702379a12718cf0c4 introduced additional complexity into the paths run by the RISC-V relaxation pass in order to resolve the issue of accurately keeping track of pcrel_hi and pcrel_lo pairs. The first commit split up relaxation of these relocs into a pass which occurred after other relaxations in order to prevent the situation where bytes were deleted in between a pcrel_lo/pcrel_hi pair, inhibiting our ability to find the corresponding pcrel_hi relocation from the address attached to the pcrel_lo. Since the relaxation was split into two passes the 'again' parameter could not be used to perform the entire relaxation process again and so the second commit added a way to restart ldelf_map_segments, thus starting the whole process again. Unfortunately this process could not account for the fact that we were not finished with the relaxation process so in some cases - such as the case where code would not fit in a memory region before the R_RISCV_ALIGN relocation was relaxed - sanity checks in generic code would fail. This patch fixes all three of these concerns by reverting back to a system of having only one target relax pass but updating entries in the table of pcrel_hi/pcrel_lo relocs every time any bytes are deleted. Thus we can keep track of the pairs accurately, and we can use the 'again' parameter to restart the entire target relax pass, behaving in the way that generic code expects. Unfortunately we must still have an additional pass to delay deleting AUIPC bytes to avoid ambiguity between pcrel_hi relocs stored in the table after deletion. This pass can only be run once so we may potentially miss out on relaxation opportunities but this is likely to be rare. https://sourceware.org/bugzilla/show_bug.cgi?id=28410 bfd/ * elfnn-riscv.c (riscv_elf_link_hash_table): Removed restart_relax. (riscv_elf_link_hash_table_create): Updated. (riscv_relax_delete_bytes): Moved after the riscv_update_pcgp_relocs. Update the pcgp_relocs table whenever bytes are deleted. (riscv_update_pcgp_relocs): Add function to update the section offset of pcrel_hi and pcrel_lo, and also update the symbol value of pcrel_hi. (_bfd_riscv_relax_call): Need to update the pcgp_relocs table when deleting codes. (_bfd_riscv_relax_lui): Likewise. (_bfd_riscv_relax_tls_le): Likewise. (_bfd_riscv_relax_align): Once we've handled an R_RISCV_ALIGN, we can't relax anything else, so set the sec->sec_flg0 to true. Besides, we don't need to update the pcgp_relocs table at this stage, so just pass NULL pointer as the pcgp_relocs table for riscv_relax_delete_bytes. (_bfd_riscv_relax_section): Use only one pass for all target relaxations. (_bfd_riscv_relax_delete): Likewise, we don't need to update the pcgp_relocs table at this stage, and don't need to set the `again' since restart_relax mechanism is abandoned. (bfd_elfNN_riscv_restart_relax_sections): Removed. (_bfd_riscv_relax_section): Updated. * elfxx-riscv.h (bfd_elf32_riscv_restart_relax_sections): Removed. (bfd_elf64_riscv_restart_relax_sections): Likewise. ld/ * emultempl/riscvelf.em: Revert restart_relax changes and set relax_pass to 3. * testsuite/ld-riscv-elf/align-small-region.d: New testcase. * testsuite/ld-riscv-elf/align-small-region.ld: Likewise. * testsuite/ld-riscv-elf/align-small-region.s: Likewise. * testsuite/ld-riscv-elf/restart-relax.d: Removed sine the restart_relax mechanism is abandoned. * testsuite/ld-riscv-elf/restart-relax.s: Likewise. * testsuite/ld-riscv-elf/ld-riscv-elf.exp: Updated.
Diffstat (limited to 'ld')
-rw-r--r--ld/emultempl/riscvelf.em8
-rw-r--r--ld/testsuite/ld-riscv-elf/align-small-region.d12
-rw-r--r--ld/testsuite/ld-riscv-elf/align-small-region.ld12
-rw-r--r--ld/testsuite/ld-riscv-elf/align-small-region.s7
-rw-r--r--ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp2
-rw-r--r--ld/testsuite/ld-riscv-elf/restart-relax.d14
-rw-r--r--ld/testsuite/ld-riscv-elf/restart-relax.s17
7 files changed, 34 insertions, 38 deletions
diff --git a/ld/emultempl/riscvelf.em b/ld/emultempl/riscvelf.em
index c625a63..80b7b37 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 = 4;
+ link_info.relax_pass = 3;
}
static void
@@ -76,11 +76,7 @@ gld${EMULATION_NAME}_after_allocation (void)
enum phase_enum *phase = &(expld.dataseg.phase);
bfd_elf${ELFSIZE}_riscv_set_data_segment_info (&link_info, (int *) phase);
- do
- {
- ldelf_map_segments (need_layout);
- }
- while (bfd_elf${ELFSIZE}_riscv_restart_relax_sections (&link_info));
+ ldelf_map_segments (need_layout);
}
/* This is a convenient point to tell BFD about target specific flags.
diff --git a/ld/testsuite/ld-riscv-elf/align-small-region.d b/ld/testsuite/ld-riscv-elf/align-small-region.d
new file mode 100644
index 0000000..3799129
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/align-small-region.d
@@ -0,0 +1,12 @@
+#source: align-small-region.s
+#as: -march=rv32i
+#ld: -melf32lriscv --relax -Talign-small-region.ld --defsym=_start=0x100
+#objdump: -d
+
+.*:[ ]+file format .*
+
+Disassembly of section \.entry:
+
+00000000 <_reset>:
+.*:[ ]+[0-9a-f]+[ ]+j[ ]+100[ ]+<_start>
+#pass
diff --git a/ld/testsuite/ld-riscv-elf/align-small-region.ld b/ld/testsuite/ld-riscv-elf/align-small-region.ld
new file mode 100644
index 0000000..a5a3783
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/align-small-region.ld
@@ -0,0 +1,12 @@
+MEMORY
+{
+ reset : ORIGIN = 0x0, LENGTH = 32
+}
+
+SECTIONS
+{
+ .entry :
+ {
+ KEEP (*(.entry))
+ } > reset
+}
diff --git a/ld/testsuite/ld-riscv-elf/align-small-region.s b/ld/testsuite/ld-riscv-elf/align-small-region.s
new file mode 100644
index 0000000..1c0f3cc
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/align-small-region.s
@@ -0,0 +1,7 @@
+ .section .entry, "xa"
+ .align 5
+ .globl _reset
+ .type _reset, @function
+_reset:
+ tail _start
+ .size _reset, . - _reset
diff --git a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
index 1197761..20ca3bd 100644
--- a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
+++ b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
@@ -119,6 +119,7 @@ proc run_relax_twice_test {} {
}
if [istarget "riscv*-*-*"] {
+ run_dump_test "align-small-region"
run_dump_test "call-relax"
run_dump_test "pcgp-relax"
run_dump_test "c-lui"
@@ -130,7 +131,6 @@ if [istarget "riscv*-*-*"] {
run_dump_test "pcrel-lo-addend-3a"
run_dump_test "pcrel-lo-addend-3b"
run_dump_test "pcrel-lo-addend-3c"
- run_dump_test "restart-relax"
run_dump_test "attr-merge-arch-01"
run_dump_test "attr-merge-arch-02"
run_dump_test "attr-merge-arch-03"
diff --git a/ld/testsuite/ld-riscv-elf/restart-relax.d b/ld/testsuite/ld-riscv-elf/restart-relax.d
deleted file mode 100644
index 57b62eb..0000000
--- a/ld/testsuite/ld-riscv-elf/restart-relax.d
+++ /dev/null
@@ -1,14 +0,0 @@
-#source: restart-relax.s
-#as:
-#ld:
-#objdump: -d
-
-#...
-Disassembly of section .text:
-
-0+[0-9a-f]+ <_start>:
-.*:[ ]+[0-9a-f]+[ ]+addi[ ]+.*
-#...
-.*:[ ]+[0-9a-f]+[ ]+jal[ ]+ra,[0-9a-f]+ <_start>
-.*:[ ]+[0-9a-f]+[ ]+add[ ]+a0,a1,a2
-#pass
diff --git a/ld/testsuite/ld-riscv-elf/restart-relax.s b/ld/testsuite/ld-riscv-elf/restart-relax.s
deleted file mode 100644
index efc881d..0000000
--- a/ld/testsuite/ld-riscv-elf/restart-relax.s
+++ /dev/null
@@ -1,17 +0,0 @@
- .text
- .global _start
-_start:
- lla a0, data_g
-.rept 0x3fffe
- nop
-.endr
- call _start
- .option rvc
- .align 2
- add a0, a1, a2
-
- .data
- .global data_g
- .dword 0x0
-data_g:
- .word 0x1000