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.
This commit is contained in:
Lulu Cai 2025-01-14 21:13:01 +08:00 committed by cailulu
parent 2c4b5f54b8
commit 48984d3da7
6 changed files with 69 additions and 9 deletions

View 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;

View File

@ -0,0 +1,8 @@
#...
.*pcalau12i.*
.*addi.d.*
.*ld.d.*
.*jirl.*
.*pcalau12i.*
.*ld.d.*
#pass

View File

@ -0,0 +1,3 @@
#...
.*R_LARCH_TLS_DESC64.*
#pass

View File

@ -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)

View File

@ -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 ................

View 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-*-*"] {