summaryrefslogtreecommitdiff
path: root/lld/COFF/Writer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/COFF/Writer.cpp')
-rw-r--r--lld/COFF/Writer.cpp81
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