Index: ELF/Arch/RISCV.cpp =================================================================== --- ELF/Arch/RISCV.cpp +++ ELF/Arch/RISCV.cpp @@ -20,6 +20,8 @@ using namespace lld; using namespace lld::elf; +static constexpr uint64_t TLS_DTP_OFFSET = 0x800; + namespace { class RISCV final : public TargetInfo { @@ -57,6 +59,15 @@ GotHeaderEntriesNum = 1; GotPltHeaderEntriesNum = 2; GotBaseSymInGotPlt = false; + if (Config->Is64) { + TlsGotRel = R_RISCV_TLS_TPREL64; + TlsModuleIndexRel = R_RISCV_TLS_DTPMOD64; + TlsOffsetRel = R_RISCV_TLS_DTPREL64; + } else { + TlsGotRel = R_RISCV_TLS_TPREL32; + TlsModuleIndexRel = R_RISCV_TLS_DTPMOD32; + TlsOffsetRel = R_RISCV_TLS_DTPREL32; + } } static uint32_t getEFlags(InputFile *F) { @@ -176,9 +187,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; @@ -288,7 +307,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: { checkInt(Loc, Val, 32, Type); uint32_t Hi = Val + 0x800; @@ -297,6 +319,7 @@ } case R_RISCV_PCREL_LO12_I: + case R_RISCV_TPREL_LO12_I: case R_RISCV_LO12_I: { checkInt(Loc, Val, 32, Type); uint32_t Hi = Val + 0x800; @@ -306,6 +329,7 @@ } case R_RISCV_PCREL_LO12_S: + case R_RISCV_TPREL_LO12_S: case R_RISCV_LO12_S: { checkInt(Loc, Val, 32, Type); uint32_t Hi = Val + 0x800; @@ -316,6 +340,27 @@ return; } + case R_RISCV_TLS_DTPMOD32: + write32le(Loc, 1); + return; + case R_RISCV_TLS_DTPMOD64: + write64le(Loc, 1); + return; + case R_RISCV_TLS_DTPREL32: + write32le(Loc, Val - TLS_DTP_OFFSET); + return; + case R_RISCV_TLS_DTPREL64: + write64le(Loc, Val - TLS_DTP_OFFSET); + 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 @@ -500,7 +500,7 @@ auto Range = std::equal_range(IS->Relocations.begin(), IS->Relocations.end(), D->Value, RelocationOffsetComparator{}); for (auto It = std::get<0>(Range); It != std::get<1>(Range); ++It) - if (isRelExprOneOf(It->Expr)) + if (isRelExprOneOf(It->Expr)) return &*It; error("R_RISCV_PCREL_LO12 relocation points to " + IS->getObjMsg(D->Value) + @@ -661,7 +661,8 @@ // For TLS variant 1 the TCB is a fixed size, whereas for TLS variant 2 the // TCB is on unspecified size and content. Targets that implement variant 1 // should set TcbSize. - if (Target->TcbSize) { + // RISC-V uses variant I but tp points to the end of TCB. + if (Target->TcbSize || Config->EMachine == EM_RISCV) { // PPC64 V2 ABI has the thread pointer offset into the middle of the TLS // storage area by TlsTpOffset for efficient addressing TCB and up to // 4KB – 8 B of other thread library information (placed before the TCB). Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -171,7 +171,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-shared.yaml =================================================================== --- test/ELF/Inputs/riscv-shared.yaml +++ test/ELF/Inputs/riscv-shared.yaml @@ -20,6 +20,11 @@ Type: SHT_NOBITS Flags: [ SHF_WRITE, SHF_ALLOC ] AddressAlign: 0x0000000000000001 + - Name: .tdata + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ] + AddressAlign: 0x0000000000000001 + Content: 2A000000 Symbols: Local: - Name: .text @@ -31,12 +36,22 @@ - Name: .bss Type: STT_SECTION Section: .bss + - Name: .tdata + Type: STT_SECTION + Section: .tdata Global: - Name: f Type: STT_FUNC Section: .text + - Name: __tls_get_addr + Type: STT_FUNC + Section: .text - Name: x Type: STT_OBJECT Section: .data Size: 0x0000000000000004 + - Name: tx + Type: STT_TLS + Section: .tdata + Size: 0x0000000000000004 ... Index: test/ELF/riscv-tls-gd.test =================================================================== --- /dev/null +++ test/ELF/riscv-tls-gd.test @@ -0,0 +1,96 @@ +# .option norelax +# .option pic +# +# .global _start +# _start: +# L1: +# la.tls.gd a0, tx +# call __tls_get_addr@plt +# lw a0, 0(a0) +# +# REQUIRES: riscv +# RUN: yaml2obj %s -o %t.o +# RUN: yaml2obj %p/Inputs/riscv-shared.yaml -o %t2.o +# RUN: ld.lld -shared %t2.o -o %t3.so +# RUN: ld.lld %t.o %t3.so -o %t --section-start .got=0x20000 --section-start .text=0x10000 -z norelro +# RUN: obj2yaml %t | FileCheck %s +# +# CHECK: - Name: .text +# CHECK: Content: '170501001305050097200100E78080010841' +# 10000: 00010517 auipc a0,0x10 +# 10004: 00050513 mv a0,a0 +# 10008: 00012097 auipc ra,0x12 +# 1000c: 018080e7 jalr 24(ra) # 22020 <__tls_get_addr@plt> +# 10010: 4108 lw a0,0(a0) +# +# CHECK: - Name: .got +# CHECK: Content: '0000000000000000' +# CHECK: - Name: .rela.dyn +# CHECK: Relocations: +# CHECK: - Offset: 0x0000000000020000 +# CHECK: Symbol: tx +# CHECK: Type: R_RISCV_TLS_DTPMOD32 +# CHECK: - Offset: 0x0000000000020004 +# CHECK: Symbol: tx +# CHECK: Type: R_RISCV_TLS_DTPREL32 + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_RISCV + Flags: [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SOFT ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000002 + Content: '170500001305050097000000E78000000841' + - Name: .rela.text + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .text + Relocations: + - Offset: 0x0000000000000000 + Symbol: tx + Type: R_RISCV_TLS_GD_HI20 + - Offset: 0x0000000000000004 + Symbol: '.L0 ' + Type: R_RISCV_PCREL_LO12_I + - Offset: 0x0000000000000008 + Symbol: __tls_get_addr + Type: R_RISCV_CALL_PLT + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 +Symbols: + Local: + - Name: .text + Type: STT_SECTION + Section: .text + - Name: .data + Type: STT_SECTION + Section: .data + - Name: .bss + Type: STT_SECTION + Section: .bss + - Name: L1 + Section: .text + - Name: '.L0 ' + Section: .text + Global: + - Name: _start + Section: .text + - Name: tx + Type: STT_TLS + - Name: __tls_get_addr +... Index: test/ELF/riscv-tls-ie.test =================================================================== --- /dev/null +++ test/ELF/riscv-tls-ie.test @@ -0,0 +1,87 @@ +# .option norelax +# .option pic +# .global _start +# _start: +# L1: +# la.tls.ie a5, tx +# add a5, a5, tp +# lw a5, 0(a5) +# +# REQUIRES: riscv +# RUN: yaml2obj %s -o %t.o +# RUN: yaml2obj %p/Inputs/riscv-shared.yaml -o %t2.o +# RUN: ld.lld -shared %t2.o -o %t3.so +# RUN: ld.lld %t.o %t3.so -o %t --section-start .got=0x20000 --section-start .text=0x10000 -z norelro +# RUN: obj2yaml %t | FileCheck %s +# +# CHECK: - Name: .text +# CHECK: Content: 9707010083A7070092979C43 +# 10000: 00010797 auipc a5,0x10 +# 10004: 0007a783 lw a5,0(a5) # 20000 <_start+0x10000> +# 10008: 9792 add a5,a5,tp +# 1000a: 439c lw a5,0(a5) +# +# CHECK: - Name: .got +# CHECK: Content: '00000000' +# CHECK: - Name: .rela.dyn +# CHECK: Relocations: +# CHECK: - Offset: 0x0000000000020000 +# CHECK: Symbol: tx +# CHECK: Type: R_RISCV_TLS_TPREL32 + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_RISCV + Flags: [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SOFT ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000002 + Content: 9707000083A7070092979C43 + - Name: .rela.text + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .text + Relocations: + - Offset: 0x0000000000000000 + Symbol: tx + Type: R_RISCV_TLS_GOT_HI20 + - Offset: 0x0000000000000004 + Symbol: '.L0 ' + Type: R_RISCV_PCREL_LO12_I + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 +Symbols: + Local: + - Name: .text + Type: STT_SECTION + Section: .text + - Name: .data + Type: STT_SECTION + Section: .data + - Name: .bss + Type: STT_SECTION + Section: .bss + - Name: L1 + Section: .text + - Name: '.L0 ' + Section: .text + Global: + - Name: _start + Section: .text + - Name: tx + Type: STT_TLS +... Index: test/ELF/riscv-tls-le.test =================================================================== --- /dev/null +++ test/ELF/riscv-tls-le.test @@ -0,0 +1,96 @@ +# .option norelax +# .global _start +# _start: +# L1: +# lui a5, %tprel_hi(x) +# add a5, a5, tp, %tprel_add(x) +# lw a5, %tprel_lo(x)(a5) +# +# .section .tdata, "awT", @progbits +# .type x, @object +# .size x, 4 +# x: +# .word 42 +# +# +# REQUIRES: riscv +# RUN: yaml2obj %s -o %t.o +# RUN: ld.lld %t.o -o %t +# RUN: obj2yaml %t | FileCheck %s +# +# CHECK: - Name: .text +# CHECK: Content: B7070000B387470083A70700 +# 11000: 000007b7 lui a5,0x0 +# 11004: 004787b3 add a5,a5,tp +# 11008: 0007a783 lw a5,0(a5) # 0 +# +# CHECK: - Name: .tdata +# CHECK: Content: 2A000000 + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_RISCV + Flags: [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SOFT ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000002 + Content: B7070000B387470083A70700 + - Name: .rela.text + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .text + Relocations: + - Offset: 0x0000000000000000 + Symbol: x + Type: R_RISCV_TPREL_HI20 + - Offset: 0x0000000000000004 + Symbol: x + Type: R_RISCV_TPREL_ADD + - Offset: 0x0000000000000008 + Symbol: x + Type: R_RISCV_TPREL_LO12_I + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + - Name: .tdata + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ] + AddressAlign: 0x0000000000000001 + Content: 2A000000 +Symbols: + Local: + - Name: .text + Type: STT_SECTION + Section: .text + - Name: .data + Type: STT_SECTION + Section: .data + - Name: .bss + Type: STT_SECTION + Section: .bss + - Name: L1 + Section: .text + - Name: x + Type: STT_TLS + Section: .tdata + Size: 0x0000000000000004 + - Name: .tdata + Type: STT_SECTION + Section: .tdata + Global: + - Name: _start + Section: .text +...