]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
LoongArch: Fix assertion failure with DT_RELR
authorXi Ruoyao <xry111@xry111.site>
Mon, 12 Aug 2024 10:23:46 +0000 (18:23 +0800)
committerliuzhensong <liuzhensong@loongson.cn>
Wed, 14 Aug 2024 09:45:02 +0000 (17:45 +0800)
In the DT_RELR implementation I missed a code path emiting relative
reloc entries.  Then the already packed relative reloc entries will be
(unnecessarily) pushed into .rela.dyn but we've not allocated the space
for them, triggering an assertion failure.

Unfortunately I failed to notice the issue until profiled bootstrapping
GCC with LTO and -Wl,-z,pack-relative-relocs.  The failure can be easily
triggered by linking a "hello world" program with -fprofile-generate and
LTO:

    $ PATH=$HOME/ld-test:$PATH gcc hw.c -fprofile-generate -Wl,-z,pack-relative-relocs -flto
    /home/xry111/git-repos/binutils-build/TEST/ld: BFD (GNU Binutils) 2.43.50.20240802 assertion fail ../../binutils-gdb/bfd/elfnn-loongarch.c:2628
    /home/xry111/git-repos/binutils-build/TEST/ld: BFD (GNU Binutils) 2.43.50.20240802 assertion fail ../../binutils-gdb/bfd/elfnn-loongarch.c:2628
    collect2: error: ld returned 1 exit status

And the reduced test case is just incredibly simple (included in the
patch) so it seems I'm just stupid enough to fail to detect it before.
Let's fix it now anyway.

Signed-off-by: Xi Ruoyao <xry111@xry111.site>
bfd/elfnn-loongarch.c
ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp
ld/testsuite/ld-loongarch-elf/relr-got-start.d [new file with mode: 0644]
ld/testsuite/ld-loongarch-elf/relr-got-start.s [new file with mode: 0644]

index af8cb2575e777547b1a46341361c81c334036acd..eecf7a800e897ee15b8de2cc376d01aed0dafb5c 100644 (file)
@@ -4131,7 +4131,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;
index 16d89cd5a432d3d513e395d42ff7b54e7c6ae037..d80014d9563cefe8fb4d9cce2f4e897e9b1ca22a 100644 (file)
@@ -161,6 +161,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 (file)
index 0000000..0b1a5b9
--- /dev/null
@@ -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 (file)
index 0000000..c89fb42
--- /dev/null
@@ -0,0 +1,5 @@
+.globl _start
+_start:
+        pcalau12i       $r5,%got_pc_hi20(_start)
+        ld.d    $r5,$r5,%got_pc_lo12(_start)
+        ret