From: Tatsuyuki Ishi <ishitatsuyuki@gmail.com>
To: binutils@sourceware.org
Cc: i@maskray.me, nelson@rivosinc.com, rui314@gmail.com,
ruiu@bluewhale.systems, Tatsuyuki Ishi <ishitatsuyuki@gmail.com>
Subject: [PATCH v4 9/9] RISC-V: Introduce TLSDESC relaxation.
Date: Wed, 21 Feb 2024 02:55:56 +0900 [thread overview]
Message-ID: <20240220175556.304692-10-ishitatsuyuki@gmail.com> (raw)
In-Reply-To: <20240220175556.304692-1-ishitatsuyuki@gmail.com>
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
next prev parent reply other threads:[~2024-02-20 17:56 UTC|newest]
Thread overview: 52+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-08-17 18:08 [PATCH 0/4] RISC-V: Implement TLS Descriptors Tatsuyuki Ishi
2023-08-17 18:08 ` [PATCH 1/4] RISC-V: Add TLSDESC reloc definitions Tatsuyuki Ishi
2023-08-17 18:08 ` [PATCH 2/4] RISC-V: Add assembly support for TLSDESC Tatsuyuki Ishi
2023-08-17 18:08 ` [PATCH 3/4] RISC-V: Define and use GOT entry size constants for TLS Tatsuyuki Ishi
2023-08-17 18:08 ` [PATCH 4/4] RISC-V: Initial ld.bfd support for TLSDESC Tatsuyuki Ishi
2023-08-18 0:22 ` [PATCH 0/4] RISC-V: Implement TLS Descriptors Nelson Chu
2023-08-18 7:13 ` Fangrui Song
2023-08-31 17:13 ` [PATCH v2 0/5] " Tatsuyuki Ishi
2023-08-31 17:13 ` [PATCH v2 1/5] RISC-V: Fix local GOT and reloc size calculation for TLS Tatsuyuki Ishi
2024-02-21 0:49 ` Nelson Chu
2024-02-21 7:04 ` Nelson Chu
2023-08-31 17:13 ` [PATCH v2 2/5] RISC-V: Add TLSDESC reloc definitions Tatsuyuki Ishi
2023-08-31 17:13 ` [PATCH v2 3/5] RISC-V: Add assembly support for TLSDESC Tatsuyuki Ishi
2023-08-31 17:13 ` [PATCH v2 4/5] RISC-V: Define and use GOT entry size constants for TLS Tatsuyuki Ishi
2023-08-31 17:13 ` [PATCH v2 5/5] RISC-V: Initial ld.bfd support for TLSDESC Tatsuyuki Ishi
2023-11-28 8:51 ` [PATCH v3 0/9] RISC-V: Implement TLS Descriptors Tatsuyuki Ishi
2023-11-28 8:51 ` [PATCH v3 1/9] RISC-V: Fix local GOT and reloc size calculation for TLS Tatsuyuki Ishi
2023-11-28 8:51 ` [PATCH v3 2/9] RISC-V: Add TLSDESC reloc definitions Tatsuyuki Ishi
2024-02-19 0:49 ` Nelson Chu
2024-02-20 17:28 ` Tatsuyuki Ishi
2023-11-28 8:51 ` [PATCH v3 3/9] RISC-V: Add assembly support for TLSDESC Tatsuyuki Ishi
2024-02-19 1:44 ` Nelson Chu
2024-02-20 17:29 ` Tatsuyuki Ishi
2023-11-28 8:51 ` [PATCH v3 4/9] RISC-V: Define and use GOT entry size constants for TLS Tatsuyuki Ishi
2024-02-19 1:57 ` Nelson Chu
2024-02-20 17:32 ` Tatsuyuki Ishi
2023-11-28 8:51 ` [PATCH v3 5/9] RISC-V: Initial ld.bfd support for TLSDESC Tatsuyuki Ishi
2024-02-19 4:33 ` Nelson Chu
2024-02-20 17:36 ` Tatsuyuki Ishi
2023-11-28 8:51 ` [PATCH v3 6/9] RISC-V: Move STATIC_TLS handling into record_tls_type Tatsuyuki Ishi
2023-11-28 8:51 ` [PATCH v3 7/9] RISC-V: Unify TLS handling in check_relocs Tatsuyuki Ishi
2023-11-28 8:51 ` [PATCH v3 8/9] RISC-V: Add elf_link_hash_entry to relax_func args Tatsuyuki Ishi
2023-11-28 8:51 ` [PATCH v3 9/9] RISC-V: Introduce TLSDESC relaxation Tatsuyuki Ishi
2023-12-05 16:44 ` [PATCH v3 0/9] RISC-V: Implement TLS Descriptors Tatsuyuki Ishi
2023-12-06 0:33 ` Nelson Chu
2023-12-07 3:35 ` Fangrui Song
2023-12-13 0:27 ` Palmer Dabbelt
2023-12-13 1:53 ` Tatsuyuki Ishi
2024-01-27 0:57 ` Fangrui Song
2024-02-20 17:55 ` [PATCH v4 " Tatsuyuki Ishi
2024-02-20 17:55 ` [PATCH v4 1/9] RISC-V: Fix local GOT and reloc size calculation for TLS Tatsuyuki Ishi
2024-02-20 17:55 ` [PATCH v4 2/9] RISC-V: Add TLSDESC reloc definitions Tatsuyuki Ishi
2024-02-20 17:55 ` [PATCH v4 3/9] RISC-V: Add assembly support for TLSDESC Tatsuyuki Ishi
2024-02-20 17:55 ` [PATCH v4 4/9] RISC-V: Define and use GOT entry size constants for TLS Tatsuyuki Ishi
2024-02-20 17:55 ` [PATCH v4 5/9] RISC-V: Initial ld.bfd support for TLSDESC Tatsuyuki Ishi
2024-02-20 17:55 ` [PATCH v4 6/9] RISC-V: Move STATIC_TLS handling into record_tls_type Tatsuyuki Ishi
2024-02-20 17:55 ` [PATCH v4 7/9] RISC-V: Unify TLS handling in check_relocs Tatsuyuki Ishi
2024-02-20 17:55 ` [PATCH v4 8/9] RISC-V: Add elf_link_hash_entry to relax_func args Tatsuyuki Ishi
2024-02-20 17:55 ` Tatsuyuki Ishi [this message]
2024-02-29 7:06 ` [PATCH v4 0/9] RISC-V: Implement TLS Descriptors Nelson Chu
2024-02-29 7:14 ` Tatsuyuki Ishi
2024-03-29 6:22 ` Tatsuyuki Ishi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240220175556.304692-10-ishitatsuyuki@gmail.com \
--to=ishitatsuyuki@gmail.com \
--cc=binutils@sourceware.org \
--cc=i@maskray.me \
--cc=nelson@rivosinc.com \
--cc=rui314@gmail.com \
--cc=ruiu@bluewhale.systems \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).