-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[RISCV] Support RISC-V TLSDESC in LLD #77516
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[RISCV] Support RISC-V TLSDESC in LLD #77516
Conversation
Created using spr 1.3.4
@llvm/pr-subscribers-lld @llvm/pr-subscribers-lld-elf Author: Paul Kirth (ilovepi) ChangesThis patch adds support for RISC-V TLSDESC relocations, as described in It does not attempt to handle relaxation for these cases, which will be Full diff: https://github.com/llvm/llvm-project/pull/77516.diff 6 Files Affected:
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 1d3d179e5d6fb5..460cccbabdb002 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -44,6 +44,7 @@ class RISCV final : public TargetInfo {
void relocate(uint8_t *loc, const Relocation &rel,
uint64_t val) const override;
void relocateAlloc(InputSectionBase &sec, uint8_t *buf) const override;
+ RelExpr adjustTlsExpr(RelType type, RelExpr expr) const override;
bool relaxOnce(int pass) const override;
};
@@ -120,6 +121,8 @@ RISCV::RISCV() {
}
gotRel = symbolicRel;
+ tlsDescRel = R_RISCV_TLSDESC_CALL;
+
// .got[0] = _DYNAMIC
gotHeaderEntriesNum = 1;
@@ -298,6 +301,13 @@ RelExpr RISCV::getRelExpr(const RelType type, const Symbol &s,
return R_TLSGD_PC;
case R_RISCV_TLS_GOT_HI20:
return R_GOT_PC;
+ case R_RISCV_TLSDESC_HI20:
+ return R_TLSDESC_PC;
+ case R_RISCV_TLSDESC_LOAD_LO12:
+ case R_RISCV_TLSDESC_ADD_LO12:
+ return R_TLSDESC;
+ case R_RISCV_TLSDESC_CALL:
+ return R_TLSDESC_CALL;
case R_RISCV_TPREL_HI20:
case R_RISCV_TPREL_LO12_I:
case R_RISCV_TPREL_LO12_S:
@@ -420,6 +430,7 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
case R_RISCV_PCREL_HI20:
case R_RISCV_TLS_GD_HI20:
case R_RISCV_TLS_GOT_HI20:
+ case R_RISCV_TLSDESC_HI20:
case R_RISCV_TPREL_HI20:
case R_RISCV_HI20: {
uint64_t hi = val + 0x800;
@@ -430,6 +441,8 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
case R_RISCV_PCREL_LO12_I:
case R_RISCV_TPREL_LO12_I:
+ case R_RISCV_TLSDESC_LOAD_LO12:
+ case R_RISCV_TLSDESC_ADD_LO12:
case R_RISCV_LO12_I: {
uint64_t hi = (val + 0x800) >> 12;
uint64_t lo = val - (hi << 12);
@@ -557,6 +570,13 @@ void RISCV::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const {
}
}
+RelExpr RISCV::adjustTlsExpr(RelType type, RelExpr expr) const {
+ if (expr == R_RELAX_TLS_GD_TO_IE) {
+ return R_RELAX_TLS_GD_TO_IE_ABS;
+ }
+ return expr;
+}
+
namespace {
struct SymbolAnchor {
uint64_t offset;
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index 53b496bd084258..90f55c4b8a6b1c 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -851,6 +851,7 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type,
return sym.getSize() + a;
case R_TLSDESC:
return in.got->getTlsDescAddr(sym) + a;
+ case R_RISCV_TLSDESC_HI:
case R_TLSDESC_PC:
return in.got->getTlsDescAddr(sym) + a - p;
case R_TLSDESC_GOTPLT:
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 20eb02b8798447..6e67a13731fea8 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -1269,7 +1269,7 @@ static unsigned handleTlsRelocation(RelType type, Symbol &sym,
return handleMipsTlsRelocation(type, sym, c, offset, addend, expr);
if (oneof<R_AARCH64_TLSDESC_PAGE, R_TLSDESC, R_TLSDESC_CALL, R_TLSDESC_PC,
- R_TLSDESC_GOTPLT>(expr) &&
+ R_TLSDESC_GOTPLT, R_RISCV_TLSDESC_HI>(expr) &&
config->shared) {
if (expr != R_TLSDESC_CALL) {
sym.setFlags(NEEDS_TLSDESC);
@@ -1333,7 +1333,7 @@ static unsigned handleTlsRelocation(RelType type, Symbol &sym,
if (oneof<R_AARCH64_TLSDESC_PAGE, R_TLSDESC, R_TLSDESC_CALL, R_TLSDESC_PC,
R_TLSDESC_GOTPLT, R_TLSGD_GOT, R_TLSGD_GOTPLT, R_TLSGD_PC,
- R_LOONGARCH_TLSGD_PAGE_PC>(expr)) {
+ R_LOONGARCH_TLSGD_PAGE_PC, R_RISCV_TLSDESC_HI>(expr)) {
if (!toExecRelax) {
sym.setFlags(NEEDS_TLSGD);
c.addReloc({expr, type, offset, addend, &sym});
diff --git a/lld/ELF/Relocations.h b/lld/ELF/Relocations.h
index cfb9092149f3e0..9a24fe8a219dab 100644
--- a/lld/ELF/Relocations.h
+++ b/lld/ELF/Relocations.h
@@ -103,6 +103,10 @@ enum RelExpr {
R_RISCV_ADD,
R_RISCV_LEB128,
R_RISCV_PC_INDIRECT,
+ R_RISCV_TLSDESC_HI,
+ R_RISCV_TLSDESC_LOAD_LO,
+ R_RISCV_TLSDESC_ADD_LO,
+ R_RISCV_TLSDESC_CALLER,
// Same as R_PC but with page-aligned semantics.
R_LOONGARCH_PAGE_PC,
// Same as R_PLT_PC but with page-aligned semantics.
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index dfec5e07301a74..34bb3da2a1c343 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -1950,7 +1950,8 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
}
}
- if (config->emachine == EM_386 || config->emachine == EM_X86_64) {
+ if (config->emachine == EM_386 || config->emachine == EM_X86_64 ||
+ config->emachine == EM_RISCV) {
// On targets that support TLSDESC, _TLS_MODULE_BASE_ is defined in such a
// way that:
//
diff --git a/lld/test/ELF/riscv-tlsdesc-le.s b/lld/test/ELF/riscv-tlsdesc-le.s
new file mode 100644
index 00000000000000..6aa670cffb59b8
--- /dev/null
+++ b/lld/test/ELF/riscv-tlsdesc-le.s
@@ -0,0 +1,43 @@
+// RUN: llvm-mc -filetype=obj -triple=riscv64-pc-linux %s -o %t.o
+// RUN: ld.lld -shared %t.o -o %t.so
+// RUN: llvm-objdump --no-print-imm-hex -d --no-show-raw-insn %t.so | FileCheck %s
+// RUN: llvm-readelf -r %t.so | FileCheck --check-prefix=REL %s
+
+// CHECK: 00000000000012d8 <_start>:
+// CHECK-NEXT: 12d8: auipc a0, 1
+// CHECK-NEXT: 12dc: ld a1, 920(a0)
+// CHECK-NEXT: 12e0: addi a0, a0, 920
+// CHECK-NEXT: 12e4: jalr t0, a1
+// CHECK-NEXT: 12e8: add a0, a0, tp
+// CHECK-NEXT: 12ec: ret
+
+// REL: Relocation section '.rela.dyn' at offset 0x{{[0-9a-f]+}} contains 2 entries
+// REL: R_RISCV_TLSDESC_CALL ffffffffffffffe8
+// REL-NEXT: R_RISCV_TLSDESC_CALL 0
+
+ .text
+ .attribute 4, 16
+ .attribute 5, "rv64i2p1"
+ .file "<stdin>"
+ .globl _start # -- Begin function _start
+ .p2align 2
+ .type _start,@function
+_start: # @_start
+# %bb.0: # %entry
+.Ltlsdesc_hi0:
+ auipc a0, %tlsdesc_hi(unspecified)
+ ld a1, %tlsdesc_load_lo(.Ltlsdesc_hi0)(a0)
+ addi a0, a0, %tlsdesc_add_lo(.Ltlsdesc_hi0)
+ jalr t0, 0(a1), %tlsdesc_call(.Ltlsdesc_hi0)
+ add a0, a0, tp
+ ret
+.Lfunc_end0:
+ .size _start, .Lfunc_end0-_start
+ # -- End function
+ .section ".note.GNU-stack","",@progbits
+
+ .section .tbss,"awT",@nobits
+ .p2align 2
+
+unspecified:
+ .zero 4
|
Created using spr 1.3.4
The patch does not need address TLSDESC to TLS LE and IE optimizations, which is pretty important. I think we don't need linker relaxation, but we do need TLS optimization for correctness. The changes are pretty subtle, I'll probably create patch based on this with you as a co-author. |
I have found several issues.
#79099 reuses an old revision of the LLVM part but otherwise is a rewrite and should fix these issues as well as implement linker relaxation. |
Abandon in favor of #79239 |
This patch adds support for RISC-V TLSDESC relocations, as described in
riscv-non-isa/riscv-elf-psabi-doc#373.
It does not attempt to handle relaxation for these cases, which will be
handled separately.