1ece8a530Spatrick //===- Writer.cpp ---------------------------------------------------------===//
2ece8a530Spatrick //
3ece8a530Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4ece8a530Spatrick // See https://llvm.org/LICENSE.txt for license information.
5ece8a530Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ece8a530Spatrick //
7ece8a530Spatrick //===----------------------------------------------------------------------===//
8ece8a530Spatrick
9ece8a530Spatrick #include "Writer.h"
10*dfe94b16Srobert #include "COFFLinkerContext.h"
111cf9926bSpatrick #include "CallGraphSort.h"
12ece8a530Spatrick #include "Config.h"
13ece8a530Spatrick #include "DLL.h"
14ece8a530Spatrick #include "InputFiles.h"
15bb684c34Spatrick #include "LLDMapFile.h"
16ece8a530Spatrick #include "MapFile.h"
17ece8a530Spatrick #include "PDB.h"
18ece8a530Spatrick #include "SymbolTable.h"
19ece8a530Spatrick #include "Symbols.h"
20ece8a530Spatrick #include "lld/Common/ErrorHandler.h"
21ece8a530Spatrick #include "lld/Common/Memory.h"
22ece8a530Spatrick #include "lld/Common/Timer.h"
23ece8a530Spatrick #include "llvm/ADT/DenseMap.h"
24ece8a530Spatrick #include "llvm/ADT/STLExtras.h"
25ece8a530Spatrick #include "llvm/ADT/StringSet.h"
26*dfe94b16Srobert #include "llvm/BinaryFormat/COFF.h"
27ece8a530Spatrick #include "llvm/Support/BinaryStreamReader.h"
28ece8a530Spatrick #include "llvm/Support/Debug.h"
29ece8a530Spatrick #include "llvm/Support/Endian.h"
30ece8a530Spatrick #include "llvm/Support/FileOutputBuffer.h"
31ece8a530Spatrick #include "llvm/Support/Parallel.h"
32ece8a530Spatrick #include "llvm/Support/Path.h"
33ece8a530Spatrick #include "llvm/Support/RandomNumberGenerator.h"
34ece8a530Spatrick #include "llvm/Support/xxhash.h"
35ece8a530Spatrick #include <algorithm>
36ece8a530Spatrick #include <cstdio>
37ece8a530Spatrick #include <map>
38ece8a530Spatrick #include <memory>
39ece8a530Spatrick #include <utility>
40ece8a530Spatrick
41ece8a530Spatrick using namespace llvm;
42ece8a530Spatrick using namespace llvm::COFF;
43ece8a530Spatrick using namespace llvm::object;
44ece8a530Spatrick using namespace llvm::support;
45ece8a530Spatrick using namespace llvm::support::endian;
46bb684c34Spatrick using namespace lld;
47bb684c34Spatrick using namespace lld::coff;
48ece8a530Spatrick
49ece8a530Spatrick /* To re-generate DOSProgram:
50ece8a530Spatrick $ cat > /tmp/DOSProgram.asm
51ece8a530Spatrick org 0
52ece8a530Spatrick ; Copy cs to ds.
53ece8a530Spatrick push cs
54ece8a530Spatrick pop ds
55ece8a530Spatrick ; Point ds:dx at the $-terminated string.
56ece8a530Spatrick mov dx, str
57ece8a530Spatrick ; Int 21/AH=09h: Write string to standard output.
58ece8a530Spatrick mov ah, 0x9
59ece8a530Spatrick int 0x21
60ece8a530Spatrick ; Int 21/AH=4Ch: Exit with return code (in AL).
61ece8a530Spatrick mov ax, 0x4C01
62ece8a530Spatrick int 0x21
63ece8a530Spatrick str:
64ece8a530Spatrick db 'This program cannot be run in DOS mode.$'
65ece8a530Spatrick align 8, db 0
66ece8a530Spatrick $ nasm -fbin /tmp/DOSProgram.asm -o /tmp/DOSProgram.bin
67ece8a530Spatrick $ xxd -i /tmp/DOSProgram.bin
68ece8a530Spatrick */
69ece8a530Spatrick static unsigned char dosProgram[] = {
70ece8a530Spatrick 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c,
71ece8a530Spatrick 0xcd, 0x21, 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,
72ece8a530Spatrick 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65,
73ece8a530Spatrick 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
74ece8a530Spatrick 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x24, 0x00, 0x00
75ece8a530Spatrick };
76ece8a530Spatrick static_assert(sizeof(dosProgram) % 8 == 0,
77ece8a530Spatrick "DOSProgram size must be multiple of 8");
78ece8a530Spatrick
79ece8a530Spatrick static const int dosStubSize = sizeof(dos_header) + sizeof(dosProgram);
80ece8a530Spatrick static_assert(dosStubSize % 8 == 0, "DOSStub size must be multiple of 8");
81ece8a530Spatrick
82ece8a530Spatrick static const int numberOfDataDirectory = 16;
83ece8a530Spatrick
84ece8a530Spatrick namespace {
85ece8a530Spatrick
86ece8a530Spatrick class DebugDirectoryChunk : public NonSectionChunk {
87ece8a530Spatrick public:
DebugDirectoryChunk(const COFFLinkerContext & c,const std::vector<std::pair<COFF::DebugType,Chunk * >> & r,bool writeRepro)88*dfe94b16Srobert DebugDirectoryChunk(const COFFLinkerContext &c,
89*dfe94b16Srobert const std::vector<std::pair<COFF::DebugType, Chunk *>> &r,
90bb684c34Spatrick bool writeRepro)
91*dfe94b16Srobert : records(r), writeRepro(writeRepro), ctx(c) {}
92ece8a530Spatrick
getSize() const93ece8a530Spatrick size_t getSize() const override {
94ece8a530Spatrick return (records.size() + int(writeRepro)) * sizeof(debug_directory);
95ece8a530Spatrick }
96ece8a530Spatrick
writeTo(uint8_t * b) const97ece8a530Spatrick void writeTo(uint8_t *b) const override {
98ece8a530Spatrick auto *d = reinterpret_cast<debug_directory *>(b);
99ece8a530Spatrick
100bb684c34Spatrick for (const std::pair<COFF::DebugType, Chunk *>& record : records) {
101bb684c34Spatrick Chunk *c = record.second;
102*dfe94b16Srobert const OutputSection *os = ctx.getOutputSection(c);
103bb684c34Spatrick uint64_t offs = os->getFileOff() + (c->getRVA() - os->getRVA());
104bb684c34Spatrick fillEntry(d, record.first, c->getSize(), c->getRVA(), offs);
105ece8a530Spatrick ++d;
106ece8a530Spatrick }
107ece8a530Spatrick
108ece8a530Spatrick if (writeRepro) {
109ece8a530Spatrick // FIXME: The COFF spec allows either a 0-sized entry to just say
110ece8a530Spatrick // "the timestamp field is really a hash", or a 4-byte size field
111ece8a530Spatrick // followed by that many bytes containing a longer hash (with the
112ece8a530Spatrick // lowest 4 bytes usually being the timestamp in little-endian order).
113ece8a530Spatrick // Consider storing the full 8 bytes computed by xxHash64 here.
114ece8a530Spatrick fillEntry(d, COFF::IMAGE_DEBUG_TYPE_REPRO, 0, 0, 0);
115ece8a530Spatrick }
116ece8a530Spatrick }
117ece8a530Spatrick
setTimeDateStamp(uint32_t timeDateStamp)118ece8a530Spatrick void setTimeDateStamp(uint32_t timeDateStamp) {
119ece8a530Spatrick for (support::ulittle32_t *tds : timeDateStamps)
120ece8a530Spatrick *tds = timeDateStamp;
121ece8a530Spatrick }
122ece8a530Spatrick
123ece8a530Spatrick private:
fillEntry(debug_directory * d,COFF::DebugType debugType,size_t size,uint64_t rva,uint64_t offs) const124ece8a530Spatrick void fillEntry(debug_directory *d, COFF::DebugType debugType, size_t size,
125ece8a530Spatrick uint64_t rva, uint64_t offs) const {
126ece8a530Spatrick d->Characteristics = 0;
127ece8a530Spatrick d->TimeDateStamp = 0;
128ece8a530Spatrick d->MajorVersion = 0;
129ece8a530Spatrick d->MinorVersion = 0;
130ece8a530Spatrick d->Type = debugType;
131ece8a530Spatrick d->SizeOfData = size;
132ece8a530Spatrick d->AddressOfRawData = rva;
133ece8a530Spatrick d->PointerToRawData = offs;
134ece8a530Spatrick
135ece8a530Spatrick timeDateStamps.push_back(&d->TimeDateStamp);
136ece8a530Spatrick }
137ece8a530Spatrick
138ece8a530Spatrick mutable std::vector<support::ulittle32_t *> timeDateStamps;
139bb684c34Spatrick const std::vector<std::pair<COFF::DebugType, Chunk *>> &records;
140ece8a530Spatrick bool writeRepro;
141*dfe94b16Srobert const COFFLinkerContext &ctx;
142ece8a530Spatrick };
143ece8a530Spatrick
144ece8a530Spatrick class CVDebugRecordChunk : public NonSectionChunk {
145ece8a530Spatrick public:
CVDebugRecordChunk(const COFFLinkerContext & c)146*dfe94b16Srobert CVDebugRecordChunk(const COFFLinkerContext &c) : ctx(c) {}
147*dfe94b16Srobert
getSize() const148ece8a530Spatrick size_t getSize() const override {
149*dfe94b16Srobert return sizeof(codeview::DebugInfo) + ctx.config.pdbAltPath.size() + 1;
150ece8a530Spatrick }
151ece8a530Spatrick
writeTo(uint8_t * b) const152ece8a530Spatrick void writeTo(uint8_t *b) const override {
153ece8a530Spatrick // Save off the DebugInfo entry to backfill the file signature (build id)
154ece8a530Spatrick // in Writer::writeBuildId
155ece8a530Spatrick buildId = reinterpret_cast<codeview::DebugInfo *>(b);
156ece8a530Spatrick
157ece8a530Spatrick // variable sized field (PDB Path)
158ece8a530Spatrick char *p = reinterpret_cast<char *>(b + sizeof(*buildId));
159*dfe94b16Srobert if (!ctx.config.pdbAltPath.empty())
160*dfe94b16Srobert memcpy(p, ctx.config.pdbAltPath.data(), ctx.config.pdbAltPath.size());
161*dfe94b16Srobert p[ctx.config.pdbAltPath.size()] = '\0';
162ece8a530Spatrick }
163ece8a530Spatrick
164ece8a530Spatrick mutable codeview::DebugInfo *buildId = nullptr;
165*dfe94b16Srobert
166*dfe94b16Srobert private:
167*dfe94b16Srobert const COFFLinkerContext &ctx;
168ece8a530Spatrick };
169ece8a530Spatrick
170bb684c34Spatrick class ExtendedDllCharacteristicsChunk : public NonSectionChunk {
171bb684c34Spatrick public:
ExtendedDllCharacteristicsChunk(uint32_t c)172bb684c34Spatrick ExtendedDllCharacteristicsChunk(uint32_t c) : characteristics(c) {}
173bb684c34Spatrick
getSize() const174bb684c34Spatrick size_t getSize() const override { return 4; }
175bb684c34Spatrick
writeTo(uint8_t * buf) const176bb684c34Spatrick void writeTo(uint8_t *buf) const override { write32le(buf, characteristics); }
177bb684c34Spatrick
178bb684c34Spatrick uint32_t characteristics = 0;
179bb684c34Spatrick };
180bb684c34Spatrick
181ece8a530Spatrick // PartialSection represents a group of chunks that contribute to an
182ece8a530Spatrick // OutputSection. Collating a collection of PartialSections of same name and
183ece8a530Spatrick // characteristics constitutes the OutputSection.
184ece8a530Spatrick class PartialSectionKey {
185ece8a530Spatrick public:
186ece8a530Spatrick StringRef name;
187ece8a530Spatrick unsigned characteristics;
188ece8a530Spatrick
operator <(const PartialSectionKey & other) const189ece8a530Spatrick bool operator<(const PartialSectionKey &other) const {
190ece8a530Spatrick int c = name.compare(other.name);
191*dfe94b16Srobert if (c > 0)
192ece8a530Spatrick return false;
193ece8a530Spatrick if (c == 0)
194ece8a530Spatrick return characteristics < other.characteristics;
195ece8a530Spatrick return true;
196ece8a530Spatrick }
197ece8a530Spatrick };
198ece8a530Spatrick
199ece8a530Spatrick // The writer writes a SymbolTable result to a file.
200ece8a530Spatrick class Writer {
201ece8a530Spatrick public:
Writer(COFFLinkerContext & c)202*dfe94b16Srobert Writer(COFFLinkerContext &c)
203*dfe94b16Srobert : buffer(errorHandler().outputBuffer), delayIdata(c), edata(c), ctx(c) {}
204ece8a530Spatrick void run();
205ece8a530Spatrick
206ece8a530Spatrick private:
207ece8a530Spatrick void createSections();
208ece8a530Spatrick void createMiscChunks();
209ece8a530Spatrick void createImportTables();
210ece8a530Spatrick void appendImportThunks();
211ece8a530Spatrick void locateImportTables();
212ece8a530Spatrick void createExportTable();
213ece8a530Spatrick void mergeSections();
214ece8a530Spatrick void removeUnusedSections();
215ece8a530Spatrick void assignAddresses();
216*dfe94b16Srobert bool isInRange(uint16_t relType, uint64_t s, uint64_t p, int margin);
217*dfe94b16Srobert std::pair<Defined *, bool> getThunk(DenseMap<uint64_t, Defined *> &lastThunks,
218*dfe94b16Srobert Defined *target, uint64_t p,
219*dfe94b16Srobert uint16_t type, int margin);
220*dfe94b16Srobert bool createThunks(OutputSection *os, int margin);
221*dfe94b16Srobert bool verifyRanges(const std::vector<Chunk *> chunks);
222ece8a530Spatrick void finalizeAddresses();
223ece8a530Spatrick void removeEmptySections();
224ece8a530Spatrick void assignOutputSectionIndices();
225ece8a530Spatrick void createSymbolAndStringTable();
226ece8a530Spatrick void openFile(StringRef outputPath);
227ece8a530Spatrick template <typename PEHeaderTy> void writeHeader();
228ece8a530Spatrick void createSEHTable();
229ece8a530Spatrick void createRuntimePseudoRelocs();
230ece8a530Spatrick void insertCtorDtorSymbols();
231*dfe94b16Srobert void markSymbolsWithRelocations(ObjFile *file, SymbolRVASet &usedSymbols);
232ece8a530Spatrick void createGuardCFTables();
233ece8a530Spatrick void markSymbolsForRVATable(ObjFile *file,
234ece8a530Spatrick ArrayRef<SectionChunk *> symIdxChunks,
235ece8a530Spatrick SymbolRVASet &tableSymbols);
2361cf9926bSpatrick void getSymbolsFromSections(ObjFile *file,
2371cf9926bSpatrick ArrayRef<SectionChunk *> symIdxChunks,
2381cf9926bSpatrick std::vector<Symbol *> &symbols);
239ece8a530Spatrick void maybeAddRVATable(SymbolRVASet tableSymbols, StringRef tableSym,
2401cf9926bSpatrick StringRef countSym, bool hasFlag=false);
241ece8a530Spatrick void setSectionPermissions();
242ece8a530Spatrick void writeSections();
243ece8a530Spatrick void writeBuildId();
244*dfe94b16Srobert void writePEChecksum();
2451cf9926bSpatrick void sortSections();
246ece8a530Spatrick void sortExceptionTable();
247ece8a530Spatrick void sortCRTSectionChunks(std::vector<Chunk *> &chunks);
248ece8a530Spatrick void addSyntheticIdata();
249*dfe94b16Srobert void sortBySectionOrder(std::vector<Chunk *> &chunks);
250ece8a530Spatrick void fixPartialSectionChars(StringRef name, uint32_t chars);
251ece8a530Spatrick bool fixGnuImportChunks();
2521cf9926bSpatrick void fixTlsAlignment();
253ece8a530Spatrick PartialSection *createPartialSection(StringRef name, uint32_t outChars);
254ece8a530Spatrick PartialSection *findPartialSection(StringRef name, uint32_t outChars);
255ece8a530Spatrick
256*dfe94b16Srobert std::optional<coff_symbol16> createSymbol(Defined *d);
257ece8a530Spatrick size_t addEntryToStringTable(StringRef str);
258ece8a530Spatrick
259ece8a530Spatrick OutputSection *findSection(StringRef name);
260ece8a530Spatrick void addBaserels();
261ece8a530Spatrick void addBaserelBlocks(std::vector<Baserel> &v);
262ece8a530Spatrick
263ece8a530Spatrick uint32_t getSizeOfInitializedData();
264ece8a530Spatrick
265*dfe94b16Srobert void checkLoadConfig();
266*dfe94b16Srobert template <typename T> void checkLoadConfigGuardData(const T *loadConfig);
267*dfe94b16Srobert
268ece8a530Spatrick std::unique_ptr<FileOutputBuffer> &buffer;
269ece8a530Spatrick std::map<PartialSectionKey, PartialSection *> partialSections;
270ece8a530Spatrick std::vector<char> strtab;
271ece8a530Spatrick std::vector<llvm::object::coff_symbol16> outputSymtab;
272ece8a530Spatrick IdataContents idata;
273ece8a530Spatrick Chunk *importTableStart = nullptr;
274ece8a530Spatrick uint64_t importTableSize = 0;
275ece8a530Spatrick Chunk *edataStart = nullptr;
276ece8a530Spatrick Chunk *edataEnd = nullptr;
277ece8a530Spatrick Chunk *iatStart = nullptr;
278ece8a530Spatrick uint64_t iatSize = 0;
279ece8a530Spatrick DelayLoadContents delayIdata;
280ece8a530Spatrick EdataContents edata;
281ece8a530Spatrick bool setNoSEHCharacteristic = false;
2821cf9926bSpatrick uint32_t tlsAlignment = 0;
283ece8a530Spatrick
284ece8a530Spatrick DebugDirectoryChunk *debugDirectory = nullptr;
285bb684c34Spatrick std::vector<std::pair<COFF::DebugType, Chunk *>> debugRecords;
286ece8a530Spatrick CVDebugRecordChunk *buildId = nullptr;
287ece8a530Spatrick ArrayRef<uint8_t> sectionTable;
288ece8a530Spatrick
289ece8a530Spatrick uint64_t fileSize;
290ece8a530Spatrick uint32_t pointerToSymbolTable = 0;
291ece8a530Spatrick uint64_t sizeOfImage;
292ece8a530Spatrick uint64_t sizeOfHeaders;
293ece8a530Spatrick
294ece8a530Spatrick OutputSection *textSec;
295ece8a530Spatrick OutputSection *rdataSec;
296ece8a530Spatrick OutputSection *buildidSec;
297ece8a530Spatrick OutputSection *dataSec;
298ece8a530Spatrick OutputSection *pdataSec;
299ece8a530Spatrick OutputSection *idataSec;
300ece8a530Spatrick OutputSection *edataSec;
301ece8a530Spatrick OutputSection *didatSec;
302ece8a530Spatrick OutputSection *rsrcSec;
303ece8a530Spatrick OutputSection *relocSec;
304ece8a530Spatrick OutputSection *ctorsSec;
305ece8a530Spatrick OutputSection *dtorsSec;
306ece8a530Spatrick
307ece8a530Spatrick // The first and last .pdata sections in the output file.
308ece8a530Spatrick //
309ece8a530Spatrick // We need to keep track of the location of .pdata in whichever section it
310ece8a530Spatrick // gets merged into so that we can sort its contents and emit a correct data
311ece8a530Spatrick // directory entry for the exception table. This is also the case for some
312ece8a530Spatrick // other sections (such as .edata) but because the contents of those sections
313ece8a530Spatrick // are entirely linker-generated we can keep track of their locations using
314ece8a530Spatrick // the chunks that the linker creates. All .pdata chunks come from input
315ece8a530Spatrick // files, so we need to keep track of them separately.
316ece8a530Spatrick Chunk *firstPdata = nullptr;
317ece8a530Spatrick Chunk *lastPdata;
318*dfe94b16Srobert
319*dfe94b16Srobert COFFLinkerContext &ctx;
320ece8a530Spatrick };
321ece8a530Spatrick } // anonymous namespace
322ece8a530Spatrick
writeResult(COFFLinkerContext & ctx)323*dfe94b16Srobert void lld::coff::writeResult(COFFLinkerContext &ctx) { Writer(ctx).run(); }
324ece8a530Spatrick
addChunk(Chunk * c)325ece8a530Spatrick void OutputSection::addChunk(Chunk *c) {
326ece8a530Spatrick chunks.push_back(c);
327ece8a530Spatrick }
328ece8a530Spatrick
insertChunkAtStart(Chunk * c)329ece8a530Spatrick void OutputSection::insertChunkAtStart(Chunk *c) {
330ece8a530Spatrick chunks.insert(chunks.begin(), c);
331ece8a530Spatrick }
332ece8a530Spatrick
setPermissions(uint32_t c)333ece8a530Spatrick void OutputSection::setPermissions(uint32_t c) {
334ece8a530Spatrick header.Characteristics &= ~permMask;
335ece8a530Spatrick header.Characteristics |= c;
336ece8a530Spatrick }
337ece8a530Spatrick
merge(OutputSection * other)338ece8a530Spatrick void OutputSection::merge(OutputSection *other) {
339ece8a530Spatrick chunks.insert(chunks.end(), other->chunks.begin(), other->chunks.end());
340ece8a530Spatrick other->chunks.clear();
341ece8a530Spatrick contribSections.insert(contribSections.end(), other->contribSections.begin(),
342ece8a530Spatrick other->contribSections.end());
343ece8a530Spatrick other->contribSections.clear();
344ece8a530Spatrick }
345ece8a530Spatrick
346ece8a530Spatrick // Write the section header to a given buffer.
writeHeaderTo(uint8_t * buf,bool isDebug)347*dfe94b16Srobert void OutputSection::writeHeaderTo(uint8_t *buf, bool isDebug) {
348ece8a530Spatrick auto *hdr = reinterpret_cast<coff_section *>(buf);
349ece8a530Spatrick *hdr = header;
350ece8a530Spatrick if (stringTableOff) {
351ece8a530Spatrick // If name is too long, write offset into the string table as a name.
352*dfe94b16Srobert encodeSectionName(hdr->Name, stringTableOff);
353ece8a530Spatrick } else {
354*dfe94b16Srobert assert(!isDebug || name.size() <= COFF::NameSize ||
355ece8a530Spatrick (hdr->Characteristics & IMAGE_SCN_MEM_DISCARDABLE) == 0);
356ece8a530Spatrick strncpy(hdr->Name, name.data(),
357ece8a530Spatrick std::min(name.size(), (size_t)COFF::NameSize));
358ece8a530Spatrick }
359ece8a530Spatrick }
360ece8a530Spatrick
addContributingPartialSection(PartialSection * sec)361ece8a530Spatrick void OutputSection::addContributingPartialSection(PartialSection *sec) {
362ece8a530Spatrick contribSections.push_back(sec);
363ece8a530Spatrick }
364ece8a530Spatrick
365ece8a530Spatrick // Check whether the target address S is in range from a relocation
366ece8a530Spatrick // of type relType at address P.
isInRange(uint16_t relType,uint64_t s,uint64_t p,int margin)367*dfe94b16Srobert bool Writer::isInRange(uint16_t relType, uint64_t s, uint64_t p, int margin) {
368*dfe94b16Srobert if (ctx.config.machine == ARMNT) {
369ece8a530Spatrick int64_t diff = AbsoluteDifference(s, p + 4) + margin;
370ece8a530Spatrick switch (relType) {
371ece8a530Spatrick case IMAGE_REL_ARM_BRANCH20T:
372ece8a530Spatrick return isInt<21>(diff);
373ece8a530Spatrick case IMAGE_REL_ARM_BRANCH24T:
374ece8a530Spatrick case IMAGE_REL_ARM_BLX23T:
375ece8a530Spatrick return isInt<25>(diff);
376ece8a530Spatrick default:
377ece8a530Spatrick return true;
378ece8a530Spatrick }
379*dfe94b16Srobert } else if (ctx.config.machine == ARM64) {
380ece8a530Spatrick int64_t diff = AbsoluteDifference(s, p) + margin;
381ece8a530Spatrick switch (relType) {
382ece8a530Spatrick case IMAGE_REL_ARM64_BRANCH26:
383ece8a530Spatrick return isInt<28>(diff);
384ece8a530Spatrick case IMAGE_REL_ARM64_BRANCH19:
385ece8a530Spatrick return isInt<21>(diff);
386ece8a530Spatrick case IMAGE_REL_ARM64_BRANCH14:
387ece8a530Spatrick return isInt<16>(diff);
388ece8a530Spatrick default:
389ece8a530Spatrick return true;
390ece8a530Spatrick }
391ece8a530Spatrick } else {
392ece8a530Spatrick llvm_unreachable("Unexpected architecture");
393ece8a530Spatrick }
394ece8a530Spatrick }
395ece8a530Spatrick
396ece8a530Spatrick // Return the last thunk for the given target if it is in range,
397ece8a530Spatrick // or create a new one.
398*dfe94b16Srobert std::pair<Defined *, bool>
getThunk(DenseMap<uint64_t,Defined * > & lastThunks,Defined * target,uint64_t p,uint16_t type,int margin)399*dfe94b16Srobert Writer::getThunk(DenseMap<uint64_t, Defined *> &lastThunks, Defined *target,
400*dfe94b16Srobert uint64_t p, uint16_t type, int margin) {
401ece8a530Spatrick Defined *&lastThunk = lastThunks[target->getRVA()];
402ece8a530Spatrick if (lastThunk && isInRange(type, lastThunk->getRVA(), p, margin))
403ece8a530Spatrick return {lastThunk, false};
404ece8a530Spatrick Chunk *c;
405*dfe94b16Srobert switch (ctx.config.machine) {
406ece8a530Spatrick case ARMNT:
407*dfe94b16Srobert c = make<RangeExtensionThunkARM>(ctx, target);
408ece8a530Spatrick break;
409ece8a530Spatrick case ARM64:
410*dfe94b16Srobert c = make<RangeExtensionThunkARM64>(ctx, target);
411ece8a530Spatrick break;
412ece8a530Spatrick default:
413ece8a530Spatrick llvm_unreachable("Unexpected architecture");
414ece8a530Spatrick }
415*dfe94b16Srobert Defined *d = make<DefinedSynthetic>("range_extension_thunk", c);
416ece8a530Spatrick lastThunk = d;
417ece8a530Spatrick return {d, true};
418ece8a530Spatrick }
419ece8a530Spatrick
420ece8a530Spatrick // This checks all relocations, and for any relocation which isn't in range
421ece8a530Spatrick // it adds a thunk after the section chunk that contains the relocation.
422ece8a530Spatrick // If the latest thunk for the specific target is in range, that is used
423ece8a530Spatrick // instead of creating a new thunk. All range checks are done with the
424ece8a530Spatrick // specified margin, to make sure that relocations that originally are in
425ece8a530Spatrick // range, but only barely, also get thunks - in case other added thunks makes
426ece8a530Spatrick // the target go out of range.
427ece8a530Spatrick //
428ece8a530Spatrick // After adding thunks, we verify that all relocations are in range (with
429ece8a530Spatrick // no extra margin requirements). If this failed, we restart (throwing away
430ece8a530Spatrick // the previously created thunks) and retry with a wider margin.
createThunks(OutputSection * os,int margin)431*dfe94b16Srobert bool Writer::createThunks(OutputSection *os, int margin) {
432ece8a530Spatrick bool addressesChanged = false;
433ece8a530Spatrick DenseMap<uint64_t, Defined *> lastThunks;
434ece8a530Spatrick DenseMap<std::pair<ObjFile *, Defined *>, uint32_t> thunkSymtabIndices;
435ece8a530Spatrick size_t thunksSize = 0;
436ece8a530Spatrick // Recheck Chunks.size() each iteration, since we can insert more
437ece8a530Spatrick // elements into it.
438ece8a530Spatrick for (size_t i = 0; i != os->chunks.size(); ++i) {
439ece8a530Spatrick SectionChunk *sc = dyn_cast_or_null<SectionChunk>(os->chunks[i]);
440ece8a530Spatrick if (!sc)
441ece8a530Spatrick continue;
442ece8a530Spatrick size_t thunkInsertionSpot = i + 1;
443ece8a530Spatrick
444ece8a530Spatrick // Try to get a good enough estimate of where new thunks will be placed.
445ece8a530Spatrick // Offset this by the size of the new thunks added so far, to make the
446ece8a530Spatrick // estimate slightly better.
447ece8a530Spatrick size_t thunkInsertionRVA = sc->getRVA() + sc->getSize() + thunksSize;
448ece8a530Spatrick ObjFile *file = sc->file;
449ece8a530Spatrick std::vector<std::pair<uint32_t, uint32_t>> relocReplacements;
450ece8a530Spatrick ArrayRef<coff_relocation> originalRelocs =
451ece8a530Spatrick file->getCOFFObj()->getRelocations(sc->header);
452ece8a530Spatrick for (size_t j = 0, e = originalRelocs.size(); j < e; ++j) {
453ece8a530Spatrick const coff_relocation &rel = originalRelocs[j];
454ece8a530Spatrick Symbol *relocTarget = file->getSymbol(rel.SymbolTableIndex);
455ece8a530Spatrick
456ece8a530Spatrick // The estimate of the source address P should be pretty accurate,
457ece8a530Spatrick // but we don't know whether the target Symbol address should be
458ece8a530Spatrick // offset by thunksSize or not (or by some of thunksSize but not all of
459ece8a530Spatrick // it), giving us some uncertainty once we have added one thunk.
460ece8a530Spatrick uint64_t p = sc->getRVA() + rel.VirtualAddress + thunksSize;
461ece8a530Spatrick
462ece8a530Spatrick Defined *sym = dyn_cast_or_null<Defined>(relocTarget);
463ece8a530Spatrick if (!sym)
464ece8a530Spatrick continue;
465ece8a530Spatrick
466ece8a530Spatrick uint64_t s = sym->getRVA();
467ece8a530Spatrick
468ece8a530Spatrick if (isInRange(rel.Type, s, p, margin))
469ece8a530Spatrick continue;
470ece8a530Spatrick
471*dfe94b16Srobert // If the target isn't in range, hook it up to an existing or new thunk.
472*dfe94b16Srobert auto [thunk, wasNew] = getThunk(lastThunks, sym, p, rel.Type, margin);
473ece8a530Spatrick if (wasNew) {
474ece8a530Spatrick Chunk *thunkChunk = thunk->getChunk();
475ece8a530Spatrick thunkChunk->setRVA(
476ece8a530Spatrick thunkInsertionRVA); // Estimate of where it will be located.
477ece8a530Spatrick os->chunks.insert(os->chunks.begin() + thunkInsertionSpot, thunkChunk);
478ece8a530Spatrick thunkInsertionSpot++;
479ece8a530Spatrick thunksSize += thunkChunk->getSize();
480ece8a530Spatrick thunkInsertionRVA += thunkChunk->getSize();
481ece8a530Spatrick addressesChanged = true;
482ece8a530Spatrick }
483ece8a530Spatrick
484ece8a530Spatrick // To redirect the relocation, add a symbol to the parent object file's
485ece8a530Spatrick // symbol table, and replace the relocation symbol table index with the
486ece8a530Spatrick // new index.
487ece8a530Spatrick auto insertion = thunkSymtabIndices.insert({{file, thunk}, ~0U});
488ece8a530Spatrick uint32_t &thunkSymbolIndex = insertion.first->second;
489ece8a530Spatrick if (insertion.second)
490ece8a530Spatrick thunkSymbolIndex = file->addRangeThunkSymbol(thunk);
491ece8a530Spatrick relocReplacements.push_back({j, thunkSymbolIndex});
492ece8a530Spatrick }
493ece8a530Spatrick
494ece8a530Spatrick // Get a writable copy of this section's relocations so they can be
495ece8a530Spatrick // modified. If the relocations point into the object file, allocate new
496ece8a530Spatrick // memory. Otherwise, this must be previously allocated memory that can be
497ece8a530Spatrick // modified in place.
498ece8a530Spatrick ArrayRef<coff_relocation> curRelocs = sc->getRelocs();
499ece8a530Spatrick MutableArrayRef<coff_relocation> newRelocs;
500ece8a530Spatrick if (originalRelocs.data() == curRelocs.data()) {
501*dfe94b16Srobert newRelocs = MutableArrayRef(
502*dfe94b16Srobert bAlloc().Allocate<coff_relocation>(originalRelocs.size()),
503ece8a530Spatrick originalRelocs.size());
504ece8a530Spatrick } else {
505*dfe94b16Srobert newRelocs = MutableArrayRef(
506ece8a530Spatrick const_cast<coff_relocation *>(curRelocs.data()), curRelocs.size());
507ece8a530Spatrick }
508ece8a530Spatrick
509ece8a530Spatrick // Copy each relocation, but replace the symbol table indices which need
510ece8a530Spatrick // thunks.
511ece8a530Spatrick auto nextReplacement = relocReplacements.begin();
512ece8a530Spatrick auto endReplacement = relocReplacements.end();
513ece8a530Spatrick for (size_t i = 0, e = originalRelocs.size(); i != e; ++i) {
514ece8a530Spatrick newRelocs[i] = originalRelocs[i];
515ece8a530Spatrick if (nextReplacement != endReplacement && nextReplacement->first == i) {
516ece8a530Spatrick newRelocs[i].SymbolTableIndex = nextReplacement->second;
517ece8a530Spatrick ++nextReplacement;
518ece8a530Spatrick }
519ece8a530Spatrick }
520ece8a530Spatrick
521ece8a530Spatrick sc->setRelocs(newRelocs);
522ece8a530Spatrick }
523ece8a530Spatrick return addressesChanged;
524ece8a530Spatrick }
525ece8a530Spatrick
526ece8a530Spatrick // Verify that all relocations are in range, with no extra margin requirements.
verifyRanges(const std::vector<Chunk * > chunks)527*dfe94b16Srobert bool Writer::verifyRanges(const std::vector<Chunk *> chunks) {
528ece8a530Spatrick for (Chunk *c : chunks) {
529ece8a530Spatrick SectionChunk *sc = dyn_cast_or_null<SectionChunk>(c);
530ece8a530Spatrick if (!sc)
531ece8a530Spatrick continue;
532ece8a530Spatrick
533ece8a530Spatrick ArrayRef<coff_relocation> relocs = sc->getRelocs();
534ece8a530Spatrick for (size_t j = 0, e = relocs.size(); j < e; ++j) {
535ece8a530Spatrick const coff_relocation &rel = relocs[j];
536ece8a530Spatrick Symbol *relocTarget = sc->file->getSymbol(rel.SymbolTableIndex);
537ece8a530Spatrick
538ece8a530Spatrick Defined *sym = dyn_cast_or_null<Defined>(relocTarget);
539ece8a530Spatrick if (!sym)
540ece8a530Spatrick continue;
541ece8a530Spatrick
542ece8a530Spatrick uint64_t p = sc->getRVA() + rel.VirtualAddress;
543ece8a530Spatrick uint64_t s = sym->getRVA();
544ece8a530Spatrick
545ece8a530Spatrick if (!isInRange(rel.Type, s, p, 0))
546ece8a530Spatrick return false;
547ece8a530Spatrick }
548ece8a530Spatrick }
549ece8a530Spatrick return true;
550ece8a530Spatrick }
551ece8a530Spatrick
552ece8a530Spatrick // Assign addresses and add thunks if necessary.
finalizeAddresses()553ece8a530Spatrick void Writer::finalizeAddresses() {
554ece8a530Spatrick assignAddresses();
555*dfe94b16Srobert if (ctx.config.machine != ARMNT && ctx.config.machine != ARM64)
556ece8a530Spatrick return;
557ece8a530Spatrick
558ece8a530Spatrick size_t origNumChunks = 0;
559*dfe94b16Srobert for (OutputSection *sec : ctx.outputSections) {
560ece8a530Spatrick sec->origChunks = sec->chunks;
561ece8a530Spatrick origNumChunks += sec->chunks.size();
562ece8a530Spatrick }
563ece8a530Spatrick
564ece8a530Spatrick int pass = 0;
565ece8a530Spatrick int margin = 1024 * 100;
566ece8a530Spatrick while (true) {
567ece8a530Spatrick // First check whether we need thunks at all, or if the previous pass of
568ece8a530Spatrick // adding them turned out ok.
569ece8a530Spatrick bool rangesOk = true;
570ece8a530Spatrick size_t numChunks = 0;
571*dfe94b16Srobert for (OutputSection *sec : ctx.outputSections) {
572ece8a530Spatrick if (!verifyRanges(sec->chunks)) {
573ece8a530Spatrick rangesOk = false;
574ece8a530Spatrick break;
575ece8a530Spatrick }
576ece8a530Spatrick numChunks += sec->chunks.size();
577ece8a530Spatrick }
578ece8a530Spatrick if (rangesOk) {
579ece8a530Spatrick if (pass > 0)
580ece8a530Spatrick log("Added " + Twine(numChunks - origNumChunks) + " thunks with " +
581ece8a530Spatrick "margin " + Twine(margin) + " in " + Twine(pass) + " passes");
582ece8a530Spatrick return;
583ece8a530Spatrick }
584ece8a530Spatrick
585ece8a530Spatrick if (pass >= 10)
586ece8a530Spatrick fatal("adding thunks hasn't converged after " + Twine(pass) + " passes");
587ece8a530Spatrick
588ece8a530Spatrick if (pass > 0) {
589ece8a530Spatrick // If the previous pass didn't work out, reset everything back to the
590ece8a530Spatrick // original conditions before retrying with a wider margin. This should
591ece8a530Spatrick // ideally never happen under real circumstances.
592*dfe94b16Srobert for (OutputSection *sec : ctx.outputSections)
593ece8a530Spatrick sec->chunks = sec->origChunks;
594ece8a530Spatrick margin *= 2;
595ece8a530Spatrick }
596ece8a530Spatrick
597ece8a530Spatrick // Try adding thunks everywhere where it is needed, with a margin
598ece8a530Spatrick // to avoid things going out of range due to the added thunks.
599ece8a530Spatrick bool addressesChanged = false;
600*dfe94b16Srobert for (OutputSection *sec : ctx.outputSections)
601ece8a530Spatrick addressesChanged |= createThunks(sec, margin);
602ece8a530Spatrick // If the verification above thought we needed thunks, we should have
603ece8a530Spatrick // added some.
604ece8a530Spatrick assert(addressesChanged);
6051cf9926bSpatrick (void)addressesChanged;
606ece8a530Spatrick
607ece8a530Spatrick // Recalculate the layout for the whole image (and verify the ranges at
608ece8a530Spatrick // the start of the next round).
609ece8a530Spatrick assignAddresses();
610ece8a530Spatrick
611ece8a530Spatrick pass++;
612ece8a530Spatrick }
613ece8a530Spatrick }
614ece8a530Spatrick
writePEChecksum()615*dfe94b16Srobert void Writer::writePEChecksum() {
616*dfe94b16Srobert if (!ctx.config.writeCheckSum) {
617*dfe94b16Srobert return;
618*dfe94b16Srobert }
619*dfe94b16Srobert
620*dfe94b16Srobert // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#checksum
621*dfe94b16Srobert uint32_t *buf = (uint32_t *)buffer->getBufferStart();
622*dfe94b16Srobert uint32_t size = (uint32_t)(buffer->getBufferSize());
623*dfe94b16Srobert
624*dfe94b16Srobert coff_file_header *coffHeader =
625*dfe94b16Srobert (coff_file_header *)((uint8_t *)buf + dosStubSize + sizeof(PEMagic));
626*dfe94b16Srobert pe32_header *peHeader =
627*dfe94b16Srobert (pe32_header *)((uint8_t *)coffHeader + sizeof(coff_file_header));
628*dfe94b16Srobert
629*dfe94b16Srobert uint64_t sum = 0;
630*dfe94b16Srobert uint32_t count = size;
631*dfe94b16Srobert ulittle16_t *addr = (ulittle16_t *)buf;
632*dfe94b16Srobert
633*dfe94b16Srobert // The PE checksum algorithm, implemented as suggested in RFC1071
634*dfe94b16Srobert while (count > 1) {
635*dfe94b16Srobert sum += *addr++;
636*dfe94b16Srobert count -= 2;
637*dfe94b16Srobert }
638*dfe94b16Srobert
639*dfe94b16Srobert // Add left-over byte, if any
640*dfe94b16Srobert if (count > 0)
641*dfe94b16Srobert sum += *(unsigned char *)addr;
642*dfe94b16Srobert
643*dfe94b16Srobert // Fold 32-bit sum to 16 bits
644*dfe94b16Srobert while (sum >> 16) {
645*dfe94b16Srobert sum = (sum & 0xffff) + (sum >> 16);
646*dfe94b16Srobert }
647*dfe94b16Srobert
648*dfe94b16Srobert sum += size;
649*dfe94b16Srobert peHeader->CheckSum = sum;
650*dfe94b16Srobert }
651*dfe94b16Srobert
652ece8a530Spatrick // The main function of the writer.
run()653ece8a530Spatrick void Writer::run() {
654*dfe94b16Srobert ScopedTimer t1(ctx.codeLayoutTimer);
655ece8a530Spatrick
656ece8a530Spatrick createImportTables();
657ece8a530Spatrick createSections();
658ece8a530Spatrick appendImportThunks();
6591cf9926bSpatrick // Import thunks must be added before the Control Flow Guard tables are added.
6601cf9926bSpatrick createMiscChunks();
661ece8a530Spatrick createExportTable();
662ece8a530Spatrick mergeSections();
663ece8a530Spatrick removeUnusedSections();
664ece8a530Spatrick finalizeAddresses();
665ece8a530Spatrick removeEmptySections();
666ece8a530Spatrick assignOutputSectionIndices();
667ece8a530Spatrick setSectionPermissions();
668ece8a530Spatrick createSymbolAndStringTable();
669ece8a530Spatrick
670ece8a530Spatrick if (fileSize > UINT32_MAX)
671ece8a530Spatrick fatal("image size (" + Twine(fileSize) + ") " +
672ece8a530Spatrick "exceeds maximum allowable size (" + Twine(UINT32_MAX) + ")");
673ece8a530Spatrick
674*dfe94b16Srobert openFile(ctx.config.outputFile);
675*dfe94b16Srobert if (ctx.config.is64()) {
676ece8a530Spatrick writeHeader<pe32plus_header>();
677ece8a530Spatrick } else {
678ece8a530Spatrick writeHeader<pe32_header>();
679ece8a530Spatrick }
680ece8a530Spatrick writeSections();
681*dfe94b16Srobert checkLoadConfig();
682ece8a530Spatrick sortExceptionTable();
683ece8a530Spatrick
6841cf9926bSpatrick // Fix up the alignment in the TLS Directory's characteristic field,
6851cf9926bSpatrick // if a specific alignment value is needed
6861cf9926bSpatrick if (tlsAlignment)
6871cf9926bSpatrick fixTlsAlignment();
6881cf9926bSpatrick
689ece8a530Spatrick t1.stop();
690ece8a530Spatrick
691*dfe94b16Srobert if (!ctx.config.pdbPath.empty() && ctx.config.debug) {
692ece8a530Spatrick assert(buildId);
693*dfe94b16Srobert createPDB(ctx, sectionTable, buildId->buildId);
694ece8a530Spatrick }
695ece8a530Spatrick writeBuildId();
696ece8a530Spatrick
697*dfe94b16Srobert writeLLDMapFile(ctx);
698*dfe94b16Srobert writeMapFile(ctx);
699*dfe94b16Srobert
700*dfe94b16Srobert writePEChecksum();
701ece8a530Spatrick
702ece8a530Spatrick if (errorCount())
703ece8a530Spatrick return;
704ece8a530Spatrick
705*dfe94b16Srobert ScopedTimer t2(ctx.outputCommitTimer);
706ece8a530Spatrick if (auto e = buffer->commit())
707*dfe94b16Srobert fatal("failed to write output '" + buffer->getPath() +
708*dfe94b16Srobert "': " + toString(std::move(e)));
709ece8a530Spatrick }
710ece8a530Spatrick
getOutputSectionName(StringRef name)711ece8a530Spatrick static StringRef getOutputSectionName(StringRef name) {
712ece8a530Spatrick StringRef s = name.split('$').first;
713ece8a530Spatrick
714ece8a530Spatrick // Treat a later period as a separator for MinGW, for sections like
715ece8a530Spatrick // ".ctors.01234".
716ece8a530Spatrick return s.substr(0, s.find('.', 1));
717ece8a530Spatrick }
718ece8a530Spatrick
719ece8a530Spatrick // For /order.
sortBySectionOrder(std::vector<Chunk * > & chunks)720*dfe94b16Srobert void Writer::sortBySectionOrder(std::vector<Chunk *> &chunks) {
721*dfe94b16Srobert auto getPriority = [&ctx = ctx](const Chunk *c) {
722ece8a530Spatrick if (auto *sec = dyn_cast<SectionChunk>(c))
723ece8a530Spatrick if (sec->sym)
724*dfe94b16Srobert return ctx.config.order.lookup(sec->sym->getName());
725ece8a530Spatrick return 0;
726ece8a530Spatrick };
727ece8a530Spatrick
728ece8a530Spatrick llvm::stable_sort(chunks, [=](const Chunk *a, const Chunk *b) {
729ece8a530Spatrick return getPriority(a) < getPriority(b);
730ece8a530Spatrick });
731ece8a530Spatrick }
732ece8a530Spatrick
733ece8a530Spatrick // Change the characteristics of existing PartialSections that belong to the
734ece8a530Spatrick // section Name to Chars.
fixPartialSectionChars(StringRef name,uint32_t chars)735ece8a530Spatrick void Writer::fixPartialSectionChars(StringRef name, uint32_t chars) {
736ece8a530Spatrick for (auto it : partialSections) {
737ece8a530Spatrick PartialSection *pSec = it.second;
738ece8a530Spatrick StringRef curName = pSec->name;
739ece8a530Spatrick if (!curName.consume_front(name) ||
740ece8a530Spatrick (!curName.empty() && !curName.startswith("$")))
741ece8a530Spatrick continue;
742ece8a530Spatrick if (pSec->characteristics == chars)
743ece8a530Spatrick continue;
744ece8a530Spatrick PartialSection *destSec = createPartialSection(pSec->name, chars);
745ece8a530Spatrick destSec->chunks.insert(destSec->chunks.end(), pSec->chunks.begin(),
746ece8a530Spatrick pSec->chunks.end());
747ece8a530Spatrick pSec->chunks.clear();
748ece8a530Spatrick }
749ece8a530Spatrick }
750ece8a530Spatrick
751ece8a530Spatrick // Sort concrete section chunks from GNU import libraries.
752ece8a530Spatrick //
753ece8a530Spatrick // GNU binutils doesn't use short import files, but instead produces import
754ece8a530Spatrick // libraries that consist of object files, with section chunks for the .idata$*
755ece8a530Spatrick // sections. These are linked just as regular static libraries. Each import
756ece8a530Spatrick // library consists of one header object, one object file for every imported
757ece8a530Spatrick // symbol, and one trailer object. In order for the .idata tables/lists to
758ece8a530Spatrick // be formed correctly, the section chunks within each .idata$* section need
759ece8a530Spatrick // to be grouped by library, and sorted alphabetically within each library
760ece8a530Spatrick // (which makes sure the header comes first and the trailer last).
fixGnuImportChunks()761ece8a530Spatrick bool Writer::fixGnuImportChunks() {
762ece8a530Spatrick uint32_t rdata = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ;
763ece8a530Spatrick
764ece8a530Spatrick // Make sure all .idata$* section chunks are mapped as RDATA in order to
765ece8a530Spatrick // be sorted into the same sections as our own synthesized .idata chunks.
766ece8a530Spatrick fixPartialSectionChars(".idata", rdata);
767ece8a530Spatrick
768ece8a530Spatrick bool hasIdata = false;
769ece8a530Spatrick // Sort all .idata$* chunks, grouping chunks from the same library,
770*dfe94b16Srobert // with alphabetical ordering of the object files within a library.
771ece8a530Spatrick for (auto it : partialSections) {
772ece8a530Spatrick PartialSection *pSec = it.second;
773ece8a530Spatrick if (!pSec->name.startswith(".idata"))
774ece8a530Spatrick continue;
775ece8a530Spatrick
776ece8a530Spatrick if (!pSec->chunks.empty())
777ece8a530Spatrick hasIdata = true;
778ece8a530Spatrick llvm::stable_sort(pSec->chunks, [&](Chunk *s, Chunk *t) {
779ece8a530Spatrick SectionChunk *sc1 = dyn_cast_or_null<SectionChunk>(s);
780ece8a530Spatrick SectionChunk *sc2 = dyn_cast_or_null<SectionChunk>(t);
781ece8a530Spatrick if (!sc1 || !sc2) {
782ece8a530Spatrick // if SC1, order them ascending. If SC2 or both null,
783ece8a530Spatrick // S is not less than T.
784ece8a530Spatrick return sc1 != nullptr;
785ece8a530Spatrick }
786ece8a530Spatrick // Make a string with "libraryname/objectfile" for sorting, achieving
787ece8a530Spatrick // both grouping by library and sorting of objects within a library,
788ece8a530Spatrick // at once.
789ece8a530Spatrick std::string key1 =
790ece8a530Spatrick (sc1->file->parentName + "/" + sc1->file->getName()).str();
791ece8a530Spatrick std::string key2 =
792ece8a530Spatrick (sc2->file->parentName + "/" + sc2->file->getName()).str();
793ece8a530Spatrick return key1 < key2;
794ece8a530Spatrick });
795ece8a530Spatrick }
796ece8a530Spatrick return hasIdata;
797ece8a530Spatrick }
798ece8a530Spatrick
799ece8a530Spatrick // Add generated idata chunks, for imported symbols and DLLs, and a
800ece8a530Spatrick // terminator in .idata$2.
addSyntheticIdata()801ece8a530Spatrick void Writer::addSyntheticIdata() {
802ece8a530Spatrick uint32_t rdata = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ;
803*dfe94b16Srobert idata.create(ctx);
804ece8a530Spatrick
805ece8a530Spatrick // Add the .idata content in the right section groups, to allow
806ece8a530Spatrick // chunks from other linked in object files to be grouped together.
807ece8a530Spatrick // See Microsoft PE/COFF spec 5.4 for details.
808ece8a530Spatrick auto add = [&](StringRef n, std::vector<Chunk *> &v) {
809ece8a530Spatrick PartialSection *pSec = createPartialSection(n, rdata);
810ece8a530Spatrick pSec->chunks.insert(pSec->chunks.end(), v.begin(), v.end());
811ece8a530Spatrick };
812ece8a530Spatrick
813ece8a530Spatrick // The loader assumes a specific order of data.
814ece8a530Spatrick // Add each type in the correct order.
815ece8a530Spatrick add(".idata$2", idata.dirs);
816ece8a530Spatrick add(".idata$4", idata.lookups);
817ece8a530Spatrick add(".idata$5", idata.addresses);
818ece8a530Spatrick if (!idata.hints.empty())
819ece8a530Spatrick add(".idata$6", idata.hints);
820ece8a530Spatrick add(".idata$7", idata.dllNames);
821ece8a530Spatrick }
822ece8a530Spatrick
823ece8a530Spatrick // Locate the first Chunk and size of the import directory list and the
824ece8a530Spatrick // IAT.
locateImportTables()825ece8a530Spatrick void Writer::locateImportTables() {
826ece8a530Spatrick uint32_t rdata = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ;
827ece8a530Spatrick
828ece8a530Spatrick if (PartialSection *importDirs = findPartialSection(".idata$2", rdata)) {
829ece8a530Spatrick if (!importDirs->chunks.empty())
830ece8a530Spatrick importTableStart = importDirs->chunks.front();
831ece8a530Spatrick for (Chunk *c : importDirs->chunks)
832ece8a530Spatrick importTableSize += c->getSize();
833ece8a530Spatrick }
834ece8a530Spatrick
835ece8a530Spatrick if (PartialSection *importAddresses = findPartialSection(".idata$5", rdata)) {
836ece8a530Spatrick if (!importAddresses->chunks.empty())
837ece8a530Spatrick iatStart = importAddresses->chunks.front();
838ece8a530Spatrick for (Chunk *c : importAddresses->chunks)
839ece8a530Spatrick iatSize += c->getSize();
840ece8a530Spatrick }
841ece8a530Spatrick }
842ece8a530Spatrick
843ece8a530Spatrick // Return whether a SectionChunk's suffix (the dollar and any trailing
844ece8a530Spatrick // suffix) should be removed and sorted into the main suffixless
845ece8a530Spatrick // PartialSection.
shouldStripSectionSuffix(SectionChunk * sc,StringRef name,bool isMinGW)846*dfe94b16Srobert static bool shouldStripSectionSuffix(SectionChunk *sc, StringRef name,
847*dfe94b16Srobert bool isMinGW) {
848ece8a530Spatrick // On MinGW, comdat groups are formed by putting the comdat group name
849ece8a530Spatrick // after the '$' in the section name. For .eh_frame$<symbol>, that must
850ece8a530Spatrick // still be sorted before the .eh_frame trailer from crtend.o, thus just
851ece8a530Spatrick // strip the section name trailer. For other sections, such as
852ece8a530Spatrick // .tls$$<symbol> (where non-comdat .tls symbols are otherwise stored in
853ece8a530Spatrick // ".tls$"), they must be strictly sorted after .tls. And for the
854ece8a530Spatrick // hypothetical case of comdat .CRT$XCU, we definitely need to keep the
855ece8a530Spatrick // suffix for sorting. Thus, to play it safe, only strip the suffix for
856ece8a530Spatrick // the standard sections.
857*dfe94b16Srobert if (!isMinGW)
858ece8a530Spatrick return false;
859ece8a530Spatrick if (!sc || !sc->isCOMDAT())
860ece8a530Spatrick return false;
861ece8a530Spatrick return name.startswith(".text$") || name.startswith(".data$") ||
862ece8a530Spatrick name.startswith(".rdata$") || name.startswith(".pdata$") ||
863ece8a530Spatrick name.startswith(".xdata$") || name.startswith(".eh_frame$");
864ece8a530Spatrick }
865ece8a530Spatrick
sortSections()8661cf9926bSpatrick void Writer::sortSections() {
867*dfe94b16Srobert if (!ctx.config.callGraphProfile.empty()) {
868*dfe94b16Srobert DenseMap<const SectionChunk *, int> order =
869*dfe94b16Srobert computeCallGraphProfileOrder(ctx);
8701cf9926bSpatrick for (auto it : order) {
8711cf9926bSpatrick if (DefinedRegular *sym = it.first->sym)
872*dfe94b16Srobert ctx.config.order[sym->getName()] = it.second;
8731cf9926bSpatrick }
8741cf9926bSpatrick }
875*dfe94b16Srobert if (!ctx.config.order.empty())
8761cf9926bSpatrick for (auto it : partialSections)
8771cf9926bSpatrick sortBySectionOrder(it.second->chunks);
8781cf9926bSpatrick }
8791cf9926bSpatrick
880ece8a530Spatrick // Create output section objects and add them to OutputSections.
createSections()881ece8a530Spatrick void Writer::createSections() {
882ece8a530Spatrick // First, create the builtin sections.
883ece8a530Spatrick const uint32_t data = IMAGE_SCN_CNT_INITIALIZED_DATA;
884ece8a530Spatrick const uint32_t bss = IMAGE_SCN_CNT_UNINITIALIZED_DATA;
885ece8a530Spatrick const uint32_t code = IMAGE_SCN_CNT_CODE;
886ece8a530Spatrick const uint32_t discardable = IMAGE_SCN_MEM_DISCARDABLE;
887ece8a530Spatrick const uint32_t r = IMAGE_SCN_MEM_READ;
888ece8a530Spatrick const uint32_t w = IMAGE_SCN_MEM_WRITE;
889ece8a530Spatrick const uint32_t x = IMAGE_SCN_MEM_EXECUTE;
890ece8a530Spatrick
891ece8a530Spatrick SmallDenseMap<std::pair<StringRef, uint32_t>, OutputSection *> sections;
892ece8a530Spatrick auto createSection = [&](StringRef name, uint32_t outChars) {
893ece8a530Spatrick OutputSection *&sec = sections[{name, outChars}];
894ece8a530Spatrick if (!sec) {
895ece8a530Spatrick sec = make<OutputSection>(name, outChars);
896*dfe94b16Srobert ctx.outputSections.push_back(sec);
897ece8a530Spatrick }
898ece8a530Spatrick return sec;
899ece8a530Spatrick };
900ece8a530Spatrick
901ece8a530Spatrick // Try to match the section order used by link.exe.
902ece8a530Spatrick textSec = createSection(".text", code | r | x);
903ece8a530Spatrick createSection(".bss", bss | r | w);
904ece8a530Spatrick rdataSec = createSection(".rdata", data | r);
905ece8a530Spatrick buildidSec = createSection(".buildid", data | r);
906ece8a530Spatrick dataSec = createSection(".data", data | r | w);
907ece8a530Spatrick pdataSec = createSection(".pdata", data | r);
908ece8a530Spatrick idataSec = createSection(".idata", data | r);
909ece8a530Spatrick edataSec = createSection(".edata", data | r);
910ece8a530Spatrick didatSec = createSection(".didat", data | r);
911ece8a530Spatrick rsrcSec = createSection(".rsrc", data | r);
912ece8a530Spatrick relocSec = createSection(".reloc", data | discardable | r);
913ece8a530Spatrick ctorsSec = createSection(".ctors", data | r | w);
914ece8a530Spatrick dtorsSec = createSection(".dtors", data | r | w);
915ece8a530Spatrick
916ece8a530Spatrick // Then bin chunks by name and output characteristics.
917*dfe94b16Srobert for (Chunk *c : ctx.symtab.getChunks()) {
918ece8a530Spatrick auto *sc = dyn_cast<SectionChunk>(c);
919ece8a530Spatrick if (sc && !sc->live) {
920*dfe94b16Srobert if (ctx.config.verbose)
921ece8a530Spatrick sc->printDiscardedMessage();
922ece8a530Spatrick continue;
923ece8a530Spatrick }
924ece8a530Spatrick StringRef name = c->getSectionName();
925*dfe94b16Srobert if (shouldStripSectionSuffix(sc, name, ctx.config.mingw))
926ece8a530Spatrick name = name.split('$').first;
9271cf9926bSpatrick
9281cf9926bSpatrick if (name.startswith(".tls"))
9291cf9926bSpatrick tlsAlignment = std::max(tlsAlignment, c->getAlignment());
9301cf9926bSpatrick
931ece8a530Spatrick PartialSection *pSec = createPartialSection(name,
932ece8a530Spatrick c->getOutputCharacteristics());
933ece8a530Spatrick pSec->chunks.push_back(c);
934ece8a530Spatrick }
935ece8a530Spatrick
936ece8a530Spatrick fixPartialSectionChars(".rsrc", data | r);
937ece8a530Spatrick fixPartialSectionChars(".edata", data | r);
938ece8a530Spatrick // Even in non MinGW cases, we might need to link against GNU import
939ece8a530Spatrick // libraries.
940ece8a530Spatrick bool hasIdata = fixGnuImportChunks();
941ece8a530Spatrick if (!idata.empty())
942ece8a530Spatrick hasIdata = true;
943ece8a530Spatrick
944ece8a530Spatrick if (hasIdata)
945ece8a530Spatrick addSyntheticIdata();
946ece8a530Spatrick
9471cf9926bSpatrick sortSections();
948ece8a530Spatrick
949ece8a530Spatrick if (hasIdata)
950ece8a530Spatrick locateImportTables();
951ece8a530Spatrick
952ece8a530Spatrick // Then create an OutputSection for each section.
953ece8a530Spatrick // '$' and all following characters in input section names are
954ece8a530Spatrick // discarded when determining output section. So, .text$foo
955ece8a530Spatrick // contributes to .text, for example. See PE/COFF spec 3.2.
956ece8a530Spatrick for (auto it : partialSections) {
957ece8a530Spatrick PartialSection *pSec = it.second;
958ece8a530Spatrick StringRef name = getOutputSectionName(pSec->name);
959ece8a530Spatrick uint32_t outChars = pSec->characteristics;
960ece8a530Spatrick
961ece8a530Spatrick if (name == ".CRT") {
962ece8a530Spatrick // In link.exe, there is a special case for the I386 target where .CRT
963ece8a530Spatrick // sections are treated as if they have output characteristics DATA | R if
964ece8a530Spatrick // their characteristics are DATA | R | W. This implements the same
965ece8a530Spatrick // special case for all architectures.
966ece8a530Spatrick outChars = data | r;
967ece8a530Spatrick
968ece8a530Spatrick log("Processing section " + pSec->name + " -> " + name);
969ece8a530Spatrick
970ece8a530Spatrick sortCRTSectionChunks(pSec->chunks);
971ece8a530Spatrick }
972ece8a530Spatrick
973ece8a530Spatrick OutputSection *sec = createSection(name, outChars);
974ece8a530Spatrick for (Chunk *c : pSec->chunks)
975ece8a530Spatrick sec->addChunk(c);
976ece8a530Spatrick
977ece8a530Spatrick sec->addContributingPartialSection(pSec);
978ece8a530Spatrick }
979ece8a530Spatrick
980ece8a530Spatrick // Finally, move some output sections to the end.
981ece8a530Spatrick auto sectionOrder = [&](const OutputSection *s) {
982ece8a530Spatrick // Move DISCARDABLE (or non-memory-mapped) sections to the end of file
983ece8a530Spatrick // because the loader cannot handle holes. Stripping can remove other
984ece8a530Spatrick // discardable ones than .reloc, which is first of them (created early).
985*dfe94b16Srobert if (s->header.Characteristics & IMAGE_SCN_MEM_DISCARDABLE) {
986*dfe94b16Srobert // Move discardable sections named .debug_ to the end, after other
987*dfe94b16Srobert // discardable sections. Stripping only removes the sections named
988*dfe94b16Srobert // .debug_* - thus try to avoid leaving holes after stripping.
989*dfe94b16Srobert if (s->name.startswith(".debug_"))
990*dfe94b16Srobert return 3;
991ece8a530Spatrick return 2;
992*dfe94b16Srobert }
993ece8a530Spatrick // .rsrc should come at the end of the non-discardable sections because its
994ece8a530Spatrick // size may change by the Win32 UpdateResources() function, causing
995ece8a530Spatrick // subsequent sections to move (see https://crbug.com/827082).
996ece8a530Spatrick if (s == rsrcSec)
997ece8a530Spatrick return 1;
998ece8a530Spatrick return 0;
999ece8a530Spatrick };
1000*dfe94b16Srobert llvm::stable_sort(ctx.outputSections,
1001ece8a530Spatrick [&](const OutputSection *s, const OutputSection *t) {
1002ece8a530Spatrick return sectionOrder(s) < sectionOrder(t);
1003ece8a530Spatrick });
1004ece8a530Spatrick }
1005ece8a530Spatrick
createMiscChunks()1006ece8a530Spatrick void Writer::createMiscChunks() {
1007*dfe94b16Srobert Configuration *config = &ctx.config;
1008*dfe94b16Srobert
1009*dfe94b16Srobert for (MergeChunk *p : ctx.mergeChunkInstances) {
1010ece8a530Spatrick if (p) {
1011ece8a530Spatrick p->finalizeContents();
1012ece8a530Spatrick rdataSec->addChunk(p);
1013ece8a530Spatrick }
1014ece8a530Spatrick }
1015ece8a530Spatrick
1016ece8a530Spatrick // Create thunks for locally-dllimported symbols.
1017*dfe94b16Srobert if (!ctx.symtab.localImportChunks.empty()) {
1018*dfe94b16Srobert for (Chunk *c : ctx.symtab.localImportChunks)
1019ece8a530Spatrick rdataSec->addChunk(c);
1020ece8a530Spatrick }
1021ece8a530Spatrick
1022ece8a530Spatrick // Create Debug Information Chunks
1023ece8a530Spatrick OutputSection *debugInfoSec = config->mingw ? buildidSec : rdataSec;
1024bb684c34Spatrick if (config->debug || config->repro || config->cetCompat) {
1025*dfe94b16Srobert debugDirectory =
1026*dfe94b16Srobert make<DebugDirectoryChunk>(ctx, debugRecords, config->repro);
1027bb684c34Spatrick debugDirectory->setAlignment(4);
1028ece8a530Spatrick debugInfoSec->addChunk(debugDirectory);
1029ece8a530Spatrick }
1030ece8a530Spatrick
1031ece8a530Spatrick if (config->debug) {
1032ece8a530Spatrick // Make a CVDebugRecordChunk even when /DEBUG:CV is not specified. We
1033ece8a530Spatrick // output a PDB no matter what, and this chunk provides the only means of
1034ece8a530Spatrick // allowing a debugger to match a PDB and an executable. So we need it even
1035ece8a530Spatrick // if we're ultimately not going to write CodeView data to the PDB.
1036*dfe94b16Srobert buildId = make<CVDebugRecordChunk>(ctx);
1037bb684c34Spatrick debugRecords.push_back({COFF::IMAGE_DEBUG_TYPE_CODEVIEW, buildId});
1038bb684c34Spatrick }
1039ece8a530Spatrick
1040bb684c34Spatrick if (config->cetCompat) {
10411cf9926bSpatrick debugRecords.push_back({COFF::IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS,
1042bb684c34Spatrick make<ExtendedDllCharacteristicsChunk>(
10431cf9926bSpatrick IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT)});
1044bb684c34Spatrick }
1045bb684c34Spatrick
10461cf9926bSpatrick // Align and add each chunk referenced by the debug data directory.
10471cf9926bSpatrick for (std::pair<COFF::DebugType, Chunk *> r : debugRecords) {
10481cf9926bSpatrick r.second->setAlignment(4);
1049bb684c34Spatrick debugInfoSec->addChunk(r.second);
1050ece8a530Spatrick }
1051ece8a530Spatrick
1052ece8a530Spatrick // Create SEH table. x86-only.
1053ece8a530Spatrick if (config->safeSEH)
1054ece8a530Spatrick createSEHTable();
1055ece8a530Spatrick
1056ece8a530Spatrick // Create /guard:cf tables if requested.
1057ece8a530Spatrick if (config->guardCF != GuardCFLevel::Off)
1058ece8a530Spatrick createGuardCFTables();
1059ece8a530Spatrick
1060bb684c34Spatrick if (config->autoImport)
1061ece8a530Spatrick createRuntimePseudoRelocs();
1062ece8a530Spatrick
1063bb684c34Spatrick if (config->mingw)
1064ece8a530Spatrick insertCtorDtorSymbols();
1065ece8a530Spatrick }
1066ece8a530Spatrick
1067ece8a530Spatrick // Create .idata section for the DLL-imported symbol table.
1068ece8a530Spatrick // The format of this section is inherently Windows-specific.
1069ece8a530Spatrick // IdataContents class abstracted away the details for us,
1070ece8a530Spatrick // so we just let it create chunks and add them to the section.
createImportTables()1071ece8a530Spatrick void Writer::createImportTables() {
1072ece8a530Spatrick // Initialize DLLOrder so that import entries are ordered in
1073ece8a530Spatrick // the same order as in the command line. (That affects DLL
1074ece8a530Spatrick // initialization order, and this ordering is MSVC-compatible.)
1075*dfe94b16Srobert for (ImportFile *file : ctx.importFileInstances) {
1076ece8a530Spatrick if (!file->live)
1077ece8a530Spatrick continue;
1078ece8a530Spatrick
1079ece8a530Spatrick std::string dll = StringRef(file->dllName).lower();
1080*dfe94b16Srobert if (ctx.config.dllOrder.count(dll) == 0)
1081*dfe94b16Srobert ctx.config.dllOrder[dll] = ctx.config.dllOrder.size();
1082ece8a530Spatrick
1083ece8a530Spatrick if (file->impSym && !isa<DefinedImportData>(file->impSym))
1084*dfe94b16Srobert fatal(toString(ctx, *file->impSym) + " was replaced");
1085ece8a530Spatrick DefinedImportData *impSym = cast_or_null<DefinedImportData>(file->impSym);
1086*dfe94b16Srobert if (ctx.config.delayLoads.count(StringRef(file->dllName).lower())) {
1087ece8a530Spatrick if (!file->thunkSym)
1088ece8a530Spatrick fatal("cannot delay-load " + toString(file) +
1089*dfe94b16Srobert " due to import of data: " + toString(ctx, *impSym));
1090ece8a530Spatrick delayIdata.add(impSym);
1091ece8a530Spatrick } else {
1092ece8a530Spatrick idata.add(impSym);
1093ece8a530Spatrick }
1094ece8a530Spatrick }
1095ece8a530Spatrick }
1096ece8a530Spatrick
appendImportThunks()1097ece8a530Spatrick void Writer::appendImportThunks() {
1098*dfe94b16Srobert if (ctx.importFileInstances.empty())
1099ece8a530Spatrick return;
1100ece8a530Spatrick
1101*dfe94b16Srobert for (ImportFile *file : ctx.importFileInstances) {
1102ece8a530Spatrick if (!file->live)
1103ece8a530Spatrick continue;
1104ece8a530Spatrick
1105ece8a530Spatrick if (!file->thunkSym)
1106ece8a530Spatrick continue;
1107ece8a530Spatrick
1108ece8a530Spatrick if (!isa<DefinedImportThunk>(file->thunkSym))
1109*dfe94b16Srobert fatal(toString(ctx, *file->thunkSym) + " was replaced");
1110ece8a530Spatrick DefinedImportThunk *thunk = cast<DefinedImportThunk>(file->thunkSym);
1111ece8a530Spatrick if (file->thunkLive)
1112ece8a530Spatrick textSec->addChunk(thunk->getChunk());
1113ece8a530Spatrick }
1114ece8a530Spatrick
1115ece8a530Spatrick if (!delayIdata.empty()) {
1116*dfe94b16Srobert Defined *helper = cast<Defined>(ctx.config.delayLoadHelper);
1117ece8a530Spatrick delayIdata.create(helper);
1118ece8a530Spatrick for (Chunk *c : delayIdata.getChunks())
1119ece8a530Spatrick didatSec->addChunk(c);
1120ece8a530Spatrick for (Chunk *c : delayIdata.getDataChunks())
1121ece8a530Spatrick dataSec->addChunk(c);
1122ece8a530Spatrick for (Chunk *c : delayIdata.getCodeChunks())
1123ece8a530Spatrick textSec->addChunk(c);
1124*dfe94b16Srobert for (Chunk *c : delayIdata.getCodePData())
1125*dfe94b16Srobert pdataSec->addChunk(c);
1126*dfe94b16Srobert for (Chunk *c : delayIdata.getCodeUnwindInfo())
1127*dfe94b16Srobert rdataSec->addChunk(c);
1128ece8a530Spatrick }
1129ece8a530Spatrick }
1130ece8a530Spatrick
createExportTable()1131ece8a530Spatrick void Writer::createExportTable() {
1132ece8a530Spatrick if (!edataSec->chunks.empty()) {
1133ece8a530Spatrick // Allow using a custom built export table from input object files, instead
1134ece8a530Spatrick // of having the linker synthesize the tables.
1135*dfe94b16Srobert if (ctx.config.hadExplicitExports)
1136ece8a530Spatrick warn("literal .edata sections override exports");
1137*dfe94b16Srobert } else if (!ctx.config.exports.empty()) {
1138ece8a530Spatrick for (Chunk *c : edata.chunks)
1139ece8a530Spatrick edataSec->addChunk(c);
1140ece8a530Spatrick }
1141ece8a530Spatrick if (!edataSec->chunks.empty()) {
1142ece8a530Spatrick edataStart = edataSec->chunks.front();
1143ece8a530Spatrick edataEnd = edataSec->chunks.back();
1144ece8a530Spatrick }
11451cf9926bSpatrick // Warn on exported deleting destructor.
1146*dfe94b16Srobert for (auto e : ctx.config.exports)
11471cf9926bSpatrick if (e.sym && e.sym->getName().startswith("??_G"))
1148*dfe94b16Srobert warn("export of deleting dtor: " + toString(ctx, *e.sym));
1149ece8a530Spatrick }
1150ece8a530Spatrick
removeUnusedSections()1151ece8a530Spatrick void Writer::removeUnusedSections() {
1152ece8a530Spatrick // Remove sections that we can be sure won't get content, to avoid
1153ece8a530Spatrick // allocating space for their section headers.
1154ece8a530Spatrick auto isUnused = [this](OutputSection *s) {
1155ece8a530Spatrick if (s == relocSec)
1156ece8a530Spatrick return false; // This section is populated later.
1157ece8a530Spatrick // MergeChunks have zero size at this point, as their size is finalized
1158ece8a530Spatrick // later. Only remove sections that have no Chunks at all.
1159ece8a530Spatrick return s->chunks.empty();
1160ece8a530Spatrick };
1161*dfe94b16Srobert llvm::erase_if(ctx.outputSections, isUnused);
1162ece8a530Spatrick }
1163ece8a530Spatrick
1164ece8a530Spatrick // The Windows loader doesn't seem to like empty sections,
1165ece8a530Spatrick // so we remove them if any.
removeEmptySections()1166ece8a530Spatrick void Writer::removeEmptySections() {
1167ece8a530Spatrick auto isEmpty = [](OutputSection *s) { return s->getVirtualSize() == 0; };
1168*dfe94b16Srobert llvm::erase_if(ctx.outputSections, isEmpty);
1169ece8a530Spatrick }
1170ece8a530Spatrick
assignOutputSectionIndices()1171ece8a530Spatrick void Writer::assignOutputSectionIndices() {
1172ece8a530Spatrick // Assign final output section indices, and assign each chunk to its output
1173ece8a530Spatrick // section.
1174ece8a530Spatrick uint32_t idx = 1;
1175*dfe94b16Srobert for (OutputSection *os : ctx.outputSections) {
1176ece8a530Spatrick os->sectionIndex = idx;
1177ece8a530Spatrick for (Chunk *c : os->chunks)
1178ece8a530Spatrick c->setOutputSectionIdx(idx);
1179ece8a530Spatrick ++idx;
1180ece8a530Spatrick }
1181ece8a530Spatrick
1182ece8a530Spatrick // Merge chunks are containers of chunks, so assign those an output section
1183ece8a530Spatrick // too.
1184*dfe94b16Srobert for (MergeChunk *mc : ctx.mergeChunkInstances)
1185ece8a530Spatrick if (mc)
1186ece8a530Spatrick for (SectionChunk *sc : mc->sections)
1187ece8a530Spatrick if (sc && sc->live)
1188ece8a530Spatrick sc->setOutputSectionIdx(mc->getOutputSectionIdx());
1189ece8a530Spatrick }
1190ece8a530Spatrick
addEntryToStringTable(StringRef str)1191ece8a530Spatrick size_t Writer::addEntryToStringTable(StringRef str) {
1192ece8a530Spatrick assert(str.size() > COFF::NameSize);
1193ece8a530Spatrick size_t offsetOfEntry = strtab.size() + 4; // +4 for the size field
1194ece8a530Spatrick strtab.insert(strtab.end(), str.begin(), str.end());
1195ece8a530Spatrick strtab.push_back('\0');
1196ece8a530Spatrick return offsetOfEntry;
1197ece8a530Spatrick }
1198ece8a530Spatrick
createSymbol(Defined * def)1199*dfe94b16Srobert std::optional<coff_symbol16> Writer::createSymbol(Defined *def) {
1200ece8a530Spatrick coff_symbol16 sym;
1201ece8a530Spatrick switch (def->kind()) {
1202*dfe94b16Srobert case Symbol::DefinedAbsoluteKind: {
1203*dfe94b16Srobert auto *da = dyn_cast<DefinedAbsolute>(def);
1204*dfe94b16Srobert // Note: COFF symbol can only store 32-bit values, so 64-bit absolute
1205*dfe94b16Srobert // values will be truncated.
1206*dfe94b16Srobert sym.Value = da->getVA();
1207ece8a530Spatrick sym.SectionNumber = IMAGE_SYM_ABSOLUTE;
1208ece8a530Spatrick break;
1209*dfe94b16Srobert }
1210ece8a530Spatrick default: {
1211ece8a530Spatrick // Don't write symbols that won't be written to the output to the symbol
1212ece8a530Spatrick // table.
1213*dfe94b16Srobert // We also try to write DefinedSynthetic as a normal symbol. Some of these
1214*dfe94b16Srobert // symbols do point to an actual chunk, like __safe_se_handler_table. Others
1215*dfe94b16Srobert // like __ImageBase are outside of sections and thus cannot be represented.
1216ece8a530Spatrick Chunk *c = def->getChunk();
1217ece8a530Spatrick if (!c)
1218*dfe94b16Srobert return std::nullopt;
1219*dfe94b16Srobert OutputSection *os = ctx.getOutputSection(c);
1220ece8a530Spatrick if (!os)
1221*dfe94b16Srobert return std::nullopt;
1222ece8a530Spatrick
1223ece8a530Spatrick sym.Value = def->getRVA() - os->getRVA();
1224ece8a530Spatrick sym.SectionNumber = os->sectionIndex;
1225ece8a530Spatrick break;
1226ece8a530Spatrick }
1227ece8a530Spatrick }
1228ece8a530Spatrick
1229ece8a530Spatrick // Symbols that are runtime pseudo relocations don't point to the actual
1230ece8a530Spatrick // symbol data itself (as they are imported), but points to the IAT entry
1231ece8a530Spatrick // instead. Avoid emitting them to the symbol table, as they can confuse
1232ece8a530Spatrick // debuggers.
1233ece8a530Spatrick if (def->isRuntimePseudoReloc)
1234*dfe94b16Srobert return std::nullopt;
1235ece8a530Spatrick
1236ece8a530Spatrick StringRef name = def->getName();
1237ece8a530Spatrick if (name.size() > COFF::NameSize) {
1238ece8a530Spatrick sym.Name.Offset.Zeroes = 0;
1239ece8a530Spatrick sym.Name.Offset.Offset = addEntryToStringTable(name);
1240ece8a530Spatrick } else {
1241ece8a530Spatrick memset(sym.Name.ShortName, 0, COFF::NameSize);
1242ece8a530Spatrick memcpy(sym.Name.ShortName, name.data(), name.size());
1243ece8a530Spatrick }
1244ece8a530Spatrick
1245ece8a530Spatrick if (auto *d = dyn_cast<DefinedCOFF>(def)) {
1246ece8a530Spatrick COFFSymbolRef ref = d->getCOFFSymbol();
1247ece8a530Spatrick sym.Type = ref.getType();
1248ece8a530Spatrick sym.StorageClass = ref.getStorageClass();
1249*dfe94b16Srobert } else if (def->kind() == Symbol::DefinedImportThunkKind) {
1250*dfe94b16Srobert sym.Type = (IMAGE_SYM_DTYPE_FUNCTION << SCT_COMPLEX_TYPE_SHIFT) |
1251*dfe94b16Srobert IMAGE_SYM_TYPE_NULL;
1252*dfe94b16Srobert sym.StorageClass = IMAGE_SYM_CLASS_EXTERNAL;
1253ece8a530Spatrick } else {
1254ece8a530Spatrick sym.Type = IMAGE_SYM_TYPE_NULL;
1255ece8a530Spatrick sym.StorageClass = IMAGE_SYM_CLASS_EXTERNAL;
1256ece8a530Spatrick }
1257ece8a530Spatrick sym.NumberOfAuxSymbols = 0;
1258ece8a530Spatrick return sym;
1259ece8a530Spatrick }
1260ece8a530Spatrick
createSymbolAndStringTable()1261ece8a530Spatrick void Writer::createSymbolAndStringTable() {
1262ece8a530Spatrick // PE/COFF images are limited to 8 byte section names. Longer names can be
1263ece8a530Spatrick // supported by writing a non-standard string table, but this string table is
1264ece8a530Spatrick // not mapped at runtime and the long names will therefore be inaccessible.
1265ece8a530Spatrick // link.exe always truncates section names to 8 bytes, whereas binutils always
1266ece8a530Spatrick // preserves long section names via the string table. LLD adopts a hybrid
1267ece8a530Spatrick // solution where discardable sections have long names preserved and
1268ece8a530Spatrick // non-discardable sections have their names truncated, to ensure that any
1269ece8a530Spatrick // section which is mapped at runtime also has its name mapped at runtime.
1270*dfe94b16Srobert for (OutputSection *sec : ctx.outputSections) {
1271ece8a530Spatrick if (sec->name.size() <= COFF::NameSize)
1272ece8a530Spatrick continue;
1273ece8a530Spatrick if ((sec->header.Characteristics & IMAGE_SCN_MEM_DISCARDABLE) == 0)
1274ece8a530Spatrick continue;
1275*dfe94b16Srobert if (ctx.config.warnLongSectionNames) {
1276ece8a530Spatrick warn("section name " + sec->name +
1277ece8a530Spatrick " is longer than 8 characters and will use a non-standard string "
1278ece8a530Spatrick "table");
1279ece8a530Spatrick }
1280ece8a530Spatrick sec->setStringTableOff(addEntryToStringTable(sec->name));
1281ece8a530Spatrick }
1282ece8a530Spatrick
1283*dfe94b16Srobert if (ctx.config.debugDwarf || ctx.config.debugSymtab) {
1284*dfe94b16Srobert for (ObjFile *file : ctx.objFileInstances) {
1285ece8a530Spatrick for (Symbol *b : file->getSymbols()) {
1286ece8a530Spatrick auto *d = dyn_cast_or_null<Defined>(b);
1287ece8a530Spatrick if (!d || d->writtenToSymtab)
1288ece8a530Spatrick continue;
1289ece8a530Spatrick d->writtenToSymtab = true;
1290*dfe94b16Srobert if (auto *dc = dyn_cast_or_null<DefinedCOFF>(d)) {
1291*dfe94b16Srobert COFFSymbolRef symRef = dc->getCOFFSymbol();
1292*dfe94b16Srobert if (symRef.isSectionDefinition() ||
1293*dfe94b16Srobert symRef.getStorageClass() == COFF::IMAGE_SYM_CLASS_LABEL)
1294*dfe94b16Srobert continue;
1295*dfe94b16Srobert }
1296ece8a530Spatrick
1297*dfe94b16Srobert if (std::optional<coff_symbol16> sym = createSymbol(d))
1298ece8a530Spatrick outputSymtab.push_back(*sym);
1299*dfe94b16Srobert
1300*dfe94b16Srobert if (auto *dthunk = dyn_cast<DefinedImportThunk>(d)) {
1301*dfe94b16Srobert if (!dthunk->wrappedSym->writtenToSymtab) {
1302*dfe94b16Srobert dthunk->wrappedSym->writtenToSymtab = true;
1303*dfe94b16Srobert if (std::optional<coff_symbol16> sym =
1304*dfe94b16Srobert createSymbol(dthunk->wrappedSym))
1305*dfe94b16Srobert outputSymtab.push_back(*sym);
1306*dfe94b16Srobert }
1307*dfe94b16Srobert }
1308ece8a530Spatrick }
1309ece8a530Spatrick }
1310ece8a530Spatrick }
1311ece8a530Spatrick
1312ece8a530Spatrick if (outputSymtab.empty() && strtab.empty())
1313ece8a530Spatrick return;
1314ece8a530Spatrick
1315ece8a530Spatrick // We position the symbol table to be adjacent to the end of the last section.
1316ece8a530Spatrick uint64_t fileOff = fileSize;
1317ece8a530Spatrick pointerToSymbolTable = fileOff;
1318ece8a530Spatrick fileOff += outputSymtab.size() * sizeof(coff_symbol16);
1319ece8a530Spatrick fileOff += 4 + strtab.size();
1320*dfe94b16Srobert fileSize = alignTo(fileOff, ctx.config.fileAlign);
1321ece8a530Spatrick }
1322ece8a530Spatrick
mergeSections()1323ece8a530Spatrick void Writer::mergeSections() {
1324ece8a530Spatrick if (!pdataSec->chunks.empty()) {
1325ece8a530Spatrick firstPdata = pdataSec->chunks.front();
1326ece8a530Spatrick lastPdata = pdataSec->chunks.back();
1327ece8a530Spatrick }
1328ece8a530Spatrick
1329*dfe94b16Srobert for (auto &p : ctx.config.merge) {
1330ece8a530Spatrick StringRef toName = p.second;
1331ece8a530Spatrick if (p.first == toName)
1332ece8a530Spatrick continue;
1333ece8a530Spatrick StringSet<> names;
1334*dfe94b16Srobert while (true) {
1335ece8a530Spatrick if (!names.insert(toName).second)
1336ece8a530Spatrick fatal("/merge: cycle found for section '" + p.first + "'");
1337*dfe94b16Srobert auto i = ctx.config.merge.find(toName);
1338*dfe94b16Srobert if (i == ctx.config.merge.end())
1339ece8a530Spatrick break;
1340ece8a530Spatrick toName = i->second;
1341ece8a530Spatrick }
1342ece8a530Spatrick OutputSection *from = findSection(p.first);
1343ece8a530Spatrick OutputSection *to = findSection(toName);
1344ece8a530Spatrick if (!from)
1345ece8a530Spatrick continue;
1346ece8a530Spatrick if (!to) {
1347ece8a530Spatrick from->name = toName;
1348ece8a530Spatrick continue;
1349ece8a530Spatrick }
1350ece8a530Spatrick to->merge(from);
1351ece8a530Spatrick }
1352ece8a530Spatrick }
1353ece8a530Spatrick
1354ece8a530Spatrick // Visits all sections to assign incremental, non-overlapping RVAs and
1355ece8a530Spatrick // file offsets.
assignAddresses()1356ece8a530Spatrick void Writer::assignAddresses() {
1357*dfe94b16Srobert Configuration *config = &ctx.config;
1358*dfe94b16Srobert
1359ece8a530Spatrick sizeOfHeaders = dosStubSize + sizeof(PEMagic) + sizeof(coff_file_header) +
1360ece8a530Spatrick sizeof(data_directory) * numberOfDataDirectory +
1361*dfe94b16Srobert sizeof(coff_section) * ctx.outputSections.size();
1362ece8a530Spatrick sizeOfHeaders +=
1363ece8a530Spatrick config->is64() ? sizeof(pe32plus_header) : sizeof(pe32_header);
1364ece8a530Spatrick sizeOfHeaders = alignTo(sizeOfHeaders, config->fileAlign);
1365ece8a530Spatrick fileSize = sizeOfHeaders;
1366ece8a530Spatrick
1367ece8a530Spatrick // The first page is kept unmapped.
1368ece8a530Spatrick uint64_t rva = alignTo(sizeOfHeaders, config->align);
1369ece8a530Spatrick
1370*dfe94b16Srobert for (OutputSection *sec : ctx.outputSections) {
1371ece8a530Spatrick if (sec == relocSec)
1372ece8a530Spatrick addBaserels();
1373ece8a530Spatrick uint64_t rawSize = 0, virtualSize = 0;
1374ece8a530Spatrick sec->header.VirtualAddress = rva;
1375ece8a530Spatrick
1376ece8a530Spatrick // If /FUNCTIONPADMIN is used, functions are padded in order to create a
1377ece8a530Spatrick // hotpatchable image.
1378ece8a530Spatrick const bool isCodeSection =
1379ece8a530Spatrick (sec->header.Characteristics & IMAGE_SCN_CNT_CODE) &&
1380ece8a530Spatrick (sec->header.Characteristics & IMAGE_SCN_MEM_READ) &&
1381ece8a530Spatrick (sec->header.Characteristics & IMAGE_SCN_MEM_EXECUTE);
1382ece8a530Spatrick uint32_t padding = isCodeSection ? config->functionPadMin : 0;
1383ece8a530Spatrick
1384ece8a530Spatrick for (Chunk *c : sec->chunks) {
1385ece8a530Spatrick if (padding && c->isHotPatchable())
1386ece8a530Spatrick virtualSize += padding;
1387ece8a530Spatrick virtualSize = alignTo(virtualSize, c->getAlignment());
1388ece8a530Spatrick c->setRVA(rva + virtualSize);
1389ece8a530Spatrick virtualSize += c->getSize();
1390ece8a530Spatrick if (c->hasData)
1391ece8a530Spatrick rawSize = alignTo(virtualSize, config->fileAlign);
1392ece8a530Spatrick }
1393ece8a530Spatrick if (virtualSize > UINT32_MAX)
1394ece8a530Spatrick error("section larger than 4 GiB: " + sec->name);
1395ece8a530Spatrick sec->header.VirtualSize = virtualSize;
1396ece8a530Spatrick sec->header.SizeOfRawData = rawSize;
1397ece8a530Spatrick if (rawSize != 0)
1398ece8a530Spatrick sec->header.PointerToRawData = fileSize;
1399ece8a530Spatrick rva += alignTo(virtualSize, config->align);
1400ece8a530Spatrick fileSize += alignTo(rawSize, config->fileAlign);
1401ece8a530Spatrick }
1402ece8a530Spatrick sizeOfImage = alignTo(rva, config->align);
1403ece8a530Spatrick
1404ece8a530Spatrick // Assign addresses to sections in MergeChunks.
1405*dfe94b16Srobert for (MergeChunk *mc : ctx.mergeChunkInstances)
1406ece8a530Spatrick if (mc)
1407ece8a530Spatrick mc->assignSubsectionRVAs();
1408ece8a530Spatrick }
1409ece8a530Spatrick
writeHeader()1410ece8a530Spatrick template <typename PEHeaderTy> void Writer::writeHeader() {
1411ece8a530Spatrick // Write DOS header. For backwards compatibility, the first part of a PE/COFF
1412ece8a530Spatrick // executable consists of an MS-DOS MZ executable. If the executable is run
1413ece8a530Spatrick // under DOS, that program gets run (usually to just print an error message).
1414ece8a530Spatrick // When run under Windows, the loader looks at AddressOfNewExeHeader and uses
1415ece8a530Spatrick // the PE header instead.
1416*dfe94b16Srobert Configuration *config = &ctx.config;
1417ece8a530Spatrick uint8_t *buf = buffer->getBufferStart();
1418ece8a530Spatrick auto *dos = reinterpret_cast<dos_header *>(buf);
1419ece8a530Spatrick buf += sizeof(dos_header);
1420ece8a530Spatrick dos->Magic[0] = 'M';
1421ece8a530Spatrick dos->Magic[1] = 'Z';
1422ece8a530Spatrick dos->UsedBytesInTheLastPage = dosStubSize % 512;
1423ece8a530Spatrick dos->FileSizeInPages = divideCeil(dosStubSize, 512);
1424ece8a530Spatrick dos->HeaderSizeInParagraphs = sizeof(dos_header) / 16;
1425ece8a530Spatrick
1426ece8a530Spatrick dos->AddressOfRelocationTable = sizeof(dos_header);
1427ece8a530Spatrick dos->AddressOfNewExeHeader = dosStubSize;
1428ece8a530Spatrick
1429ece8a530Spatrick // Write DOS program.
1430ece8a530Spatrick memcpy(buf, dosProgram, sizeof(dosProgram));
1431ece8a530Spatrick buf += sizeof(dosProgram);
1432ece8a530Spatrick
1433ece8a530Spatrick // Write PE magic
1434ece8a530Spatrick memcpy(buf, PEMagic, sizeof(PEMagic));
1435ece8a530Spatrick buf += sizeof(PEMagic);
1436ece8a530Spatrick
1437ece8a530Spatrick // Write COFF header
1438ece8a530Spatrick auto *coff = reinterpret_cast<coff_file_header *>(buf);
1439ece8a530Spatrick buf += sizeof(*coff);
1440ece8a530Spatrick coff->Machine = config->machine;
1441*dfe94b16Srobert coff->NumberOfSections = ctx.outputSections.size();
1442ece8a530Spatrick coff->Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE;
1443ece8a530Spatrick if (config->largeAddressAware)
1444ece8a530Spatrick coff->Characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE;
1445ece8a530Spatrick if (!config->is64())
1446ece8a530Spatrick coff->Characteristics |= IMAGE_FILE_32BIT_MACHINE;
1447ece8a530Spatrick if (config->dll)
1448ece8a530Spatrick coff->Characteristics |= IMAGE_FILE_DLL;
1449ece8a530Spatrick if (config->driverUponly)
1450ece8a530Spatrick coff->Characteristics |= IMAGE_FILE_UP_SYSTEM_ONLY;
1451ece8a530Spatrick if (!config->relocatable)
1452ece8a530Spatrick coff->Characteristics |= IMAGE_FILE_RELOCS_STRIPPED;
1453ece8a530Spatrick if (config->swaprunCD)
1454ece8a530Spatrick coff->Characteristics |= IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP;
1455ece8a530Spatrick if (config->swaprunNet)
1456ece8a530Spatrick coff->Characteristics |= IMAGE_FILE_NET_RUN_FROM_SWAP;
1457ece8a530Spatrick coff->SizeOfOptionalHeader =
1458ece8a530Spatrick sizeof(PEHeaderTy) + sizeof(data_directory) * numberOfDataDirectory;
1459ece8a530Spatrick
1460ece8a530Spatrick // Write PE header
1461ece8a530Spatrick auto *pe = reinterpret_cast<PEHeaderTy *>(buf);
1462ece8a530Spatrick buf += sizeof(*pe);
1463ece8a530Spatrick pe->Magic = config->is64() ? PE32Header::PE32_PLUS : PE32Header::PE32;
1464ece8a530Spatrick
1465ece8a530Spatrick // If {Major,Minor}LinkerVersion is left at 0.0, then for some
1466ece8a530Spatrick // reason signing the resulting PE file with Authenticode produces a
1467ece8a530Spatrick // signature that fails to validate on Windows 7 (but is OK on 10).
1468ece8a530Spatrick // Set it to 14.0, which is what VS2015 outputs, and which avoids
1469ece8a530Spatrick // that problem.
1470ece8a530Spatrick pe->MajorLinkerVersion = 14;
1471ece8a530Spatrick pe->MinorLinkerVersion = 0;
1472ece8a530Spatrick
1473ece8a530Spatrick pe->ImageBase = config->imageBase;
1474ece8a530Spatrick pe->SectionAlignment = config->align;
1475ece8a530Spatrick pe->FileAlignment = config->fileAlign;
1476ece8a530Spatrick pe->MajorImageVersion = config->majorImageVersion;
1477ece8a530Spatrick pe->MinorImageVersion = config->minorImageVersion;
1478ece8a530Spatrick pe->MajorOperatingSystemVersion = config->majorOSVersion;
1479ece8a530Spatrick pe->MinorOperatingSystemVersion = config->minorOSVersion;
14801cf9926bSpatrick pe->MajorSubsystemVersion = config->majorSubsystemVersion;
14811cf9926bSpatrick pe->MinorSubsystemVersion = config->minorSubsystemVersion;
1482ece8a530Spatrick pe->Subsystem = config->subsystem;
1483ece8a530Spatrick pe->SizeOfImage = sizeOfImage;
1484ece8a530Spatrick pe->SizeOfHeaders = sizeOfHeaders;
1485ece8a530Spatrick if (!config->noEntry) {
1486ece8a530Spatrick Defined *entry = cast<Defined>(config->entry);
1487ece8a530Spatrick pe->AddressOfEntryPoint = entry->getRVA();
1488ece8a530Spatrick // Pointer to thumb code must have the LSB set, so adjust it.
1489ece8a530Spatrick if (config->machine == ARMNT)
1490ece8a530Spatrick pe->AddressOfEntryPoint |= 1;
1491ece8a530Spatrick }
1492ece8a530Spatrick pe->SizeOfStackReserve = config->stackReserve;
1493ece8a530Spatrick pe->SizeOfStackCommit = config->stackCommit;
1494ece8a530Spatrick pe->SizeOfHeapReserve = config->heapReserve;
1495ece8a530Spatrick pe->SizeOfHeapCommit = config->heapCommit;
1496ece8a530Spatrick if (config->appContainer)
1497ece8a530Spatrick pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_APPCONTAINER;
1498ece8a530Spatrick if (config->driverWdm)
1499ece8a530Spatrick pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER;
1500ece8a530Spatrick if (config->dynamicBase)
1501ece8a530Spatrick pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE;
1502ece8a530Spatrick if (config->highEntropyVA)
1503ece8a530Spatrick pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA;
1504ece8a530Spatrick if (!config->allowBind)
1505ece8a530Spatrick pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_BIND;
1506ece8a530Spatrick if (config->nxCompat)
1507ece8a530Spatrick pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NX_COMPAT;
1508ece8a530Spatrick if (!config->allowIsolation)
1509ece8a530Spatrick pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION;
1510ece8a530Spatrick if (config->guardCF != GuardCFLevel::Off)
1511ece8a530Spatrick pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_GUARD_CF;
1512ece8a530Spatrick if (config->integrityCheck)
1513ece8a530Spatrick pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY;
1514bb684c34Spatrick if (setNoSEHCharacteristic || config->noSEH)
1515ece8a530Spatrick pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_SEH;
1516ece8a530Spatrick if (config->terminalServerAware)
1517ece8a530Spatrick pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE;
1518ece8a530Spatrick pe->NumberOfRvaAndSize = numberOfDataDirectory;
1519ece8a530Spatrick if (textSec->getVirtualSize()) {
1520ece8a530Spatrick pe->BaseOfCode = textSec->getRVA();
1521ece8a530Spatrick pe->SizeOfCode = textSec->getRawSize();
1522ece8a530Spatrick }
1523ece8a530Spatrick pe->SizeOfInitializedData = getSizeOfInitializedData();
1524ece8a530Spatrick
1525ece8a530Spatrick // Write data directory
1526ece8a530Spatrick auto *dir = reinterpret_cast<data_directory *>(buf);
1527ece8a530Spatrick buf += sizeof(*dir) * numberOfDataDirectory;
1528ece8a530Spatrick if (edataStart) {
1529ece8a530Spatrick dir[EXPORT_TABLE].RelativeVirtualAddress = edataStart->getRVA();
1530ece8a530Spatrick dir[EXPORT_TABLE].Size =
1531ece8a530Spatrick edataEnd->getRVA() + edataEnd->getSize() - edataStart->getRVA();
1532ece8a530Spatrick }
1533ece8a530Spatrick if (importTableStart) {
1534ece8a530Spatrick dir[IMPORT_TABLE].RelativeVirtualAddress = importTableStart->getRVA();
1535ece8a530Spatrick dir[IMPORT_TABLE].Size = importTableSize;
1536ece8a530Spatrick }
1537ece8a530Spatrick if (iatStart) {
1538ece8a530Spatrick dir[IAT].RelativeVirtualAddress = iatStart->getRVA();
1539ece8a530Spatrick dir[IAT].Size = iatSize;
1540ece8a530Spatrick }
1541ece8a530Spatrick if (rsrcSec->getVirtualSize()) {
1542ece8a530Spatrick dir[RESOURCE_TABLE].RelativeVirtualAddress = rsrcSec->getRVA();
1543ece8a530Spatrick dir[RESOURCE_TABLE].Size = rsrcSec->getVirtualSize();
1544ece8a530Spatrick }
1545ece8a530Spatrick if (firstPdata) {
1546ece8a530Spatrick dir[EXCEPTION_TABLE].RelativeVirtualAddress = firstPdata->getRVA();
1547ece8a530Spatrick dir[EXCEPTION_TABLE].Size =
1548ece8a530Spatrick lastPdata->getRVA() + lastPdata->getSize() - firstPdata->getRVA();
1549ece8a530Spatrick }
1550ece8a530Spatrick if (relocSec->getVirtualSize()) {
1551ece8a530Spatrick dir[BASE_RELOCATION_TABLE].RelativeVirtualAddress = relocSec->getRVA();
1552ece8a530Spatrick dir[BASE_RELOCATION_TABLE].Size = relocSec->getVirtualSize();
1553ece8a530Spatrick }
1554*dfe94b16Srobert if (Symbol *sym = ctx.symtab.findUnderscore("_tls_used")) {
1555ece8a530Spatrick if (Defined *b = dyn_cast<Defined>(sym)) {
1556ece8a530Spatrick dir[TLS_TABLE].RelativeVirtualAddress = b->getRVA();
1557ece8a530Spatrick dir[TLS_TABLE].Size = config->is64()
1558ece8a530Spatrick ? sizeof(object::coff_tls_directory64)
1559ece8a530Spatrick : sizeof(object::coff_tls_directory32);
1560ece8a530Spatrick }
1561ece8a530Spatrick }
1562ece8a530Spatrick if (debugDirectory) {
1563ece8a530Spatrick dir[DEBUG_DIRECTORY].RelativeVirtualAddress = debugDirectory->getRVA();
1564ece8a530Spatrick dir[DEBUG_DIRECTORY].Size = debugDirectory->getSize();
1565ece8a530Spatrick }
1566*dfe94b16Srobert if (Symbol *sym = ctx.symtab.findUnderscore("_load_config_used")) {
1567ece8a530Spatrick if (auto *b = dyn_cast<DefinedRegular>(sym)) {
1568ece8a530Spatrick SectionChunk *sc = b->getChunk();
1569ece8a530Spatrick assert(b->getRVA() >= sc->getRVA());
1570ece8a530Spatrick uint64_t offsetInChunk = b->getRVA() - sc->getRVA();
1571ece8a530Spatrick if (!sc->hasData || offsetInChunk + 4 > sc->getSize())
1572ece8a530Spatrick fatal("_load_config_used is malformed");
1573ece8a530Spatrick
1574ece8a530Spatrick ArrayRef<uint8_t> secContents = sc->getContents();
1575ece8a530Spatrick uint32_t loadConfigSize =
1576ece8a530Spatrick *reinterpret_cast<const ulittle32_t *>(&secContents[offsetInChunk]);
1577ece8a530Spatrick if (offsetInChunk + loadConfigSize > sc->getSize())
1578ece8a530Spatrick fatal("_load_config_used is too large");
1579ece8a530Spatrick dir[LOAD_CONFIG_TABLE].RelativeVirtualAddress = b->getRVA();
1580ece8a530Spatrick dir[LOAD_CONFIG_TABLE].Size = loadConfigSize;
1581ece8a530Spatrick }
1582ece8a530Spatrick }
1583ece8a530Spatrick if (!delayIdata.empty()) {
1584ece8a530Spatrick dir[DELAY_IMPORT_DESCRIPTOR].RelativeVirtualAddress =
1585ece8a530Spatrick delayIdata.getDirRVA();
1586ece8a530Spatrick dir[DELAY_IMPORT_DESCRIPTOR].Size = delayIdata.getDirSize();
1587ece8a530Spatrick }
1588ece8a530Spatrick
1589ece8a530Spatrick // Write section table
1590*dfe94b16Srobert for (OutputSection *sec : ctx.outputSections) {
1591*dfe94b16Srobert sec->writeHeaderTo(buf, config->debug);
1592ece8a530Spatrick buf += sizeof(coff_section);
1593ece8a530Spatrick }
1594ece8a530Spatrick sectionTable = ArrayRef<uint8_t>(
1595*dfe94b16Srobert buf - ctx.outputSections.size() * sizeof(coff_section), buf);
1596ece8a530Spatrick
1597ece8a530Spatrick if (outputSymtab.empty() && strtab.empty())
1598ece8a530Spatrick return;
1599ece8a530Spatrick
1600ece8a530Spatrick coff->PointerToSymbolTable = pointerToSymbolTable;
1601ece8a530Spatrick uint32_t numberOfSymbols = outputSymtab.size();
1602ece8a530Spatrick coff->NumberOfSymbols = numberOfSymbols;
1603ece8a530Spatrick auto *symbolTable = reinterpret_cast<coff_symbol16 *>(
1604ece8a530Spatrick buffer->getBufferStart() + coff->PointerToSymbolTable);
1605ece8a530Spatrick for (size_t i = 0; i != numberOfSymbols; ++i)
1606ece8a530Spatrick symbolTable[i] = outputSymtab[i];
1607ece8a530Spatrick // Create the string table, it follows immediately after the symbol table.
1608ece8a530Spatrick // The first 4 bytes is length including itself.
1609ece8a530Spatrick buf = reinterpret_cast<uint8_t *>(&symbolTable[numberOfSymbols]);
1610ece8a530Spatrick write32le(buf, strtab.size() + 4);
1611ece8a530Spatrick if (!strtab.empty())
1612ece8a530Spatrick memcpy(buf + 4, strtab.data(), strtab.size());
1613ece8a530Spatrick }
1614ece8a530Spatrick
openFile(StringRef path)1615ece8a530Spatrick void Writer::openFile(StringRef path) {
1616ece8a530Spatrick buffer = CHECK(
1617ece8a530Spatrick FileOutputBuffer::create(path, fileSize, FileOutputBuffer::F_executable),
1618ece8a530Spatrick "failed to open " + path);
1619ece8a530Spatrick }
1620ece8a530Spatrick
createSEHTable()1621ece8a530Spatrick void Writer::createSEHTable() {
1622ece8a530Spatrick SymbolRVASet handlers;
1623*dfe94b16Srobert for (ObjFile *file : ctx.objFileInstances) {
1624ece8a530Spatrick if (!file->hasSafeSEH())
1625ece8a530Spatrick error("/safeseh: " + file->getName() + " is not compatible with SEH");
1626ece8a530Spatrick markSymbolsForRVATable(file, file->getSXDataChunks(), handlers);
1627ece8a530Spatrick }
1628ece8a530Spatrick
1629ece8a530Spatrick // Set the "no SEH" characteristic if there really were no handlers, or if
1630ece8a530Spatrick // there is no load config object to point to the table of handlers.
1631ece8a530Spatrick setNoSEHCharacteristic =
1632*dfe94b16Srobert handlers.empty() || !ctx.symtab.findUnderscore("_load_config_used");
1633ece8a530Spatrick
1634ece8a530Spatrick maybeAddRVATable(std::move(handlers), "__safe_se_handler_table",
1635ece8a530Spatrick "__safe_se_handler_count");
1636ece8a530Spatrick }
1637ece8a530Spatrick
1638ece8a530Spatrick // Add a symbol to an RVA set. Two symbols may have the same RVA, but an RVA set
1639ece8a530Spatrick // cannot contain duplicates. Therefore, the set is uniqued by Chunk and the
1640ece8a530Spatrick // symbol's offset into that Chunk.
addSymbolToRVASet(SymbolRVASet & rvaSet,Defined * s)1641ece8a530Spatrick static void addSymbolToRVASet(SymbolRVASet &rvaSet, Defined *s) {
1642ece8a530Spatrick Chunk *c = s->getChunk();
1643ece8a530Spatrick if (auto *sc = dyn_cast<SectionChunk>(c))
1644ece8a530Spatrick c = sc->repl; // Look through ICF replacement.
1645ece8a530Spatrick uint32_t off = s->getRVA() - (c ? c->getRVA() : 0);
1646ece8a530Spatrick rvaSet.insert({c, off});
1647ece8a530Spatrick }
1648ece8a530Spatrick
1649ece8a530Spatrick // Given a symbol, add it to the GFIDs table if it is a live, defined, function
1650ece8a530Spatrick // symbol in an executable section.
maybeAddAddressTakenFunction(SymbolRVASet & addressTakenSyms,Symbol * s)1651ece8a530Spatrick static void maybeAddAddressTakenFunction(SymbolRVASet &addressTakenSyms,
1652ece8a530Spatrick Symbol *s) {
1653ece8a530Spatrick if (!s)
1654ece8a530Spatrick return;
1655ece8a530Spatrick
1656ece8a530Spatrick switch (s->kind()) {
1657ece8a530Spatrick case Symbol::DefinedLocalImportKind:
1658ece8a530Spatrick case Symbol::DefinedImportDataKind:
1659ece8a530Spatrick // Defines an __imp_ pointer, so it is data, so it is ignored.
1660ece8a530Spatrick break;
1661ece8a530Spatrick case Symbol::DefinedCommonKind:
1662ece8a530Spatrick // Common is always data, so it is ignored.
1663ece8a530Spatrick break;
1664ece8a530Spatrick case Symbol::DefinedAbsoluteKind:
1665ece8a530Spatrick case Symbol::DefinedSyntheticKind:
1666ece8a530Spatrick // Absolute is never code, synthetic generally isn't and usually isn't
1667ece8a530Spatrick // determinable.
1668ece8a530Spatrick break;
1669ece8a530Spatrick case Symbol::LazyArchiveKind:
1670ece8a530Spatrick case Symbol::LazyObjectKind:
16711cf9926bSpatrick case Symbol::LazyDLLSymbolKind:
1672ece8a530Spatrick case Symbol::UndefinedKind:
1673ece8a530Spatrick // Undefined symbols resolve to zero, so they don't have an RVA. Lazy
1674ece8a530Spatrick // symbols shouldn't have relocations.
1675ece8a530Spatrick break;
1676ece8a530Spatrick
1677ece8a530Spatrick case Symbol::DefinedImportThunkKind:
1678ece8a530Spatrick // Thunks are always code, include them.
1679ece8a530Spatrick addSymbolToRVASet(addressTakenSyms, cast<Defined>(s));
1680ece8a530Spatrick break;
1681ece8a530Spatrick
1682ece8a530Spatrick case Symbol::DefinedRegularKind: {
1683ece8a530Spatrick // This is a regular, defined, symbol from a COFF file. Mark the symbol as
1684ece8a530Spatrick // address taken if the symbol type is function and it's in an executable
1685ece8a530Spatrick // section.
1686ece8a530Spatrick auto *d = cast<DefinedRegular>(s);
1687ece8a530Spatrick if (d->getCOFFSymbol().getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION) {
1688ece8a530Spatrick SectionChunk *sc = dyn_cast<SectionChunk>(d->getChunk());
1689ece8a530Spatrick if (sc && sc->live &&
1690ece8a530Spatrick sc->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE)
1691ece8a530Spatrick addSymbolToRVASet(addressTakenSyms, d);
1692ece8a530Spatrick }
1693ece8a530Spatrick break;
1694ece8a530Spatrick }
1695ece8a530Spatrick }
1696ece8a530Spatrick }
1697ece8a530Spatrick
1698ece8a530Spatrick // Visit all relocations from all section contributions of this object file and
1699ece8a530Spatrick // mark the relocation target as address-taken.
markSymbolsWithRelocations(ObjFile * file,SymbolRVASet & usedSymbols)1700*dfe94b16Srobert void Writer::markSymbolsWithRelocations(ObjFile *file,
1701ece8a530Spatrick SymbolRVASet &usedSymbols) {
1702ece8a530Spatrick for (Chunk *c : file->getChunks()) {
1703ece8a530Spatrick // We only care about live section chunks. Common chunks and other chunks
1704ece8a530Spatrick // don't generally contain relocations.
1705ece8a530Spatrick SectionChunk *sc = dyn_cast<SectionChunk>(c);
1706ece8a530Spatrick if (!sc || !sc->live)
1707ece8a530Spatrick continue;
1708ece8a530Spatrick
1709ece8a530Spatrick for (const coff_relocation &reloc : sc->getRelocs()) {
1710*dfe94b16Srobert if (ctx.config.machine == I386 &&
1711*dfe94b16Srobert reloc.Type == COFF::IMAGE_REL_I386_REL32)
1712ece8a530Spatrick // Ignore relative relocations on x86. On x86_64 they can't be ignored
1713ece8a530Spatrick // since they're also used to compute absolute addresses.
1714ece8a530Spatrick continue;
1715ece8a530Spatrick
1716ece8a530Spatrick Symbol *ref = sc->file->getSymbol(reloc.SymbolTableIndex);
1717ece8a530Spatrick maybeAddAddressTakenFunction(usedSymbols, ref);
1718ece8a530Spatrick }
1719ece8a530Spatrick }
1720ece8a530Spatrick }
1721ece8a530Spatrick
1722ece8a530Spatrick // Create the guard function id table. This is a table of RVAs of all
1723ece8a530Spatrick // address-taken functions. It is sorted and uniqued, just like the safe SEH
1724ece8a530Spatrick // table.
createGuardCFTables()1725ece8a530Spatrick void Writer::createGuardCFTables() {
1726*dfe94b16Srobert Configuration *config = &ctx.config;
1727*dfe94b16Srobert
1728ece8a530Spatrick SymbolRVASet addressTakenSyms;
17291cf9926bSpatrick SymbolRVASet giatsRVASet;
17301cf9926bSpatrick std::vector<Symbol *> giatsSymbols;
1731ece8a530Spatrick SymbolRVASet longJmpTargets;
17321cf9926bSpatrick SymbolRVASet ehContTargets;
1733*dfe94b16Srobert for (ObjFile *file : ctx.objFileInstances) {
1734ece8a530Spatrick // If the object was compiled with /guard:cf, the address taken symbols
17351cf9926bSpatrick // are in .gfids$y sections, the longjmp targets are in .gljmp$y sections,
17361cf9926bSpatrick // and ehcont targets are in .gehcont$y sections. If the object was not
17371cf9926bSpatrick // compiled with /guard:cf, we assume there were no setjmp and ehcont
17381cf9926bSpatrick // targets, and that all code symbols with relocations are possibly
17391cf9926bSpatrick // address-taken.
1740ece8a530Spatrick if (file->hasGuardCF()) {
1741ece8a530Spatrick markSymbolsForRVATable(file, file->getGuardFidChunks(), addressTakenSyms);
17421cf9926bSpatrick markSymbolsForRVATable(file, file->getGuardIATChunks(), giatsRVASet);
17431cf9926bSpatrick getSymbolsFromSections(file, file->getGuardIATChunks(), giatsSymbols);
1744ece8a530Spatrick markSymbolsForRVATable(file, file->getGuardLJmpChunks(), longJmpTargets);
17451cf9926bSpatrick markSymbolsForRVATable(file, file->getGuardEHContChunks(), ehContTargets);
1746ece8a530Spatrick } else {
1747ece8a530Spatrick markSymbolsWithRelocations(file, addressTakenSyms);
1748ece8a530Spatrick }
1749ece8a530Spatrick }
1750ece8a530Spatrick
1751ece8a530Spatrick // Mark the image entry as address-taken.
1752ece8a530Spatrick if (config->entry)
1753ece8a530Spatrick maybeAddAddressTakenFunction(addressTakenSyms, config->entry);
1754ece8a530Spatrick
1755ece8a530Spatrick // Mark exported symbols in executable sections as address-taken.
1756ece8a530Spatrick for (Export &e : config->exports)
1757ece8a530Spatrick maybeAddAddressTakenFunction(addressTakenSyms, e.sym);
1758ece8a530Spatrick
17591cf9926bSpatrick // For each entry in the .giats table, check if it has a corresponding load
17601cf9926bSpatrick // thunk (e.g. because the DLL that defines it will be delay-loaded) and, if
17611cf9926bSpatrick // so, add the load thunk to the address taken (.gfids) table.
17621cf9926bSpatrick for (Symbol *s : giatsSymbols) {
17631cf9926bSpatrick if (auto *di = dyn_cast<DefinedImportData>(s)) {
17641cf9926bSpatrick if (di->loadThunkSym)
17651cf9926bSpatrick addSymbolToRVASet(addressTakenSyms, di->loadThunkSym);
17661cf9926bSpatrick }
17671cf9926bSpatrick }
17681cf9926bSpatrick
1769ece8a530Spatrick // Ensure sections referenced in the gfid table are 16-byte aligned.
1770ece8a530Spatrick for (const ChunkAndOffset &c : addressTakenSyms)
1771ece8a530Spatrick if (c.inputChunk->getAlignment() < 16)
1772ece8a530Spatrick c.inputChunk->setAlignment(16);
1773ece8a530Spatrick
1774ece8a530Spatrick maybeAddRVATable(std::move(addressTakenSyms), "__guard_fids_table",
1775ece8a530Spatrick "__guard_fids_count");
1776ece8a530Spatrick
17771cf9926bSpatrick // Add the Guard Address Taken IAT Entry Table (.giats).
17781cf9926bSpatrick maybeAddRVATable(std::move(giatsRVASet), "__guard_iat_table",
17791cf9926bSpatrick "__guard_iat_count");
17801cf9926bSpatrick
1781ece8a530Spatrick // Add the longjmp target table unless the user told us not to.
17821cf9926bSpatrick if (config->guardCF & GuardCFLevel::LongJmp)
1783ece8a530Spatrick maybeAddRVATable(std::move(longJmpTargets), "__guard_longjmp_table",
1784ece8a530Spatrick "__guard_longjmp_count");
1785ece8a530Spatrick
17861cf9926bSpatrick // Add the ehcont target table unless the user told us not to.
17871cf9926bSpatrick if (config->guardCF & GuardCFLevel::EHCont)
17881cf9926bSpatrick maybeAddRVATable(std::move(ehContTargets), "__guard_eh_cont_table",
17891cf9926bSpatrick "__guard_eh_cont_count", true);
17901cf9926bSpatrick
1791ece8a530Spatrick // Set __guard_flags, which will be used in the load config to indicate that
1792ece8a530Spatrick // /guard:cf was enabled.
1793*dfe94b16Srobert uint32_t guardFlags = uint32_t(GuardFlags::CF_INSTRUMENTED) |
1794*dfe94b16Srobert uint32_t(GuardFlags::CF_FUNCTION_TABLE_PRESENT);
17951cf9926bSpatrick if (config->guardCF & GuardCFLevel::LongJmp)
1796*dfe94b16Srobert guardFlags |= uint32_t(GuardFlags::CF_LONGJUMP_TABLE_PRESENT);
17971cf9926bSpatrick if (config->guardCF & GuardCFLevel::EHCont)
1798*dfe94b16Srobert guardFlags |= uint32_t(GuardFlags::EH_CONTINUATION_TABLE_PRESENT);
1799*dfe94b16Srobert Symbol *flagSym = ctx.symtab.findUnderscore("__guard_flags");
1800ece8a530Spatrick cast<DefinedAbsolute>(flagSym)->setVA(guardFlags);
1801ece8a530Spatrick }
1802ece8a530Spatrick
1803ece8a530Spatrick // Take a list of input sections containing symbol table indices and add those
18041cf9926bSpatrick // symbols to a vector. The challenge is that symbol RVAs are not known and
1805ece8a530Spatrick // depend on the table size, so we can't directly build a set of integers.
getSymbolsFromSections(ObjFile * file,ArrayRef<SectionChunk * > symIdxChunks,std::vector<Symbol * > & symbols)18061cf9926bSpatrick void Writer::getSymbolsFromSections(ObjFile *file,
1807ece8a530Spatrick ArrayRef<SectionChunk *> symIdxChunks,
18081cf9926bSpatrick std::vector<Symbol *> &symbols) {
1809ece8a530Spatrick for (SectionChunk *c : symIdxChunks) {
1810ece8a530Spatrick // Skip sections discarded by linker GC. This comes up when a .gfids section
1811ece8a530Spatrick // is associated with something like a vtable and the vtable is discarded.
1812ece8a530Spatrick // In this case, the associated gfids section is discarded, and we don't
1813ece8a530Spatrick // mark the virtual member functions as address-taken by the vtable.
1814ece8a530Spatrick if (!c->live)
1815ece8a530Spatrick continue;
1816ece8a530Spatrick
1817ece8a530Spatrick // Validate that the contents look like symbol table indices.
1818ece8a530Spatrick ArrayRef<uint8_t> data = c->getContents();
1819ece8a530Spatrick if (data.size() % 4 != 0) {
1820ece8a530Spatrick warn("ignoring " + c->getSectionName() +
1821ece8a530Spatrick " symbol table index section in object " + toString(file));
1822ece8a530Spatrick continue;
1823ece8a530Spatrick }
1824ece8a530Spatrick
1825ece8a530Spatrick // Read each symbol table index and check if that symbol was included in the
18261cf9926bSpatrick // final link. If so, add it to the vector of symbols.
1827ece8a530Spatrick ArrayRef<ulittle32_t> symIndices(
1828ece8a530Spatrick reinterpret_cast<const ulittle32_t *>(data.data()), data.size() / 4);
1829ece8a530Spatrick ArrayRef<Symbol *> objSymbols = file->getSymbols();
1830ece8a530Spatrick for (uint32_t symIndex : symIndices) {
1831ece8a530Spatrick if (symIndex >= objSymbols.size()) {
1832ece8a530Spatrick warn("ignoring invalid symbol table index in section " +
1833ece8a530Spatrick c->getSectionName() + " in object " + toString(file));
1834ece8a530Spatrick continue;
1835ece8a530Spatrick }
1836ece8a530Spatrick if (Symbol *s = objSymbols[symIndex]) {
1837ece8a530Spatrick if (s->isLive())
18381cf9926bSpatrick symbols.push_back(cast<Symbol>(s));
18391cf9926bSpatrick }
18401cf9926bSpatrick }
18411cf9926bSpatrick }
18421cf9926bSpatrick }
18431cf9926bSpatrick
18441cf9926bSpatrick // Take a list of input sections containing symbol table indices and add those
18451cf9926bSpatrick // symbols to an RVA table.
markSymbolsForRVATable(ObjFile * file,ArrayRef<SectionChunk * > symIdxChunks,SymbolRVASet & tableSymbols)18461cf9926bSpatrick void Writer::markSymbolsForRVATable(ObjFile *file,
18471cf9926bSpatrick ArrayRef<SectionChunk *> symIdxChunks,
18481cf9926bSpatrick SymbolRVASet &tableSymbols) {
18491cf9926bSpatrick std::vector<Symbol *> syms;
18501cf9926bSpatrick getSymbolsFromSections(file, symIdxChunks, syms);
18511cf9926bSpatrick
18521cf9926bSpatrick for (Symbol *s : syms)
1853ece8a530Spatrick addSymbolToRVASet(tableSymbols, cast<Defined>(s));
1854ece8a530Spatrick }
1855ece8a530Spatrick
1856ece8a530Spatrick // Replace the absolute table symbol with a synthetic symbol pointing to
1857ece8a530Spatrick // tableChunk so that we can emit base relocations for it and resolve section
1858ece8a530Spatrick // relative relocations.
maybeAddRVATable(SymbolRVASet tableSymbols,StringRef tableSym,StringRef countSym,bool hasFlag)1859ece8a530Spatrick void Writer::maybeAddRVATable(SymbolRVASet tableSymbols, StringRef tableSym,
18601cf9926bSpatrick StringRef countSym, bool hasFlag) {
1861ece8a530Spatrick if (tableSymbols.empty())
1862ece8a530Spatrick return;
1863ece8a530Spatrick
18641cf9926bSpatrick NonSectionChunk *tableChunk;
18651cf9926bSpatrick if (hasFlag)
18661cf9926bSpatrick tableChunk = make<RVAFlagTableChunk>(std::move(tableSymbols));
18671cf9926bSpatrick else
18681cf9926bSpatrick tableChunk = make<RVATableChunk>(std::move(tableSymbols));
1869ece8a530Spatrick rdataSec->addChunk(tableChunk);
1870ece8a530Spatrick
1871*dfe94b16Srobert Symbol *t = ctx.symtab.findUnderscore(tableSym);
1872*dfe94b16Srobert Symbol *c = ctx.symtab.findUnderscore(countSym);
1873ece8a530Spatrick replaceSymbol<DefinedSynthetic>(t, t->getName(), tableChunk);
18741cf9926bSpatrick cast<DefinedAbsolute>(c)->setVA(tableChunk->getSize() / (hasFlag ? 5 : 4));
1875ece8a530Spatrick }
1876ece8a530Spatrick
1877ece8a530Spatrick // MinGW specific. Gather all relocations that are imported from a DLL even
1878ece8a530Spatrick // though the code didn't expect it to, produce the table that the runtime
1879ece8a530Spatrick // uses for fixing them up, and provide the synthetic symbols that the
1880ece8a530Spatrick // runtime uses for finding the table.
createRuntimePseudoRelocs()1881ece8a530Spatrick void Writer::createRuntimePseudoRelocs() {
1882ece8a530Spatrick std::vector<RuntimePseudoReloc> rels;
1883ece8a530Spatrick
1884*dfe94b16Srobert for (Chunk *c : ctx.symtab.getChunks()) {
1885ece8a530Spatrick auto *sc = dyn_cast<SectionChunk>(c);
1886ece8a530Spatrick if (!sc || !sc->live)
1887ece8a530Spatrick continue;
1888ece8a530Spatrick sc->getRuntimePseudoRelocs(rels);
1889ece8a530Spatrick }
1890ece8a530Spatrick
1891*dfe94b16Srobert if (!ctx.config.pseudoRelocs) {
1892bb684c34Spatrick // Not writing any pseudo relocs; if some were needed, error out and
1893bb684c34Spatrick // indicate what required them.
1894bb684c34Spatrick for (const RuntimePseudoReloc &rpr : rels)
1895bb684c34Spatrick error("automatic dllimport of " + rpr.sym->getName() + " in " +
1896bb684c34Spatrick toString(rpr.target->file) + " requires pseudo relocations");
1897bb684c34Spatrick return;
1898bb684c34Spatrick }
1899bb684c34Spatrick
1900ece8a530Spatrick if (!rels.empty())
1901ece8a530Spatrick log("Writing " + Twine(rels.size()) + " runtime pseudo relocations");
1902ece8a530Spatrick PseudoRelocTableChunk *table = make<PseudoRelocTableChunk>(rels);
1903ece8a530Spatrick rdataSec->addChunk(table);
1904ece8a530Spatrick EmptyChunk *endOfList = make<EmptyChunk>();
1905ece8a530Spatrick rdataSec->addChunk(endOfList);
1906ece8a530Spatrick
1907*dfe94b16Srobert Symbol *headSym = ctx.symtab.findUnderscore("__RUNTIME_PSEUDO_RELOC_LIST__");
1908*dfe94b16Srobert Symbol *endSym =
1909*dfe94b16Srobert ctx.symtab.findUnderscore("__RUNTIME_PSEUDO_RELOC_LIST_END__");
1910ece8a530Spatrick replaceSymbol<DefinedSynthetic>(headSym, headSym->getName(), table);
1911ece8a530Spatrick replaceSymbol<DefinedSynthetic>(endSym, endSym->getName(), endOfList);
1912ece8a530Spatrick }
1913ece8a530Spatrick
1914ece8a530Spatrick // MinGW specific.
1915ece8a530Spatrick // The MinGW .ctors and .dtors lists have sentinels at each end;
1916ece8a530Spatrick // a (uintptr_t)-1 at the start and a (uintptr_t)0 at the end.
1917ece8a530Spatrick // There's a symbol pointing to the start sentinel pointer, __CTOR_LIST__
1918ece8a530Spatrick // and __DTOR_LIST__ respectively.
insertCtorDtorSymbols()1919ece8a530Spatrick void Writer::insertCtorDtorSymbols() {
1920*dfe94b16Srobert AbsolutePointerChunk *ctorListHead = make<AbsolutePointerChunk>(ctx, -1);
1921*dfe94b16Srobert AbsolutePointerChunk *ctorListEnd = make<AbsolutePointerChunk>(ctx, 0);
1922*dfe94b16Srobert AbsolutePointerChunk *dtorListHead = make<AbsolutePointerChunk>(ctx, -1);
1923*dfe94b16Srobert AbsolutePointerChunk *dtorListEnd = make<AbsolutePointerChunk>(ctx, 0);
1924ece8a530Spatrick ctorsSec->insertChunkAtStart(ctorListHead);
1925ece8a530Spatrick ctorsSec->addChunk(ctorListEnd);
1926ece8a530Spatrick dtorsSec->insertChunkAtStart(dtorListHead);
1927ece8a530Spatrick dtorsSec->addChunk(dtorListEnd);
1928ece8a530Spatrick
1929*dfe94b16Srobert Symbol *ctorListSym = ctx.symtab.findUnderscore("__CTOR_LIST__");
1930*dfe94b16Srobert Symbol *dtorListSym = ctx.symtab.findUnderscore("__DTOR_LIST__");
1931ece8a530Spatrick replaceSymbol<DefinedSynthetic>(ctorListSym, ctorListSym->getName(),
1932ece8a530Spatrick ctorListHead);
1933ece8a530Spatrick replaceSymbol<DefinedSynthetic>(dtorListSym, dtorListSym->getName(),
1934ece8a530Spatrick dtorListHead);
1935ece8a530Spatrick }
1936ece8a530Spatrick
1937ece8a530Spatrick // Handles /section options to allow users to overwrite
1938ece8a530Spatrick // section attributes.
setSectionPermissions()1939ece8a530Spatrick void Writer::setSectionPermissions() {
1940*dfe94b16Srobert for (auto &p : ctx.config.section) {
1941ece8a530Spatrick StringRef name = p.first;
1942ece8a530Spatrick uint32_t perm = p.second;
1943*dfe94b16Srobert for (OutputSection *sec : ctx.outputSections)
1944ece8a530Spatrick if (sec->name == name)
1945ece8a530Spatrick sec->setPermissions(perm);
1946ece8a530Spatrick }
1947ece8a530Spatrick }
1948ece8a530Spatrick
1949ece8a530Spatrick // Write section contents to a mmap'ed file.
writeSections()1950ece8a530Spatrick void Writer::writeSections() {
1951ece8a530Spatrick uint8_t *buf = buffer->getBufferStart();
1952*dfe94b16Srobert for (OutputSection *sec : ctx.outputSections) {
1953ece8a530Spatrick uint8_t *secBuf = buf + sec->getFileOff();
1954ece8a530Spatrick // Fill gaps between functions in .text with INT3 instructions
1955ece8a530Spatrick // instead of leaving as NUL bytes (which can be interpreted as
1956ece8a530Spatrick // ADD instructions).
1957ece8a530Spatrick if (sec->header.Characteristics & IMAGE_SCN_CNT_CODE)
1958ece8a530Spatrick memset(secBuf, 0xCC, sec->getRawSize());
1959ece8a530Spatrick parallelForEach(sec->chunks, [&](Chunk *c) {
1960ece8a530Spatrick c->writeTo(secBuf + c->getRVA() - sec->getRVA());
1961ece8a530Spatrick });
1962ece8a530Spatrick }
1963ece8a530Spatrick }
1964ece8a530Spatrick
writeBuildId()1965ece8a530Spatrick void Writer::writeBuildId() {
1966ece8a530Spatrick // There are two important parts to the build ID.
1967ece8a530Spatrick // 1) If building with debug info, the COFF debug directory contains a
1968ece8a530Spatrick // timestamp as well as a Guid and Age of the PDB.
1969ece8a530Spatrick // 2) In all cases, the PE COFF file header also contains a timestamp.
1970ece8a530Spatrick // For reproducibility, instead of a timestamp we want to use a hash of the
1971ece8a530Spatrick // PE contents.
1972*dfe94b16Srobert Configuration *config = &ctx.config;
1973*dfe94b16Srobert
1974ece8a530Spatrick if (config->debug) {
1975ece8a530Spatrick assert(buildId && "BuildId is not set!");
1976ece8a530Spatrick // BuildId->BuildId was filled in when the PDB was written.
1977ece8a530Spatrick }
1978ece8a530Spatrick
1979ece8a530Spatrick // At this point the only fields in the COFF file which remain unset are the
1980ece8a530Spatrick // "timestamp" in the COFF file header, and the ones in the coff debug
1981ece8a530Spatrick // directory. Now we can hash the file and write that hash to the various
1982ece8a530Spatrick // timestamp fields in the file.
1983ece8a530Spatrick StringRef outputFileData(
1984ece8a530Spatrick reinterpret_cast<const char *>(buffer->getBufferStart()),
1985ece8a530Spatrick buffer->getBufferSize());
1986ece8a530Spatrick
1987ece8a530Spatrick uint32_t timestamp = config->timestamp;
1988ece8a530Spatrick uint64_t hash = 0;
1989ece8a530Spatrick bool generateSyntheticBuildId =
1990ece8a530Spatrick config->mingw && config->debug && config->pdbPath.empty();
1991ece8a530Spatrick
1992ece8a530Spatrick if (config->repro || generateSyntheticBuildId)
1993ece8a530Spatrick hash = xxHash64(outputFileData);
1994ece8a530Spatrick
1995ece8a530Spatrick if (config->repro)
1996ece8a530Spatrick timestamp = static_cast<uint32_t>(hash);
1997ece8a530Spatrick
1998ece8a530Spatrick if (generateSyntheticBuildId) {
1999ece8a530Spatrick // For MinGW builds without a PDB file, we still generate a build id
2000ece8a530Spatrick // to allow associating a crash dump to the executable.
2001ece8a530Spatrick buildId->buildId->PDB70.CVSignature = OMF::Signature::PDB70;
2002ece8a530Spatrick buildId->buildId->PDB70.Age = 1;
2003ece8a530Spatrick memcpy(buildId->buildId->PDB70.Signature, &hash, 8);
2004ece8a530Spatrick // xxhash only gives us 8 bytes, so put some fixed data in the other half.
2005ece8a530Spatrick memcpy(&buildId->buildId->PDB70.Signature[8], "LLD PDB.", 8);
2006ece8a530Spatrick }
2007ece8a530Spatrick
2008ece8a530Spatrick if (debugDirectory)
2009ece8a530Spatrick debugDirectory->setTimeDateStamp(timestamp);
2010ece8a530Spatrick
2011ece8a530Spatrick uint8_t *buf = buffer->getBufferStart();
2012ece8a530Spatrick buf += dosStubSize + sizeof(PEMagic);
2013ece8a530Spatrick object::coff_file_header *coffHeader =
2014ece8a530Spatrick reinterpret_cast<coff_file_header *>(buf);
2015ece8a530Spatrick coffHeader->TimeDateStamp = timestamp;
2016ece8a530Spatrick }
2017ece8a530Spatrick
2018ece8a530Spatrick // Sort .pdata section contents according to PE/COFF spec 5.5.
sortExceptionTable()2019ece8a530Spatrick void Writer::sortExceptionTable() {
2020ece8a530Spatrick if (!firstPdata)
2021ece8a530Spatrick return;
2022ece8a530Spatrick // We assume .pdata contains function table entries only.
2023ece8a530Spatrick auto bufAddr = [&](Chunk *c) {
2024*dfe94b16Srobert OutputSection *os = ctx.getOutputSection(c);
2025ece8a530Spatrick return buffer->getBufferStart() + os->getFileOff() + c->getRVA() -
2026ece8a530Spatrick os->getRVA();
2027ece8a530Spatrick };
2028ece8a530Spatrick uint8_t *begin = bufAddr(firstPdata);
2029ece8a530Spatrick uint8_t *end = bufAddr(lastPdata) + lastPdata->getSize();
2030*dfe94b16Srobert if (ctx.config.machine == AMD64) {
2031ece8a530Spatrick struct Entry { ulittle32_t begin, end, unwind; };
2032bb684c34Spatrick if ((end - begin) % sizeof(Entry) != 0) {
2033bb684c34Spatrick fatal("unexpected .pdata size: " + Twine(end - begin) +
2034bb684c34Spatrick " is not a multiple of " + Twine(sizeof(Entry)));
2035bb684c34Spatrick }
2036ece8a530Spatrick parallelSort(
2037ece8a530Spatrick MutableArrayRef<Entry>((Entry *)begin, (Entry *)end),
2038ece8a530Spatrick [](const Entry &a, const Entry &b) { return a.begin < b.begin; });
2039ece8a530Spatrick return;
2040ece8a530Spatrick }
2041*dfe94b16Srobert if (ctx.config.machine == ARMNT || ctx.config.machine == ARM64) {
2042ece8a530Spatrick struct Entry { ulittle32_t begin, unwind; };
2043bb684c34Spatrick if ((end - begin) % sizeof(Entry) != 0) {
2044bb684c34Spatrick fatal("unexpected .pdata size: " + Twine(end - begin) +
2045bb684c34Spatrick " is not a multiple of " + Twine(sizeof(Entry)));
2046bb684c34Spatrick }
2047ece8a530Spatrick parallelSort(
2048ece8a530Spatrick MutableArrayRef<Entry>((Entry *)begin, (Entry *)end),
2049ece8a530Spatrick [](const Entry &a, const Entry &b) { return a.begin < b.begin; });
2050ece8a530Spatrick return;
2051ece8a530Spatrick }
2052ece8a530Spatrick lld::errs() << "warning: don't know how to handle .pdata.\n";
2053ece8a530Spatrick }
2054ece8a530Spatrick
2055ece8a530Spatrick // The CRT section contains, among other things, the array of function
2056ece8a530Spatrick // pointers that initialize every global variable that is not trivially
2057ece8a530Spatrick // constructed. The CRT calls them one after the other prior to invoking
2058ece8a530Spatrick // main().
2059ece8a530Spatrick //
2060ece8a530Spatrick // As per C++ spec, 3.6.2/2.3,
2061ece8a530Spatrick // "Variables with ordered initialization defined within a single
2062ece8a530Spatrick // translation unit shall be initialized in the order of their definitions
2063ece8a530Spatrick // in the translation unit"
2064ece8a530Spatrick //
2065ece8a530Spatrick // It is therefore critical to sort the chunks containing the function
2066ece8a530Spatrick // pointers in the order that they are listed in the object file (top to
2067ece8a530Spatrick // bottom), otherwise global objects might not be initialized in the
2068ece8a530Spatrick // correct order.
sortCRTSectionChunks(std::vector<Chunk * > & chunks)2069ece8a530Spatrick void Writer::sortCRTSectionChunks(std::vector<Chunk *> &chunks) {
2070ece8a530Spatrick auto sectionChunkOrder = [](const Chunk *a, const Chunk *b) {
2071ece8a530Spatrick auto sa = dyn_cast<SectionChunk>(a);
2072ece8a530Spatrick auto sb = dyn_cast<SectionChunk>(b);
2073ece8a530Spatrick assert(sa && sb && "Non-section chunks in CRT section!");
2074ece8a530Spatrick
2075ece8a530Spatrick StringRef sAObj = sa->file->mb.getBufferIdentifier();
2076ece8a530Spatrick StringRef sBObj = sb->file->mb.getBufferIdentifier();
2077ece8a530Spatrick
2078ece8a530Spatrick return sAObj == sBObj && sa->getSectionNumber() < sb->getSectionNumber();
2079ece8a530Spatrick };
2080ece8a530Spatrick llvm::stable_sort(chunks, sectionChunkOrder);
2081ece8a530Spatrick
2082*dfe94b16Srobert if (ctx.config.verbose) {
2083ece8a530Spatrick for (auto &c : chunks) {
2084ece8a530Spatrick auto sc = dyn_cast<SectionChunk>(c);
2085ece8a530Spatrick log(" " + sc->file->mb.getBufferIdentifier().str() +
2086ece8a530Spatrick ", SectionID: " + Twine(sc->getSectionNumber()));
2087ece8a530Spatrick }
2088ece8a530Spatrick }
2089ece8a530Spatrick }
2090ece8a530Spatrick
findSection(StringRef name)2091ece8a530Spatrick OutputSection *Writer::findSection(StringRef name) {
2092*dfe94b16Srobert for (OutputSection *sec : ctx.outputSections)
2093ece8a530Spatrick if (sec->name == name)
2094ece8a530Spatrick return sec;
2095ece8a530Spatrick return nullptr;
2096ece8a530Spatrick }
2097ece8a530Spatrick
getSizeOfInitializedData()2098ece8a530Spatrick uint32_t Writer::getSizeOfInitializedData() {
2099ece8a530Spatrick uint32_t res = 0;
2100*dfe94b16Srobert for (OutputSection *s : ctx.outputSections)
2101ece8a530Spatrick if (s->header.Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)
2102ece8a530Spatrick res += s->getRawSize();
2103ece8a530Spatrick return res;
2104ece8a530Spatrick }
2105ece8a530Spatrick
2106ece8a530Spatrick // Add base relocations to .reloc section.
addBaserels()2107ece8a530Spatrick void Writer::addBaserels() {
2108*dfe94b16Srobert if (!ctx.config.relocatable)
2109ece8a530Spatrick return;
2110ece8a530Spatrick relocSec->chunks.clear();
2111ece8a530Spatrick std::vector<Baserel> v;
2112*dfe94b16Srobert for (OutputSection *sec : ctx.outputSections) {
2113ece8a530Spatrick if (sec->header.Characteristics & IMAGE_SCN_MEM_DISCARDABLE)
2114ece8a530Spatrick continue;
2115ece8a530Spatrick // Collect all locations for base relocations.
2116ece8a530Spatrick for (Chunk *c : sec->chunks)
2117ece8a530Spatrick c->getBaserels(&v);
2118ece8a530Spatrick // Add the addresses to .reloc section.
2119ece8a530Spatrick if (!v.empty())
2120ece8a530Spatrick addBaserelBlocks(v);
2121ece8a530Spatrick v.clear();
2122ece8a530Spatrick }
2123ece8a530Spatrick }
2124ece8a530Spatrick
2125ece8a530Spatrick // Add addresses to .reloc section. Note that addresses are grouped by page.
addBaserelBlocks(std::vector<Baserel> & v)2126ece8a530Spatrick void Writer::addBaserelBlocks(std::vector<Baserel> &v) {
2127ece8a530Spatrick const uint32_t mask = ~uint32_t(pageSize - 1);
2128ece8a530Spatrick uint32_t page = v[0].rva & mask;
2129ece8a530Spatrick size_t i = 0, j = 1;
2130ece8a530Spatrick for (size_t e = v.size(); j < e; ++j) {
2131ece8a530Spatrick uint32_t p = v[j].rva & mask;
2132ece8a530Spatrick if (p == page)
2133ece8a530Spatrick continue;
2134ece8a530Spatrick relocSec->addChunk(make<BaserelChunk>(page, &v[i], &v[0] + j));
2135ece8a530Spatrick i = j;
2136ece8a530Spatrick page = p;
2137ece8a530Spatrick }
2138ece8a530Spatrick if (i == j)
2139ece8a530Spatrick return;
2140ece8a530Spatrick relocSec->addChunk(make<BaserelChunk>(page, &v[i], &v[0] + j));
2141ece8a530Spatrick }
2142ece8a530Spatrick
createPartialSection(StringRef name,uint32_t outChars)2143ece8a530Spatrick PartialSection *Writer::createPartialSection(StringRef name,
2144ece8a530Spatrick uint32_t outChars) {
2145ece8a530Spatrick PartialSection *&pSec = partialSections[{name, outChars}];
2146ece8a530Spatrick if (pSec)
2147ece8a530Spatrick return pSec;
2148ece8a530Spatrick pSec = make<PartialSection>(name, outChars);
2149ece8a530Spatrick return pSec;
2150ece8a530Spatrick }
2151ece8a530Spatrick
findPartialSection(StringRef name,uint32_t outChars)2152ece8a530Spatrick PartialSection *Writer::findPartialSection(StringRef name, uint32_t outChars) {
2153ece8a530Spatrick auto it = partialSections.find({name, outChars});
2154ece8a530Spatrick if (it != partialSections.end())
2155ece8a530Spatrick return it->second;
2156ece8a530Spatrick return nullptr;
2157ece8a530Spatrick }
21581cf9926bSpatrick
fixTlsAlignment()21591cf9926bSpatrick void Writer::fixTlsAlignment() {
21601cf9926bSpatrick Defined *tlsSym =
2161*dfe94b16Srobert dyn_cast_or_null<Defined>(ctx.symtab.findUnderscore("_tls_used"));
21621cf9926bSpatrick if (!tlsSym)
21631cf9926bSpatrick return;
21641cf9926bSpatrick
2165*dfe94b16Srobert OutputSection *sec = ctx.getOutputSection(tlsSym->getChunk());
21661cf9926bSpatrick assert(sec && tlsSym->getRVA() >= sec->getRVA() &&
21671cf9926bSpatrick "no output section for _tls_used");
21681cf9926bSpatrick
21691cf9926bSpatrick uint8_t *secBuf = buffer->getBufferStart() + sec->getFileOff();
21701cf9926bSpatrick uint64_t tlsOffset = tlsSym->getRVA() - sec->getRVA();
2171*dfe94b16Srobert uint64_t directorySize = ctx.config.is64()
21721cf9926bSpatrick ? sizeof(object::coff_tls_directory64)
21731cf9926bSpatrick : sizeof(object::coff_tls_directory32);
21741cf9926bSpatrick
21751cf9926bSpatrick if (tlsOffset + directorySize > sec->getRawSize())
21761cf9926bSpatrick fatal("_tls_used sym is malformed");
21771cf9926bSpatrick
2178*dfe94b16Srobert if (ctx.config.is64()) {
21791cf9926bSpatrick object::coff_tls_directory64 *tlsDir =
21801cf9926bSpatrick reinterpret_cast<object::coff_tls_directory64 *>(&secBuf[tlsOffset]);
21811cf9926bSpatrick tlsDir->setAlignment(tlsAlignment);
21821cf9926bSpatrick } else {
21831cf9926bSpatrick object::coff_tls_directory32 *tlsDir =
21841cf9926bSpatrick reinterpret_cast<object::coff_tls_directory32 *>(&secBuf[tlsOffset]);
21851cf9926bSpatrick tlsDir->setAlignment(tlsAlignment);
21861cf9926bSpatrick }
21871cf9926bSpatrick }
2188*dfe94b16Srobert
checkLoadConfig()2189*dfe94b16Srobert void Writer::checkLoadConfig() {
2190*dfe94b16Srobert Symbol *sym = ctx.symtab.findUnderscore("_load_config_used");
2191*dfe94b16Srobert auto *b = cast_if_present<DefinedRegular>(sym);
2192*dfe94b16Srobert if (!b) {
2193*dfe94b16Srobert if (ctx.config.guardCF != GuardCFLevel::Off)
2194*dfe94b16Srobert warn("Control Flow Guard is enabled but '_load_config_used' is missing");
2195*dfe94b16Srobert return;
2196*dfe94b16Srobert }
2197*dfe94b16Srobert
2198*dfe94b16Srobert OutputSection *sec = ctx.getOutputSection(b->getChunk());
2199*dfe94b16Srobert uint8_t *buf = buffer->getBufferStart();
2200*dfe94b16Srobert uint8_t *secBuf = buf + sec->getFileOff();
2201*dfe94b16Srobert uint8_t *symBuf = secBuf + (b->getRVA() - sec->getRVA());
2202*dfe94b16Srobert uint32_t expectedAlign = ctx.config.is64() ? 8 : 4;
2203*dfe94b16Srobert if (b->getChunk()->getAlignment() < expectedAlign)
2204*dfe94b16Srobert warn("'_load_config_used' is misaligned (expected alignment to be " +
2205*dfe94b16Srobert Twine(expectedAlign) + " bytes, got " +
2206*dfe94b16Srobert Twine(b->getChunk()->getAlignment()) + " instead)");
2207*dfe94b16Srobert else if (!isAligned(Align(expectedAlign), b->getRVA()))
2208*dfe94b16Srobert warn("'_load_config_used' is misaligned (RVA is 0x" +
2209*dfe94b16Srobert Twine::utohexstr(b->getRVA()) + " not aligned to " +
2210*dfe94b16Srobert Twine(expectedAlign) + " bytes)");
2211*dfe94b16Srobert
2212*dfe94b16Srobert if (ctx.config.is64())
2213*dfe94b16Srobert checkLoadConfigGuardData(
2214*dfe94b16Srobert reinterpret_cast<const coff_load_configuration64 *>(symBuf));
2215*dfe94b16Srobert else
2216*dfe94b16Srobert checkLoadConfigGuardData(
2217*dfe94b16Srobert reinterpret_cast<const coff_load_configuration32 *>(symBuf));
2218*dfe94b16Srobert }
2219*dfe94b16Srobert
2220*dfe94b16Srobert template <typename T>
checkLoadConfigGuardData(const T * loadConfig)2221*dfe94b16Srobert void Writer::checkLoadConfigGuardData(const T *loadConfig) {
2222*dfe94b16Srobert size_t loadConfigSize = loadConfig->Size;
2223*dfe94b16Srobert
2224*dfe94b16Srobert #define RETURN_IF_NOT_CONTAINS(field) \
2225*dfe94b16Srobert if (loadConfigSize < offsetof(T, field) + sizeof(T::field)) { \
2226*dfe94b16Srobert warn("'_load_config_used' structure too small to include " #field); \
2227*dfe94b16Srobert return; \
2228*dfe94b16Srobert }
2229*dfe94b16Srobert
2230*dfe94b16Srobert #define IF_CONTAINS(field) \
2231*dfe94b16Srobert if (loadConfigSize >= offsetof(T, field) + sizeof(T::field))
2232*dfe94b16Srobert
2233*dfe94b16Srobert #define CHECK_VA(field, sym) \
2234*dfe94b16Srobert if (auto *s = dyn_cast<DefinedSynthetic>(ctx.symtab.findUnderscore(sym))) \
2235*dfe94b16Srobert if (loadConfig->field != ctx.config.imageBase + s->getRVA()) \
2236*dfe94b16Srobert warn(#field " not set correctly in '_load_config_used'");
2237*dfe94b16Srobert
2238*dfe94b16Srobert #define CHECK_ABSOLUTE(field, sym) \
2239*dfe94b16Srobert if (auto *s = dyn_cast<DefinedAbsolute>(ctx.symtab.findUnderscore(sym))) \
2240*dfe94b16Srobert if (loadConfig->field != s->getVA()) \
2241*dfe94b16Srobert warn(#field " not set correctly in '_load_config_used'");
2242*dfe94b16Srobert
2243*dfe94b16Srobert if (ctx.config.guardCF == GuardCFLevel::Off)
2244*dfe94b16Srobert return;
2245*dfe94b16Srobert RETURN_IF_NOT_CONTAINS(GuardFlags)
2246*dfe94b16Srobert CHECK_VA(GuardCFFunctionTable, "__guard_fids_table")
2247*dfe94b16Srobert CHECK_ABSOLUTE(GuardCFFunctionCount, "__guard_fids_count")
2248*dfe94b16Srobert CHECK_ABSOLUTE(GuardFlags, "__guard_flags")
2249*dfe94b16Srobert IF_CONTAINS(GuardAddressTakenIatEntryCount) {
2250*dfe94b16Srobert CHECK_VA(GuardAddressTakenIatEntryTable, "__guard_iat_table")
2251*dfe94b16Srobert CHECK_ABSOLUTE(GuardAddressTakenIatEntryCount, "__guard_iat_count")
2252*dfe94b16Srobert }
2253*dfe94b16Srobert
2254*dfe94b16Srobert if (!(ctx.config.guardCF & GuardCFLevel::LongJmp))
2255*dfe94b16Srobert return;
2256*dfe94b16Srobert RETURN_IF_NOT_CONTAINS(GuardLongJumpTargetCount)
2257*dfe94b16Srobert CHECK_VA(GuardLongJumpTargetTable, "__guard_longjmp_table")
2258*dfe94b16Srobert CHECK_ABSOLUTE(GuardLongJumpTargetCount, "__guard_longjmp_count")
2259*dfe94b16Srobert
2260*dfe94b16Srobert if (!(ctx.config.guardCF & GuardCFLevel::EHCont))
2261*dfe94b16Srobert return;
2262*dfe94b16Srobert RETURN_IF_NOT_CONTAINS(GuardEHContinuationCount)
2263*dfe94b16Srobert CHECK_VA(GuardEHContinuationTable, "__guard_eh_cont_table")
2264*dfe94b16Srobert CHECK_ABSOLUTE(GuardEHContinuationCount, "__guard_eh_cont_count")
2265*dfe94b16Srobert
2266*dfe94b16Srobert #undef RETURN_IF_NOT_CONTAINS
2267*dfe94b16Srobert #undef IF_CONTAINS
2268*dfe94b16Srobert #undef CHECK_VA
2269*dfe94b16Srobert #undef CHECK_ABSOLUTE
2270*dfe94b16Srobert }
2271