Index: ELF/Arch/RISCV.cpp =================================================================== --- ELF/Arch/RISCV.cpp +++ ELF/Arch/RISCV.cpp @@ -45,7 +45,6 @@ NoneRel = R_RISCV_NONE; CopyRel = R_RISCV_COPY; RelativeRel = R_RISCV_RELATIVE; - GotRel = Config->Is64 ? R_RISCV_64 : R_RISCV_32; PltRel = R_RISCV_JUMP_SLOT; GotEntrySize = Config->Wordsize; GotPltEntrySize = Config->Wordsize; @@ -53,6 +52,17 @@ PltHeaderSize = 32; GotPltHeaderEntriesNum = 2; GotBaseSymInGotPlt = false; + if (Config->Is64) { + GotRel = R_RISCV_64; + TlsGotRel = R_RISCV_TLS_TPREL64; + TlsModuleIndexRel = R_RISCV_TLS_DTPMOD64; + TlsOffsetRel = R_RISCV_TLS_DTPREL64; + } else { + GotRel = R_RISCV_32; + TlsGotRel = R_RISCV_TLS_TPREL32; + TlsModuleIndexRel = R_RISCV_TLS_DTPMOD32; + TlsOffsetRel = R_RISCV_TLS_DTPREL32; + } } static uint32_t getEFlags(InputFile *F) { @@ -179,9 +189,17 @@ case R_RISCV_PCREL_LO12_S: return R_RISCV_PC_INDIRECT; case R_RISCV_GOT_HI20: + case R_RISCV_TLS_GOT_HI20: return R_GOT_PC; + case R_RISCV_TPREL_HI20: + case R_RISCV_TPREL_LO12_I: + case R_RISCV_TPREL_LO12_S: + return R_TLS; + case R_RISCV_TLS_GD_HI20: + return R_TLSGD_PC; case R_RISCV_ALIGN: case R_RISCV_RELAX: + case R_RISCV_TPREL_ADD: return R_HINT; default: return R_ABS; @@ -294,7 +312,10 @@ } case R_RISCV_PCREL_HI20: + case R_RISCV_TPREL_HI20: case R_RISCV_GOT_HI20: + case R_RISCV_TLS_GOT_HI20: + case R_RISCV_TLS_GD_HI20: case R_RISCV_HI20: { uint64_t Hi = Val + 0x800; checkInt(Loc, SignExtend64(Hi, Bits) >> 12, 20, Type); @@ -303,6 +324,7 @@ } case R_RISCV_PCREL_LO12_I: + case R_RISCV_TPREL_LO12_I: case R_RISCV_LO12_I: { uint64_t Hi = (Val + 0x800) >> 12; uint64_t Lo = Val - (Hi << 12); @@ -311,6 +333,7 @@ } case R_RISCV_PCREL_LO12_S: + case R_RISCV_TPREL_LO12_S: case R_RISCV_LO12_S: { uint64_t Hi = (Val + 0x800) >> 12; uint64_t Lo = Val - (Hi << 12); @@ -320,6 +343,29 @@ return; } + case R_RISCV_TLS_DTPMOD32: + write32le(Loc, 1); + return; + case R_RISCV_TLS_DTPMOD64: + write64le(Loc, 1); + return; + case R_RISCV_TLS_DTPREL32: + // The pointer in dynamic thread vector (DTV) points to 0x800 past the + // TLS block. + write32le(Loc, Val - 0x800); + return; + case R_RISCV_TLS_DTPREL64: + write64le(Loc, Val - 0x800); + return; + case R_RISCV_TLS_TPREL32: + write32le(Loc, Val); + return; + case R_RISCV_TLS_TPREL64: + write64le(Loc, Val); + return; + case R_RISCV_TPREL_ADD: + return; // Do nothing + case R_RISCV_ADD8: *Loc += Val; return; Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -571,7 +571,8 @@ }); for (auto It = Range.first; It != Range.second; ++It) - if (It->Expr == R_PC || It->Expr == R_PLT_PC || It->Expr == R_GOT_PC) + if (It->Expr == R_PC || It->Expr == R_PLT_PC || It->Expr == R_GOT_PC || + It->Expr == R_TLSGD_PC) return &*It; error("R_RISCV_PCREL_LO12 relocation points to " + IS->getObjMsg(D->Value) + @@ -603,6 +604,9 @@ // offset to reach 0x1000 of TCB/thread-library data and 0xf000 of the // program's TLS segment. return -0x7000; + case EM_RISCV: + // RISC-V's tp points to the start of the executable's TLS segment. + return 0; default: llvm_unreachable("unhandled Config->EMachine"); } Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -212,7 +212,9 @@ if (!Sym.isTls()) return 0; - if (Config->EMachine == EM_ARM) + // TODO: RISC-V currently doesn't implement TLS relaxation yet, so we reuse + // the same logic for ARM tls relocation. + if (Config->EMachine == EM_ARM || Config->EMachine == EM_RISCV) return handleARMTlsRelocation(Type, Sym, C, Offset, Addend, Expr); if (Config->EMachine == EM_MIPS) return handleMipsTlsRelocation(Type, Sym, C, Offset, Addend, Expr); Index: test/ELF/Inputs/riscv-tls.s =================================================================== --- /dev/null +++ test/ELF/Inputs/riscv-tls.s @@ -0,0 +1,10 @@ +.global __tls_get_addr +.type __tls_get_addr, @function +__tls_get_addr: + +.section .tdata, "awT", @progbits +.global tx +.type tx, @object +.size tx, 4 +tx: + .word 42 Index: test/ELF/riscv-tls-gd.s =================================================================== --- /dev/null +++ test/ELF/riscv-tls-gd.s @@ -0,0 +1,59 @@ +# REQUIRES: riscv + +# RUN: llvm-mc -filetype=obj -triple=riscv32-unknown-elf -mattr=-relax -position-independent %s -o %t.rv32.o +# RUN: llvm-mc -filetype=obj -triple=riscv32-unknown-elf -mattr=-relax -position-independent %p/Inputs/riscv-tls.s -o %t.shared.rv32.o +# RUN: ld.lld -shared %t.shared.rv32.o -o %t.shared.rv32.so +# RUN: ld.lld %t.rv32.o %t.shared.rv32.so -o %t.rv32 + +# RUN: llvm-mc -filetype=obj -triple=riscv64-unknown-elf -mattr=-relax -position-independent %s -o %t.rv64.o +# RUN: llvm-mc -filetype=obj -triple=riscv64-unknown-elf -mattr=-relax -position-independent %p/Inputs/riscv-tls.s -o %t.shared.rv64.o +# RUN: ld.lld -shared %t.shared.rv64.o -o %t.shared.rv64.so +# RUN: ld.lld %t.rv64.o %t.shared.rv64.so -o %t.rv64 + +# RUN: llvm-readobj -dyn-relocations -dyn-symbols %t.rv32 | FileCheck -DXLEN=32 -DTPMOD=0x12064 -DTPREL=0x12068 %s +# RUN: llvm-readobj -dyn-relocations -dyn-symbols %t.rv64 | FileCheck -DXLEN=64 -DTPMOD=0x120C8 -DTPREL=0x120D0 %s +# CHECK: Dynamic Relocations { +# CHECK-NEXT: [[TPMOD]] R_RISCV_TLS_DTPMOD[[XLEN]] tx 0x0 +# CHECK-NEXT: [[TPREL]] R_RISCV_TLS_DTPREL[[XLEN]] tx 0x0 +# CHECK-NEXT: } + +# CHECK: DynamicSymbols [ +# CHECK: Name: tx +# CHECK-NOT: Name: ty + +# RUN: llvm-objdump -d %t.rv32 | FileCheck --check-prefix=DIS32 %s +# _start = 0x11000, tx = 0x12064, ty = 0x1206c +# DIS32: _start: +# DIS32-NEXT: auipc a0, 1 +# DIS32-NEXT: addi a0, a0, 100 +# DIS32: auipc a1, 1 +# DIS32-NEXT: addi a1, a1, 100 + +# RUN: llvm-objdump -d %t.rv64 | FileCheck --check-prefix=DIS64 %s +# _start = 0x11000, tx = 0x120c8, ty = 0x120d8 +# DIS64: _start: +# DIS64-NEXT: auipc a0, 1 +# DIS64-NEXT: addi a0, a0, 200 +# DIS64: auipc a1, 1 +# DIS64-NEXT: addi a1, a1, 208 + +# RUN: llvm-objdump -s -j.got %t.rv32 | FileCheck --check-prefix=GOT32 %s +# GOT32: Contents of section .got: +# GOT32-NEXT: 12064 00000000 00000000 01000000 00f8ffff + +# RUN: llvm-objdump -s -j.got %t.rv64 | FileCheck --check-prefix=GOT64 %s +# GOT64: Contents of section .got: +# GOT64-NEXT: 120c8 00000000 00000000 00000000 00000000 +# GOT64-NEXT: 120d8 01000000 00000000 00f8ffff ffffffff + +.global _start +_start: +L1: + la.tls.gd a0, tx + la.tls.gd a1, ty + +.section .tdata, "awT", @progbits +.type ty, @object +.size ty, 4 +ty: + .word 42 Index: test/ELF/riscv-tls-ie.s =================================================================== --- /dev/null +++ test/ELF/riscv-tls-ie.s @@ -0,0 +1,56 @@ +# REQUIRES: riscv + +# RUN: llvm-mc -filetype=obj -triple=riscv32-unknown-elf -mattr=-relax -position-independent %s -o %t.rv32.o +# RUN: llvm-mc -filetype=obj -triple=riscv32-unknown-elf -mattr=-relax -position-independent %p/Inputs/riscv-tls.s -o %t.shared.rv32.o +# RUN: ld.lld -shared %t.shared.rv32.o -o %t.shared.rv32.so +# RUN: ld.lld %t.rv32.o %t.shared.rv32.so -o %t.rv32 + +# RUN: llvm-mc -filetype=obj -triple=riscv64-unknown-elf -mattr=-relax -position-independent %s -o %t.rv64.o +# RUN: llvm-mc -filetype=obj -triple=riscv64-unknown-elf -mattr=-relax -position-independent %p/Inputs/riscv-tls.s -o %t.shared.rv64.o +# RUN: ld.lld -shared %t.shared.rv64.o -o %t.shared.rv64.so +# RUN: ld.lld %t.rv64.o %t.shared.rv64.so -o %t.rv64 + +# RUN: llvm-readobj -dyn-relocations -dyn-symbols %t.rv32 | FileCheck -DXLEN=32 -DGOT=0x12064 %s +# RUN: llvm-readobj -dyn-relocations -dyn-symbols %t.rv64 | FileCheck -DXLEN=64 -DGOT=0x120C8 %s +# CHECK: Dynamic Relocations { +# CHECK-NEXT: [[GOT]] R_RISCV_TLS_TPREL[[XLEN]] tx 0x0 +# CHECK-NEXT: } + +# CHECK: DynamicSymbols [ +# CHECK: Name: tx +# CHECK-NOT: Name: ty + +# RUN: llvm-objdump -d %t.rv32 | FileCheck --check-prefix=DIS32 %s +# _start = 0x11000, tx = 0x12064, ty = 0x12068 +# DIS32: _start: +# DIS32-NEXT: auipc a0, 1 +# DIS32-NEXT: lw a0, 100(a0) +# DIS32: auipc a1, 1 +# DIS32-NEXT: lw a1, 96(a1) + +# RUN: llvm-objdump -d %t.rv64 | FileCheck --check-prefix=DIS64 %s +# _start = 0x11000, tx = 0x120c8, ty = 0x120d0 +# DIS64: _start: +# DIS64-NEXT: auipc a0, 1 +# DIS64-NEXT: ld a0, 200(a0) +# DIS64: auipc a1, 1 +# DIS64-NEXT: ld a1, 200(a1) + +# RUN: llvm-objdump -s -j.got %t.rv32 | FileCheck --check-prefix=GOT32 %s +# GOT32: Contents of section .got: +# GOT32-NEXT: 12064 00000000 00000000 + +# RUN: llvm-objdump -s -j.got %t.rv64 | FileCheck --check-prefix=GOT64 %s +# GOT64: Contents of section .got: +# GOT64-NEXT: 120c8 00000000 00000000 00000000 00000000 + +.global _start +_start: + la.tls.ie a0, tx + la.tls.ie a1, ty + +.section .tdata, "awT", @progbits +.type ty, @object +.size ty, 4 +ty: + .word 42 Index: test/ELF/riscv-tls-le.s =================================================================== --- /dev/null +++ test/ELF/riscv-tls-le.s @@ -0,0 +1,43 @@ +# REQUIRES: riscv + +# RUN: llvm-mc -filetype=obj -triple=riscv32-unknown-elf -mattr=-relax %s -o %t.rv32.o +# RUN: ld.lld %t.rv32.o -o %t.rv32 + +# RUN: llvm-mc -filetype=obj -triple=riscv64-unknown-elf -mattr=-relax %s -o %t.rv64.o +# RUN: ld.lld %t.rv64.o -o %t.rv64 + +# RUN: llvm-objdump -d %t.rv32 | FileCheck --check-prefix=DIS %s +# RUN: llvm-objdump -d %t.rv64 | FileCheck --check-prefix=DIS %s +# x = tp+0, y = tp+4 +# DIS: lui a0, 0 +# DIS-NEXT: add a0, a0, tp +# DIS-NEXT: lw a0, 0(a0) +# DIS-NEXT: lui a1, 0 +# DIS-NEXT: add a1, a1, tp +# DIS-NEXT: lw a1, 4(a1) + +# RUN: llvm-objdump -s -j.tdata %t.rv32 | FileCheck --check-prefix=TDATA %s +# RUN: llvm-objdump -s -j.tdata %t.rv64 | FileCheck --check-prefix=TDATA %s +# TDATA: Contents of section .tdata: +# TDATA-NEXT: {{[0-9a-f]+}} 2a000000 + +.global _start +_start: + lui a0, %tprel_hi(x) + add a0, a0, tp, %tprel_add(x) + lw a0, %tprel_lo(x)(a0) + lui a1, %tprel_hi(y) + add a1, a1, tp, %tprel_add(y) + lw a1, %tprel_lo(y)(a1) + +.section .tdata, "awT", @progbits +.type x, @object +.size x, 4 +x: + .word 42 + +.section .tbss, "awT", @nobits +.type y, @object +.size y, 4 +y: + .zero 4