Skip to content

Commit 8b70d52

Browse files
committed
[LLD] Set alignment as part of Characteristics in TLS table.
Differential Revision: https://reviews.llvm.org/D88637
1 parent b3a38bc commit 8b70d52

File tree

2 files changed

+54
-1
lines changed

2 files changed

+54
-1
lines changed

lld/COFF/Writer.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@ class Writer {
241241
void addSyntheticIdata();
242242
void fixPartialSectionChars(StringRef name, uint32_t chars);
243243
bool fixGnuImportChunks();
244+
void fixTlsAlignment();
244245
PartialSection *createPartialSection(StringRef name, uint32_t outChars);
245246
PartialSection *findPartialSection(StringRef name, uint32_t outChars);
246247

@@ -267,6 +268,7 @@ class Writer {
267268
DelayLoadContents delayIdata;
268269
EdataContents edata;
269270
bool setNoSEHCharacteristic = false;
271+
uint32_t tlsAlignment = 0;
270272

271273
DebugDirectoryChunk *debugDirectory = nullptr;
272274
std::vector<std::pair<COFF::DebugType, Chunk *>> debugRecords;
@@ -633,6 +635,11 @@ void Writer::run() {
633635
writeSections();
634636
sortExceptionTable();
635637

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+
636643
t1.stop();
637644

638645
if (!config->pdbPath.empty() && config->debug) {
@@ -866,6 +873,10 @@ void Writer::createSections() {
866873
StringRef name = c->getSectionName();
867874
if (shouldStripSectionSuffix(sc, name))
868875
name = name.split('$').first;
876+
877+
if (name.startswith(".tls"))
878+
tlsAlignment = std::max(tlsAlignment, c->getAlignment());
879+
869880
PartialSection *pSec = createPartialSection(name,
870881
c->getOutputCharacteristics());
871882
pSec->chunks.push_back(c);
@@ -2038,3 +2049,34 @@ PartialSection *Writer::findPartialSection(StringRef name, uint32_t outChars) {
20382049
return it->second;
20392050
return nullptr;
20402051
}
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+
}

llvm/include/llvm/Object/COFF.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,11 +576,22 @@ struct coff_tls_directory {
576576

577577
uint32_t getAlignment() const {
578578
// Bit [20:24] contains section alignment.
579-
uint32_t Shift = (Characteristics & 0x00F00000) >> 20;
579+
uint32_t Shift = (Characteristics & COFF::IMAGE_SCN_ALIGN_MASK) >> 20;
580580
if (Shift > 0)
581581
return 1U << (Shift - 1);
582582
return 0;
583583
}
584+
585+
void setAlignment(uint32_t align) {
586+
if (!align) {
587+
Characteristics &= ~COFF::IMAGE_SCN_ALIGN_MASK;
588+
} else {
589+
assert(llvm::isPowerOf2_32(align) && "alignment is not a power of 2");
590+
uint32_t p2Align = llvm::Log2_32(align);
591+
assert(p2Align <= 13 && "invalid alignment requested");
592+
Characteristics |= (p2Align + 1) << 20;
593+
}
594+
}
584595
};
585596

586597
using coff_tls_directory32 = coff_tls_directory<support::little32_t>;

0 commit comments

Comments
 (0)