diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 72b7be8165e05f..6d5c4cb5928789 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -312,6 +312,9 @@ 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 58a61b4154dc42..f2b312c7729c33 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; - sym.needsTlsLd = true; + config->needsTlsLd = true; c.relocations.push_back({expr, type, offset, addend, &sym}); return 1; } @@ -1681,15 +1681,6 @@ 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( @@ -1700,6 +1691,16 @@ void elf::postScanRelocations() { addTpOffsetGotEntry(sym); }; + if (config->needsTlsLd && in.got->addTlsIndex()) { + static Undefined dummy(nullptr, "", STB_LOCAL, 0, 0); + 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, &dummy}); + } + assert(symAux.empty()); for (Symbol *sym : symtab->symbols()) fn(*sym); diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h index b6826016679907..271b0fadae23c2 100644 --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -247,8 +247,8 @@ class Symbol { isInIplt(false), gotInIgot(false), folded(false), needsTocRestore(false), scriptDefined(false), needsCopy(false), needsGot(false), needsPlt(false), needsTlsDesc(false), - needsTlsGd(false), needsTlsGdToIe(false), needsTlsLd(false), - needsGotDtprel(false), needsTlsIe(false), hasDirectReloc(false) {} + needsTlsGd(false), needsTlsGdToIe(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,7 +283,6 @@ class Symbol { 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; @@ -301,7 +300,7 @@ class Symbol { bool needsDynReloc() const { return needsCopy || needsGot || needsPlt || needsTlsDesc || needsTlsGd || - needsTlsGdToIe || needsTlsLd || needsGotDtprel || needsTlsIe; + needsTlsGdToIe || needsGotDtprel || needsTlsIe; } void allocateAux() { assert(auxIdx == uint32_t(-1)); @@ -513,9 +512,9 @@ union SymbolUnion { }; // It is important to keep the size of SymbolUnion small for performance and -// memory usage reasons. 72 bytes is a soft limit based on the size of Defined +// memory usage reasons. 64 bytes is a soft limit based on the size of Defined // on a 64-bit system. -static_assert(sizeof(SymbolUnion) <= 72, "SymbolUnion too large"); +static_assert(sizeof(SymbolUnion) <= 64, "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 d61ee5526bb118..cff442e8ead399 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: 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: 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: } # 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 -4128(,%ebx), %eax +# DIS-NEXT: 1260: leal -4120(,%ebx), %eax # DIS-NEXT: 1267: calll 0x12d0 -# DIS-NEXT: 126c: leal -4116(,%ebx), %eax +# DIS-NEXT: 126c: leal -4108(,%ebx), %eax # DIS-NEXT: 1273: calll 0x12d0 ## Local dynamic model: ## -16 is a local module tls index offset. -# DIS-NEXT: 1278: leal -4104(%ebx), %eax +# DIS-NEXT: 1278: leal -4128(%ebx), %eax # DIS-NEXT: 127e: calll 0x12d0 # DIS-NEXT: 1283: leal 8(%eax), %edx -# DIS-NEXT: 1289: leal -4104(%ebx), %eax +# DIS-NEXT: 1289: leal -4128(%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 -4120(%ebx), %eax +# DIS-NEXT: 12a0: addl -4112(%ebx), %eax # DIS-NEXT: 12a6: movl %gs:0, %eax -# DIS-NEXT: 12ac: addl -4108(%ebx), %eax +# DIS-NEXT: 12ac: addl -4100(%ebx), %eax diff --git a/lld/test/ELF/ppc64-tls-missing-gdld.s b/lld/test/ELF/ppc64-tls-missing-gdld.s index 2d1954e95b1912..16a3085872c075 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:]] 0080ffff ffffffff 01000000 00000000 -# HEX-NEXT: [[#%x,IGNORE:]] 00000000 00000000 0090ffff ffffffff +# HEX-NEXT: [[#%x,IGNORE:]] 00000000 00000000 01000000 00000000 +# HEX-NEXT: [[#%x,IGNORE:]] 0080ffff ffffffff 0090ffff ffffffff ## .TOC.-32768 = (.got+0x8000)-32768 = .got # DIS-LABEL: : # DIS-NEXT: addis 3, 2, 0 -# DIS-NEXT: addi 3, 3, -32760 +# DIS-NEXT: addi 3, 3, -32744 # DIS-NEXT: bl [[#%x,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]] ## 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, -32744 +# DIS-NEXT: addi 3, 3, -32760 # DIS-NEXT: bl [[#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]] ## Technically we don't have to disable IE to LE relaxation,