[binutils-gdb/binutils-2_43-branch] LoongArch: Fix DT_RELR and relaxation interaction

Nick Clifton nickc@sourceware.org
Mon Aug 5 14:16:19 GMT 2024


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=7999dae69612295e1bbffe64aff87044372a0059

commit 7999dae69612295e1bbffe64aff87044372a0059
Author: Xi Ruoyao <xry111@xry111.site>
Date:   Mon Aug 5 15:15:54 2024 +0100

    LoongArch: Fix DT_RELR and relaxation interaction

Diff:
---
 bfd/elfnn-loongarch.c                              | 17 ++++++++++++++++-
 ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp |  1 +
 ld/testsuite/ld-loongarch-elf/relr-got-start.d     |  7 +++++++
 ld/testsuite/ld-loongarch-elf/relr-got-start.s     |  5 +++++
 4 files changed, 29 insertions(+), 1 deletion(-)

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


More information about the Binutils-cvs mailing list