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