diff options
-rw-r--r-- | bfd/elfnn-loongarch.c | 179 | ||||
-rw-r--r-- | ld/testsuite/ld-loongarch-elf/desc-ie.d | 4 | ||||
-rw-r--r-- | ld/testsuite/ld-loongarch-elf/tlsdesc-dso.d | 94 |
3 files changed, 142 insertions, 135 deletions
diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c index 1679aa5..952c42d 100644 --- a/bfd/elfnn-loongarch.c +++ b/bfd/elfnn-loongarch.c @@ -159,6 +159,27 @@ struct loongarch_elf_link_hash_table || (R_TYPE) == R_LARCH_TLS_LE64_LO20 \ || (R_TYPE) == R_LARCH_TLS_LE64_HI12) +/* If TLS GD/IE need dynamic relocations, INDX will be the dynamic indx, + and set NEED_RELOC to true used in allocate_dynrelocs and + loongarch_elf_relocate_section for TLS GD/IE. */ +#define LARCH_TLS_GD_IE_NEED_DYN_RELOC(INFO, DYN, H, INDX, NEED_RELOC) \ + do \ + { \ + if ((H) != NULL \ + && (H)->dynindx != -1 \ + && WILL_CALL_FINISH_DYNAMIC_SYMBOL ((DYN), \ + bfd_link_pic (INFO), (H))) \ + (INDX) = (H)->dynindx; \ + if (((H) == NULL \ + || ELF_ST_VISIBILITY ((H)->other) == STV_DEFAULT \ + || (H)->root.type != bfd_link_hash_undefweak) \ + && (!bfd_link_executable (INFO) \ + || (INDX) != 0)) \ + (NEED_RELOC) = true; \ + } \ + while (0) + + /* Generate a PLT header. */ static bool @@ -1276,40 +1297,24 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) h->got.offset = s->size; if (tls_type & (GOT_TLS_GD | GOT_TLS_IE | GOT_TLS_GDESC)) { + int indx = 0; + bool need_reloc = false; + LARCH_TLS_GD_IE_NEED_DYN_RELOC (info, dyn, h, indx, + need_reloc); /* TLS_GD needs two dynamic relocs and two GOT slots. */ if (tls_type & GOT_TLS_GD) { s->size += 2 * GOT_ENTRY_SIZE; - if (bfd_link_executable (info)) - { - /* Link exe and not defined local. */ - if (!SYMBOL_REFERENCES_LOCAL (info, h)) - htab->elf.srelgot->size += 2 * sizeof (ElfNN_External_Rela); - } - else - { - if (SYMBOL_REFERENCES_LOCAL (info, h)) - htab->elf.srelgot->size += sizeof (ElfNN_External_Rela); - else - htab->elf.srelgot->size += 2 * sizeof (ElfNN_External_Rela); - } + if (need_reloc) + htab->elf.srelgot->size += 2 * sizeof (ElfNN_External_Rela); } /* TLS_IE needs one dynamic reloc and one GOT slot. */ if (tls_type & GOT_TLS_IE) { s->size += GOT_ENTRY_SIZE; - - if (bfd_link_executable (info)) - { - /* Link exe and not defined local. */ - if (!SYMBOL_REFERENCES_LOCAL (info, h)) - htab->elf.srelgot->size += sizeof (ElfNN_External_Rela); - } - else - { - htab->elf.srelgot->size += sizeof (ElfNN_External_Rela); - } + if (need_reloc) + htab->elf.srelgot->size += 2 * sizeof (ElfNN_External_Rela); } /* TLS_DESC needs one dynamic reloc and two GOT slot. */ @@ -2550,13 +2555,18 @@ loongarch_reloc_is_fatal (struct bfd_link_info *info, }) +/* Compute the tp/dtp offset of a tls symbol. + It is dtp offset in dynamic tls model (gd/ld) and tp + offset in static tls model (ie/le). Both offsets are + calculated the same way on LoongArch, so the same + function is used. */ static bfd_vma -tls_dtpoff_base (struct bfd_link_info *info) +tlsoff (struct bfd_link_info *info, bfd_vma addr) { /* If tls_sec is NULL, we should have signalled an error already. */ if (elf_hash_table (info)->tls_sec == NULL) return 0; - return elf_hash_table (info)->tls_sec->vma; + return addr - elf_hash_table (info)->tls_sec->vma; } @@ -2890,7 +2900,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, is_undefweak, name, "TLS section not be created"); } else - relocation -= elf_hash_table (info)->tls_sec->vma; + relocation = tlsoff (info, relocation); } else { @@ -3416,7 +3426,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, case R_LARCH_TLS_LE_HI20_R: relocation += rel->r_addend; - relocation -= elf_hash_table (info)->tls_sec->vma; + relocation = tlsoff (info, relocation); RELOCATE_TLS_TP32_HI20 (relocation); break; @@ -3599,7 +3609,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, BFD_ASSERT (resolved_local && elf_hash_table (info)->tls_sec); relocation += rel->r_addend; - relocation -= elf_hash_table (info)->tls_sec->vma; + relocation = tlsoff (info, relocation); break; /* TLS IE LD/GD process separately is troublesome. @@ -3654,71 +3664,72 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, /* If a tls variable is accessed in multiple ways, GD uses the first two slots of GOT, desc follows with two slots, and IE uses one slot at the end. */ - desc_off = 0; - if (GOT_TLS_GD_BOTH_P (tls_type)) - desc_off = 2 * GOT_ENTRY_SIZE; - - ie_off = 0; - if (GOT_TLS_GD_BOTH_P (tls_type) && (tls_type & GOT_TLS_IE)) - ie_off = 4 * GOT_ENTRY_SIZE; - else if (GOT_TLS_GD_ANY_P (tls_type) && (tls_type & GOT_TLS_IE)) - ie_off = 2 * GOT_ENTRY_SIZE; + off = 0; + if (tls_type & GOT_TLS_GD) + off += 2 * GOT_ENTRY_SIZE; + desc_off = off; + if (tls_type & GOT_TLS_GDESC) + off += 2 * GOT_ENTRY_SIZE; + ie_off = off; if ((got_off & 1) == 0) { Elf_Internal_Rela rela; asection *relgot = htab->elf.srelgot; - bfd_vma tls_block_off = 0; - if (SYMBOL_REFERENCES_LOCAL (info, h)) - { - BFD_ASSERT (elf_hash_table (info)->tls_sec); - tls_block_off = relocation - - elf_hash_table (info)->tls_sec->vma; - } + int indx = 0; + bool need_reloc = false; + LARCH_TLS_GD_IE_NEED_DYN_RELOC (info, is_dyn, h, indx, + need_reloc); if (tls_type & GOT_TLS_GD) { - rela.r_offset = sec_addr (got) + got_off; - rela.r_addend = 0; - if (SYMBOL_REFERENCES_LOCAL (info, h)) + if (need_reloc) { - /* Local sym, used in exec, set module id 1. */ - if (bfd_link_executable (info)) - bfd_put_NN (output_bfd, 1, got->contents + got_off); + /* Dynamic resolved Module ID. */ + rela.r_offset = sec_addr (got) + got_off; + rela.r_addend = 0; + rela.r_info = ELFNN_R_INFO (indx,R_LARCH_TLS_DTPMODNN); + bfd_put_NN (output_bfd, 0, got->contents + got_off); + loongarch_elf_append_rela (output_bfd, relgot, &rela); + + if (indx == 0) + { + /* Local symbol, tp offset has been known. */ + BFD_ASSERT (! unresolved_reloc); + bfd_put_NN (output_bfd, + tlsoff (info, relocation), + (got->contents + got_off + GOT_ENTRY_SIZE)); + } else { - rela.r_info = ELFNN_R_INFO (0, R_LARCH_TLS_DTPMODNN); + /* Dynamic resolved block offset. */ + bfd_put_NN (output_bfd, 0, + got->contents + got_off + GOT_ENTRY_SIZE); + rela.r_info = ELFNN_R_INFO (indx, + R_LARCH_TLS_DTPRELNN); + rela.r_offset += GOT_ENTRY_SIZE; loongarch_elf_append_rela (output_bfd, relgot, &rela); } - - bfd_put_NN (output_bfd, tls_block_off, - got->contents + got_off + GOT_ENTRY_SIZE); } - /* Dynamic resolved. */ else { - /* Dynamic relocate module id. */ - rela.r_info = ELFNN_R_INFO (h->dynindx, - R_LARCH_TLS_DTPMODNN); - loongarch_elf_append_rela (output_bfd, relgot, &rela); - - /* Dynamic relocate offset of block. */ - rela.r_offset += GOT_ENTRY_SIZE; - rela.r_info = ELFNN_R_INFO (h->dynindx, - R_LARCH_TLS_DTPRELNN); - loongarch_elf_append_rela (output_bfd, relgot, &rela); + /* In a static link or an executable link with the symbol + binding locally. Mark it as belonging to module 1. */ + bfd_put_NN (output_bfd, 1, got->contents + got_off); + bfd_put_NN (output_bfd, tlsoff (info, relocation), + got->contents + got_off + GOT_ENTRY_SIZE); } } if (tls_type & GOT_TLS_GDESC) { /* Unless it is a static link, DESC always emits a dynamic relocation. */ - int indx = h && h->dynindx != -1 ? h->dynindx : 0; + indx = h && h->dynindx != -1 ? h->dynindx : 0; rela.r_offset = sec_addr (got) + got_off + desc_off; rela.r_addend = 0; if (indx == 0) - rela.r_addend = relocation - tls_dtpoff_base (info); + rela.r_addend = tlsoff (info, relocation); rela.r_info = ELFNN_R_INFO (indx, R_LARCH_TLS_DESCNN); loongarch_elf_append_rela (output_bfd, relgot, &rela); @@ -3727,28 +3738,24 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, } if (tls_type & GOT_TLS_IE) { - rela.r_offset = sec_addr (got) + got_off + ie_off; - if (SYMBOL_REFERENCES_LOCAL (info, h)) + if (need_reloc) { - /* Local sym, used in exec, set module id 1. */ - if (!bfd_link_executable (info)) - { - rela.r_info = ELFNN_R_INFO (0, R_LARCH_TLS_TPRELNN); - rela.r_addend = tls_block_off; - loongarch_elf_append_rela (output_bfd, relgot, &rela); - } + bfd_put_NN (output_bfd, 0, + got->contents + got_off + ie_off); + rela.r_offset = sec_addr (got) + got_off + ie_off; + rela.r_addend = 0; - bfd_put_NN (output_bfd, tls_block_off, - got->contents + got_off + ie_off); + if (indx == 0) + rela.r_addend = tlsoff (info, relocation); + rela.r_info = ELFNN_R_INFO (indx, R_LARCH_TLS_TPRELNN); + loongarch_elf_append_rela (output_bfd, relgot, &rela); } - /* Dynamic resolved. */ else { - /* Dynamic relocate offset of block. */ - rela.r_info = ELFNN_R_INFO (h->dynindx, - R_LARCH_TLS_TPRELNN); - rela.r_addend = 0; - loongarch_elf_append_rela (output_bfd, relgot, &rela); + /* In a static link or an executable link with the symbol + bindinglocally, compute offset directly. */ + bfd_put_NN (output_bfd, tlsoff (info, relocation), + got->contents + got_off + ie_off); } } } @@ -3787,7 +3794,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx); /* Use both TLS_GD and TLS_DESC. */ - if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_GDESC)) + if (GOT_TLS_GD_BOTH_P (tls_type)) relocation += 2 * GOT_ENTRY_SIZE; if (r_type == R_LARCH_TLS_DESC64_PC_LO20) diff --git a/ld/testsuite/ld-loongarch-elf/desc-ie.d b/ld/testsuite/ld-loongarch-elf/desc-ie.d index e1f49e2..c833b23 100644 --- a/ld/testsuite/ld-loongarch-elf/desc-ie.d +++ b/ld/testsuite/ld-loongarch-elf/desc-ie.d @@ -9,6 +9,6 @@ Disassembly of section .text: [0-9a-f]+ <fn1>: +[0-9a-f]+: 1a000084 pcalau12i \$a0, .* - +[0-9a-f]+: 28cca084 ld.d \$a0, \$a0, .* + +[0-9a-f]+: 28cd0084 ld.d \$a0, \$a0, .* +[0-9a-f]+: 1a000084 pcalau12i \$a0, .* - +[0-9a-f]+: 28cca084 ld.d \$a0, \$a0, .* + +[0-9a-f]+: 28cd0084 ld.d \$a0, \$a0, .* diff --git a/ld/testsuite/ld-loongarch-elf/tlsdesc-dso.d b/ld/testsuite/ld-loongarch-elf/tlsdesc-dso.d index 84ea97e..8f66302 100644 --- a/ld/testsuite/ld-loongarch-elf/tlsdesc-dso.d +++ b/ld/testsuite/ld-loongarch-elf/tlsdesc-dso.d @@ -8,53 +8,53 @@ Disassembly of section .text: -0+448 <fun_gl1>: - 448: 18021584 pcaddi \$a0, 4268 - 44c: 1a000084 pcalau12i \$a0, 4 - 450: 28dc2084 ld.d \$a0, \$a0, 1800 - 454: 18021364 pcaddi \$a0, 4251 - 458: 180213c4 pcaddi \$a0, 4254 - 45c: 28c00081 ld.d \$ra, \$a0, 0 - 460: 4c000021 jirl \$ra, \$ra, 0 - 464: 1a000084 pcalau12i \$a0, 4 - 468: 28dae084 ld.d \$a0, \$a0, 1720 - 46c: 1a000084 pcalau12i \$a0, 4 - 470: 28dae084 ld.d \$a0, \$a0, 1720 - 474: 18021364 pcaddi \$a0, 4251 - 478: 18021344 pcaddi \$a0, 4250 - 47c: 28c00081 ld.d \$ra, \$a0, 0 - 480: 4c000021 jirl \$ra, \$ra, 0 - 484: 1a000084 pcalau12i \$a0, 4 - 488: 28dbc084 ld.d \$a0, \$a0, 1776 +[0-9a-f]+ <fun_gl1>: + +[0-9a-f]+: 18021584 pcaddi \$a0, 4268 + +[0-9a-f]+: 1a000084 pcalau12i \$a0, 4 + +[0-9a-f]+: 28dd4084 ld.d \$a0, \$a0, 1872 + +[0-9a-f]+: 18021364 pcaddi \$a0, 4251 + +[0-9a-f]+: 180213c4 pcaddi \$a0, 4254 + +[0-9a-f]+: 28c00081 ld.d \$ra, \$a0, 0 + +[0-9a-f]+: 4c000021 jirl \$ra, \$ra, 0 + +[0-9a-f]+: 1a000084 pcalau12i \$a0, 4 + +[0-9a-f]+: 28dc0084 ld.d \$a0, \$a0, 1792 + +[0-9a-f]+: 1a000084 pcalau12i \$a0, 4 + +[0-9a-f]+: 28dc0084 ld.d \$a0, \$a0, 1792 + +[0-9a-f]+: 18021364 pcaddi \$a0, 4251 + +[0-9a-f]+: 180213c4 pcaddi \$a0, 4254 + +[0-9a-f]+: 28c00081 ld.d \$ra, \$a0, 0 + +[0-9a-f]+: 4c000021 jirl \$ra, \$ra, 0 + +[0-9a-f]+: 1a000084 pcalau12i \$a0, 4 + +[0-9a-f]+: 28dce084 ld.d \$a0, \$a0, 1848 -0+48c <fun_lo>: - 48c: 1a000084 pcalau12i \$a0, 4 - 490: 28d98084 ld.d \$a0, \$a0, 1632 - 494: 18020de4 pcaddi \$a0, 4207 - 498: 18020f04 pcaddi \$a0, 4216 - 49c: 28c00081 ld.d \$ra, \$a0, 0 - 4a0: 4c000021 jirl \$ra, \$ra, 0 - 4a4: 18020e24 pcaddi \$a0, 4209 - 4a8: 1a000084 pcalau12i \$a0, 4 - 4ac: 28da2084 ld.d \$a0, \$a0, 1672 - 4b0: 1a000084 pcalau12i \$a0, 4 - 4b4: 28da2084 ld.d \$a0, \$a0, 1672 - 4b8: 18020ec4 pcaddi \$a0, 4214 - 4bc: 28c00081 ld.d \$ra, \$a0, 0 - 4c0: 4c000021 jirl \$ra, \$ra, 0 - 4c4: 18020e64 pcaddi \$a0, 4211 - 4c8: 1a000084 pcalau12i \$a0, 4 - 4cc: 28da8084 ld.d \$a0, \$a0, 1696 +[0-9a-f]+ <fun_lo>: + +[0-9a-f]+: 1a000084 pcalau12i \$a0, 4 + +[0-9a-f]+: 28daa084 ld.d \$a0, \$a0, 1704 + +[0-9a-f]+: 18020de4 pcaddi \$a0, 4207 + +[0-9a-f]+: 18020f04 pcaddi \$a0, 4216 + +[0-9a-f]+: 28c00081 ld.d \$ra, \$a0, 0 + +[0-9a-f]+: 4c000021 jirl \$ra, \$ra, 0 + +[0-9a-f]+: 18020e24 pcaddi \$a0, 4209 + +[0-9a-f]+: 1a000084 pcalau12i \$a0, 4 + +[0-9a-f]+: 28db4084 ld.d \$a0, \$a0, 1744 + +[0-9a-f]+: 1a000084 pcalau12i \$a0, 4 + +[0-9a-f]+: 28db4084 ld.d \$a0, \$a0, 1744 + +[0-9a-f]+: 18020f44 pcaddi \$a0, 4218 + +[0-9a-f]+: 28c00081 ld.d \$ra, \$a0, 0 + +[0-9a-f]+: 4c000021 jirl \$ra, \$ra, 0 + +[0-9a-f]+: 18020e64 pcaddi \$a0, 4211 + +[0-9a-f]+: 1a000084 pcalau12i \$a0, 4 + +[0-9a-f]+: 28dba084 ld.d \$a0, \$a0, 1768 -0+4d0 <fun_external>: - 4d0: 18020ec4 pcaddi \$a0, 4214 - 4d4: 28c00081 ld.d \$ra, \$a0, 0 - 4d8: 4c000021 jirl \$ra, \$ra, 0 +[0-9a-f]+ <fun_external>: + +[0-9a-f]+: 18020ec4 pcaddi \$a0, 4214 + +[0-9a-f]+: 28c00081 ld.d \$ra, \$a0, 0 + +[0-9a-f]+: 4c000021 jirl \$ra, \$ra, 0 -0+4dc <fun_hidden>: - 4dc: 18021224 pcaddi \$a0, 4241 - 4e0: 28c00081 ld.d \$ra, \$a0, 0 - 4e4: 4c000021 jirl \$ra, \$ra, 0 - 4e8: 18021144 pcaddi \$a0, 4234 - 4ec: 28c00081 ld.d \$ra, \$a0, 0 - 4f0: 4c000021 jirl \$ra, \$ra, 0 +[0-9a-f]+ <fun_hidden>: + +[0-9a-f]+: 18021224 pcaddi \$a0, 4241 + +[0-9a-f]+: 28c00081 ld.d \$ra, \$a0, 0 + +[0-9a-f]+: 4c000021 jirl \$ra, \$ra, 0 + +[0-9a-f]+: 18021144 pcaddi \$a0, 4234 + +[0-9a-f]+: 28c00081 ld.d \$ra, \$a0, 0 + +[0-9a-f]+: 4c000021 jirl \$ra, \$ra, 0 |