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