From patchwork Fri Dec 15 10:11:24 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lulu Cai X-Patchwork-Id: 82216 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 696E838449F2 for ; Fri, 15 Dec 2023 10:12:14 +0000 (GMT) X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by sourceware.org (Postfix) with ESMTP id 370CE38618F3 for ; Fri, 15 Dec 2023 10:11:50 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 370CE38618F3 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 370CE38618F3 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=1702635114; cv=none; b=SncGHRUXYoIplsgajXoz6jJzNH6pF1dINK04MAD7Fofmz5GqNE5yuEDLPgoSPir4ni38K2+bM/5ZBZ6zd5iyKbyZYVLbY3gEtAkSQ2JMlkLYDgY2UeppMgLzy1cvez4fx4UwtM9s8LwwQ0prTOaEfw7O5/RSbAeamFDt//MmvFY= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1702635114; c=relaxed/simple; bh=WCHNalZMsnTPrIU7NmLuOZ/k7RBPt/jsC3bYh7Iwuto=; h=From:To:Subject:Date:Message-Id:MIME-Version; b=RGHEZOQQUPCELMgP02ukze5K+2oCfUakUPsU7n6mxvlWR1PQ/OETXWf/tkEDTAI5AZkwvTpYSTVeOKPbRIhhOKjlHeORSM5wUWy/jBlvW2OSooPSplfJC9p2nrAhhnz/p1zJ0GbyLXaWkdOA97y1S9pMvpQDk/MZDggKffjZbAA= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from loongson.cn (unknown [10.2.6.5]) by gateway (Coremail) with SMTP id _____8CxRPBkJnxlvVABAA--.7368S3; Fri, 15 Dec 2023 18:11:48 +0800 (CST) Received: from 5.5.5 (unknown [10.2.6.5]) by localhost.localdomain (Coremail) with SMTP id AQAAf8CxOXNdJnxlNGAFAA--.12847S6; Fri, 15 Dec 2023 18:11:48 +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 v4 2/5] LoongArch: Add support for TLSDESC in ld. Date: Fri, 15 Dec 2023 18:11:24 +0800 Message-Id: <20231215101127.2536311-3-cailulu@loongson.cn> X-Mailer: git-send-email 2.39.3 In-Reply-To: <20231215101127.2536311-1-cailulu@loongson.cn> References: <20231215101127.2536311-1-cailulu@loongson.cn> MIME-Version: 1.0 X-CM-TRANSID: AQAAf8CxOXNdJnxlNGAFAA--.12847S6 X-CM-SenderInfo: xfdlz3tox6z05rqj20fqof0/1tbiAQAGB2V7t60H8wAAsw X-Coremail-Antispam: 1Uk129KBj93XoW3KFW5tF17tFWrXr48XF45XFc_yoWDXrW5pr ZxAr4UKw48urW7W34aq3WrZa1Fg3y8ury2qr9xt3909Fn3Xr95WF47Xr15ZFW5KF4qyw42 v3sY93W8Za48A3XCm3ZEXasCq-sJn29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7KY7ZEXa sCq-sGcSsGvfJ3Ic02F40EFcxC0VAKzVAqx4xG6I80ebIjqfuFe4nvWSU5nxnvy29KBjDU 0xBIdaVrnRJUUUk2b4IE77IF4wAFF20E14v26r1j6r4UM7CY07I20VC2zVCF04k26cxKx2 IYs7xG6rWj6s0DM7CIcVAFz4kK6r1Y6r17M28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48v e4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_Xr0_Ar1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI 0_Gr0_Cr1l84ACjcxK6I8E87Iv67AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVCY1x0267AK xVW8Jr0_Cr1UM2AIxVAIcxkEcVAq07x20xvEncxIr21l57IF6xkI12xvs2x26I8E6xACxx 1l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6xIIjxv20xvE14v26r1q6rW5McIj6I8E87Iv 67AKxVW8JVWxJwAm72CE4IkC6x0Yz7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr41l42xK82IYc2 Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s02 6x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26r1q6r43MIIYrxkI7VAKI48JMIIF0x vE2Ix0cI8IcVAFwI0_Gr0_Xr1lIxAIcVC0I7IYx2IY6xkF7I0E14v26r4j6F4UMIIF0xvE 42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVW8JVWxJwCI42IY6I8E87Iv6x kF7I0E14v26r4j6r4UJbIYCTnIWIevJa73UjIFyTuYvjxUcCD7UUUUU X-Spam-Status: No, score=-13.2 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 X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: binutils-bounces+patchwork=sourceware.org@sourceware.org --- 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)) {