]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
LoongArch: Fix DT_RELR and relaxation interaction
authorXi Ruoyao <xry111@xry111.site>
Mon, 5 Aug 2024 14:15:54 +0000 (15:15 +0100)
committerNick Clifton <nickc@redhat.com>
Mon, 5 Aug 2024 14:15:54 +0000 (15:15 +0100)
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 db6d419a052e6400f8a0c1f02d64822372c862ba..731af6a79a672c9dec2b968da21893056cb57af0 100644 (file)
@@ -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
index fb34eeb80cbb812b728a83dbe7d747f5861a3312..09c4c9fd5b2cb22b5b4729df5b863624f6a0dec3 100644 (file)
@@ -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 (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