aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLulu Cai <cailulu@loongson.cn>2025-01-14 21:13:01 +0800
committercailulu <cailulu@loongson.cn>2025-01-17 18:35:56 +0800
commit48984d3da79f340b814e43b6576993ea1a927f5a (patch)
tree610072c2124d63330c0b3b75eb76c6fdbd7a9659
parent2c4b5f54b8432bb442f95748cd60fcdcc48f239b (diff)
downloadbinutils-48984d3da79f340b814e43b6576993ea1a927f5a.zip
binutils-48984d3da79f340b814e43b6576993ea1a927f5a.tar.gz
binutils-48984d3da79f340b814e43b6576993ea1a927f5a.tar.bz2
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.
-rw-r--r--bfd/elfnn-loongarch.c31
-rw-r--r--ld/testsuite/ld-loongarch-elf/desc-ie-norelax.dd8
-rw-r--r--ld/testsuite/ld-loongarch-elf/desc-ie-norelax.rd3
-rw-r--r--ld/testsuite/ld-loongarch-elf/desc-ie-norelax.s15
-rw-r--r--ld/testsuite/ld-loongarch-elf/desc-ie-norelax.sd6
-rw-r--r--ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp15
6 files changed, 69 insertions, 9 deletions
diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
index be5ff00..80d2c44 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 0000000..bf26f31
--- /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 0000000..17e74a5
--- /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 0000000..2905d5d
--- /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 0000000..053c886
--- /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 105305c..0295be8 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-*-*"] {