From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pl1-x636.google.com (mail-pl1-x636.google.com [IPv6:2607:f8b0:4864:20::636]) by sourceware.org (Postfix) with ESMTPS id F1C6B386547E for ; Tue, 28 Nov 2023 08:51:52 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org F1C6B386547E Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org F1C6B386547E Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::636 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701161515; cv=none; b=O/t9LA9OAj6RqyDRvbit+BgeC22ZB16MSeDOcAPFBg7tYd07772FP7WqrKRuefwKLpl4rKbu1DhiQ7gI88F6UHL0tUyhCLMDF+y65VkQhOcFnJ5RgXHN0PLXzsA3Ltgh4BV5TG+FwqnYgR8+cgKHwsj5ZcgFZtQLdTCkT7C7e1g= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701161515; c=relaxed/simple; bh=wmRM4ZrkOeGbEevkEcrz7ad9P/O3jsT9c8ja8dNIuc8=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=ufovoLfi+aqXarMOc0qM6iHx7QSgzQ0MoDcLqCDV+bySQCId3OaVZARLgK09Q4zv7gH9Lrd42OqNGAyC6WvPT+t+7aHjJVM9k76cNwUqyIpSq5x2tphrjEiyVycuhaWweWHfFIrJWSelhS+B7rSZi/h4+pLlWjiPV2f34x708Kk= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pl1-x636.google.com with SMTP id d9443c01a7336-1cfa3fe1701so10010035ad.0 for ; Tue, 28 Nov 2023 00:51:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1701161511; x=1701766311; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=d0Mta4aPG4ZJZduq6nbKN5UcUtZxuvX02vjtfu8LklI=; b=RCpzHIUDkpWqj4EnA3TbhkgxW0ftpj3JkPcqveN1lK/GLd708NczyYKlBrALFGo8/u OP759NgXnLeRK2beDn3m3b8guS2RpLcBkgaJPR348rsMwsDbmorAIOwV9iQMiGgNHajT 2Wyb+tk8bC9QF12x9qJ5w+IoF7BPL+JbKzKeWgDtimxj61NYvYKTwOhEEhEWjbMrU5S2 Vux0joOD0F9s394WYzfb58U28BYm8xVteO8TQ/NNZstIWBVPXJ5F0lz2lbFGcIq/TtEq 7thFIi4goJ8rL0R3YMfMwwBoD8Fj8Sk94Bkb8uQOFgCbbOqwuLCibZOF0dWKhuBV1y9F rhEA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701161511; x=1701766311; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=d0Mta4aPG4ZJZduq6nbKN5UcUtZxuvX02vjtfu8LklI=; b=oG/O3F/j9J0CcJHjTWwKB9Axmu/yVVnHKFoMg+O8Ok2aiHZ+tAgi4T/pvxsCl0/WkV H4BKVOAFTk5Mt/tNyJeC0PT9jClY2FVLYbOjo0mlW3bPS0EB+7sBmX0HhODWlg7EwjJr 5uUH/C/hV77BBl+lxuNTepd7OiNPv6T7+XCT9X2fz7BMOJowntQE41t8gSCzzlEro+tT Vym803Q8Knxarz1SKiVUOIg6SL2jf3X0ZFA1Be2RelxtI/JsXdu04x3DdSJ6sJb+8uLz UHv0/SjRwZoyrdRrq3iuaDEXKTCDoZBgxOQZSDbxUStgpJH942H5S97dYAId7xXXqwaA dEtg== X-Gm-Message-State: AOJu0Yw421Jw6jUuTR/U1bmsqlip6AdofibDnrS5YYOi1Dfxeezd4tzF ldMm7Xih2LFh+jrw7rJpRUg6ZlgpsLDFFDB8 X-Google-Smtp-Source: AGHT+IETRoUS1mvDSRwunaack/Hc6pMUIRFSNFSeiM1UYeF9QS2/ZITuE+SPG8rNr9+UxZMQpmt1ag== X-Received: by 2002:a05:6a20:728c:b0:18c:19ac:d771 with SMTP id o12-20020a056a20728c00b0018c19acd771mr16221481pzk.4.1701161510995; Tue, 28 Nov 2023 00:51:50 -0800 (PST) Received: from localhost (zz20184013906F627101.userreverse.dion.ne.jp. [111.98.113.1]) by smtp.gmail.com with ESMTPSA id g23-20020a1709029f9700b001cfad034756sm6871221plq.138.2023.11.28.00.51.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 28 Nov 2023 00:51:50 -0800 (PST) From: Tatsuyuki Ishi To: binutils@sourceware.org Cc: i@maskray.me, nelson@rivosinc.com, rui314@gmail.com, ruiu@bluewhale.systems, Tatsuyuki Ishi Subject: [PATCH v3 9/9] RISC-V: Introduce TLSDESC relaxation. Date: Tue, 28 Nov 2023 17:51:09 +0900 Message-ID: <20231128085109.28422-10-ishitatsuyuki@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231128085109.28422-1-ishitatsuyuki@gmail.com> References: <20230817180852.121628-2-ishitatsuyuki@gmail.com> <20231128085109.28422-1-ishitatsuyuki@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-10.4 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,GIT_PATCH_0,KAM_STOCKGEN,RCVD_IN_DNSWL_NONE,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: For now, only the 2 instruction (long) forms. This allows static binaries to correctly execute when TLSDESC is used. bfd/ * elfnn-riscv.c (riscv_elf_tls_type_from_hi_reloc): Decide TLS type based on relaxation eligibility as well. (riscv_elf_check_relocs): Pass the required eligibility information to riscv_elf_tls_type_from_hi_reloc. (perform_relocation): Handle encoding for TLSDESC relaxation relocations. (riscv_elf_relocate_section): Emit relaxation instruction sequence. (_bfd_riscv_relax_tlsdesc): Added for handling of relaxable TLSDESC relocs. (_bfd_riscv_relax_section): Call _bfd_riscv_relax_tlsdesc when eligible. * elfxx-riscv.c (howto_table_internal): Add internal relocations for TLSDESC -> LE / IE relaxation. include/ elf/riscv.h: Add internal relocations, same as above. opcode/riscv.h: Add X_A0 for use in TLSDESC relaxation sequence. ld/ * testsuite/ld-riscv-elf/tlsbin.d: Remove TLSDESC relocs from expectation to now that we have relaxation. --- bfd/elfnn-riscv.c | 146 ++++++++++++++++++++++++++++- bfd/elfxx-riscv.c | 55 +++++++++++ include/elf/riscv.h | 16 ++-- include/opcode/riscv.h | 1 + ld/testsuite/ld-riscv-elf/tlsbin.d | 5 - 5 files changed, 209 insertions(+), 14 deletions(-) diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c index b98264319d8..61bfa763799 100644 --- a/bfd/elfnn-riscv.c +++ b/bfd/elfnn-riscv.c @@ -663,8 +663,12 @@ riscv_elf_copy_indirect_symbol (struct bfd_link_info *info, } static char -riscv_elf_tls_type_from_hi_reloc (unsigned int r_type) +riscv_elf_tls_type_from_hi_reloc (struct bfd_link_info *info, + unsigned int r_type, + struct elf_link_hash_entry *h, + bool can_relax) { + bool local_exec = SYMBOL_REFERENCES_LOCAL (info, h); switch (r_type) { case R_RISCV_TLS_GD_HI20: @@ -672,7 +676,10 @@ riscv_elf_tls_type_from_hi_reloc (unsigned int r_type) case R_RISCV_TLS_GOT_HI20: return GOT_TLS_IE; case R_RISCV_TLSDESC_HI20: - return GOT_TLSDESC; + if (!can_relax || !bfd_link_executable (info)) + return GOT_TLSDESC; + else + return local_exec ? GOT_TLS_LE : GOT_TLS_IE; case R_RISCV_TPREL_HI20: return GOT_TLS_LE; default: @@ -866,7 +873,10 @@ riscv_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_RISCV_TLSDESC_HI20: case R_RISCV_TPREL_HI20: { - char tls_type = riscv_elf_tls_type_from_hi_reloc (r_type); + bool can_relax = rel != relocs + sec->reloc_count - 1 + && ELFNN_R_TYPE ((rel + 1)->r_info) == R_RISCV_RELAX + && rel->r_offset == (rel + 1)->r_offset; + char tls_type = riscv_elf_tls_type_from_hi_reloc (info, r_type, h, can_relax); /* Local exec is only allowed for executables. */ if (tls_type == GOT_TLS_LE && !bfd_link_executable (info)) @@ -1826,6 +1836,8 @@ perform_relocation (const reloc_howto_type *howto, case R_RISCV_TLS_GOT_HI20: case R_RISCV_TLS_GD_HI20: case R_RISCV_TLSDESC_HI20: + case R_RISCV_TLSDESC_LE_HI: + case R_RISCV_TLSDESC_IE_HI: if (ARCH_SIZE > 32 && !VALID_UTYPE_IMM (RISCV_CONST_HIGH_PART (value))) return bfd_reloc_overflow; value = ENCODE_UTYPE_IMM (RISCV_CONST_HIGH_PART (value)); @@ -1838,6 +1850,8 @@ perform_relocation (const reloc_howto_type *howto, case R_RISCV_PCREL_LO12_I: case R_RISCV_TLSDESC_LOAD_LO12: case R_RISCV_TLSDESC_ADD_LO12: + case R_RISCV_TLSDESC_LE_LO: + case R_RISCV_TLSDESC_IE_LO: value = ENCODE_ITYPE_IMM (value); break; @@ -2818,6 +2832,35 @@ riscv_elf_relocate_section (bfd *output_bfd, r = bfd_reloc_overflow; break; + case R_RISCV_TLSDESC_IE_HI: + { + bfd_vma insn = MATCH_AUIPC | (X_A0 << OP_SH_RD); + relocation = dtpoff (info, relocation); + bfd_putl32 (insn, contents + rel->r_offset); + break; + } + case R_RISCV_TLSDESC_IE_LO: + { + bfd_vma insn = MATCH_LREG | (X_A0 << OP_SH_RD) | (X_A0 << OP_SH_RS1); + relocation = dtpoff (info, relocation); + bfd_putl32 (insn, contents + rel->r_offset); + break; + } + case R_RISCV_TLSDESC_LE_HI: + { + bfd_vma insn = MATCH_LUI | (X_A0 << OP_SH_RD); + relocation = tpoff (info, relocation); + bfd_putl32 (insn, contents + rel->r_offset); + break; + } + case R_RISCV_TLSDESC_LE_LO: + { + bfd_vma insn = MATCH_ADDI | (X_A0 << OP_SH_RD) | (X_A0 << OP_SH_RS1); + relocation = tpoff (info, relocation); + bfd_putl32 (insn, contents + rel->r_offset); + break; + } + case R_RISCV_GPREL_I: case R_RISCV_GPREL_S: { @@ -4855,6 +4898,97 @@ _bfd_riscv_relax_tls_le (bfd *abfd, } } +/* Relax TLSDESC (global-dynamic) references to TLS IE or LE references. */ + +static bool +_bfd_riscv_relax_tlsdesc (bfd *abfd, + asection *sec, + asection *sym_sec, + struct bfd_link_info *link_info, + struct elf_link_hash_entry *h, + Elf_Internal_Rela *rel, + bfd_vma symval, + bfd_vma max_alignment ATTRIBUTE_UNUSED, + bfd_vma reserve_size ATTRIBUTE_UNUSED, + bool *again, + riscv_pcgp_relocs *pcgp_relocs, + bool undefined_weak) +{ + BFD_ASSERT (rel->r_offset + 4 <= sec->size); + BFD_ASSERT (bfd_link_executable (link_info)); + riscv_pcgp_hi_reloc *hi = NULL; + bool local_exec; + unsigned sym; + + /* Chain the _LO relocs to their corresponding _HI reloc to compute the + actual target address. */ + switch (ELFNN_R_TYPE (rel->r_info)) { + case R_RISCV_TLSDESC_HI20: { + /* If the corresponding lo relocation has already been seen then it's not + safe to relax this relocation. */ + if (riscv_find_pcgp_lo_reloc (pcgp_relocs, rel->r_offset)) + return true; + riscv_record_pcgp_hi_reloc (pcgp_relocs, + rel->r_offset, + rel->r_addend, + symval, + ELFNN_R_SYM (rel->r_info), + sym_sec, + h, + undefined_weak); + sym = ELFNN_R_SYM (rel->r_info); + break; + } + + case R_RISCV_TLSDESC_LOAD_LO12: + case R_RISCV_TLSDESC_ADD_LO12: + case R_RISCV_TLSDESC_CALL: { + /* _LO addends are not allowed in the psABI, but handle them similarly to + PC_LO for now. */ + bfd_vma hi_sec_off = symval - sec_addr (sym_sec) - rel->r_addend; + hi = riscv_find_pcgp_hi_reloc (pcgp_relocs, hi_sec_off); + if (hi == NULL) { + riscv_record_pcgp_lo_reloc (pcgp_relocs, hi_sec_off); + return true; + } + sym = hi->hi_sym; + symval = hi->hi_addr; + sym_sec = hi->sym_sec; + h = hi->h; + break; + } + default: + abort (); + } + + local_exec = SYMBOL_REFERENCES_LOCAL (link_info, h); + + switch (ELFNN_R_TYPE (rel->r_info)) { + case R_RISCV_TLSDESC_HI20: + *again = true; + riscv_relax_delete_bytes (abfd, sec, rel->r_offset, 4, link_info, + pcgp_relocs, rel); + break; + case R_RISCV_TLSDESC_LOAD_LO12: + riscv_relax_delete_bytes (abfd, sec, rel->r_offset, 4, link_info, + pcgp_relocs, rel); + break; + case R_RISCV_TLSDESC_ADD_LO12: + rel->r_info = ELFNN_R_INFO (sym, local_exec ? R_RISCV_TLSDESC_LE_HI : R_RISCV_TLSDESC_IE_HI); + rel->r_addend += hi->hi_addend; + break; + case R_RISCV_TLSDESC_CALL: + rel->r_info = ELFNN_R_INFO (sym, local_exec ? R_RISCV_TLSDESC_LE_LO : R_RISCV_TLSDESC_IE_LO); + rel->r_addend += hi->hi_addend; + break; + default: + abort (); + } + + return true; +} + + /* Implement R_RISCV_ALIGN by deleting excess alignment NOPs. Once we've handled an R_RISCV_ALIGN, we can't relax anything else. */ @@ -5159,6 +5293,12 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec, || type == R_RISCV_TPREL_LO12_I || type == R_RISCV_TPREL_LO12_S) relax_func = _bfd_riscv_relax_tls_le; + else if (bfd_link_executable (info) + && (type == R_RISCV_TLSDESC_HI20 + || type == R_RISCV_TLSDESC_LOAD_LO12 + || type == R_RISCV_TLSDESC_ADD_LO12 + || type == R_RISCV_TLSDESC_CALL)) + relax_func = _bfd_riscv_relax_tlsdesc; else if (!bfd_link_pic (info) && (type == R_RISCV_PCREL_HI20 || type == R_RISCV_PCREL_LO12_I diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c index 65d676b06b1..dbca69a89d1 100644 --- a/bfd/elfxx-riscv.c +++ b/bfd/elfxx-riscv.c @@ -958,6 +958,61 @@ static reloc_howto_type howto_table_internal[] = 0, /* src_mask */ ENCODE_STYPE_IMM (-1U), /* dst_mask */ false), /* pcrel_offset */ + + /* TLSDESC relaxed to Initial Exec. */ + HOWTO (R_RISCV_TLSDESC_IE_HI, /* type */ + 0, /* rightshift */ + 4, /* size */ + 32, /* bitsize */ + true, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_RISCV_TLSDESC_IE_HI", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + ENCODE_UTYPE_IMM (-1U), /* dst_mask */ + false), /* pcrel_offset */ + HOWTO (R_RISCV_TLSDESC_IE_LO, /* type */ + 0, /* rightshift */ + 4, /* size */ + 32, /* bitsize */ + true, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_RISCV_TLSDESC_IE_LO", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + ENCODE_ITYPE_IMM (-1U), /* dst_mask */ + false), /* pcrel_offset */ + /* TLSDESC relaxed to Local Exec. */ + HOWTO (R_RISCV_TLSDESC_LE_HI, /* type */ + 0, /* rightshift */ + 4, /* size */ + 32, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_RISCV_TLSDESC_LE_HI", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + ENCODE_UTYPE_IMM (-1U), /* dst_mask */ + false), /* pcrel_offset */ + HOWTO (R_RISCV_TLSDESC_LE_LO, /* type */ + 0, /* rightshift */ + 4, /* size */ + 32, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_RISCV_TLSDESC_LE_LO", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + ENCODE_ITYPE_IMM (-1U), /* dst_mask */ + false), /* pcrel_offset */ }; /* A mapping from BFD reloc types to RISC-V ELF reloc types. */ diff --git a/include/elf/riscv.h b/include/elf/riscv.h index 7f5c0407ac8..903c7645d68 100644 --- a/include/elf/riscv.h +++ b/include/elf/riscv.h @@ -98,12 +98,16 @@ START_RELOC_NUMBERS (elf_riscv_reloc_type) END_RELOC_NUMBERS (R_RISCV_max) /* Internal relocations used exclusively by the relaxation pass. */ -#define R_RISCV_DELETE (R_RISCV_max) -#define R_RISCV_RVC_LUI (R_RISCV_max + 1) -#define R_RISCV_GPREL_I (R_RISCV_max + 2) -#define R_RISCV_GPREL_S (R_RISCV_max + 3) -#define R_RISCV_TPREL_I (R_RISCV_max + 4) -#define R_RISCV_TPREL_S (R_RISCV_max + 5) +#define R_RISCV_DELETE (R_RISCV_max) +#define R_RISCV_RVC_LUI (R_RISCV_max + 1) +#define R_RISCV_GPREL_I (R_RISCV_max + 2) +#define R_RISCV_GPREL_S (R_RISCV_max + 3) +#define R_RISCV_TPREL_I (R_RISCV_max + 4) +#define R_RISCV_TPREL_S (R_RISCV_max + 5) +#define R_RISCV_TLSDESC_IE_HI (R_RISCV_max + 6) +#define R_RISCV_TLSDESC_IE_LO (R_RISCV_max + 7) +#define R_RISCV_TLSDESC_LE_HI (R_RISCV_max + 8) +#define R_RISCV_TLSDESC_LE_LO (R_RISCV_max + 9) /* Processor specific flags for the ELF header e_flags field. */ diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h index 25486869606..e60e1ba9502 100644 --- a/include/opcode/riscv.h +++ b/include/opcode/riscv.h @@ -340,6 +340,7 @@ static inline unsigned int riscv_insn_length (insn_t insn) #define X_T0 5 #define X_T1 6 #define X_T2 7 +#define X_A0 10 #define X_T3 28 #define NGPR 32 diff --git a/ld/testsuite/ld-riscv-elf/tlsbin.d b/ld/testsuite/ld-riscv-elf/tlsbin.d index 79b7ade405e..cdcd51a9199 100644 --- a/ld/testsuite/ld-riscv-elf/tlsbin.d +++ b/ld/testsuite/ld-riscv-elf/tlsbin.d @@ -2,11 +2,6 @@ #ld: -no-pie tmpdir/tlslib.so #readelf: -Wr -Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 2 entries: - +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend -[0-9a-f]+ +[0-9a-f]+ R_RISCV_TLSDESC +4 -[0-9a-f]+ +[0-9a-f]+ R_RISCV_TLSDESC +0 - Relocation section '.rela.plt' at offset 0x[0-9a-f]+ contains 1 entry: +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend [0-9a-f]+ +[0-9a-f]+ R_RISCV_JUMP_SLOT +[0-9a-f]+ __tls_get_addr \+ 0 -- 2.43.0