]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
LoongArch: Allocate GOT entry for TLS DESC when -mno-relax is enabled
authorLulu Cai <cailulu@loongson.cn>
Tue, 14 Jan 2025 13:13:01 +0000 (21:13 +0800)
committercailulu <cailulu@loongson.cn>
Fri, 17 Jan 2025 10:35:56 +0000 (18:35 +0800)
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.

bfd/elfnn-loongarch.c
ld/testsuite/ld-loongarch-elf/desc-ie-norelax.dd [new file with mode: 0644]
ld/testsuite/ld-loongarch-elf/desc-ie-norelax.rd [new file with mode: 0644]
ld/testsuite/ld-loongarch-elf/desc-ie-norelax.s [new file with mode: 0644]
ld/testsuite/ld-loongarch-elf/desc-ie-norelax.sd [new file with mode: 0644]
ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp

index be5ff00b41696ce9f88932855aa1cf2e13b28673..80d2c445d034bb5b74314c7d48d553b0c3e80bda 100644 (file)
@@ -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 (file)
index 0000000..bf26f31
--- /dev/null
@@ -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 (file)
index 0000000..17e74a5
--- /dev/null
@@ -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 (file)
index 0000000..2905d5d
--- /dev/null
@@ -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 (file)
index 0000000..053c886
--- /dev/null
@@ -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  ................
index 105305cd6b52cfd29dcfb099402c340039f87eea..0295be815623cf0af167f5acf8f56449fca35531 100644 (file)
@@ -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-*-*"] {