Index: ELF/Arch/RISCV.cpp =================================================================== --- ELF/Arch/RISCV.cpp +++ ELF/Arch/RISCV.cpp @@ -36,6 +36,8 @@ using namespace lld; using namespace lld::elf; +constexpr uint64_t TLS_DTV_OFFSET = 0x800; + namespace { class RISCV final : public TargetInfo { @@ -80,6 +82,15 @@ PltEntrySize = 16; PltHeaderSize = 32; GotPltHeaderEntriesNum = 2; + 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; + } } bool RISCV::usesOnlyLowPageBits(RelType Type) const { @@ -163,9 +174,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; @@ -274,7 +293,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<32>(Loc, Val, Type); uint32_t Hi = Val + 0x800; @@ -282,6 +304,7 @@ return; } case R_RISCV_PCREL_LO12_I: + case R_RISCV_TPREL_LO12_I: case R_RISCV_LO12_I: { checkInt<32>(Loc, Val, Type); uint32_t Hi = Val + 0x800; @@ -290,6 +313,7 @@ return; } case R_RISCV_PCREL_LO12_S: + case R_RISCV_TPREL_LO12_S: case R_RISCV_LO12_S: { checkInt<32>(Loc, Val, Type); uint32_t Hi = Val + 0x800; @@ -300,6 +324,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_DTV_OFFSET); + return; + case R_RISCV_TLS_DTPREL64: + write64le(Loc, Val - TLS_DTV_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 @@ -576,7 +576,7 @@ uint64_t HiOffset = IS->getOffset(HiRel.Offset); uint64_t HiAddrLoc = IS->getOutputSection()->Addr + HiOffset; if (Label == HiAddrLoc && - isRelExprOneOf(HiRel.Expr)) { + isRelExprOneOf(HiRel.Expr)) { return getRelocTargetVA(HiRel.Type, HiRel.Addend, HiAddrLoc, *HiRel.Sym, HiRel.Expr); } @@ -640,7 +640,8 @@ // statically to zero. if (Body.isTls() && Body.isUndefWeak()) return 0; - if (Target->TcbSize) + // RISC-V uses variant I but tp points to the end of TCB. + if (Target->TcbSize || Config->EMachine == EM_RISCV) return Body.getVA(A) + alignTo(Target->TcbSize, Out::TlsPhdr->p_align); return Body.getVA(A) - Out::TlsPhdr->p_memsz; case R_RELAX_TLS_GD_TO_LE_NEG: Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -205,7 +205,9 @@ if (!Body.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, Body, C, Offset, Addend, Expr); if (Config->EMachine == EM_MIPS) return handleMipsTlsRelocation(Type, Body, 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 +# 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 +# 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 +...