diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 6d5c4cb59287..72b7be8165e0 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -312,9 +312,6 @@ struct Configuration { // if that's true.) bool isMips64EL; - // True if we need to reserve two .got entries for local-dynamic TLS model. - bool needsTlsLd = false; - // True if we need to set the DF_STATIC_TLS flag to an output file, which // works as a hint to the dynamic loader that the shared object contains code // compiled with the initial-exec TLS model. diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 1994a2b35199..58a61b4154dc 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -1238,7 +1238,7 @@ static unsigned handleTlsRelocation(RelType type, Symbol &sym, } if (expr == R_TLSLD_HINT) return 1; - config->needsTlsLd = true; + sym.needsTlsLd = true; c.relocations.push_back({expr, type, offset, addend, &sym}); return 1; } @@ -1681,6 +1681,15 @@ void elf::postScanRelocations() { mainPart->relaDyn->addSymbolReloc(target->tlsGotRel, *in.got, sym.getGotOffset(), sym); } + + if (sym.needsTlsLd && in.got->addTlsIndex()) { + if (isLocalInExecutable) + in.got->relocations.push_back( + {R_ADDEND, target->symbolicRel, in.got->getTlsIndexOff(), 1, &sym}); + else + mainPart->relaDyn->addReloc({target->tlsModuleIndexRel, in.got.get(), + in.got->getTlsIndexOff()}); + } if (sym.needsGotDtprel) { in.got->addEntry(sym); in.got->relocations.push_back( @@ -1691,15 +1700,6 @@ void elf::postScanRelocations() { addTpOffsetGotEntry(sym); }; - if (config->needsTlsLd && in.got->addTlsIndex()) { - if (config->shared) - mainPart->relaDyn->addReloc( - {target->tlsModuleIndexRel, in.got.get(), in.got->getTlsIndexOff()}); - else - in.got->relocations.push_back({R_ADDEND, target->symbolicRel, - in.got->getTlsIndexOff(), 1, nullptr}); - } - assert(symAux.empty()); for (Symbol *sym : symtab->symbols()) fn(*sym); diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h index 271b0fadae23..b68260166799 100644 --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -247,8 +247,8 @@ protected: isInIplt(false), gotInIgot(false), folded(false), needsTocRestore(false), scriptDefined(false), needsCopy(false), needsGot(false), needsPlt(false), needsTlsDesc(false), - needsTlsGd(false), needsTlsGdToIe(false), needsGotDtprel(false), - needsTlsIe(false), hasDirectReloc(false) {} + needsTlsGd(false), needsTlsGdToIe(false), needsTlsLd(false), + needsGotDtprel(false), needsTlsIe(false), hasDirectReloc(false) {} public: // True if this symbol is in the Iplt sub-section of the Plt and the Igot @@ -283,6 +283,7 @@ public: uint8_t needsTlsDesc : 1; uint8_t needsTlsGd : 1; uint8_t needsTlsGdToIe : 1; + uint8_t needsTlsLd : 1; uint8_t needsGotDtprel : 1; uint8_t needsTlsIe : 1; uint8_t hasDirectReloc : 1; @@ -300,7 +301,7 @@ public: bool needsDynReloc() const { return needsCopy || needsGot || needsPlt || needsTlsDesc || needsTlsGd || - needsTlsGdToIe || needsGotDtprel || needsTlsIe; + needsTlsGdToIe || needsTlsLd || needsGotDtprel || needsTlsIe; } void allocateAux() { assert(auxIdx == uint32_t(-1)); @@ -512,9 +513,9 @@ union SymbolUnion { }; // It is important to keep the size of SymbolUnion small for performance and -// memory usage reasons. 64 bytes is a soft limit based on the size of Defined +// memory usage reasons. 72 bytes is a soft limit based on the size of Defined // on a 64-bit system. -static_assert(sizeof(SymbolUnion) <= 64, "SymbolUnion too large"); +static_assert(sizeof(SymbolUnion) <= 72, "SymbolUnion too large"); template struct AssertSymbol { static_assert(std::is_trivially_destructible(), diff --git a/lld/test/ELF/i386-tls-dynamic.s b/lld/test/ELF/i386-tls-dynamic.s index cff442e8ead3..d61ee5526bb1 100644 --- a/lld/test/ELF/i386-tls-dynamic.s +++ b/lld/test/ELF/i386-tls-dynamic.s @@ -66,13 +66,13 @@ addl tls1@gotntpoff(%ebx),%eax # CHECK: Relocations [ # CHECK: Section ({{.+}}) .rel.dyn { -# CHECK-NEXT: 0x2358 R_386_TLS_DTPMOD32 - -# CHECK-NEXT: 0x2360 R_386_TLS_DTPMOD32 tls0 -# CHECK-NEXT: 0x2364 R_386_TLS_DTPOFF32 tls0 -# CHECK-NEXT: 0x2368 R_386_TLS_TPOFF tls0 -# CHECK-NEXT: 0x236C R_386_TLS_DTPMOD32 tls1 -# CHECK-NEXT: 0x2370 R_386_TLS_DTPOFF32 tls1 -# CHECK-NEXT: 0x2374 R_386_TLS_TPOFF tls1 +# CHECK-NEXT: 0x2370 R_386_TLS_DTPMOD32 - +# CHECK-NEXT: 0x2358 R_386_TLS_DTPMOD32 tls0 +# CHECK-NEXT: 0x235C R_386_TLS_DTPOFF32 tls0 +# CHECK-NEXT: 0x2360 R_386_TLS_TPOFF tls0 +# CHECK-NEXT: 0x2364 R_386_TLS_DTPMOD32 tls1 +# CHECK-NEXT: 0x2368 R_386_TLS_DTPOFF32 tls1 +# CHECK-NEXT: 0x236C R_386_TLS_TPOFF tls1 # CHECK-NEXT: } # DIS: Disassembly of section .text: @@ -81,20 +81,20 @@ addl tls1@gotntpoff(%ebx),%eax ## General dynamic model: ## -4128 and -4116 are first and second GOT entries offsets. ## Each one is a pair of records. -# DIS-NEXT: 1260: leal -4120(,%ebx), %eax +# DIS-NEXT: 1260: leal -4128(,%ebx), %eax # DIS-NEXT: 1267: calll 0x12d0 -# DIS-NEXT: 126c: leal -4108(,%ebx), %eax +# DIS-NEXT: 126c: leal -4116(,%ebx), %eax # DIS-NEXT: 1273: calll 0x12d0 ## Local dynamic model: ## -16 is a local module tls index offset. -# DIS-NEXT: 1278: leal -4128(%ebx), %eax +# DIS-NEXT: 1278: leal -4104(%ebx), %eax # DIS-NEXT: 127e: calll 0x12d0 # DIS-NEXT: 1283: leal 8(%eax), %edx -# DIS-NEXT: 1289: leal -4128(%ebx), %eax +# DIS-NEXT: 1289: leal -4104(%ebx), %eax # DIS-NEXT: 128f: calll 0x12d0 # DIS-NEXT: 1294: leal 12(%eax), %edx ## Initial exec model: # DIS-NEXT: 129a: movl %gs:0, %eax -# DIS-NEXT: 12a0: addl -4112(%ebx), %eax +# DIS-NEXT: 12a0: addl -4120(%ebx), %eax # DIS-NEXT: 12a6: movl %gs:0, %eax -# DIS-NEXT: 12ac: addl -4100(%ebx), %eax +# DIS-NEXT: 12ac: addl -4108(%ebx), %eax diff --git a/lld/test/ELF/ppc64-tls-missing-gdld.s b/lld/test/ELF/ppc64-tls-missing-gdld.s index 16a3085872c0..2d1954e95b19 100644 --- a/lld/test/ELF/ppc64-tls-missing-gdld.s +++ b/lld/test/ELF/ppc64-tls-missing-gdld.s @@ -25,28 +25,28 @@ ## .got+32: TPOFFSET for x = st_value-0x7000 # HEX: section '.got': # HEX-NEXT: [[#%x,IGNORE:]] 50820210 00000000 01000000 00000000 -# HEX-NEXT: [[#%x,IGNORE:]] 00000000 00000000 01000000 00000000 -# HEX-NEXT: [[#%x,IGNORE:]] 0080ffff ffffffff 0090ffff ffffffff +# HEX-NEXT: [[#%x,IGNORE:]] 0080ffff ffffffff 01000000 00000000 +# HEX-NEXT: [[#%x,IGNORE:]] 00000000 00000000 0090ffff ffffffff ## .TOC.-32768 = (.got+0x8000)-32768 = .got # DIS-LABEL: : # DIS-NEXT: addis 3, 2, 0 -# DIS-NEXT: addi 3, 3, -32744 +# DIS-NEXT: addi 3, 3, -32760 # DIS-NEXT: bl [[#%x,TGA:]] # DIS-LABEL: : # DIS-NEXT: addis 3, 2, 0 -# DIS-NEXT: addi 3, 3, -32744 +# DIS-NEXT: addi 3, 3, -32760 # DIS-NEXT: bl [[#TGA]] ## LocalDynamic references _TLS_MODULE_BASE_. ## .TOC.-32752 = (.got+0x8000)-32752 = .got+16 # DIS-LABEL: : # DIS-NEXT: addis 3, 2, 0 -# DIS-NEXT: addi 3, 3, -32760 +# DIS-NEXT: addi 3, 3, -32744 # DIS-NEXT: bl [[#TGA]] # DIS-LABEL: : # DIS-NEXT: addis 3, 2, 0 -# DIS-NEXT: addi 3, 3, -32760 +# DIS-NEXT: addi 3, 3, -32744 # DIS-NEXT: bl [[#TGA]] ## Technically we don't have to disable IE to LE relaxation,