Skip to content

Commit 2e3d34a

Browse files
committed
[RISCV] Support RISC-V TLSDESC in LLD
This patch adds support for RISC-V TLSDESC relocations, as described in riscv-non-isa/riscv-elf-psabi-doc#373. It does not attempt to handle relaxation for these cases, which will be handled separately.
1 parent cde5cba commit 2e3d34a

File tree

6 files changed

+72
-3
lines changed

6 files changed

+72
-3
lines changed

lld/ELF/Arch/RISCV.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ class RISCV final : public TargetInfo {
4343
const uint8_t *loc) const override;
4444
void relocate(uint8_t *loc, const Relocation &rel,
4545
uint64_t val) const override;
46+
RelExpr adjustTlsExpr(RelType type, RelExpr expr) const override;
4647
bool relaxOnce(int pass) const override;
4748
};
4849

@@ -119,6 +120,8 @@ RISCV::RISCV() {
119120
}
120121
gotRel = symbolicRel;
121122

123+
tlsDescRel = R_RISCV_TLSDESC_CALL;
124+
122125
// .got[0] = _DYNAMIC
123126
gotHeaderEntriesNum = 1;
124127

@@ -297,6 +300,13 @@ RelExpr RISCV::getRelExpr(const RelType type, const Symbol &s,
297300
return R_TLSGD_PC;
298301
case R_RISCV_TLS_GOT_HI20:
299302
return R_GOT_PC;
303+
case R_RISCV_TLSDESC_HI20:
304+
return R_TLSDESC_PC;
305+
case R_RISCV_TLSDESC_LOAD_LO12:
306+
case R_RISCV_TLSDESC_ADD_LO12:
307+
return R_TLSDESC;
308+
case R_RISCV_TLSDESC_CALL:
309+
return R_TLSDESC_CALL;
300310
case R_RISCV_TPREL_HI20:
301311
case R_RISCV_TPREL_LO12_I:
302312
case R_RISCV_TPREL_LO12_S:
@@ -418,6 +428,7 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
418428
case R_RISCV_PCREL_HI20:
419429
case R_RISCV_TLS_GD_HI20:
420430
case R_RISCV_TLS_GOT_HI20:
431+
case R_RISCV_TLSDESC_HI20:
421432
case R_RISCV_TPREL_HI20:
422433
case R_RISCV_HI20: {
423434
uint64_t hi = val + 0x800;
@@ -428,6 +439,8 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
428439

429440
case R_RISCV_PCREL_LO12_I:
430441
case R_RISCV_TPREL_LO12_I:
442+
case R_RISCV_TLSDESC_LOAD_LO12:
443+
case R_RISCV_TLSDESC_ADD_LO12:
431444
case R_RISCV_LO12_I: {
432445
uint64_t hi = (val + 0x800) >> 12;
433446
uint64_t lo = val - (hi << 12);
@@ -515,6 +528,13 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
515528
}
516529
}
517530

531+
RelExpr RISCV::adjustTlsExpr(RelType type, RelExpr expr) const {
532+
if (expr == R_RELAX_TLS_GD_TO_IE) {
533+
return R_RELAX_TLS_GD_TO_IE_ABS;
534+
}
535+
return expr;
536+
}
537+
518538
namespace {
519539
struct SymbolAnchor {
520540
uint64_t offset;

lld/ELF/InputSection.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -850,6 +850,7 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type,
850850
return sym.getSize() + a;
851851
case R_TLSDESC:
852852
return in.got->getTlsDescAddr(sym) + a;
853+
case R_RISCV_TLSDESC_HI:
853854
case R_TLSDESC_PC:
854855
return in.got->getTlsDescAddr(sym) + a - p;
855856
case R_TLSDESC_GOTPLT:

lld/ELF/Relocations.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1269,7 +1269,7 @@ static unsigned handleTlsRelocation(RelType type, Symbol &sym,
12691269
return handleMipsTlsRelocation(type, sym, c, offset, addend, expr);
12701270

12711271
if (oneof<R_AARCH64_TLSDESC_PAGE, R_TLSDESC, R_TLSDESC_CALL, R_TLSDESC_PC,
1272-
R_TLSDESC_GOTPLT>(expr) &&
1272+
R_TLSDESC_GOTPLT, R_RISCV_TLSDESC_HI>(expr) &&
12731273
config->shared) {
12741274
if (expr != R_TLSDESC_CALL) {
12751275
sym.setFlags(NEEDS_TLSDESC);
@@ -1333,7 +1333,7 @@ static unsigned handleTlsRelocation(RelType type, Symbol &sym,
13331333

13341334
if (oneof<R_AARCH64_TLSDESC_PAGE, R_TLSDESC, R_TLSDESC_CALL, R_TLSDESC_PC,
13351335
R_TLSDESC_GOTPLT, R_TLSGD_GOT, R_TLSGD_GOTPLT, R_TLSGD_PC,
1336-
R_LOONGARCH_TLSGD_PAGE_PC>(expr)) {
1336+
R_LOONGARCH_TLSGD_PAGE_PC, R_RISCV_TLSDESC_HI>(expr)) {
13371337
if (!toExecRelax) {
13381338
sym.setFlags(NEEDS_TLSGD);
13391339
c.addReloc({expr, type, offset, addend, &sym});

lld/ELF/Relocations.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@ enum RelExpr {
103103
R_RISCV_ADD,
104104
R_RISCV_LEB128,
105105
R_RISCV_PC_INDIRECT,
106+
R_RISCV_TLSDESC_HI,
107+
R_RISCV_TLSDESC_LOAD_LO,
108+
R_RISCV_TLSDESC_ADD_LO,
109+
R_RISCV_TLSDESC_CALLER,
106110
// Same as R_PC but with page-aligned semantics.
107111
R_LOONGARCH_PAGE_PC,
108112
// Same as R_PLT_PC but with page-aligned semantics.

lld/ELF/Writer.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1943,7 +1943,8 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
19431943
}
19441944
}
19451945

1946-
if (config->emachine == EM_386 || config->emachine == EM_X86_64) {
1946+
if (config->emachine == EM_386 || config->emachine == EM_X86_64 ||
1947+
config->emachine == EM_RISCV) {
19471948
// On targets that support TLSDESC, _TLS_MODULE_BASE_ is defined in such a
19481949
// way that:
19491950
//

lld/test/ELF/riscv-tlsdesc-le.s

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// RUN: llvm-mc -filetype=obj -triple=riscv64-pc-linux %s -o %t.o
2+
// RUN: ld.lld -shared %t.o -o %t.so
3+
// RUN: llvm-objdump --no-print-imm-hex -d --no-show-raw-insn %t.so | FileCheck %s
4+
// RUN: llvm-readelf -r %t.so | FileCheck --check-prefix=REL %s
5+
6+
// CHECK: 00000000000012d8 <_start>:
7+
// CHECK-NEXT: 12d8: auipc a0, 1
8+
// CHECK-NEXT: 12dc: ld a1, 920(a0)
9+
// CHECK-NEXT: 12e0: addi a0, a0, 920
10+
// CHECK-NEXT: 12e4: jalr t0, a1
11+
// CHECK-NEXT: 12e8: add a0, a0, tp
12+
// CHECK-NEXT: 12ec: ret
13+
14+
// REL: Relocation section '.rela.dyn' at offset 0x{{[0-9a-f]+}} contains 2 entries
15+
// REL: R_RISCV_TLSDESC_CALL ffffffffffffffe8
16+
// REL-NEXT: R_RISCV_TLSDESC_CALL 0
17+
18+
.text
19+
.attribute 4, 16
20+
.attribute 5, "rv64i2p1"
21+
.file "<stdin>"
22+
.globl _start # -- Begin function _start
23+
.p2align 2
24+
.type _start,@function
25+
_start: # @_start
26+
# %bb.0: # %entry
27+
.Ltlsdesc_hi0:
28+
auipc a0, %tlsdesc_hi(unspecified)
29+
ld a1, %tlsdesc_load_lo(.Ltlsdesc_hi0)(a0)
30+
addi a0, a0, %tlsdesc_add_lo(.Ltlsdesc_hi0)
31+
jalr t0, 0(a1), %tlsdesc_call(.Ltlsdesc_hi0)
32+
add a0, a0, tp
33+
ret
34+
.Lfunc_end0:
35+
.size _start, .Lfunc_end0-_start
36+
# -- End function
37+
.section ".note.GNU-stack","",@progbits
38+
39+
.section .tbss,"awT",@nobits
40+
.p2align 2
41+
42+
unspecified:
43+
.zero 4

0 commit comments

Comments
 (0)