Skip to content

[BOLT][RISCV] Implement TLS le/ie relocations #67112

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions bolt/lib/Core/Relocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@
using namespace llvm;
using namespace bolt;

namespace ELFReserved {
enum {
R_RISCV_TPREL_I = 49,
R_RISCV_TPREL_S = 50,
};
} // namespace ELFReserved

Triple::ArchType Relocation::Arch;

static bool isSupportedX86(uint64_t Type) {
Expand Down Expand Up @@ -111,6 +118,13 @@ static bool isSupportedRISCV(uint64_t Type) {
case ELF::R_RISCV_LO12_I:
case ELF::R_RISCV_LO12_S:
case ELF::R_RISCV_64:
case ELF::R_RISCV_TLS_GOT_HI20:
case ELF::R_RISCV_TPREL_HI20:
case ELF::R_RISCV_TPREL_ADD:
case ELF::R_RISCV_TPREL_LO12_I:
case ELF::R_RISCV_TPREL_LO12_S:
case ELFReserved::R_RISCV_TPREL_I:
case ELFReserved::R_RISCV_TPREL_S:
return true;
}
}
Expand Down Expand Up @@ -214,6 +228,7 @@ static size_t getSizeForTypeRISCV(uint64_t Type) {
return 4;
case ELF::R_RISCV_64:
case ELF::R_RISCV_GOT_HI20:
case ELF::R_RISCV_TLS_GOT_HI20:
// See extractValueRISCV for why this is necessary.
return 8;
}
Expand Down Expand Up @@ -532,6 +547,7 @@ static uint64_t extractValueRISCV(uint64_t Type, uint64_t Contents,
case ELF::R_RISCV_BRANCH:
return extractBImmRISCV(Contents);
case ELF::R_RISCV_GOT_HI20:
case ELF::R_RISCV_TLS_GOT_HI20:
// We need to know the exact address of the GOT entry so we extract the
// value from both the AUIPC and L[D|W]. We cannot rely on the symbol in the
// relocation for this since it simply refers to the object that is stored
Expand Down Expand Up @@ -600,6 +616,7 @@ static bool isGOTRISCV(uint64_t Type) {
default:
return false;
case ELF::R_RISCV_GOT_HI20:
case ELF::R_RISCV_TLS_GOT_HI20:
return true;
}
}
Expand Down Expand Up @@ -636,6 +653,14 @@ static bool isTLSRISCV(uint64_t Type) {
switch (Type) {
default:
return false;
case ELF::R_RISCV_TLS_GOT_HI20:
case ELF::R_RISCV_TPREL_HI20:
case ELF::R_RISCV_TPREL_ADD:
case ELF::R_RISCV_TPREL_LO12_I:
case ELF::R_RISCV_TPREL_LO12_S:
case ELFReserved::R_RISCV_TPREL_I:
case ELFReserved::R_RISCV_TPREL_S:
return true;
}
}

Expand Down Expand Up @@ -733,6 +758,7 @@ static bool isPCRelativeRISCV(uint64_t Type) {
case ELF::R_RISCV_RVC_JUMP:
case ELF::R_RISCV_RVC_BRANCH:
case ELF::R_RISCV_32_PCREL:
case ELF::R_RISCV_TLS_GOT_HI20:
return true;
}
}
Expand Down
3 changes: 2 additions & 1 deletion bolt/lib/Rewrite/RewriteInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2332,7 +2332,8 @@ void RewriteInstance::handleRelocation(const SectionRef &RelocatedSection,
if (BC->isX86())
return;

// The non-got related TLS relocations on AArch64 also could be skipped.
// The non-got related TLS relocations on AArch64 and RISC-V also could be
// skipped.
if (!Relocation::isGOT(RType))
return;
}
Expand Down
2 changes: 2 additions & 0 deletions bolt/lib/Target/RISCV/RISCVMCPlusBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class RISCVMCPlusBuilder : public MCPlusBuilder {
case ELF::R_RISCV_HI20:
case ELF::R_RISCV_LO12_I:
case ELF::R_RISCV_LO12_S:
case ELF::R_RISCV_TLS_GOT_HI20:
return true;
default:
llvm_unreachable("Unexpected RISCV relocation type in code");
Expand Down Expand Up @@ -396,6 +397,7 @@ class RISCVMCPlusBuilder : public MCPlusBuilder {
default:
return Expr;
case ELF::R_RISCV_GOT_HI20:
case ELF::R_RISCV_TLS_GOT_HI20:
// The GOT is reused so no need to create GOT relocations
case ELF::R_RISCV_PCREL_HI20:
return RISCVMCExpr::create(Expr, RISCVMCExpr::VK_RISCV_PCREL_HI, Ctx);
Expand Down
92 changes: 92 additions & 0 deletions bolt/test/RISCV/Inputs/tls-le-gnu-ld.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Machine: EM_RISCV
Entry: 0x100B0
ProgramHeaders:
- Type: PT_LOAD
Flags: [ PF_X, PF_R ]
FirstSec: .text
LastSec: .text
VAddr: 0x10000
Align: 0x1000
Offset: 0x0
- Type: PT_TLS
Flags: [ PF_R ]
FirstSec: .tbss
LastSec: .tbss
VAddr: 0x110C0
Align: 0x8
Offset: 0xc0
Sections:
- Name: .text
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
Address: 0x100B0
AddressAlign: 0x4
Content: '13000000832202002320520067800000'
- Name: .tbss
Type: SHT_NOBITS
Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
Address: 0x110C0
AddressAlign: 0x8
Size: 0x8
- Name: .rela.text
Type: SHT_RELA
Flags: [ SHF_INFO_LINK ]
Link: .symtab
AddressAlign: 0x8
Info: .text
Relocations:
- Offset: 0x100B4
Type: R_RISCV_NONE
- Offset: 0x100B4
Type: R_RISCV_RELAX
- Offset: 0x100B4
Type: R_RISCV_NONE
- Offset: 0x100B4
Type: R_RISCV_RELAX
- Offset: 0x100B4
Symbol: i
Type: 0x31
- Offset: 0x100B4
Type: R_RISCV_RELAX
- Offset: 0x100B8
Symbol: i
Type: 0x32
- Offset: 0x100B8
Type: R_RISCV_RELAX
- Type: SectionHeaderTable
Sections:
- Name: .text
- Name: .rela.text
- Name: .tbss
- Name: .symtab
- Name: .strtab
- Name: .shstrtab
Symbols:
- Name: .text
Type: STT_SECTION
Section: .text
Value: 0x100B0
- Name: .tbss
Type: STT_SECTION
Section: .tbss
Value: 0x110C0
- Name: '__global_pointer$'
Index: SHN_ABS
Binding: STB_GLOBAL
Value: 0x118C0
- Name: i
Type: STT_TLS
Section: .tbss
Binding: STB_GLOBAL
Size: 0x8
- Name: _start
Section: .text
Binding: STB_GLOBAL
Value: 0x100B0
Size: 0x10
...
44 changes: 44 additions & 0 deletions bolt/test/RISCV/reloc-tls.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// RUN: llvm-mc -triple riscv64 -filetype obj -o %t.o %s
// RUN: ld.lld --emit-relocs -o %t %t.o
// RUN: llvm-bolt --print-cfg --print-only=tls_le,tls_ie -o /dev/null %t \
// RUN: | FileCheck %s

// CHECK-LABEL: Binary Function "tls_le{{.*}}" after building cfg {
// CHECK: lui a5, 0
// CHECK-NEXT: add a5, a5, tp
// CHECK-NEXT: lw t0, 0(a5)
// CHECK-NEXT: sw t0, 0(a5)

// CHECK-LABEL: Binary Function "tls_ie" after building cfg {
// CHECK-LABEL: .Ltmp0
// CHECK: auipc a0, %pcrel_hi(__BOLT_got_zero+{{[0-9]+}})
// CHECK-NEXT: ld a0, %pcrel_lo(.Ltmp0)(a0)
.text
.globl tls_le, _start
.p2align 2
tls_le:
_start:
nop
lui a5, %tprel_hi(i)
add a5, a5, tp, %tprel_add(i)
lw t0, %tprel_lo(i)(a5)
sw t0, %tprel_lo(i)(a5)
ret
.size _start, .-_start

.globl tls_ie
.p2align 2
tls_ie:
nop
la.tls.ie a0, i
ret
.size tls_ie, .-tls_ie

.section .tbss,"awT",@nobits
.type i,@object
.globl i
.p2align 3
i:
.quad 0
.size i, .-i

11 changes: 11 additions & 0 deletions bolt/test/RISCV/tls-le-gnu-ld.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// This test checks that the binaries produces with GNU ld TLS le relaxation are
// properly processed by BOLT. GNU ld currently emits two non-standard
// relocations (R_RISCV_TPREL_I and R_RISCV_TPREL_S) in this case.

// RUN: yaml2obj %p/Inputs/tls-le-gnu-ld.yaml &> %t.exe
// RUN: llvm-bolt %t.exe -o %t.bolt.exe --print-cfg --print-only=_start \
// RUN: | FileCheck %s

// CHECK: Binary Function "_start" after building cfg {
// CHECK: lw t0, 0(tp)
// CHECK-NEXT: sw t0, 0(tp)