Skip to content
Open
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
13 changes: 11 additions & 2 deletions lib/Target/AArch64/AArch64Relocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -307,8 +307,15 @@ void AArch64Relocator::scanLocalReloc(InputFile &pInput, Relocation &pReloc,
if (config().isCodeStatic())
return;
AArch64GOT *G = m_Target.createGOT(GOT::TLS_IE, Obj, rsym);
if (config().isBuildingExecutable()) {
G->setValueType(GOT::TLSStaticSymbolValue);
if (rsym->reserved() == Relocator::None)
rsym->setReserved(rsym->reserved() | ReserveGOT);
return;
}
helper_DynRel_init(Obj, &pReloc, rsym, G, 0x0,
llvm::ELF::R_AARCH64_TLS_TPREL64, m_Target);
m_Target.setHasStaticTLS();
if (rsym->reserved() == Relocator::None)
rsym->setReserved(rsym->reserved() | ReserveGOT);
return;
Expand Down Expand Up @@ -535,13 +542,15 @@ void AArch64Relocator::scanGlobalReloc(InputFile &pInput, Relocation &pReloc,

// set up the got and the corresponding rel entry
AArch64GOT *G = m_Target.createGOT(GOT::TLS_IE, Obj, rsym);
if (config().isCodeStatic()) {
if (config().isCodeStatic() || (config().isBuildingExecutable() &&
!m_Target.isSymbolPreemptible(*rsym))) {
rsym->setReserved(rsym->reserved() | ReserveGOT);
G->setValueType(GOT::TLSStaticSymbolValue);
return;
}
helper_DynRel_init(Obj, &pReloc, rsym, G, 0x0,
llvm::ELF::R_AARCH64_TLS_TPREL64, m_Target);
m_Target.setHasStaticTLS();
rsym->setReserved(rsym->reserved() | ReserveGOT);
return;
}
Expand Down Expand Up @@ -1408,4 +1417,4 @@ bool AArch64Relocator::isControlFlowRelocation(
return true;
}
return false;
}
}
9 changes: 6 additions & 3 deletions lib/Target/ARM/ARMRelocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -469,13 +469,14 @@ void ARMRelocator::scanLocalReloc(InputFile &pInput, Relocation::Type Type,

// set up the got and the corresponding rel entry
ARMGOT *G = m_Target.createGOT(GOT::TLS_IE, Obj, rsym);
if (config().isCodeStatic()) {
if (config().isCodeStatic() || config().isBuildingExecutable()) {
rsym->setReserved(rsym->reserved() | ReserveGOT);
G->setValueType(GOT::TLSStaticSymbolValue);
return;
}
helper_DynRel_init(Obj, &pReloc, rsym, G, 0x0, llvm::ELF::R_ARM_TLS_TPOFF32,
m_Target);
m_Target.setHasStaticTLS();
if (rsym->reserved() == Relocator::None)
rsym->setReserved(rsym->reserved() | ReserveGOT);
return;
Expand Down Expand Up @@ -763,13 +764,15 @@ void ARMRelocator::scanGlobalReloc(InputFile &pInput, Relocation::Type Type,

// set up the got and the corresponding rel entry
ARMGOT *G = m_Target.createGOT(GOT::TLS_IE, Obj, rsym);
if (config().isCodeStatic()) {
if (config().isCodeStatic() || (config().isBuildingExecutable() &&
!m_Target.isSymbolPreemptible(*rsym))) {
rsym->setReserved(rsym->reserved() | ReserveGOT);
G->setValueType(GOT::TLSStaticSymbolValue);
return;
}
helper_DynRel_init(Obj, &pReloc, rsym, G, 0x0, llvm::ELF::R_ARM_TLS_TPOFF32,
m_Target);
m_Target.setHasStaticTLS();
rsym->setReserved(rsym->reserved() | ReserveGOT);
return;
}
Expand Down Expand Up @@ -1615,4 +1618,4 @@ void ARMRelocator::computeTLSOffsets() {
StaticTLSBlockVarOffset = 2 * WordSize;
*StaticTLSBlockVarOffset +=
((FirstTLSSegVirtualAddr - 2 * WordSize) & (MaxTLSSegAlignment - 1));
}
}
5 changes: 3 additions & 2 deletions lib/Target/Hexagon/HexagonRelocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,8 @@ void HexagonRelocator::CreateGOTIE(ELFObjectFile *Obj,

// set up the got and the corresponding rel entry
HexagonGOT *G = m_Target.createGOT(GOT::TLS_IE, Obj, rsym);
if (config().isCodeStatic())
if (config().isCodeStatic() ||
(config().isBuildingExecutable() && !m_Target.isSymbolPreemptible(*rsym)))
G->setValueType(GOT::TLSStaticSymbolValue);
else
helper_DynRel_init(Obj, &pReloc, rsym, G, 0x0, llvm::ELF::R_HEX_TPREL_32,
Expand Down Expand Up @@ -635,7 +636,7 @@ void HexagonRelocator::defineSymbolforGuard(eld::IRBuilder &pBuilder,
config().raise(Diag::target_specific_symbol) << SymbolName;
if (layoutInfo)
layoutInfo->recordFragment(guardSection->getInputFile(), guardSection,
frag);
frag);
}
config().raise(Diag::resolve_undef_weak_guard)
<< pSym->name() << pSym->resolvedOrigin()->getInput()->decoratedPath()
Expand Down
7 changes: 5 additions & 2 deletions lib/Target/RISCV/RISCVRelocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -581,14 +581,15 @@ void RISCVRelocator::scanLocalReloc(InputFile &pInput, Relocation &pReloc,
return;
RISCVGOT *G = m_Target.createGOT(GOT::TLS_IE, Obj, rsym);
rsym->setReserved(rsym->reserved() | ReserveGOT);
if (config().isCodeStatic()) {
if (config().isCodeStatic() || config().isBuildingExecutable()) {
G->setValueType(GOT::TLSStaticSymbolValue);
return;
}
helper_DynRel_init(Obj, &pReloc, rsym, G, 0x0,
is32bit() ? llvm::ELF::R_RISCV_TLS_TPREL32
: llvm::ELF::R_RISCV_TLS_TPREL64,
m_Target);
m_Target.setHasStaticTLS();
break;
}

Expand Down Expand Up @@ -733,14 +734,16 @@ void RISCVRelocator::scanGlobalReloc(InputFile &pInputFile, Relocation &pReloc,
return;
RISCVGOT *G = m_Target.createGOT(GOT::TLS_IE, Obj, rsym);
rsym->setReserved(rsym->reserved() | ReserveGOT);
if (config().isCodeStatic()) {
if (config().isCodeStatic() || (config().isBuildingExecutable() &&
!m_Target.isSymbolPreemptible(*rsym))) {
G->setValueType(GOT::TLSStaticSymbolValue);
return;
}
helper_DynRel_init(Obj, &pReloc, rsym, G, 0x0,
is32bit() ? llvm::ELF::R_RISCV_TLS_TPREL32
: llvm::ELF::R_RISCV_TLS_TPREL64,
m_Target);
m_Target.setHasStaticTLS();
break;
}

Expand Down
30 changes: 30 additions & 0 deletions test/Common/standalone/TLS/TLSIEPIE/TLSIEPIE.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/// Verifies that R_*_GOTTPOFF / R_*_TLSIE relocations against a static TLS
/// symbol cause the linker to emit a TPREL/TPOFF dynamic relocation when the
/// output is a shared object, and are statically resolved for PIE. Both a
/// local and a non-preemptible global TLS symbol are tested.

// RUN: %clang %clangopts -c -x c %s -fPIC -ftls-model=initial-exec -o %t.o
// RUN: %link %linkopts -shared %t.o -o %t.so
// RUN: %readelf -r -d %t.so | %filecheck %s --check-prefix=SHARED
// RUN: %link %linkopts -pie %t.o -o %t.pie --defsym __libc_start_main=0
// RUN: %readelf -r %t.pie | %filecheck %s --check-prefix=PIE

/// Target relocation types:
/// R_X86_64_TPOFF64
/// R_AARCH64_TLS_TPREL64
/// R_ARM_TLS_TPOFF32
/// R_RISCV_TLS_TPREL64
/// R_RISCV_TLS_TPREL32
/// R_HEX_TPREL_32
// SHARED: FLAGS
// SHARED-SAME: STATIC_TLS
/// Local symbol: dynamic reloc with no symbol name.
// SHARED: R_{{.*}}TP{{(REL|OFF)_?[0-9]+}}
/// Global symbol: dynamic reloc naming the symbol.
// SHARED: R_{{.*}}TP{{(REL|OFF)_?[0-9]+}} {{.*}}global_tls
// PIE: There are no relocations in this file.

static __thread int local_tls = 10;
__thread int global_tls = 20;
int foo(void) { return local_tls + global_tls; }
void *__aeabi_read_tp(void) { return 0; }
Loading