[llvm] 8b70d52 - [LLD] Set alignment as part of Characteristics in TLS table.
Luqman Aden via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 14 19:37:18 PDT 2020
Author: Luqman Aden
Date: 2020-10-14T19:34:31-07:00
New Revision: 8b70d527d7ec1c8b9e921177119a0d906ffad4f0
URL: https://github.com/llvm/llvm-project/commit/8b70d527d7ec1c8b9e921177119a0d906ffad4f0
DIFF: https://github.com/llvm/llvm-project/commit/8b70d527d7ec1c8b9e921177119a0d906ffad4f0.diff
LOG: [LLD] Set alignment as part of Characteristics in TLS table.
Differential Revision: https://reviews.llvm.org/D88637
Added:
Modified:
lld/COFF/Writer.cpp
llvm/include/llvm/Object/COFF.h
Removed:
################################################################################
diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index c13cd34f2ddc..ba8f502ea81c 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -241,6 +241,7 @@ class Writer {
void addSyntheticIdata();
void fixPartialSectionChars(StringRef name, uint32_t chars);
bool fixGnuImportChunks();
+ void fixTlsAlignment();
PartialSection *createPartialSection(StringRef name, uint32_t outChars);
PartialSection *findPartialSection(StringRef name, uint32_t outChars);
@@ -267,6 +268,7 @@ class Writer {
DelayLoadContents delayIdata;
EdataContents edata;
bool setNoSEHCharacteristic = false;
+ uint32_t tlsAlignment = 0;
DebugDirectoryChunk *debugDirectory = nullptr;
std::vector<std::pair<COFF::DebugType, Chunk *>> debugRecords;
@@ -633,6 +635,11 @@ void Writer::run() {
writeSections();
sortExceptionTable();
+ // Fix up the alignment in the TLS Directory's characteristic field,
+ // if a specific alignment value is needed
+ if (tlsAlignment)
+ fixTlsAlignment();
+
t1.stop();
if (!config->pdbPath.empty() && config->debug) {
@@ -866,6 +873,10 @@ void Writer::createSections() {
StringRef name = c->getSectionName();
if (shouldStripSectionSuffix(sc, name))
name = name.split('$').first;
+
+ if (name.startswith(".tls"))
+ tlsAlignment = std::max(tlsAlignment, c->getAlignment());
+
PartialSection *pSec = createPartialSection(name,
c->getOutputCharacteristics());
pSec->chunks.push_back(c);
@@ -2038,3 +2049,34 @@ PartialSection *Writer::findPartialSection(StringRef name, uint32_t outChars) {
return it->second;
return nullptr;
}
+
+void Writer::fixTlsAlignment() {
+ if (Symbol *sym = symtab->findUnderscore("_tls_used")) {
+ if (Defined *b = dyn_cast<Defined>(sym)) {
+ OutputSection *sec = b->getChunk()->getOutputSection();
+ assert(sec && b->getRVA() >= sec->getRVA() &&
+ "no output section for _tls_used");
+
+ uint8_t *secBuf = buffer->getBufferStart() + sec->getFileOff();
+ uint64_t tlsOffset = b->getRVA() - sec->getRVA();
+ uint64_t directorySize = config->is64()
+ ? sizeof(object::coff_tls_directory64)
+ : sizeof(object::coff_tls_directory32);
+
+ if (tlsOffset + directorySize > sec->getRawSize())
+ fatal("_tls_used is malformed");
+
+ if (config->is64()) {
+ object::coff_tls_directory64 *tlsDir =
+ reinterpret_cast<object::coff_tls_directory64 *>(
+ &secBuf[tlsOffset]);
+ tlsDir->setAlignment(tlsAlignment);
+ } else {
+ object::coff_tls_directory32 *tlsDir =
+ reinterpret_cast<object::coff_tls_directory32 *>(
+ &secBuf[tlsOffset]);
+ tlsDir->setAlignment(tlsAlignment);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/llvm/include/llvm/Object/COFF.h b/llvm/include/llvm/Object/COFF.h
index 505aab8bff5b..649042579c94 100644
--- a/llvm/include/llvm/Object/COFF.h
+++ b/llvm/include/llvm/Object/COFF.h
@@ -576,11 +576,22 @@ struct coff_tls_directory {
uint32_t getAlignment() const {
// Bit [20:24] contains section alignment.
- uint32_t Shift = (Characteristics & 0x00F00000) >> 20;
+ uint32_t Shift = (Characteristics & COFF::IMAGE_SCN_ALIGN_MASK) >> 20;
if (Shift > 0)
return 1U << (Shift - 1);
return 0;
}
+
+ void setAlignment(uint32_t align) {
+ if (!align) {
+ Characteristics &= ~COFF::IMAGE_SCN_ALIGN_MASK;
+ } else {
+ assert(llvm::isPowerOf2_32(align) && "alignment is not a power of 2");
+ uint32_t p2Align = llvm::Log2_32(align);
+ assert(p2Align <= 13 && "invalid alignment requested");
+ Characteristics |= (p2Align + 1) << 20;
+ }
+ }
};
using coff_tls_directory32 = coff_tls_directory<support::little32_t>;
More information about the llvm-commits
mailing list