[binutils-gdb] LoongArch: Allocate GOT entry for TLS DESC when -mno-relax is enabled

liu & zhensong liuzhensong@sourceware.org
Fri Jan 17 10:36:44 GMT 2025


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

commit 48984d3da79f340b814e43b6576993ea1a927f5a
Author: Lulu Cai <cailulu@loongson.cn>
Date:   Tue Jan 14 21:13:01 2025 +0800

    LoongArch: Allocate GOT entry for TLS DESC when -mno-relax is enabled
    
    The type transition of TLSDESC is only done when -mrelax is enabled.
    So when -mno-relax is enabled, keep GOT_TLS_GDESC to allocate the
    GOT entry instead of just keeping GOT_TLS_IE.

Diff:
---
 bfd/elfnn-loongarch.c                              | 31 +++++++++++++++-------
 ld/testsuite/ld-loongarch-elf/desc-ie-norelax.dd   |  8 ++++++
 ld/testsuite/ld-loongarch-elf/desc-ie-norelax.rd   |  3 +++
 ld/testsuite/ld-loongarch-elf/desc-ie-norelax.s    | 15 +++++++++++
 ld/testsuite/ld-loongarch-elf/desc-ie-norelax.sd   |  6 +++++
 ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp | 15 +++++++++++
 6 files changed, 69 insertions(+), 9 deletions(-)

diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
index be5ff00b416..80d2c445d03 100644
--- a/bfd/elfnn-loongarch.c
+++ b/bfd/elfnn-loongarch.c
@@ -683,7 +683,8 @@ loongarch_elf_record_tls_and_got_reference (bfd *abfd,
 					    struct bfd_link_info *info,
 					    struct elf_link_hash_entry *h,
 					    unsigned long symndx,
-					    char tls_type)
+					    char tls_type,
+					    bool with_relax_reloc)
 {
   struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
   Elf_Internal_Shdr *symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
@@ -729,9 +730,12 @@ loongarch_elf_record_tls_and_got_reference (bfd *abfd,
   char *new_tls_type = &_bfd_loongarch_elf_tls_type (abfd, h, symndx);
   *new_tls_type |= tls_type;
 
-  /* If a symbol is accessed by both IE and DESC, relax DESC to IE.  */
-  if ((*new_tls_type & GOT_TLS_IE) && (*new_tls_type & GOT_TLS_GDESC))
+  /* If DESC relocs can do transitions and accessed by both IE and DESC,
+     transition DESC to IE.  */
+  if (with_relax_reloc
+      && (*new_tls_type & GOT_TLS_IE) && (*new_tls_type & GOT_TLS_GDESC))
     *new_tls_type &= ~ (GOT_TLS_GDESC);
+
   if ((*new_tls_type & GOT_NORMAL) && (*new_tls_type & ~GOT_NORMAL))
     {
       _bfd_error_handler (_("%pB: `%s' accessed both as normal and "
@@ -1014,9 +1018,13 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 
       /* Type transitions are only possible with relocations accompanied
 	 by R_LARCH_RELAX.  */
+      bool with_relax_reloc = false;
       if (rel + 1 != relocs + sec->reloc_count
 	  && ELFNN_R_TYPE (rel[1].r_info) == R_LARCH_RELAX)
-	r_type = loongarch_tls_transition (abfd, info, h, r_symndx, r_type);
+	{
+	  r_type = loongarch_tls_transition (abfd, info, h, r_symndx, r_type);
+	  with_relax_reloc = true;
+	}
 
       /* I don't want to spend time supporting DT_RELR with old object
 	 files doing stack-based relocs.  */
@@ -1041,7 +1049,8 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	    h->pointer_equality_needed = 1;
 	  if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h,
 							   r_symndx,
-							   GOT_NORMAL))
+							   GOT_NORMAL,
+							   with_relax_reloc))
 	    return false;
 	  break;
 
@@ -1052,7 +1061,8 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	case R_LARCH_SOP_PUSH_TLS_GD:
 	  if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h,
 							   r_symndx,
-							   GOT_TLS_GD))
+							   GOT_TLS_GD,
+							   with_relax_reloc))
 	    return false;
 	  break;
 
@@ -1065,7 +1075,8 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 
 	  if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h,
 							   r_symndx,
-							   GOT_TLS_IE))
+							   GOT_TLS_IE,
+							   with_relax_reloc))
 	    return false;
 	  break;
 
@@ -1077,7 +1088,8 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 
 	  if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h,
 							   r_symndx,
-							   GOT_TLS_LE))
+							   GOT_TLS_LE,
+							   with_relax_reloc))
 	    return false;
 	  break;
 
@@ -1085,7 +1097,8 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	case R_LARCH_TLS_DESC_HI20:
 	  if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h,
 							   r_symndx,
-							   GOT_TLS_GDESC))
+							   GOT_TLS_GDESC,
+							   with_relax_reloc))
 	    return false;
 	  break;
 
diff --git a/ld/testsuite/ld-loongarch-elf/desc-ie-norelax.dd b/ld/testsuite/ld-loongarch-elf/desc-ie-norelax.dd
new file mode 100644
index 00000000000..bf26f3143c8
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/desc-ie-norelax.dd
@@ -0,0 +1,8 @@
+#...
+.*pcalau12i.*
+.*addi.d.*
+.*ld.d.*
+.*jirl.*
+.*pcalau12i.*
+.*ld.d.*
+#pass
diff --git a/ld/testsuite/ld-loongarch-elf/desc-ie-norelax.rd b/ld/testsuite/ld-loongarch-elf/desc-ie-norelax.rd
new file mode 100644
index 00000000000..17e74a52810
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/desc-ie-norelax.rd
@@ -0,0 +1,3 @@
+#...
+.*R_LARCH_TLS_DESC64.*
+#pass
diff --git a/ld/testsuite/ld-loongarch-elf/desc-ie-norelax.s b/ld/testsuite/ld-loongarch-elf/desc-ie-norelax.s
new file mode 100644
index 00000000000..2905d5daf76
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/desc-ie-norelax.s
@@ -0,0 +1,15 @@
+	.globl	var
+	.section	.tdata,"awT",@progbits
+	.type	tls, @object
+var:
+	.word 1
+	.text
+	.globl	_start
+_start:
+	pcalau12i   $a0,%desc_pc_hi20(var)
+	addi.d	    $a0,$a0,%desc_pc_lo12(var)
+	ld.d	    $ra,$a0,%desc_ld(var)
+	jirl	    $ra,$ra,%desc_call(var)
+
+	pcalau12i   $t0,%ie_pc_hi20(var)
+	ld.d	    $t0,$t0,%ie_pc_lo12(var)
diff --git a/ld/testsuite/ld-loongarch-elf/desc-ie-norelax.sd b/ld/testsuite/ld-loongarch-elf/desc-ie-norelax.sd
new file mode 100644
index 00000000000..053c886d8d3
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/desc-ie-norelax.sd
@@ -0,0 +1,6 @@
+
+.*:     file format .*
+
+Contents of section .got:
+ [0-9a-f]+ [0-9a-f]+ 00000000 00000000 00000000  ................
+ [0-9a-f]+ 00000000 00000000 00000000 00000000  ................
diff --git a/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp b/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp
index 105305cd6b5..0295be81562 100644
--- a/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp
+++ b/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp
@@ -154,6 +154,21 @@ if [istarget "loongarch64-*-*"] {
       ] \
   ]
 
+  # Using DESC and IE to access the same tls symbol but with
+  # -mno-relax requires allocating GOT entries for both DESC and IE,
+  # not just IE
+  run_ld_link_tests [list \
+      [list \
+	  "desc and ie do not type transition" \
+	  "-pie -e0 --hash-style=both" "" \
+	  "-mno-relax" \
+	  {desc-ie-norelax.s} \
+	  {{objdump {-d} desc-ie-norelax.dd} \
+	   {readelf {-rW} desc-ie-norelax.rd} \
+	   {objdump {-sj.got} desc-ie-norelax.sd}} \
+	  "desc-ie-norelax" \
+      ] \
+  ] \
 }
 
 if [istarget "loongarch64-*-*"] {


More information about the Binutils-cvs mailing list