diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp index 898e3e45b9e724..118bbf247cb5a8 100644 --- a/lld/ELF/Arch/RISCV.cpp +++ b/lld/ELF/Arch/RISCV.cpp @@ -43,6 +43,7 @@ class RISCV final : public TargetInfo { const uint8_t *loc) const override; void relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const override; + RelExpr adjustTlsExpr(RelType type, RelExpr expr) const override; bool relaxOnce(int pass) const override; }; @@ -119,6 +120,8 @@ RISCV::RISCV() { } gotRel = symbolicRel; + tlsDescRel = R_RISCV_TLSDESC_CALL; + // .got[0] = _DYNAMIC gotHeaderEntriesNum = 1; @@ -297,6 +300,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: @@ -418,6 +428,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; @@ -428,6 +439,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); @@ -515,6 +528,13 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) 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 5dfb57fda432e0..288d288e08a1e8 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -850,6 +850,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 210b4d1eb1a7a6..68ff1d6e9809ea 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(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(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 a84e4864ab0e5a..d1b24c2b181319 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1943,7 +1943,8 @@ template void Writer::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 "" + .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