Skip to content

Commit c7d6d62

Browse files
authored
[BOLT][RISCV] Implement TLS le/ie relocations (#67112)
Handle the following relocations related to TLS local-exec and initial-exec: - R_RISCV_TLS_GOT_HI20 - R_RISCV_TPREL_HI20 - R_RISCV_TPREL_ADD - R_RISCV_TPREL_LO12_I - R_RISCV_TPREL_LO12_S In addition, GNU ld has a quirk where after TLS le relaxation, two unofficial relocation types may be emitted: - R_RISCV_TPREL_I - R_RISCV_TPREL_S Since they are unofficial (defined in the reserved range of relocation types), LLVM does not define them. Hence, I've defined them locally in BOLT in a private namespace.
1 parent 7c5e4e5 commit c7d6d62

File tree

6 files changed

+177
-1
lines changed

6 files changed

+177
-1
lines changed

bolt/lib/Core/Relocation.cpp

+26
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@
2020
using namespace llvm;
2121
using namespace bolt;
2222

23+
namespace ELFReserved {
24+
enum {
25+
R_RISCV_TPREL_I = 49,
26+
R_RISCV_TPREL_S = 50,
27+
};
28+
} // namespace ELFReserved
29+
2330
Triple::ArchType Relocation::Arch;
2431

2532
static bool isSupportedX86(uint64_t Type) {
@@ -111,6 +118,13 @@ static bool isSupportedRISCV(uint64_t Type) {
111118
case ELF::R_RISCV_LO12_I:
112119
case ELF::R_RISCV_LO12_S:
113120
case ELF::R_RISCV_64:
121+
case ELF::R_RISCV_TLS_GOT_HI20:
122+
case ELF::R_RISCV_TPREL_HI20:
123+
case ELF::R_RISCV_TPREL_ADD:
124+
case ELF::R_RISCV_TPREL_LO12_I:
125+
case ELF::R_RISCV_TPREL_LO12_S:
126+
case ELFReserved::R_RISCV_TPREL_I:
127+
case ELFReserved::R_RISCV_TPREL_S:
114128
return true;
115129
}
116130
}
@@ -214,6 +228,7 @@ static size_t getSizeForTypeRISCV(uint64_t Type) {
214228
return 4;
215229
case ELF::R_RISCV_64:
216230
case ELF::R_RISCV_GOT_HI20:
231+
case ELF::R_RISCV_TLS_GOT_HI20:
217232
// See extractValueRISCV for why this is necessary.
218233
return 8;
219234
}
@@ -532,6 +547,7 @@ static uint64_t extractValueRISCV(uint64_t Type, uint64_t Contents,
532547
case ELF::R_RISCV_BRANCH:
533548
return extractBImmRISCV(Contents);
534549
case ELF::R_RISCV_GOT_HI20:
550+
case ELF::R_RISCV_TLS_GOT_HI20:
535551
// We need to know the exact address of the GOT entry so we extract the
536552
// value from both the AUIPC and L[D|W]. We cannot rely on the symbol in the
537553
// relocation for this since it simply refers to the object that is stored
@@ -600,6 +616,7 @@ static bool isGOTRISCV(uint64_t Type) {
600616
default:
601617
return false;
602618
case ELF::R_RISCV_GOT_HI20:
619+
case ELF::R_RISCV_TLS_GOT_HI20:
603620
return true;
604621
}
605622
}
@@ -636,6 +653,14 @@ static bool isTLSRISCV(uint64_t Type) {
636653
switch (Type) {
637654
default:
638655
return false;
656+
case ELF::R_RISCV_TLS_GOT_HI20:
657+
case ELF::R_RISCV_TPREL_HI20:
658+
case ELF::R_RISCV_TPREL_ADD:
659+
case ELF::R_RISCV_TPREL_LO12_I:
660+
case ELF::R_RISCV_TPREL_LO12_S:
661+
case ELFReserved::R_RISCV_TPREL_I:
662+
case ELFReserved::R_RISCV_TPREL_S:
663+
return true;
639664
}
640665
}
641666

@@ -733,6 +758,7 @@ static bool isPCRelativeRISCV(uint64_t Type) {
733758
case ELF::R_RISCV_RVC_JUMP:
734759
case ELF::R_RISCV_RVC_BRANCH:
735760
case ELF::R_RISCV_32_PCREL:
761+
case ELF::R_RISCV_TLS_GOT_HI20:
736762
return true;
737763
}
738764
}

bolt/lib/Rewrite/RewriteInstance.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -2334,7 +2334,8 @@ void RewriteInstance::handleRelocation(const SectionRef &RelocatedSection,
23342334
if (BC->isX86())
23352335
return;
23362336

2337-
// The non-got related TLS relocations on AArch64 also could be skipped.
2337+
// The non-got related TLS relocations on AArch64 and RISC-V also could be
2338+
// skipped.
23382339
if (!Relocation::isGOT(RType))
23392340
return;
23402341
}

bolt/lib/Target/RISCV/RISCVMCPlusBuilder.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class RISCVMCPlusBuilder : public MCPlusBuilder {
4646
case ELF::R_RISCV_HI20:
4747
case ELF::R_RISCV_LO12_I:
4848
case ELF::R_RISCV_LO12_S:
49+
case ELF::R_RISCV_TLS_GOT_HI20:
4950
return true;
5051
default:
5152
llvm_unreachable("Unexpected RISCV relocation type in code");
@@ -396,6 +397,7 @@ class RISCVMCPlusBuilder : public MCPlusBuilder {
396397
default:
397398
return Expr;
398399
case ELF::R_RISCV_GOT_HI20:
400+
case ELF::R_RISCV_TLS_GOT_HI20:
399401
// The GOT is reused so no need to create GOT relocations
400402
case ELF::R_RISCV_PCREL_HI20:
401403
return RISCVMCExpr::create(Expr, RISCVMCExpr::VK_RISCV_PCREL_HI, Ctx);
+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
--- !ELF
2+
FileHeader:
3+
Class: ELFCLASS64
4+
Data: ELFDATA2LSB
5+
Type: ET_EXEC
6+
Machine: EM_RISCV
7+
Entry: 0x100B0
8+
ProgramHeaders:
9+
- Type: PT_LOAD
10+
Flags: [ PF_X, PF_R ]
11+
FirstSec: .text
12+
LastSec: .text
13+
VAddr: 0x10000
14+
Align: 0x1000
15+
Offset: 0x0
16+
- Type: PT_TLS
17+
Flags: [ PF_R ]
18+
FirstSec: .tbss
19+
LastSec: .tbss
20+
VAddr: 0x110C0
21+
Align: 0x8
22+
Offset: 0xc0
23+
Sections:
24+
- Name: .text
25+
Type: SHT_PROGBITS
26+
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
27+
Address: 0x100B0
28+
AddressAlign: 0x4
29+
Content: '13000000832202002320520067800000'
30+
- Name: .tbss
31+
Type: SHT_NOBITS
32+
Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
33+
Address: 0x110C0
34+
AddressAlign: 0x8
35+
Size: 0x8
36+
- Name: .rela.text
37+
Type: SHT_RELA
38+
Flags: [ SHF_INFO_LINK ]
39+
Link: .symtab
40+
AddressAlign: 0x8
41+
Info: .text
42+
Relocations:
43+
- Offset: 0x100B4
44+
Type: R_RISCV_NONE
45+
- Offset: 0x100B4
46+
Type: R_RISCV_RELAX
47+
- Offset: 0x100B4
48+
Type: R_RISCV_NONE
49+
- Offset: 0x100B4
50+
Type: R_RISCV_RELAX
51+
- Offset: 0x100B4
52+
Symbol: i
53+
Type: 0x31
54+
- Offset: 0x100B4
55+
Type: R_RISCV_RELAX
56+
- Offset: 0x100B8
57+
Symbol: i
58+
Type: 0x32
59+
- Offset: 0x100B8
60+
Type: R_RISCV_RELAX
61+
- Type: SectionHeaderTable
62+
Sections:
63+
- Name: .text
64+
- Name: .rela.text
65+
- Name: .tbss
66+
- Name: .symtab
67+
- Name: .strtab
68+
- Name: .shstrtab
69+
Symbols:
70+
- Name: .text
71+
Type: STT_SECTION
72+
Section: .text
73+
Value: 0x100B0
74+
- Name: .tbss
75+
Type: STT_SECTION
76+
Section: .tbss
77+
Value: 0x110C0
78+
- Name: '__global_pointer$'
79+
Index: SHN_ABS
80+
Binding: STB_GLOBAL
81+
Value: 0x118C0
82+
- Name: i
83+
Type: STT_TLS
84+
Section: .tbss
85+
Binding: STB_GLOBAL
86+
Size: 0x8
87+
- Name: _start
88+
Section: .text
89+
Binding: STB_GLOBAL
90+
Value: 0x100B0
91+
Size: 0x10
92+
...

bolt/test/RISCV/reloc-tls.s

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// RUN: llvm-mc -triple riscv64 -filetype obj -o %t.o %s
2+
// RUN: ld.lld --emit-relocs -o %t %t.o
3+
// RUN: llvm-bolt --print-cfg --print-only=tls_le,tls_ie -o /dev/null %t \
4+
// RUN: | FileCheck %s
5+
6+
// CHECK-LABEL: Binary Function "tls_le{{.*}}" after building cfg {
7+
// CHECK: lui a5, 0
8+
// CHECK-NEXT: add a5, a5, tp
9+
// CHECK-NEXT: lw t0, 0(a5)
10+
// CHECK-NEXT: sw t0, 0(a5)
11+
12+
// CHECK-LABEL: Binary Function "tls_ie" after building cfg {
13+
// CHECK-LABEL: .Ltmp0
14+
// CHECK: auipc a0, %pcrel_hi(__BOLT_got_zero+{{[0-9]+}})
15+
// CHECK-NEXT: ld a0, %pcrel_lo(.Ltmp0)(a0)
16+
.text
17+
.globl tls_le, _start
18+
.p2align 2
19+
tls_le:
20+
_start:
21+
nop
22+
lui a5, %tprel_hi(i)
23+
add a5, a5, tp, %tprel_add(i)
24+
lw t0, %tprel_lo(i)(a5)
25+
sw t0, %tprel_lo(i)(a5)
26+
ret
27+
.size _start, .-_start
28+
29+
.globl tls_ie
30+
.p2align 2
31+
tls_ie:
32+
nop
33+
la.tls.ie a0, i
34+
ret
35+
.size tls_ie, .-tls_ie
36+
37+
.section .tbss,"awT",@nobits
38+
.type i,@object
39+
.globl i
40+
.p2align 3
41+
i:
42+
.quad 0
43+
.size i, .-i
44+

bolt/test/RISCV/tls-le-gnu-ld.test

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// This test checks that the binaries produces with GNU ld TLS le relaxation are
2+
// properly processed by BOLT. GNU ld currently emits two non-standard
3+
// relocations (R_RISCV_TPREL_I and R_RISCV_TPREL_S) in this case.
4+
5+
// RUN: yaml2obj %p/Inputs/tls-le-gnu-ld.yaml &> %t.exe
6+
// RUN: llvm-bolt %t.exe -o %t.bolt.exe --print-cfg --print-only=_start \
7+
// RUN: | FileCheck %s
8+
9+
// CHECK: Binary Function "_start" after building cfg {
10+
// CHECK: lw t0, 0(tp)
11+
// CHECK-NEXT: sw t0, 0(tp)

0 commit comments

Comments
 (0)