diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp index 1d3d179e5d6fb..460cccbabdb00 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 53b496bd08425..90f55c4b8a6b1 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 20eb02b879844..6e67a13731fea 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 cfb9092149f3e..9a24fe8a219da 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 dfec5e07301a7..34bb3da2a1c34 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1950,7 +1950,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 0000000000000..21541ee597701 --- /dev/null +++ b/lld/test/ELF/riscv-tlsdesc-le.s @@ -0,0 +1,60 @@ +// 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: 0000000000001318 <_start>: +// CHECK-NEXT: 1318: auipc a0, 1 +// CHECK-NEXT: 131c: ld a1, 1008(a0) +// CHECK-NEXT: 1320: addi a0, a0, 1008 +// CHECK-NEXT: 1324: jalr t0, a1 +// CHECK-NEXT: 1328: add a0, a0, tp +// CHECK-NEXT: 132c: auipc a0, 1 +// CHECK-NEXT: 1330: ld a1, 1040(a0) +// CHECK-NEXT: 1334: addi a0, a0, 1040 +// CHECK-NEXT: 1338: jalr t0, a1 +// CHECK-NEXT: 133c: add a0, a0, tp +// CHECK-NEXT: 1340: ret + +// REL: Relocation section '.rela.dyn' at offset 0x{{[0-9a-f]+}} contains 3 entries +// REL: R_RISCV_TLSDESC_CALL ffffffffffffffd4 +// REL-NEXT: R_RISCV_TLSDESC_CALL 4 +// REL-NEXT: R_RISCV_TLSDESC_CALL ffffffffffffffe8 + + .text + .attribute 4, 16 + .attribute 5, "rv64i2p1" + .file "" + .globl _start # -- Begin function _start + .p2align 2 + .type _start,@function +_start: # @_start +// access local variable +.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 + +// access global variable +.Ltlsdesc_hi1: + auipc a0, %tlsdesc_hi(unspecified) + ld a1, %tlsdesc_load_lo(.Ltlsdesc_hi1)(a0) + addi a0, a0, %tlsdesc_add_lo(.Ltlsdesc_hi1) + jalr t0, 0(a1), %tlsdesc_call(.Ltlsdesc_hi1) + 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 + .global v1 +v1: + .zero 4 + +unspecified: + .zero 4