@@ -241,6 +241,7 @@ class Writer {
241
241
void addSyntheticIdata ();
242
242
void fixPartialSectionChars (StringRef name, uint32_t chars);
243
243
bool fixGnuImportChunks ();
244
+ void fixTlsAlignment ();
244
245
PartialSection *createPartialSection (StringRef name, uint32_t outChars);
245
246
PartialSection *findPartialSection (StringRef name, uint32_t outChars);
246
247
@@ -267,6 +268,7 @@ class Writer {
267
268
DelayLoadContents delayIdata;
268
269
EdataContents edata;
269
270
bool setNoSEHCharacteristic = false ;
271
+ uint32_t tlsAlignment = 0 ;
270
272
271
273
DebugDirectoryChunk *debugDirectory = nullptr ;
272
274
std::vector<std::pair<COFF::DebugType, Chunk *>> debugRecords;
@@ -633,6 +635,11 @@ void Writer::run() {
633
635
writeSections ();
634
636
sortExceptionTable ();
635
637
638
+ // Fix up the alignment in the TLS Directory's characteristic field,
639
+ // if a specific alignment value is needed
640
+ if (tlsAlignment)
641
+ fixTlsAlignment ();
642
+
636
643
t1.stop ();
637
644
638
645
if (!config->pdbPath .empty () && config->debug ) {
@@ -866,6 +873,10 @@ void Writer::createSections() {
866
873
StringRef name = c->getSectionName ();
867
874
if (shouldStripSectionSuffix (sc, name))
868
875
name = name.split (' $' ).first ;
876
+
877
+ if (name.startswith (" .tls" ))
878
+ tlsAlignment = std::max (tlsAlignment, c->getAlignment ());
879
+
869
880
PartialSection *pSec = createPartialSection (name,
870
881
c->getOutputCharacteristics ());
871
882
pSec->chunks .push_back (c);
@@ -2038,3 +2049,34 @@ PartialSection *Writer::findPartialSection(StringRef name, uint32_t outChars) {
2038
2049
return it->second ;
2039
2050
return nullptr ;
2040
2051
}
2052
+
2053
+ void Writer::fixTlsAlignment () {
2054
+ if (Symbol *sym = symtab->findUnderscore (" _tls_used" )) {
2055
+ if (Defined *b = dyn_cast<Defined>(sym)) {
2056
+ OutputSection *sec = b->getChunk ()->getOutputSection ();
2057
+ assert (sec && b->getRVA () >= sec->getRVA () &&
2058
+ " no output section for _tls_used" );
2059
+
2060
+ uint8_t *secBuf = buffer->getBufferStart () + sec->getFileOff ();
2061
+ uint64_t tlsOffset = b->getRVA () - sec->getRVA ();
2062
+ uint64_t directorySize = config->is64 ()
2063
+ ? sizeof (object::coff_tls_directory64)
2064
+ : sizeof (object::coff_tls_directory32);
2065
+
2066
+ if (tlsOffset + directorySize > sec->getRawSize ())
2067
+ fatal (" _tls_used is malformed" );
2068
+
2069
+ if (config->is64 ()) {
2070
+ object::coff_tls_directory64 *tlsDir =
2071
+ reinterpret_cast <object::coff_tls_directory64 *>(
2072
+ &secBuf[tlsOffset]);
2073
+ tlsDir->setAlignment (tlsAlignment);
2074
+ } else {
2075
+ object::coff_tls_directory32 *tlsDir =
2076
+ reinterpret_cast <object::coff_tls_directory32 *>(
2077
+ &secBuf[tlsOffset]);
2078
+ tlsDir->setAlignment (tlsAlignment);
2079
+ }
2080
+ }
2081
+ }
2082
+ }
0 commit comments