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