From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by sourceware.org (Postfix) with ESMTP id 73D493860753 for ; Thu, 14 Dec 2023 02:51:34 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 73D493860753 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=loongson.cn ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 73D493860753 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=114.242.206.163 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1702522297; cv=none; b=uW+87XyR5azwCOHvvZ9mJKNy+Y7sGaZXFJJIWGDKVpGl7OhQXu50G72XYLecFT/BPt53DgQFmEzV73XqN373H543k1BOrsK0qB3zo3ano4f9Fa6R6MG9olveXprUVN0NnWV7HUYzkGX3Cu45vNO1WxrchIh+BhLY6+3hnUdvY/0= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1702522297; c=relaxed/simple; bh=WCHNalZMsnTPrIU7NmLuOZ/k7RBPt/jsC3bYh7Iwuto=; h=From:To:Subject:Date:Message-Id:MIME-Version; b=ZZ7LY3Jdyf5ZyeVt7+cYuOArHMjokGMYPs9Cvj/S9yoE4Hs5Z4UZ40LLh92o3yWF2kaw0uZTpAtPIzQqSXNgAbLOicxlMWM0G7H+O3fJkQ0OaT/9ybZD48E9YMGZ97J7NgUHZSaov/Yfn9xc0Cgd4em71mdrQVK+jYkeQag8BlQ= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from loongson.cn (unknown [10.2.6.5]) by gateway (Coremail) with SMTP id _____8Cxuei0bXplUuYAAA--.5252S3; Thu, 14 Dec 2023 10:51:32 +0800 (CST) Received: from 5.5.5 (unknown [10.2.6.5]) by localhost.localdomain (Coremail) with SMTP id AQAAf8CxOXOYbXplPIQDAA--.4894S6; Thu, 14 Dec 2023 10:51:31 +0800 (CST) From: Lulu Cai To: binutils@sourceware.org Cc: xuchenghua@loongson.cn, chenglulu@loongson.cn, liuzhensong@loongson.cn, mengqinggang@loongson.cn, xry111@xry111.site, i.swmail@xen0n.name, maskray@google.com, luweining@loongson.cn, wanglei@loongson.cn, hejinyang@loongson.cn, Lulu Cai Subject: [PATCH v3 2/5] LoongArch: Add support for TLSDESC in ld. Date: Thu, 14 Dec 2023 10:50:46 +0800 Message-Id: <20231214025049.1629419-3-cailulu@loongson.cn> X-Mailer: git-send-email 2.39.3 In-Reply-To: <20231214025049.1629419-1-cailulu@loongson.cn> References: <20231214025049.1629419-1-cailulu@loongson.cn> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-CM-TRANSID:AQAAf8CxOXOYbXplPIQDAA--.4894S6 X-CM-SenderInfo: xfdlz3tox6z05rqj20fqof0/1tbiAQAFB2V6Zi0A-gAAsp X-Coremail-Antispam: 1Uk129KBj93XoW3KFW5tF17tFWrXr48XF45XFc_yoWDXrW5pr ZxAr4UKw48urW7W34aq3WrZa1Fg3y8ury2qr9xt3909Fn3Xr95WF47Xr15ZFW5KF4qyw42 v3sY93W8Za48A3XCm3ZEXasCq-sJn29KB7ZKAUJUUUUx529EdanIXcx71UUUUU7KY7ZEXa sCq-sGcSsGvfJ3Ic02F40EFcxC0VAKzVAqx4xG6I80ebIjqfuFe4nvWSU5nxnvy29KBjDU 0xBIdaVrnRJUUU9Fb4IE77IF4wAFF20E14v26r1j6r4UM7CY07I20VC2zVCF04k26cxKx2 IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48v e4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_Xr0_Ar1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI 0_Gr0_Cr1l84ACjcxK6I8E87Iv67AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVCY1x0267AK xVW8Jr0_Cr1UM2kKe7AKxVWUAVWUtwAS0I0E0xvYzxvE52x082IY62kv0487Mc804VCY07 AIYIkI8VC2zVCFFI0UMc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VC0I7IYx2IY67AKxVWU tVWrXwAv7VC2z280aVAFwI0_Gr0_Cr1lOx8S6xCaFVCjc4AY6r1j6r4UM4x0Y48IcxkI7V AKI48JMxkF7I0En4kS14v26r126r1DMxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY 6r1j6r4UMI8I3I0E5I8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4CE17 CEb7AF67AKxVWUtVW8ZwCIc40Y0x0EwIxGrwCI42IY6xIIjxv20xvE14v26r1I6r4UMIIF 0xvE2Ix0cI8IcVCY1x0267AKxVWUJVW8JwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIx AIcVC2z280aVAFwI0_Gr0_Cr1lIxAIcVC2z280aVCY1x0267AKxVW8JVW8JrUvcSsGvfC2 KfnxnUUI43ZEXa7IU8g6pPUUUUU== X-Spam-Status: No, score=-13.3 required=5.0 tests=BAYES_00,GIT_PATCH_0,KAM_DMARC_STATUS,SPF_HELO_NONE,SPF_PASS,TXREP,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: --- bfd/elfnn-loongarch.c | 168 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 146 insertions(+), 22 deletions(-) diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c index 024c5d4cd96..b63f42bb6a7 100644 --- a/bfd/elfnn-loongarch.c +++ b/bfd/elfnn-loongarch.c @@ -48,6 +48,12 @@ struct loongarch_elf_link_hash_entry #define GOT_TLS_GD 2 #define GOT_TLS_IE 4 #define GOT_TLS_LE 8 +#define GOT_TLS_GDESC 16 + +#define GOT_TLS_GD_BOTH_P(tls_type) \ + ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_GDESC)) +#define GOT_TLS_GD_ANY_P(tls_type) \ + ((tls_type & GOT_TLS_GD) || (tls_type & GOT_TLS_GDESC)) char tls_type; }; @@ -563,6 +569,7 @@ loongarch_elf_record_tls_and_got_reference (bfd *abfd, case GOT_NORMAL: case GOT_TLS_GD: case GOT_TLS_IE: + case GOT_TLS_GDESC: /* Need GOT. */ if (htab->elf.sgot == NULL && !loongarch_elf_create_got_section (htab->elf.dynobj, info)) @@ -750,6 +757,14 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, return false; break; + case R_LARCH_TLS_DESC_PC_HI20: + case R_LARCH_TLS_DESC_HI20: + if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h, + r_symndx, + GOT_TLS_GDESC)) + return false; + break; + case R_LARCH_ABS_HI20: case R_LARCH_SOP_PUSH_ABSOLUTE: if (h != NULL) @@ -1129,7 +1144,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) s = htab->elf.sgot; h->got.offset = s->size; - if (tls_type & (GOT_TLS_GD | GOT_TLS_IE)) + if (tls_type & (GOT_TLS_GD | GOT_TLS_IE | GOT_TLS_GDESC)) { /* TLS_GD needs two dynamic relocs and two GOT slots. */ if (tls_type & GOT_TLS_GD) @@ -1166,7 +1181,15 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) htab->elf.srelgot->size += sizeof (ElfNN_External_Rela); } } + + /* TLS_DESC needs one dynamic reloc and two GOT slot. */ + if (tls_type & GOT_TLS_GDESC) + { + s->size += GOT_ENTRY_SIZE * 2; + htab->elf.srelgot->size += sizeof (ElfNN_External_Rela); + } } + else { s->size += GOT_ENTRY_SIZE; @@ -1669,19 +1692,34 @@ loongarch_elf_size_dynamic_sections (bfd *output_bfd, if (0 < *local_got) { *local_got = s->size; + if (*local_tls_type & (GOT_TLS_GD | GOT_TLS_IE | GOT_TLS_GDESC)) + { + /* TLS gd use two got. */ + if (*local_tls_type & GOT_TLS_GD) + { + s->size += 2 * GOT_ENTRY_SIZE; + if (!bfd_link_executable (info)) + srel->size += sizeof (ElfNN_External_Rela); + } - /* TLS gd use two got. */ - if (*local_tls_type & GOT_TLS_GD) - s->size += GOT_ENTRY_SIZE * 2; - else - /* Normal got, tls ie/ld use one got. */ - s->size += GOT_ENTRY_SIZE; + /* TLS_DESC use two got. */ + if (*local_tls_type & GOT_TLS_GDESC) + { + s->size += 2 * GOT_ENTRY_SIZE; + srel->size += sizeof (ElfNN_External_Rela); + } - if (bfd_link_executable (info) - && (*local_tls_type & (GOT_TLS_GD| GOT_TLS_IE))) - ;/* Do nothing. */ + /* TLS ie and use one got. */ + if (*local_tls_type & GOT_TLS_IE) + { + s->size += GOT_ENTRY_SIZE; + if (!bfd_link_executable (info)) + srel->size += sizeof (ElfNN_External_Rela); + } + } else { + s->size += GOT_ENTRY_SIZE; srel->size += sizeof (ElfNN_External_Rela); } } @@ -2120,6 +2158,15 @@ perform_relocation (const Elf_Internal_Rela *rel, asection *input_section, case R_LARCH_TLS_GD_PC_HI20: case R_LARCH_TLS_GD_HI20: case R_LARCH_PCREL20_S2: + case R_LARCH_TLS_DESC_PC_HI20: + case R_LARCH_TLS_DESC_ADD_PC_LO12: + case R_LARCH_TLS_DESC64_PC_LO20: + case R_LARCH_TLS_DESC64_PC_HI12: + case R_LARCH_TLS_DESC_HI20: + case R_LARCH_TLS_DESC_LO12: + case R_LARCH_TLS_DESC64_LO20: + case R_LARCH_TLS_DESC64_HI12: + r = loongarch_check_offset (rel, input_section); if (r != bfd_reloc_ok) break; @@ -2129,6 +2176,11 @@ perform_relocation (const Elf_Internal_Rela *rel, asection *input_section, contents, value); break; + case R_LARCH_TLS_DESC_LD: + case R_LARCH_TLS_DESC_CALL: + r = bfd_reloc_ok; + break; + case R_LARCH_RELAX: break; @@ -2377,10 +2429,10 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, struct elf_link_hash_entry *h = NULL; const char *name; bfd_reloc_status_type r = bfd_reloc_ok; - bool is_ie, is_undefweak, unresolved_reloc, defined_local; + bool is_ie, is_desc, is_undefweak, unresolved_reloc, defined_local; bool resolved_local, resolved_dynly, resolved_to_const; char tls_type; - bfd_vma relocation, off, ie_off; + bfd_vma relocation, off, ie_off, desc_off; int i, j; howto = loongarch_elf_rtype_to_howto (input_bfd, r_type); @@ -2509,6 +2561,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, BFD_ASSERT (!resolved_local || defined_local); + is_desc = false; is_ie = false; switch (r_type) { @@ -3398,6 +3451,8 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, case R_LARCH_TLS_LD_HI20: case R_LARCH_TLS_GD_PC_HI20: case R_LARCH_TLS_GD_HI20: + case R_LARCH_TLS_DESC_PC_HI20: + case R_LARCH_TLS_DESC_HI20: BFD_ASSERT (rel->r_addend == 0); unresolved_reloc = false; @@ -3405,6 +3460,10 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, || r_type == R_LARCH_TLS_IE_HI20) is_ie = true; + if (r_type == R_LARCH_TLS_DESC_PC_HI20 + || r_type == R_LARCH_TLS_DESC_HI20) + is_desc = true; + bfd_vma got_off = 0; if (h != NULL) { @@ -3419,9 +3478,19 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, BFD_ASSERT (got_off != MINUS_ONE); - ie_off = 0; tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx); - if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_IE)) + + /* 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; if ((got_off & 1) == 0) @@ -3470,6 +3539,21 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, loongarch_elf_append_rela (output_bfd, relgot, &rela); } } + 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; + rela.r_offset = sec_addr (got) + got_off + desc_off; + rela.r_addend = 0; + if (indx == 0) + rela.r_addend = relocation - elf_hash_table (info)->tls_sec->vma; + + rela.r_info = ELFNN_R_INFO (indx, R_LARCH_TLS_DESCNN); + loongarch_elf_append_rela (output_bfd, relgot, &rela); + bfd_put_NN (output_bfd, 0, + got->contents + got_off + desc_off); + } if (tls_type & GOT_TLS_IE) { rela.r_offset = sec_addr (got) + got_off + ie_off; @@ -3497,16 +3581,52 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, } } } - relocation = (got_off & (~(bfd_vma)1)) + sec_addr (got) - + (is_ie ? ie_off : 0); + relocation = (got_off & (~(bfd_vma)1)) + sec_addr (got); + if (is_desc) + relocation += desc_off; + else if (is_ie) + relocation += ie_off; if (r_type == R_LARCH_TLS_LD_PC_HI20 || r_type == R_LARCH_TLS_GD_PC_HI20 - || r_type == R_LARCH_TLS_IE_PC_HI20) + || r_type == R_LARCH_TLS_IE_PC_HI20 + || r_type == R_LARCH_TLS_DESC_PC_HI20) RELOCATE_CALC_PC32_HI20 (relocation, pc); break; + case R_LARCH_TLS_DESC_ADD_PC_LO12: + case R_LARCH_TLS_DESC64_PC_LO20: + case R_LARCH_TLS_DESC64_PC_HI12: + case R_LARCH_TLS_DESC_LO12: + case R_LARCH_TLS_DESC64_LO20: + case R_LARCH_TLS_DESC64_HI12: + { + unresolved_reloc = false; + + if (h) + relocation = sec_addr (got) + (h->got.offset & (~(bfd_vma)1)); + else + relocation = sec_addr (got) + + (local_got_offsets[r_symndx] & (~(bfd_vma)1)); + + 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)) + relocation += 2 * GOT_ENTRY_SIZE; + } + + if (r_type == R_LARCH_TLS_DESC64_PC_LO20 + || r_type == R_LARCH_TLS_DESC64_PC_HI12) + RELOCATE_CALC_PC64_HI32 (relocation, pc); + + break; + + case R_LARCH_TLS_DESC_LD: + case R_LARCH_TLS_DESC_CALL: + unresolved_reloc = false; + break; + case R_LARCH_TLS_IE_PC_LO12: case R_LARCH_TLS_IE64_PC_LO20: case R_LARCH_TLS_IE64_PC_HI12: @@ -3516,14 +3636,17 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, unresolved_reloc = false; if (h) - relocation = sec_addr (got) + (h->got.offset & (~(bfd_vma)3)); + relocation = sec_addr (got) + (h->got.offset & (~(bfd_vma)1)); else relocation = sec_addr (got) - + (local_got_offsets[r_symndx] & (~(bfd_vma)3)); + + (local_got_offsets[r_symndx] & (~(bfd_vma)1)); tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx); - /* Use both TLS_GD and TLS_IE. */ - if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_IE)) + /* Use TLS_GD TLS_DESC and TLS_IE. */ + if (GOT_TLS_GD_BOTH_P (tls_type) && (tls_type & GOT_TLS_IE)) + relocation += 4 * GOT_ENTRY_SIZE; + /* Use GOT_TLS_GD_ANY_P (tls_type) and TLS_IE. */ + else if (GOT_TLS_GD_ANY_P (tls_type) && (tls_type & GOT_TLS_IE)) relocation += 2 * GOT_ENTRY_SIZE; if (r_type == R_LARCH_TLS_IE64_PC_LO20 @@ -4149,7 +4272,8 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd, if (h->got.offset != MINUS_ONE /* TLS got entry have been handled in elf_relocate_section. */ - && !(loongarch_elf_hash_entry (h)->tls_type & (GOT_TLS_GD | GOT_TLS_IE)) + && !(loongarch_elf_hash_entry (h)->tls_type + & (GOT_TLS_GD | GOT_TLS_IE | GOT_TLS_GDESC)) /* Have allocated got entry but not allocated rela before. */ && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)) { -- 2.36.0