From: Lulu Cai Date: Tue, 14 Jan 2025 13:13:01 +0000 (+0800) Subject: LoongArch: Allocate GOT entry for TLS DESC when -mno-relax is enabled X-Git-Tag: binutils-2_44~58 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=48984d3da79f340b814e43b6576993ea1a927f5a;p=thirdparty%2Fbinutils-gdb.git 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 --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-*-*"] {