diff options
Diffstat (limited to 'lld/COFF/Writer.cpp')
-rw-r--r-- | lld/COFF/Writer.cpp | 81 |
1 files changed, 59 insertions, 22 deletions
diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp index fcad7739d300..3bcc1777f7ac 100644 --- a/lld/COFF/Writer.cpp +++ b/lld/COFF/Writer.cpp @@ -10,13 +10,13 @@ #include "Config.h" #include "DLL.h" #include "InputFiles.h" +#include "LLDMapFile.h" #include "MapFile.h" #include "PDB.h" #include "SymbolTable.h" #include "Symbols.h" #include "lld/Common/ErrorHandler.h" #include "lld/Common/Memory.h" -#include "lld/Common/Threads.h" #include "lld/Common/Timer.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/STLExtras.h" @@ -41,9 +41,8 @@ using namespace llvm::COFF; using namespace llvm::object; using namespace llvm::support; using namespace llvm::support::endian; - -namespace lld { -namespace coff { +using namespace lld; +using namespace lld::coff; /* To re-generate DOSProgram: $ cat > /tmp/DOSProgram.asm @@ -92,7 +91,8 @@ namespace { class DebugDirectoryChunk : public NonSectionChunk { public: - DebugDirectoryChunk(const std::vector<Chunk *> &r, bool writeRepro) + DebugDirectoryChunk(const std::vector<std::pair<COFF::DebugType, Chunk *>> &r, + bool writeRepro) : records(r), writeRepro(writeRepro) {} size_t getSize() const override { @@ -102,11 +102,11 @@ public: void writeTo(uint8_t *b) const override { auto *d = reinterpret_cast<debug_directory *>(b); - for (const Chunk *record : records) { - OutputSection *os = record->getOutputSection(); - uint64_t offs = os->getFileOff() + (record->getRVA() - os->getRVA()); - fillEntry(d, COFF::IMAGE_DEBUG_TYPE_CODEVIEW, record->getSize(), - record->getRVA(), offs); + for (const std::pair<COFF::DebugType, Chunk *>& record : records) { + Chunk *c = record.second; + OutputSection *os = c->getOutputSection(); + uint64_t offs = os->getFileOff() + (c->getRVA() - os->getRVA()); + fillEntry(d, record.first, c->getSize(), c->getRVA(), offs); ++d; } @@ -141,7 +141,7 @@ private: } mutable std::vector<support::ulittle32_t *> timeDateStamps; - const std::vector<Chunk *> &records; + const std::vector<std::pair<COFF::DebugType, Chunk *>> &records; bool writeRepro; }; @@ -166,6 +166,17 @@ public: mutable codeview::DebugInfo *buildId = nullptr; }; +class ExtendedDllCharacteristicsChunk : public NonSectionChunk { +public: + ExtendedDllCharacteristicsChunk(uint32_t c) : characteristics(c) {} + + size_t getSize() const override { return 4; } + + void writeTo(uint8_t *buf) const override { write32le(buf, characteristics); } + + uint32_t characteristics = 0; +}; + // PartialSection represents a group of chunks that contribute to an // OutputSection. Collating a collection of PartialSections of same name and // characteristics constitutes the OutputSection. @@ -251,7 +262,7 @@ private: bool setNoSEHCharacteristic = false; DebugDirectoryChunk *debugDirectory = nullptr; - std::vector<Chunk *> debugRecords; + std::vector<std::pair<COFF::DebugType, Chunk *>> debugRecords; CVDebugRecordChunk *buildId = nullptr; ArrayRef<uint8_t> sectionTable; @@ -290,7 +301,7 @@ private: static Timer codeLayoutTimer("Code Layout", Timer::root()); static Timer diskCommitTimer("Commit Output File", Timer::root()); -void writeResult() { Writer().run(); } +void lld::coff::writeResult() { Writer().run(); } void OutputSection::addChunk(Chunk *c) { chunks.push_back(c); @@ -622,6 +633,7 @@ void Writer::run() { } writeBuildId(); + writeLLDMapFile(outputSections); writeMapFile(outputSections); if (errorCount()) @@ -921,8 +933,9 @@ void Writer::createMiscChunks() { // Create Debug Information Chunks OutputSection *debugInfoSec = config->mingw ? buildidSec : rdataSec; - if (config->debug || config->repro) { + if (config->debug || config->repro || config->cetCompat) { debugDirectory = make<DebugDirectoryChunk>(debugRecords, config->repro); + debugDirectory->setAlignment(4); debugInfoSec->addChunk(debugDirectory); } @@ -932,10 +945,20 @@ void Writer::createMiscChunks() { // allowing a debugger to match a PDB and an executable. So we need it even // if we're ultimately not going to write CodeView data to the PDB. buildId = make<CVDebugRecordChunk>(); - debugRecords.push_back(buildId); + debugRecords.push_back({COFF::IMAGE_DEBUG_TYPE_CODEVIEW, buildId}); + } - for (Chunk *c : debugRecords) - debugInfoSec->addChunk(c); + if (config->cetCompat) { + ExtendedDllCharacteristicsChunk *extendedDllChars = + make<ExtendedDllCharacteristicsChunk>( + IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT); + debugRecords.push_back( + {COFF::IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS, extendedDllChars}); + } + + if (debugRecords.size() > 0) { + for (std::pair<COFF::DebugType, Chunk *> r : debugRecords) + debugInfoSec->addChunk(r.second); } // Create SEH table. x86-only. @@ -946,11 +969,11 @@ void Writer::createMiscChunks() { if (config->guardCF != GuardCFLevel::Off) createGuardCFTables(); - if (config->mingw) { + if (config->autoImport) createRuntimePseudoRelocs(); + if (config->mingw) insertCtorDtorSymbols(); - } } // Create .idata section for the DLL-imported symbol table. @@ -1699,6 +1722,15 @@ void Writer::createRuntimePseudoRelocs() { sc->getRuntimePseudoRelocs(rels); } + if (!config->pseudoRelocs) { + // Not writing any pseudo relocs; if some were needed, error out and + // indicate what required them. + for (const RuntimePseudoReloc &rpr : rels) + error("automatic dllimport of " + rpr.sym->getName() + " in " + + toString(rpr.target->file) + " requires pseudo relocations"); + return; + } + if (!rels.empty()) log("Writing " + Twine(rels.size()) + " runtime pseudo relocations"); PseudoRelocTableChunk *table = make<PseudoRelocTableChunk>(rels); @@ -1832,6 +1864,10 @@ void Writer::sortExceptionTable() { uint8_t *end = bufAddr(lastPdata) + lastPdata->getSize(); if (config->machine == AMD64) { struct Entry { ulittle32_t begin, end, unwind; }; + if ((end - begin) % sizeof(Entry) != 0) { + fatal("unexpected .pdata size: " + Twine(end - begin) + + " is not a multiple of " + Twine(sizeof(Entry))); + } parallelSort( MutableArrayRef<Entry>((Entry *)begin, (Entry *)end), [](const Entry &a, const Entry &b) { return a.begin < b.begin; }); @@ -1839,6 +1875,10 @@ void Writer::sortExceptionTable() { } if (config->machine == ARMNT || config->machine == ARM64) { struct Entry { ulittle32_t begin, unwind; }; + if ((end - begin) % sizeof(Entry) != 0) { + fatal("unexpected .pdata size: " + Twine(end - begin) + + " is not a multiple of " + Twine(sizeof(Entry))); + } parallelSort( MutableArrayRef<Entry>((Entry *)begin, (Entry *)end), [](const Entry &a, const Entry &b) { return a.begin < b.begin; }); @@ -1950,6 +1990,3 @@ PartialSection *Writer::findPartialSection(StringRef name, uint32_t outChars) { return it->second; return nullptr; } - -} // namespace coff -} // namespace lld |