Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -90,28 +90,36 @@ // support any relaxations for TLS relocations so by factoring out ARM and MIPS // handling in to the separate function we can simplify the code and do not // pollute `handleTlsRelocation` by ARM and MIPS `ifs` statements. -// FIXME: The ARM implementation always adds the module index dynamic -// relocation even for non-preemptible symbols in applications. For static -// linking support we must either resolve the module index relocation at static -// link time, or hard code the module index (1) for the application in the GOT. template static unsigned handleNoRelaxTlsRelocation( GOT *Got, uint32_t Type, SymbolBody &Body, InputSectionBase &C, typename ELFT::uint Offset, typename ELFT::uint Addend, RelExpr Expr) { + typedef typename ELFT::uint uintX_t; + auto addModuleReloc = [](SymbolBody &Body, GOT *Got, uintX_t Off, bool LD) { + // The Dynamic TLS Module Index Relocation can be statically resolved to 1 + // if we know that we are linking an executable. For ARM we resolve the + // relocation when writing the Got. MIPS has a custom Got implementation + // that writes the Module index in directly. + if (!Body.isPreemptible() && !Config->Pic && Config->EMachine == EM_ARM) + Got->Relocations.push_back( + {R_ABS, Target->TlsModuleIndexRel, Off, 0, &Body}); + else { + SymbolBody *Dest = LD ? nullptr : &Body; + In::RelaDyn->addReloc( + {Target->TlsModuleIndexRel, Got, Off, false, Dest, 0}); + } + }; if (Expr == R_MIPS_TLSLD || Expr == R_TLSLD_PC) { if (Got->addTlsIndex() && (Config->Pic || Config->EMachine == EM_ARM)) - In::RelaDyn->addReloc({Target->TlsModuleIndexRel, Got, - Got->getTlsIndexOff(), false, nullptr, 0}); + addModuleReloc(Body, Got, Got->getTlsIndexOff(), true); C.Relocations.push_back({Expr, Type, Offset, Addend, &Body}); return 1; } - typedef typename ELFT::uint uintX_t; if (Target->isTlsGlobalDynamicRel(Type)) { if (Got->addDynTlsEntry(Body) && (Body.isPreemptible() || Config->EMachine == EM_ARM)) { uintX_t Off = Got->getGlobalDynOffset(Body); - In::RelaDyn->addReloc( - {Target->TlsModuleIndexRel, Got, Off, false, &Body, 0}); + addModuleReloc(Body, Got, Off, false); if (Body.isPreemptible()) In::RelaDyn->addReloc({Target->TlsOffsetRel, Got, Off + (uintX_t)sizeof(uintX_t), false, @@ -746,9 +754,11 @@ In::Got->addEntry(Body); uintX_t Off = Body.getGotOffset(); uint32_t DynType; - if (Body.isTls()) + RelExpr GotRE = R_ABS; + if (Body.isTls()) { DynType = Target->TlsGotRel; - else if (!Preemptible && Config->Pic && !isAbsolute(Body)) + GotRE = R_TLS; + } else if (!Preemptible && Config->Pic && !isAbsolute(Body)) DynType = Target->RelativeRel; else DynType = Target->GotRel; @@ -756,7 +766,7 @@ if (Preemptible || (Config->Pic && !isAbsolute(Body))) AddDyn({DynType, In::Got, Off, !Preemptible, &Body, 0}); else - In::Got->Relocations.push_back({R_ABS, DynType, Off, 0, &Body}); + In::Got->Relocations.push_back({GotRE, DynType, Off, 0, &Body}); continue; } } Index: ELF/Target.cpp =================================================================== --- ELF/Target.cpp +++ ELF/Target.cpp @@ -1711,6 +1711,9 @@ case R_ARM_TLS_TPOFF32: write32le(Loc, Val); break; + case R_ARM_TLS_DTPMOD32: + write32le(Loc, 1); + break; case R_ARM_PREL31: checkInt<31>(Loc, Val, Type); write32le(Loc, (read32le(Loc) & 0x80000000) | (Val & ~0x80000000)); Index: test/ELF/arm-tls-norelax-gd-le.s =================================================================== --- test/ELF/arm-tls-norelax-gd-le.s +++ test/ELF/arm-tls-norelax-gd-le.s @@ -2,7 +2,7 @@ // RUN: ld.lld %t1 --shared -o %t1.so // RUN: llvm-mc %s -o %t.o -filetype=obj -triple=armv7a-linux-gnueabi // RUN: ld.lld %t1.so %t.o -o %t -// RUN: llvm-readobj -s -dyn-relocations %t | FileCheck %s +// RUN: llvm-objdump -s %t | FileCheck %s // REQUIRES: arm // This tls global-dynamic sequence is with respect to a non-preemptible @@ -31,7 +31,7 @@ .space 4 .type x, %object -// CHECK: Dynamic Relocations { -// CHECK-NEXT: 0x12078 R_ARM_TLS_DTPMOD32 -// CHECK-NEXT: 0x1300C R_ARM_JUMP_SLOT __tls_get_addr +// CHECK: Contents of section .got: +// Module index is always 1 for executable +// CHECK-NEXT: 12060 01000000 00000000 Index: test/ELF/arm-tls-norelax-ie-le.s =================================================================== --- test/ELF/arm-tls-norelax-ie-le.s +++ test/ELF/arm-tls-norelax-ie-le.s @@ -2,7 +2,7 @@ // RUN: ld.lld %t1 --shared -o %t1.so // RUN: llvm-mc %s -o %t.o -filetype=obj -triple=armv7a-linux-gnueabi // RUN: ld.lld %t1.so %t.o -o %t -// RUN: llvm-objdump -s -triple=armv7a-linux-gnueabi %t +// RUN: llvm-objdump -s -triple=armv7a-linux-gnueabi %t | FileCheck %s // REQUIRES: arm // This tls Initial Exec sequence is with respect to a non-preemptible symbol @@ -37,5 +37,5 @@ .type x2, %object // CHECK: Contents of section .got -// x1 at offset 0 from TP, x2 at offset 4 from TP -// 12064 00000000 04000000 +// x1 at offset 8 from TP, x2 at offset c from TP. Offsets include TCB size of 8 +// CHECK-NEXT: 12064 08000000 0c000000 Index: test/ELF/arm-tls-norelax-ld-le.s =================================================================== --- test/ELF/arm-tls-norelax-ld-le.s +++ test/ELF/arm-tls-norelax-ld-le.s @@ -2,7 +2,7 @@ // RUN: ld.lld %t1 --shared -o %t1.so // RUN: llvm-mc %s -o %t.o -filetype=obj -triple=armv7a-linux-gnueabi // RUN: ld.lld %t1.so %t.o -o %t -// RUN: llvm-readobj -s -dyn-relocations %t | FileCheck %s +// RUN: llvm-objdump -s %t | FileCheck %s // REQUIRES: arm .global __tls_get_addr @@ -31,6 +31,5 @@ x: .word 10 -// CHECK: Dynamic Relocations { -// CHECK-NEXT: 0x1207C R_ARM_TLS_DTPMOD32 - 0x0 -// CHECK-NEXT: 0x1300C R_ARM_JUMP_SLOT __tls_get_addr 0x0 +// CHECK: Contents of section .got: +// CHECK-NEXT: 12064 01000000 00000000