From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pg1-x532.google.com (mail-pg1-x532.google.com [IPv6:2607:f8b0:4864:20::532]) by sourceware.org (Postfix) with ESMTPS id DD6E2385840D for ; Tue, 20 Feb 2024 17:56:46 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org DD6E2385840D 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 DD6E2385840D Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::532 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1708451809; cv=none; b=uQfZEQPg5p9slOTKAJd4674lQdJ5NF54R4zM4zu0WtYcjFhcvxEtrmTzSbJ+q8ZXUOm8uRYvAIhQB1up0DvbtYrTb1yrKA4LJNPDfs7V9WUGe93YrQrMbWUDVZY3mU+UsJXBVVSbiPMmPSC3ImG9z7m/CA4N2jEls1u6UHK0ya4= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1708451809; c=relaxed/simple; bh=VCwv3Ja9QBAkvrxo5Uw92mo0i5HSgnHaOwttCVpc+Bg=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=f3dXNdlUJ6c2SdD6eM7RPiIn4yhYpFX7MIuMNayiiihW2IWYWfXjY60hluy5O4DQfzUBr634hCFGmNzm0A+9XrXqvnrXVKWPIKirpraXrGwN2b+w+zLKmzDEDlTHojeK0pSK0jHAyDWQZUtq2Jtbw2h5nh2IPdqEaJTV4igJmSQ= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pg1-x532.google.com with SMTP id 41be03b00d2f7-55b5a37acb6so1702827a12.0 for ; Tue, 20 Feb 2024 09:56:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1708451805; x=1709056605; 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=+Ln9UYSSJWhdsfTwpxR6EQ7IGvtB7+h0kd4YhBcUoZM=; b=coBoFvc0yW30MsaKqSbOVoEyPaBKhsXGmPOSZMkLgYM17ctcDRTn0fpP7xiA59Wwxr vic2e+lUqbHAROJHVfrzeBBAPLcck6vIpY5ghV8v1T56g2kynavg0pkVLgM6tU3BcBy6 lGQUD1ktGAXxC59P71DUFKeluRVp1QYJFkLjHD96tlp5m6zfXu9u5edA6dQAbvk/o0Jr ozf1Jvytgv34svafUZLjoYlWf/g9lVJ6jaQtueMZqni89ZFCzulQ7zaxKZXZUaPxhBRp EjoHCz1RuicKTrPYhc9gQUf4DRoTczdJOOt4qXLwP9nHIeVf/KFFFEa063A6bB2FsE5j CqiA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1708451805; x=1709056605; 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=+Ln9UYSSJWhdsfTwpxR6EQ7IGvtB7+h0kd4YhBcUoZM=; b=ddn7abooiQ85tjsrUAWu+CT/buHGbxsx5uQR4iSX6MgmBQFt81OWULFAl7wCmpb6Or G3q5+tdYx+VUNBiu+2w0n/ALT4stnmnWNOHhRzI1GFlNwKmTOI54qQmLqYVyM6/IfFxo 2DZviZ+i5NNIuMx7S7rvCKWzrzDMe4QLUdk6p7TLRqei6ysxQFt2pnIryh+UJ75aTbl3 3KZ+YBhtD+Dn0S9Ro5e5fp54MFsfgtTKCMLr71TW5k5/SPk4OoK5hDtslclrX+3fpi2y FMNgmyzYaCzokKifqvetqvD6/NIkTjfRn6bpB/MsQwXAjewNBwpsYiTOoVU5eFrc1fpI o1Bw== X-Gm-Message-State: AOJu0YxUE0+cCxp5M6clhGwCkhVekh7hTbERBLngVyWgCzbglW0o5n/g GojNUXsFHY7oaWzQWUImqDea47H/rgwMctT6SXOFWUPihZofi5iS3dVqi01J6zc4vw== X-Google-Smtp-Source: AGHT+IEYDWun/19unMfE5E0KZg1PG3DsjaAtDuXffcb/4FmErIHl9M/0Au9l0oPpcsZJ15RTIvK62g== X-Received: by 2002:a05:6a21:999c:b0:1a0:9abd:2801 with SMTP id ve28-20020a056a21999c00b001a09abd2801mr10187689pzb.3.1708451805166; Tue, 20 Feb 2024 09:56:45 -0800 (PST) Received: from localhost (zz20184013906F627101.userreverse.dion.ne.jp. [111.98.113.1]) by smtp.gmail.com with ESMTPSA id fa7-20020a056a002d0700b006e489e6019esm137371pfb.39.2024.02.20.09.56.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 Feb 2024 09:56:44 -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 v4 9/9] RISC-V: Introduce TLSDESC relaxation. Date: Wed, 21 Feb 2024 02:55:56 +0900 Message-ID: <20240220175556.304692-10-ishitatsuyuki@gmail.com> X-Mailer: git-send-email 2.43.2 In-Reply-To: <20240220175556.304692-1-ishitatsuyuki@gmail.com> References: <20230817180852.121628-2-ishitatsuyuki@gmail.com> <20240220175556.304692-1-ishitatsuyuki@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-10.6 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. --- v4: Remove addend from lo-hi calculation since it's required to be 0. bfd/elfnn-riscv.c | 144 ++++++++++++++++++++++++++++- 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, 207 insertions(+), 14 deletions(-) diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c index acc45ebb549..43db8f1b5c0 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)) @@ -1816,6 +1826,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)); @@ -1828,6 +1840,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; @@ -2834,6 +2848,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: { @@ -4878,6 +4921,95 @@ _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: { + bfd_vma hi_sec_off = symval - sec_addr (sym_sec); + 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. */ @@ -5182,6 +5314,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 a4aa71fd809..86f1538f69a 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 c1e73f7f5c0..a99038d42d5 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 adea7dbc794..6e359d11388 100644 --- a/include/opcode/riscv.h +++ b/include/opcode/riscv.h @@ -355,6 +355,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.2