[𝘀𝗽𝗿] initial version
Created using spr 1.3.4
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 1d3d179..460cccb 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -44,6 +44,7 @@
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 @@
}
gotRel = symbolicRel;
+ tlsDescRel = R_RISCV_TLSDESC_CALL;
+
// .got[0] = _DYNAMIC
gotHeaderEntriesNum = 1;
@@ -298,6 +301,13 @@
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 @@
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 @@
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 @@
}
}
+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 53b496b..90f55c4 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -851,6 +851,7 @@
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 20eb02b..6e67a13 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -1269,7 +1269,7 @@
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 @@
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 cfb9092..9a24fe8 100644
--- a/lld/ELF/Relocations.h
+++ b/lld/ELF/Relocations.h
@@ -103,6 +103,10 @@
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 dfec5e0..34bb3da 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -1950,7 +1950,8 @@
}
}
- 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 0000000..6aa670c
--- /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