aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXi Ruoyao <xry111@xry111.site>2024-08-05 15:15:54 +0100
committerAndreas K. Hüttel <dilfridge@gentoo.org>2024-08-06 21:59:24 +0200
commit27c785dc7cff2f8ed87feeaf15a44da41ac7fb2b (patch)
tree6494cf618f261c89fc9fc0e445932108d7e5acef
parentApply a similar libiberty fix as in 7d53105d for libopcodes and libgprofng (diff)
downloadbinutils-gdb-27c785dc7cff2f8ed87feeaf15a44da41ac7fb2b.tar.gz
binutils-gdb-27c785dc7cff2f8ed87feeaf15a44da41ac7fb2b.tar.bz2
binutils-gdb-27c785dc7cff2f8ed87feeaf15a44da41ac7fb2b.zip
LoongArch: Fix DT_RELR and relaxation interaction
(cherry picked from commit 7999dae69612295e1bbffe64aff87044372a0059)
-rw-r--r--bfd/elfnn-loongarch.c17
-rw-r--r--ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp1
-rw-r--r--ld/testsuite/ld-loongarch-elf/relr-got-start.d7
-rw-r--r--ld/testsuite/ld-loongarch-elf/relr-got-start.s5
4 files changed, 29 insertions, 1 deletions
diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
index db6d419a052..731af6a79a6 100644
--- a/bfd/elfnn-loongarch.c
+++ b/bfd/elfnn-loongarch.c
@@ -121,6 +121,12 @@ struct loongarch_elf_link_hash_table
/* Layout recomputation count. */
bfd_size_type relr_layout_iter;
+
+ /* In BFD DT_RELR is implemented as a "relaxation." If in a relax trip
+ size_relative_relocs is updating the layout, relax_section may see
+ a partially updated state (some sections have vma updated but the
+ others do not), and it's unsafe to do the normal relaxation. */
+ bool layout_mutating_for_relr;
};
struct loongarch_elf_section_data
@@ -2212,6 +2218,8 @@ loongarch_elf_size_relative_relocs (struct bfd_link_info *info,
*need_layout = false;
}
}
+
+ htab->layout_mutating_for_relr = *need_layout;
return true;
}
@@ -4133,7 +4141,8 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
bfd_link_pic (info),
h)
&& bfd_link_pic (info)
- && LARCH_REF_LOCAL (info, h))
+ && LARCH_REF_LOCAL (info, h)
+ && !info->enable_dt_relr)
{
Elf_Internal_Rela rela;
rela.r_offset = sec_addr (got) + got_off;
@@ -5259,6 +5268,12 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
*again = false;
bfd_vma max_alignment = 0;
+ /* It may happen that some sections have updated vma but the others do
+ not. Go to the next relax trip (size_relative_relocs should have
+ been demending another relax trip anyway). */
+ if (htab->layout_mutating_for_relr)
+ return true;
+
if (bfd_link_relocatable (info)
|| sec->sec_flg0
|| (sec->flags & SEC_RELOC) == 0
diff --git a/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp b/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp
index fb34eeb80cb..09c4c9fd5b2 100644
--- a/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp
+++ b/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp
@@ -149,6 +149,7 @@ if [istarget "loongarch64-*-*"] {
run_dump_test "relr-data-pie"
run_dump_test "relr-discard-pie"
run_dump_test "relr-got-pie"
+ run_dump_test "relr-got-start"
run_dump_test "relr-text-pie"
run_dump_test "abssym_pie"
}
diff --git a/ld/testsuite/ld-loongarch-elf/relr-got-start.d b/ld/testsuite/ld-loongarch-elf/relr-got-start.d
new file mode 100644
index 00000000000..0b1a5b9810d
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/relr-got-start.d
@@ -0,0 +1,7 @@
+#source: relr-got-start.s
+#ld: -pie -z pack-relative-relocs -T relr-relocs.ld
+#readelf: -rW
+
+Relocation section '\.relr\.dyn' at offset 0x[a-z0-f]+ contains 1 entry which relocates 1 location:
+Index: Entry Address Symbolic Address
+0000: 0000000000020008 0000000000020008 _GLOBAL_OFFSET_TABLE_ \+ 0x8
diff --git a/ld/testsuite/ld-loongarch-elf/relr-got-start.s b/ld/testsuite/ld-loongarch-elf/relr-got-start.s
new file mode 100644
index 00000000000..c89fb42527f
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/relr-got-start.s
@@ -0,0 +1,5 @@
+.globl _start
+_start:
+ pcalau12i $r5,%got_pc_hi20(_start)
+ ld.d $r5,$r5,%got_pc_lo12(_start)
+ ret