1//===- Writer.cpp ---------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "Writer.h"
10#include "COFFLinkerContext.h"
11#include "CallGraphSort.h"
12#include "Config.h"
13#include "DLL.h"
14#include "InputFiles.h"
15#include "LLDMapFile.h"
16#include "MapFile.h"
17#include "PDB.h"
18#include "SymbolTable.h"
19#include "Symbols.h"
20#include "lld/Common/ErrorHandler.h"
21#include "lld/Common/Memory.h"
22#include "lld/Common/Timer.h"
23#include "llvm/ADT/DenseMap.h"
24#include "llvm/ADT/STLExtras.h"
25#include "llvm/ADT/StringSet.h"
26#include "llvm/BinaryFormat/COFF.h"
27#include "llvm/MC/StringTableBuilder.h"
28#include "llvm/Support/Endian.h"
29#include "llvm/Support/FileOutputBuffer.h"
30#include "llvm/Support/FormatAdapters.h"
31#include "llvm/Support/FormatVariadic.h"
32#include "llvm/Support/Parallel.h"
33#include "llvm/Support/RandomNumberGenerator.h"
34#include "llvm/Support/TimeProfiler.h"
35#include "llvm/Support/xxhash.h"
36#include <algorithm>
37#include <cstdio>
38#include <map>
39#include <memory>
40#include <utility>
41
42using namespace llvm;
43using namespace llvm::COFF;
44using namespace llvm::object;
45using namespace llvm::support;
46using namespace llvm::support::endian;
47using namespace lld;
48using namespace lld::coff;
49
50/* To re-generate DOSProgram:
51$ cat > /tmp/DOSProgram.asm
52org 0
53 ; Copy cs to ds.
54 push cs
55 pop ds
56 ; Point ds:dx at the $-terminated string.
57 mov dx, str
58 ; Int 21/AH=09h: Write string to standard output.
59 mov ah, 0x9
60 int 0x21
61 ; Int 21/AH=4Ch: Exit with return code (in AL).
62 mov ax, 0x4C01
63 int 0x21
64str:
65 db 'This program cannot be run in DOS mode.$'
66align 8, db 0
67$ nasm -fbin /tmp/DOSProgram.asm -o /tmp/DOSProgram.bin
68$ xxd -i /tmp/DOSProgram.bin
69*/
70static unsigned char dosProgram[] = {
71 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c,
72 0xcd, 0x21, 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,
73 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65,
74 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
75 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x24, 0x00, 0x00
76};
77static_assert(sizeof(dosProgram) % 8 == 0,
78 "DOSProgram size must be multiple of 8");
79static_assert((sizeof(dos_header) + sizeof(dosProgram)) % 8 == 0,
80 "DOSStub size must be multiple of 8");
81
82static const int numberOfDataDirectory = 16;
83
84namespace {
85
86class DebugDirectoryChunk : public NonSectionChunk {
87public:
88 DebugDirectoryChunk(const COFFLinkerContext &c,
89 const std::vector<std::pair<COFF::DebugType, Chunk *>> &r,
90 bool writeRepro)
91 : records(r), writeRepro(writeRepro), ctx(c) {}
92
93 size_t getSize() const override {
94 return (records.size() + int(writeRepro)) * sizeof(debug_directory);
95 }
96
97 void writeTo(uint8_t *b) const override {
98 auto *d = reinterpret_cast<debug_directory *>(b);
99
100 for (const std::pair<COFF::DebugType, Chunk *>& record : records) {
101 Chunk *c = record.second;
102 const OutputSection *os = ctx.getOutputSection(c);
103 uint64_t offs = os->getFileOff() + (c->getRVA() - os->getRVA());
104 fillEntry(d, debugType: record.first, size: c->getSize(), rva: c->getRVA(), offs);
105 ++d;
106 }
107
108 if (writeRepro) {
109 // FIXME: The COFF spec allows either a 0-sized entry to just say
110 // "the timestamp field is really a hash", or a 4-byte size field
111 // followed by that many bytes containing a longer hash (with the
112 // lowest 4 bytes usually being the timestamp in little-endian order).
113 // Consider storing the full 8 bytes computed by xxh3_64bits here.
114 fillEntry(d, debugType: COFF::IMAGE_DEBUG_TYPE_REPRO, size: 0, rva: 0, offs: 0);
115 }
116 }
117
118 void setTimeDateStamp(uint32_t timeDateStamp) {
119 for (support::ulittle32_t *tds : timeDateStamps)
120 *tds = timeDateStamp;
121 }
122
123private:
124 void fillEntry(debug_directory *d, COFF::DebugType debugType, size_t size,
125 uint64_t rva, uint64_t offs) const {
126 d->Characteristics = 0;
127 d->TimeDateStamp = 0;
128 d->MajorVersion = 0;
129 d->MinorVersion = 0;
130 d->Type = debugType;
131 d->SizeOfData = size;
132 d->AddressOfRawData = rva;
133 d->PointerToRawData = offs;
134
135 timeDateStamps.push_back(x: &d->TimeDateStamp);
136 }
137
138 mutable std::vector<support::ulittle32_t *> timeDateStamps;
139 const std::vector<std::pair<COFF::DebugType, Chunk *>> &records;
140 bool writeRepro;
141 const COFFLinkerContext &ctx;
142};
143
144class CVDebugRecordChunk : public NonSectionChunk {
145public:
146 CVDebugRecordChunk(const COFFLinkerContext &c) : ctx(c) {}
147
148 size_t getSize() const override {
149 return sizeof(codeview::DebugInfo) + ctx.config.pdbAltPath.size() + 1;
150 }
151
152 void writeTo(uint8_t *b) const override {
153 // Save off the DebugInfo entry to backfill the file signature (build id)
154 // in Writer::writeBuildId
155 buildId = reinterpret_cast<codeview::DebugInfo *>(b);
156
157 // variable sized field (PDB Path)
158 char *p = reinterpret_cast<char *>(b + sizeof(*buildId));
159 if (!ctx.config.pdbAltPath.empty())
160 memcpy(dest: p, src: ctx.config.pdbAltPath.data(), n: ctx.config.pdbAltPath.size());
161 p[ctx.config.pdbAltPath.size()] = '\0';
162 }
163
164 mutable codeview::DebugInfo *buildId = nullptr;
165
166private:
167 const COFFLinkerContext &ctx;
168};
169
170class ExtendedDllCharacteristicsChunk : public NonSectionChunk {
171public:
172 ExtendedDllCharacteristicsChunk(uint32_t c) : characteristics(c) {}
173
174 size_t getSize() const override { return 4; }
175
176 void writeTo(uint8_t *buf) const override { write32le(P: buf, V: characteristics); }
177
178 uint32_t characteristics = 0;
179};
180
181// PartialSection represents a group of chunks that contribute to an
182// OutputSection. Collating a collection of PartialSections of same name and
183// characteristics constitutes the OutputSection.
184class PartialSectionKey {
185public:
186 StringRef name;
187 unsigned characteristics;
188
189 bool operator<(const PartialSectionKey &other) const {
190 int c = name.compare(RHS: other.name);
191 if (c > 0)
192 return false;
193 if (c == 0)
194 return characteristics < other.characteristics;
195 return true;
196 }
197};
198
199struct ChunkRange {
200 Chunk *first = nullptr, *last;
201};
202
203// The writer writes a SymbolTable result to a file.
204class Writer {
205public:
206 Writer(COFFLinkerContext &c)
207 : buffer(c.e.outputBuffer), strtab(StringTableBuilder::WinCOFF),
208 delayIdata(c), ctx(c) {}
209 void run();
210
211private:
212 void calculateStubDependentSizes();
213 void createSections();
214 void createMiscChunks();
215 void createImportTables();
216 void appendImportThunks();
217 void locateImportTables();
218 void createExportTable();
219 StringRef getMergeDestination(StringRef fromSection, StringRef toSection);
220 void mergeSection(const std::map<StringRef, StringRef>::value_type &p);
221 void mergeSections();
222 void sortECChunks();
223 void appendECImportTables();
224 void removeUnusedSections();
225 void layoutSections();
226 void assignAddresses();
227 bool isInRange(uint16_t relType, uint64_t s, uint64_t p, int margin,
228 MachineTypes machine);
229 std::pair<Defined *, bool> getThunk(DenseMap<uint64_t, Defined *> &lastThunks,
230 Defined *target, uint64_t p,
231 uint16_t type, int margin,
232 MachineTypes machine);
233 bool createThunks(OutputSection *os, int margin);
234 bool verifyRanges(const std::vector<Chunk *> chunks);
235 void createECCodeMap();
236 void finalizeAddresses();
237 void removeEmptySections();
238 void assignOutputSectionIndices();
239 void createSymbolAndStringTable();
240 void openFile(StringRef outputPath);
241 template <typename PEHeaderTy> void writeHeader();
242 void createSEHTable();
243 void createRuntimePseudoRelocs();
244 void createECChunks();
245 void insertCtorDtorSymbols();
246 void insertBssDataStartEndSymbols();
247 void markSymbolsWithRelocations(ObjFile *file, SymbolRVASet &usedSymbols);
248 void createGuardCFTables();
249 void markSymbolsForRVATable(ObjFile *file,
250 ArrayRef<SectionChunk *> symIdxChunks,
251 SymbolRVASet &tableSymbols);
252 void getSymbolsFromSections(ObjFile *file,
253 ArrayRef<SectionChunk *> symIdxChunks,
254 std::vector<Symbol *> &symbols);
255 void maybeAddRVATable(SymbolRVASet tableSymbols, StringRef tableSym,
256 StringRef countSym, bool hasFlag=false);
257 void setSectionPermissions();
258 void setECSymbols();
259 void writeSections();
260 void writeBuildId();
261 void writePEChecksum();
262 void sortSections();
263 template <typename T> void sortExceptionTable(ChunkRange &exceptionTable);
264 void sortExceptionTables();
265 void sortCRTSectionChunks(std::vector<Chunk *> &chunks);
266 void addSyntheticIdata();
267 void sortBySectionOrder(std::vector<Chunk *> &chunks);
268 void fixPartialSectionChars(StringRef name, uint32_t chars);
269 bool fixGnuImportChunks();
270 void fixTlsAlignment();
271 PartialSection *createPartialSection(StringRef name, uint32_t outChars);
272 PartialSection *findPartialSection(StringRef name, uint32_t outChars);
273
274 std::optional<coff_symbol16> createSymbol(Defined *d);
275 size_t addEntryToStringTable(StringRef str);
276
277 OutputSection *findSection(StringRef name);
278 void addBaserels();
279 void addBaserelBlocks(std::vector<Baserel> &v);
280 void createDynamicRelocs();
281
282 uint32_t getSizeOfInitializedData();
283
284 void prepareLoadConfig();
285 template <typename T>
286 void prepareLoadConfig(SymbolTable &symtab, T *loadConfig);
287
288 void printSummary();
289
290 std::unique_ptr<FileOutputBuffer> &buffer;
291 std::map<PartialSectionKey, PartialSection *> partialSections;
292 StringTableBuilder strtab;
293 std::vector<llvm::object::coff_symbol16> outputSymtab;
294 std::vector<ECCodeMapEntry> codeMap;
295 IdataContents idata;
296 Chunk *importTableStart = nullptr;
297 uint64_t importTableSize = 0;
298 Chunk *iatStart = nullptr;
299 uint64_t iatSize = 0;
300 DelayLoadContents delayIdata;
301 bool setNoSEHCharacteristic = false;
302 uint32_t tlsAlignment = 0;
303
304 DebugDirectoryChunk *debugDirectory = nullptr;
305 std::vector<std::pair<COFF::DebugType, Chunk *>> debugRecords;
306 CVDebugRecordChunk *buildId = nullptr;
307 ArrayRef<uint8_t> sectionTable;
308
309 // List of Arm64EC export thunks.
310 std::vector<std::pair<Chunk *, Defined *>> exportThunks;
311
312 uint64_t fileSize;
313 uint32_t pointerToSymbolTable = 0;
314 uint64_t sizeOfImage;
315 uint64_t sizeOfHeaders;
316
317 uint32_t dosStubSize;
318 uint32_t coffHeaderOffset;
319 uint32_t peHeaderOffset;
320 uint32_t dataDirOffset64;
321
322 OutputSection *textSec;
323 OutputSection *wowthkSec;
324 OutputSection *hexpthkSec;
325 OutputSection *bssSec;
326 OutputSection *rdataSec;
327 OutputSection *buildidSec;
328 OutputSection *cvinfoSec;
329 OutputSection *dataSec;
330 OutputSection *pdataSec;
331 OutputSection *idataSec;
332 OutputSection *edataSec;
333 OutputSection *didatSec;
334 OutputSection *a64xrmSec;
335 OutputSection *rsrcSec;
336 OutputSection *relocSec;
337 OutputSection *ctorsSec;
338 OutputSection *dtorsSec;
339 // Either .rdata section or .buildid section.
340 OutputSection *debugInfoSec;
341
342 // The range of .pdata sections in the output file.
343 //
344 // We need to keep track of the location of .pdata in whichever section it
345 // gets merged into so that we can sort its contents and emit a correct data
346 // directory entry for the exception table. This is also the case for some
347 // other sections (such as .edata) but because the contents of those sections
348 // are entirely linker-generated we can keep track of their locations using
349 // the chunks that the linker creates. All .pdata chunks come from input
350 // files, so we need to keep track of them separately.
351 ChunkRange pdata;
352
353 // x86_64 .pdata sections on ARM64EC/ARM64X targets.
354 ChunkRange hybridPdata;
355
356 // CHPE metadata symbol on ARM64C target.
357 DefinedRegular *chpeSym = nullptr;
358
359 COFFLinkerContext &ctx;
360};
361} // anonymous namespace
362
363void lld::coff::writeResult(COFFLinkerContext &ctx) {
364 llvm::TimeTraceScope timeScope("Write output(s)");
365 Writer(ctx).run();
366}
367
368void OutputSection::addChunk(Chunk *c) {
369 chunks.push_back(x: c);
370}
371
372void OutputSection::insertChunkAtStart(Chunk *c) {
373 chunks.insert(position: chunks.begin(), x: c);
374}
375
376void OutputSection::setPermissions(uint32_t c) {
377 header.Characteristics &= ~permMask;
378 header.Characteristics |= c;
379}
380
381void OutputSection::merge(OutputSection *other) {
382 chunks.insert(position: chunks.end(), first: other->chunks.begin(), last: other->chunks.end());
383 other->chunks.clear();
384 contribSections.insert(position: contribSections.end(), first: other->contribSections.begin(),
385 last: other->contribSections.end());
386 other->contribSections.clear();
387
388 // MS link.exe compatibility: when merging a code section into a data section,
389 // mark the target section as a code section.
390 if (other->header.Characteristics & IMAGE_SCN_CNT_CODE) {
391 header.Characteristics |= IMAGE_SCN_CNT_CODE;
392 header.Characteristics &=
393 ~(IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_CNT_UNINITIALIZED_DATA);
394 }
395}
396
397// Write the section header to a given buffer.
398void OutputSection::writeHeaderTo(uint8_t *buf, bool isDebug) {
399 auto *hdr = reinterpret_cast<coff_section *>(buf);
400 *hdr = header;
401 if (stringTableOff) {
402 // If name is too long, write offset into the string table as a name.
403 encodeSectionName(Out: hdr->Name, Offset: stringTableOff);
404 } else {
405 assert(!isDebug || name.size() <= COFF::NameSize ||
406 (hdr->Characteristics & IMAGE_SCN_MEM_DISCARDABLE) == 0);
407 strncpy(dest: hdr->Name, src: name.data(),
408 n: std::min(a: name.size(), b: (size_t)COFF::NameSize));
409 }
410}
411
412void OutputSection::addContributingPartialSection(PartialSection *sec) {
413 contribSections.push_back(x: sec);
414}
415
416void OutputSection::splitECChunks() {
417 llvm::stable_sort(Range&: chunks, C: [=](const Chunk *a, const Chunk *b) {
418 return (a->getMachine() != ARM64) < (b->getMachine() != ARM64);
419 });
420}
421
422// Check whether the target address S is in range from a relocation
423// of type relType at address P.
424bool Writer::isInRange(uint16_t relType, uint64_t s, uint64_t p, int margin,
425 MachineTypes machine) {
426 if (machine == ARMNT) {
427 int64_t diff = AbsoluteDifference(X: s, Y: p + 4) + margin;
428 switch (relType) {
429 case IMAGE_REL_ARM_BRANCH20T:
430 return isInt<21>(x: diff);
431 case IMAGE_REL_ARM_BRANCH24T:
432 case IMAGE_REL_ARM_BLX23T:
433 return isInt<25>(x: diff);
434 default:
435 return true;
436 }
437 } else if (isAnyArm64(Machine: machine)) {
438 int64_t diff = AbsoluteDifference(X: s, Y: p) + margin;
439 switch (relType) {
440 case IMAGE_REL_ARM64_BRANCH26:
441 return isInt<28>(x: diff);
442 case IMAGE_REL_ARM64_BRANCH19:
443 return isInt<21>(x: diff);
444 case IMAGE_REL_ARM64_BRANCH14:
445 return isInt<16>(x: diff);
446 default:
447 return true;
448 }
449 } else {
450 return true;
451 }
452}
453
454// Return the last thunk for the given target if it is in range,
455// or create a new one.
456std::pair<Defined *, bool>
457Writer::getThunk(DenseMap<uint64_t, Defined *> &lastThunks, Defined *target,
458 uint64_t p, uint16_t type, int margin, MachineTypes machine) {
459 Defined *&lastThunk = lastThunks[target->getRVA()];
460 if (lastThunk && isInRange(relType: type, s: lastThunk->getRVA(), p, margin, machine))
461 return {lastThunk, false};
462 Chunk *c;
463 switch (getMachineArchType(machine)) {
464 case Triple::thumb:
465 c = make<RangeExtensionThunkARM>(args&: ctx, args&: target);
466 break;
467 case Triple::aarch64:
468 c = make<RangeExtensionThunkARM64>(args&: machine, args&: target);
469 break;
470 default:
471 llvm_unreachable("Unexpected architecture");
472 }
473 Defined *d = make<DefinedSynthetic>(args: "range_extension_thunk", args&: c);
474 lastThunk = d;
475 return {d, true};
476}
477
478// This checks all relocations, and for any relocation which isn't in range
479// it adds a thunk after the section chunk that contains the relocation.
480// If the latest thunk for the specific target is in range, that is used
481// instead of creating a new thunk. All range checks are done with the
482// specified margin, to make sure that relocations that originally are in
483// range, but only barely, also get thunks - in case other added thunks makes
484// the target go out of range.
485//
486// After adding thunks, we verify that all relocations are in range (with
487// no extra margin requirements). If this failed, we restart (throwing away
488// the previously created thunks) and retry with a wider margin.
489bool Writer::createThunks(OutputSection *os, int margin) {
490 bool addressesChanged = false;
491 DenseMap<uint64_t, Defined *> lastThunks;
492 DenseMap<std::pair<ObjFile *, Defined *>, uint32_t> thunkSymtabIndices;
493 size_t thunksSize = 0;
494 // Recheck Chunks.size() each iteration, since we can insert more
495 // elements into it.
496 for (size_t i = 0; i != os->chunks.size(); ++i) {
497 SectionChunk *sc = dyn_cast<SectionChunk>(Val: os->chunks[i]);
498 if (!sc) {
499 auto chunk = cast<NonSectionChunk>(Val: os->chunks[i]);
500 if (uint32_t size = chunk->extendRanges()) {
501 thunksSize += size;
502 addressesChanged = true;
503 }
504 continue;
505 }
506 MachineTypes machine = sc->getMachine();
507 size_t thunkInsertionSpot = i + 1;
508
509 // Try to get a good enough estimate of where new thunks will be placed.
510 // Offset this by the size of the new thunks added so far, to make the
511 // estimate slightly better.
512 size_t thunkInsertionRVA = sc->getRVA() + sc->getSize() + thunksSize;
513 ObjFile *file = sc->file;
514 std::vector<std::pair<uint32_t, uint32_t>> relocReplacements;
515 ArrayRef<coff_relocation> originalRelocs =
516 file->getCOFFObj()->getRelocations(Sec: sc->header);
517 for (size_t j = 0, e = originalRelocs.size(); j < e; ++j) {
518 const coff_relocation &rel = originalRelocs[j];
519 Symbol *relocTarget = file->getSymbol(symbolIndex: rel.SymbolTableIndex);
520
521 // The estimate of the source address P should be pretty accurate,
522 // but we don't know whether the target Symbol address should be
523 // offset by thunksSize or not (or by some of thunksSize but not all of
524 // it), giving us some uncertainty once we have added one thunk.
525 uint64_t p = sc->getRVA() + rel.VirtualAddress + thunksSize;
526
527 Defined *sym = dyn_cast_or_null<Defined>(Val: relocTarget);
528 if (!sym)
529 continue;
530
531 uint64_t s = sym->getRVA();
532
533 if (isInRange(relType: rel.Type, s, p, margin, machine))
534 continue;
535
536 // If the target isn't in range, hook it up to an existing or new thunk.
537 auto [thunk, wasNew] =
538 getThunk(lastThunks, target: sym, p, type: rel.Type, margin, machine);
539 if (wasNew) {
540 Chunk *thunkChunk = thunk->getChunk();
541 thunkChunk->setRVA(
542 thunkInsertionRVA); // Estimate of where it will be located.
543 os->chunks.insert(position: os->chunks.begin() + thunkInsertionSpot, x: thunkChunk);
544 thunkInsertionSpot++;
545 thunksSize += thunkChunk->getSize();
546 thunkInsertionRVA += thunkChunk->getSize();
547 addressesChanged = true;
548 }
549
550 // To redirect the relocation, add a symbol to the parent object file's
551 // symbol table, and replace the relocation symbol table index with the
552 // new index.
553 auto insertion = thunkSymtabIndices.insert(KV: {{file, thunk}, ~0U});
554 uint32_t &thunkSymbolIndex = insertion.first->second;
555 if (insertion.second)
556 thunkSymbolIndex = file->addRangeThunkSymbol(thunk);
557 relocReplacements.emplace_back(args&: j, args&: thunkSymbolIndex);
558 }
559
560 // Get a writable copy of this section's relocations so they can be
561 // modified. If the relocations point into the object file, allocate new
562 // memory. Otherwise, this must be previously allocated memory that can be
563 // modified in place.
564 ArrayRef<coff_relocation> curRelocs = sc->getRelocs();
565 MutableArrayRef<coff_relocation> newRelocs;
566 if (originalRelocs.data() == curRelocs.data()) {
567 newRelocs = MutableArrayRef(
568 bAlloc().Allocate<coff_relocation>(Num: originalRelocs.size()),
569 originalRelocs.size());
570 } else {
571 newRelocs = MutableArrayRef(
572 const_cast<coff_relocation *>(curRelocs.data()), curRelocs.size());
573 }
574
575 // Copy each relocation, but replace the symbol table indices which need
576 // thunks.
577 auto nextReplacement = relocReplacements.begin();
578 auto endReplacement = relocReplacements.end();
579 for (size_t i = 0, e = originalRelocs.size(); i != e; ++i) {
580 newRelocs[i] = originalRelocs[i];
581 if (nextReplacement != endReplacement && nextReplacement->first == i) {
582 newRelocs[i].SymbolTableIndex = nextReplacement->second;
583 ++nextReplacement;
584 }
585 }
586
587 sc->setRelocs(newRelocs);
588 }
589 return addressesChanged;
590}
591
592// Create a code map for CHPE metadata.
593void Writer::createECCodeMap() {
594 if (!ctx.symtab.isEC())
595 return;
596
597 // Clear the map in case we were're recomputing the map after adding
598 // a range extension thunk.
599 codeMap.clear();
600
601 std::optional<chpe_range_type> lastType;
602 Chunk *first, *last;
603
604 auto closeRange = [&]() {
605 if (lastType) {
606 codeMap.push_back(x: {first, last, *lastType});
607 lastType.reset();
608 }
609 };
610
611 for (OutputSection *sec : ctx.outputSections) {
612 for (Chunk *c : sec->chunks) {
613 // Skip empty section chunks. MS link.exe does not seem to do that and
614 // generates empty code ranges in some cases.
615 if (isa<SectionChunk>(Val: c) && !c->getSize())
616 continue;
617
618 std::optional<chpe_range_type> chunkType = c->getArm64ECRangeType();
619 if (chunkType != lastType) {
620 closeRange();
621 first = c;
622 lastType = chunkType;
623 }
624 last = c;
625 }
626 }
627
628 closeRange();
629
630 Symbol *tableCountSym = ctx.symtab.findUnderscore(name: "__hybrid_code_map_count");
631 cast<DefinedAbsolute>(Val: tableCountSym)->setVA(codeMap.size());
632}
633
634// Verify that all relocations are in range, with no extra margin requirements.
635bool Writer::verifyRanges(const std::vector<Chunk *> chunks) {
636 for (Chunk *c : chunks) {
637 SectionChunk *sc = dyn_cast<SectionChunk>(Val: c);
638 if (!sc) {
639 if (!cast<NonSectionChunk>(Val: c)->verifyRanges())
640 return false;
641 continue;
642 }
643 MachineTypes machine = sc->getMachine();
644
645 ArrayRef<coff_relocation> relocs = sc->getRelocs();
646 for (const coff_relocation &rel : relocs) {
647 Symbol *relocTarget = sc->file->getSymbol(symbolIndex: rel.SymbolTableIndex);
648
649 Defined *sym = dyn_cast_or_null<Defined>(Val: relocTarget);
650 if (!sym)
651 continue;
652
653 uint64_t p = sc->getRVA() + rel.VirtualAddress;
654 uint64_t s = sym->getRVA();
655
656 if (!isInRange(relType: rel.Type, s, p, margin: 0, machine))
657 return false;
658 }
659 }
660 return true;
661}
662
663// Assign addresses and add thunks if necessary.
664void Writer::finalizeAddresses() {
665 assignAddresses();
666 if (ctx.config.machine != ARMNT && !isAnyArm64(Machine: ctx.config.machine))
667 return;
668
669 size_t origNumChunks = 0;
670 for (OutputSection *sec : ctx.outputSections) {
671 sec->origChunks = sec->chunks;
672 origNumChunks += sec->chunks.size();
673 }
674
675 int pass = 0;
676 int margin = 1024 * 100;
677 while (true) {
678 llvm::TimeTraceScope timeScope2("Add thunks pass");
679
680 // First check whether we need thunks at all, or if the previous pass of
681 // adding them turned out ok.
682 bool rangesOk = true;
683 size_t numChunks = 0;
684 {
685 llvm::TimeTraceScope timeScope3("Verify ranges");
686 for (OutputSection *sec : ctx.outputSections) {
687 if (!verifyRanges(chunks: sec->chunks)) {
688 rangesOk = false;
689 break;
690 }
691 numChunks += sec->chunks.size();
692 }
693 }
694 if (rangesOk) {
695 if (pass > 0)
696 Log(ctx) << "Added " << (numChunks - origNumChunks) << " thunks with "
697 << "margin " << margin << " in " << pass << " passes";
698 return;
699 }
700
701 if (pass >= 10)
702 Fatal(ctx) << "adding thunks hasn't converged after " << pass
703 << " passes";
704
705 if (pass > 0) {
706 // If the previous pass didn't work out, reset everything back to the
707 // original conditions before retrying with a wider margin. This should
708 // ideally never happen under real circumstances.
709 for (OutputSection *sec : ctx.outputSections)
710 sec->chunks = sec->origChunks;
711 margin *= 2;
712 }
713
714 // Try adding thunks everywhere where it is needed, with a margin
715 // to avoid things going out of range due to the added thunks.
716 bool addressesChanged = false;
717 {
718 llvm::TimeTraceScope timeScope3("Create thunks");
719 for (OutputSection *sec : ctx.outputSections)
720 addressesChanged |= createThunks(os: sec, margin);
721 }
722 // If the verification above thought we needed thunks, we should have
723 // added some.
724 assert(addressesChanged);
725 (void)addressesChanged;
726
727 // Recalculate the layout for the whole image (and verify the ranges at
728 // the start of the next round).
729 assignAddresses();
730
731 pass++;
732 }
733}
734
735void Writer::writePEChecksum() {
736 if (!ctx.config.writeCheckSum) {
737 return;
738 }
739
740 llvm::TimeTraceScope timeScope("PE checksum");
741
742 // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#checksum
743 uint32_t *buf = (uint32_t *)buffer->getBufferStart();
744 uint32_t size = (uint32_t)(buffer->getBufferSize());
745
746 pe32_header *peHeader = (pe32_header *)((uint8_t *)buf + coffHeaderOffset +
747 sizeof(coff_file_header));
748
749 uint64_t sum = 0;
750 uint32_t count = size;
751 ulittle16_t *addr = (ulittle16_t *)buf;
752
753 // The PE checksum algorithm, implemented as suggested in RFC1071
754 while (count > 1) {
755 sum += *addr++;
756 count -= 2;
757 }
758
759 // Add left-over byte, if any
760 if (count > 0)
761 sum += *(unsigned char *)addr;
762
763 // Fold 32-bit sum to 16 bits
764 while (sum >> 16) {
765 sum = (sum & 0xffff) + (sum >> 16);
766 }
767
768 sum += size;
769 peHeader->CheckSum = sum;
770}
771
772// The main function of the writer.
773void Writer::run() {
774 {
775 llvm::TimeTraceScope timeScope("Write PE");
776 ScopedTimer t1(ctx.codeLayoutTimer);
777
778 calculateStubDependentSizes();
779 if (ctx.config.machine == ARM64X)
780 ctx.dynamicRelocs = make<DynamicRelocsChunk>();
781 createImportTables();
782 createSections();
783 appendImportThunks();
784 // Import thunks must be added before the Control Flow Guard tables are
785 // added.
786 createMiscChunks();
787 createExportTable();
788 mergeSections();
789 sortECChunks();
790 appendECImportTables();
791 createDynamicRelocs();
792 removeUnusedSections();
793 layoutSections();
794 finalizeAddresses();
795 removeEmptySections();
796 assignOutputSectionIndices();
797 setSectionPermissions();
798 setECSymbols();
799 createSymbolAndStringTable();
800
801 if (fileSize > UINT32_MAX)
802 Fatal(ctx) << "image size (" << fileSize << ") "
803 << "exceeds maximum allowable size (" << UINT32_MAX << ")";
804
805 openFile(outputPath: ctx.config.outputFile);
806 if (ctx.config.is64()) {
807 writeHeader<pe32plus_header>();
808 } else {
809 writeHeader<pe32_header>();
810 }
811 writeSections();
812 prepareLoadConfig();
813 sortExceptionTables();
814
815 // Fix up the alignment in the TLS Directory's characteristic field,
816 // if a specific alignment value is needed
817 if (tlsAlignment)
818 fixTlsAlignment();
819 }
820
821 if (!ctx.config.pdbPath.empty() && ctx.config.debug) {
822 assert(buildId);
823 createPDB(ctx, sectionTable, buildId: buildId->buildId);
824 }
825 writeBuildId();
826
827 writeLLDMapFile(ctx);
828 writeMapFile(ctx);
829
830 writePEChecksum();
831
832 printSummary();
833
834 if (errorCount())
835 return;
836
837 llvm::TimeTraceScope timeScope("Commit PE to disk");
838 ScopedTimer t2(ctx.outputCommitTimer);
839 if (auto e = buffer->commit())
840 Fatal(ctx) << "failed to write output '" << buffer->getPath()
841 << "': " << toString(E: std::move(e));
842}
843
844static StringRef getOutputSectionName(StringRef name, bool isMinGW) {
845 StringRef s = name.split(Separator: '$').first;
846 if (!isMinGW)
847 return s;
848
849 // Treat a later period as a separator for MinGW, for sections like
850 // ".ctors.01234".
851 return s.substr(Start: 0, N: s.find(C: '.', From: 1));
852}
853
854// For /order.
855void Writer::sortBySectionOrder(std::vector<Chunk *> &chunks) {
856 auto getPriority = [&ctx = ctx](const Chunk *c) {
857 if (auto *sec = dyn_cast<SectionChunk>(Val: c))
858 if (sec->sym)
859 return ctx.config.order.lookup(Key: sec->sym->getName());
860 return 0;
861 };
862
863 llvm::stable_sort(Range&: chunks, C: [=](const Chunk *a, const Chunk *b) {
864 return getPriority(a) < getPriority(b);
865 });
866}
867
868// Change the characteristics of existing PartialSections that belong to the
869// section Name to Chars.
870void Writer::fixPartialSectionChars(StringRef name, uint32_t chars) {
871 for (auto it : partialSections) {
872 PartialSection *pSec = it.second;
873 StringRef curName = pSec->name;
874 if (!curName.consume_front(Prefix: name) ||
875 (!curName.empty() && !curName.starts_with(Prefix: "$")))
876 continue;
877 if (pSec->characteristics == chars)
878 continue;
879 PartialSection *destSec = createPartialSection(name: pSec->name, outChars: chars);
880 destSec->chunks.insert(position: destSec->chunks.end(), first: pSec->chunks.begin(),
881 last: pSec->chunks.end());
882 pSec->chunks.clear();
883 }
884}
885
886// Sort concrete section chunks from GNU import libraries.
887//
888// GNU binutils doesn't use short import files, but instead produces import
889// libraries that consist of object files, with section chunks for the .idata$*
890// sections. These are linked just as regular static libraries. Each import
891// library consists of one header object, one object file for every imported
892// symbol, and one trailer object. In order for the .idata tables/lists to
893// be formed correctly, the section chunks within each .idata$* section need
894// to be grouped by library, and sorted alphabetically within each library
895// (which makes sure the header comes first and the trailer last).
896bool Writer::fixGnuImportChunks() {
897 uint32_t rdata = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ;
898
899 // Make sure all .idata$* section chunks are mapped as RDATA in order to
900 // be sorted into the same sections as our own synthesized .idata chunks.
901 fixPartialSectionChars(name: ".idata", chars: rdata);
902
903 bool hasIdata = false;
904 // Sort all .idata$* chunks, grouping chunks from the same library,
905 // with alphabetical ordering of the object files within a library.
906 for (auto it : partialSections) {
907 PartialSection *pSec = it.second;
908 if (!pSec->name.starts_with(Prefix: ".idata"))
909 continue;
910
911 if (!pSec->chunks.empty())
912 hasIdata = true;
913 llvm::stable_sort(Range&: pSec->chunks, C: [&](Chunk *s, Chunk *t) {
914 SectionChunk *sc1 = dyn_cast<SectionChunk>(Val: s);
915 SectionChunk *sc2 = dyn_cast<SectionChunk>(Val: t);
916 if (!sc1 || !sc2) {
917 // if SC1, order them ascending. If SC2 or both null,
918 // S is not less than T.
919 return sc1 != nullptr;
920 }
921 // Make a string with "libraryname/objectfile" for sorting, achieving
922 // both grouping by library and sorting of objects within a library,
923 // at once.
924 std::string key1 =
925 (sc1->file->parentName + "/" + sc1->file->getName()).str();
926 std::string key2 =
927 (sc2->file->parentName + "/" + sc2->file->getName()).str();
928 return key1 < key2;
929 });
930 }
931 return hasIdata;
932}
933
934// Add generated idata chunks, for imported symbols and DLLs, and a
935// terminator in .idata$2.
936void Writer::addSyntheticIdata() {
937 uint32_t rdata = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ;
938 idata.create(ctx);
939
940 // Add the .idata content in the right section groups, to allow
941 // chunks from other linked in object files to be grouped together.
942 // See Microsoft PE/COFF spec 5.4 for details.
943 auto add = [&](StringRef n, std::vector<Chunk *> &v) {
944 PartialSection *pSec = createPartialSection(name: n, outChars: rdata);
945 pSec->chunks.insert(position: pSec->chunks.end(), first: v.begin(), last: v.end());
946 };
947
948 // The loader assumes a specific order of data.
949 // Add each type in the correct order.
950 add(".idata$2", idata.dirs);
951 add(".idata$4", idata.lookups);
952 add(".idata$5", idata.addresses);
953 if (!idata.hints.empty())
954 add(".idata$6", idata.hints);
955 add(".idata$7", idata.dllNames);
956 if (!idata.auxIat.empty())
957 add(".idata$9", idata.auxIat);
958 if (!idata.auxIatCopy.empty())
959 add(".idata$a", idata.auxIatCopy);
960}
961
962void Writer::appendECImportTables() {
963 if (!isArm64EC(Machine: ctx.config.machine))
964 return;
965
966 const uint32_t rdata = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ;
967
968 // IAT is always placed at the beginning of .rdata section and its size
969 // is aligned to 4KB. Insert it here, after all merges all done.
970 if (PartialSection *importAddresses = findPartialSection(name: ".idata$5", outChars: rdata)) {
971 if (!rdataSec->chunks.empty())
972 rdataSec->chunks.front()->setAlignment(
973 std::max(a: 0x1000u, b: rdataSec->chunks.front()->getAlignment()));
974 iatSize = alignTo(Value: iatSize, Align: 0x1000);
975
976 rdataSec->chunks.insert(position: rdataSec->chunks.begin(),
977 first: importAddresses->chunks.begin(),
978 last: importAddresses->chunks.end());
979 rdataSec->contribSections.insert(position: rdataSec->contribSections.begin(),
980 x: importAddresses);
981 }
982
983 // The auxiliary IAT is always placed at the end of the .rdata section
984 // and is aligned to 4KB.
985 if (PartialSection *auxIat = findPartialSection(name: ".idata$9", outChars: rdata)) {
986 auxIat->chunks.front()->setAlignment(0x1000);
987 rdataSec->chunks.insert(position: rdataSec->chunks.end(), first: auxIat->chunks.begin(),
988 last: auxIat->chunks.end());
989 rdataSec->addContributingPartialSection(sec: auxIat);
990 }
991
992 if (!delayIdata.getAuxIat().empty()) {
993 delayIdata.getAuxIat().front()->setAlignment(0x1000);
994 rdataSec->chunks.insert(position: rdataSec->chunks.end(),
995 first: delayIdata.getAuxIat().begin(),
996 last: delayIdata.getAuxIat().end());
997 }
998}
999
1000// Locate the first Chunk and size of the import directory list and the
1001// IAT.
1002void Writer::locateImportTables() {
1003 uint32_t rdata = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ;
1004
1005 if (PartialSection *importDirs = findPartialSection(name: ".idata$2", outChars: rdata)) {
1006 if (!importDirs->chunks.empty())
1007 importTableStart = importDirs->chunks.front();
1008 for (Chunk *c : importDirs->chunks)
1009 importTableSize += c->getSize();
1010 }
1011
1012 if (PartialSection *importAddresses = findPartialSection(name: ".idata$5", outChars: rdata)) {
1013 if (!importAddresses->chunks.empty())
1014 iatStart = importAddresses->chunks.front();
1015 for (Chunk *c : importAddresses->chunks)
1016 iatSize += c->getSize();
1017 }
1018}
1019
1020// Return whether a SectionChunk's suffix (the dollar and any trailing
1021// suffix) should be removed and sorted into the main suffixless
1022// PartialSection.
1023static bool shouldStripSectionSuffix(SectionChunk *sc, StringRef name,
1024 bool isMinGW) {
1025 // On MinGW, comdat groups are formed by putting the comdat group name
1026 // after the '$' in the section name. For .eh_frame$<symbol>, that must
1027 // still be sorted before the .eh_frame trailer from crtend.o, thus just
1028 // strip the section name trailer. For other sections, such as
1029 // .tls$$<symbol> (where non-comdat .tls symbols are otherwise stored in
1030 // ".tls$"), they must be strictly sorted after .tls. And for the
1031 // hypothetical case of comdat .CRT$XCU, we definitely need to keep the
1032 // suffix for sorting. Thus, to play it safe, only strip the suffix for
1033 // the standard sections.
1034 if (!isMinGW)
1035 return false;
1036 if (!sc || !sc->isCOMDAT())
1037 return false;
1038 return name.starts_with(Prefix: ".text$") || name.starts_with(Prefix: ".data$") ||
1039 name.starts_with(Prefix: ".rdata$") || name.starts_with(Prefix: ".pdata$") ||
1040 name.starts_with(Prefix: ".xdata$") || name.starts_with(Prefix: ".eh_frame$");
1041}
1042
1043void Writer::sortSections() {
1044 if (!ctx.config.callGraphProfile.empty()) {
1045 DenseMap<const SectionChunk *, int> order =
1046 computeCallGraphProfileOrder(ctx);
1047 for (auto it : order) {
1048 if (DefinedRegular *sym = it.first->sym)
1049 ctx.config.order[sym->getName()] = it.second;
1050 }
1051 }
1052 if (!ctx.config.order.empty())
1053 for (auto it : partialSections)
1054 sortBySectionOrder(chunks&: it.second->chunks);
1055}
1056
1057void Writer::calculateStubDependentSizes() {
1058 if (ctx.config.dosStub)
1059 dosStubSize = alignTo(Value: ctx.config.dosStub->getBufferSize(), Align: 8);
1060 else
1061 dosStubSize = sizeof(dos_header) + sizeof(dosProgram);
1062
1063 coffHeaderOffset = dosStubSize + sizeof(PEMagic);
1064 peHeaderOffset = coffHeaderOffset + sizeof(coff_file_header);
1065 dataDirOffset64 = peHeaderOffset + sizeof(pe32plus_header);
1066}
1067
1068// Create output section objects and add them to OutputSections.
1069void Writer::createSections() {
1070 llvm::TimeTraceScope timeScope("Output sections");
1071 // First, create the builtin sections.
1072 const uint32_t data = IMAGE_SCN_CNT_INITIALIZED_DATA;
1073 const uint32_t bss = IMAGE_SCN_CNT_UNINITIALIZED_DATA;
1074 const uint32_t code = IMAGE_SCN_CNT_CODE;
1075 const uint32_t discardable = IMAGE_SCN_MEM_DISCARDABLE;
1076 const uint32_t r = IMAGE_SCN_MEM_READ;
1077 const uint32_t w = IMAGE_SCN_MEM_WRITE;
1078 const uint32_t x = IMAGE_SCN_MEM_EXECUTE;
1079
1080 SmallDenseMap<std::pair<StringRef, uint32_t>, OutputSection *> sections;
1081 auto createSection = [&](StringRef name, uint32_t outChars) {
1082 OutputSection *&sec = sections[{name, outChars}];
1083 if (!sec) {
1084 sec = make<OutputSection>(args&: name, args&: outChars);
1085 ctx.outputSections.push_back(x: sec);
1086 }
1087 return sec;
1088 };
1089
1090 // Try to match the section order used by link.exe.
1091 textSec = createSection(".text", code | r | x);
1092 if (isArm64EC(Machine: ctx.config.machine)) {
1093 wowthkSec = createSection(".wowthk", code | r | x);
1094 hexpthkSec = createSection(".hexpthk", code | r | x);
1095 }
1096 bssSec = createSection(".bss", bss | r | w);
1097 rdataSec = createSection(".rdata", data | r);
1098 buildidSec = createSection(".buildid", data | r);
1099 cvinfoSec = createSection(".cvinfo", data | r);
1100 dataSec = createSection(".data", data | r | w);
1101 pdataSec = createSection(".pdata", data | r);
1102 idataSec = createSection(".idata", data | r);
1103 edataSec = createSection(".edata", data | r);
1104 didatSec = createSection(".didat", data | r);
1105 if (isArm64EC(Machine: ctx.config.machine))
1106 a64xrmSec = createSection(".a64xrm", data | r);
1107 rsrcSec = createSection(".rsrc", data | r);
1108 relocSec = createSection(".reloc", data | discardable | r);
1109 ctorsSec = createSection(".ctors", data | r | w);
1110 dtorsSec = createSection(".dtors", data | r | w);
1111
1112 // Then bin chunks by name and output characteristics.
1113 for (Chunk *c : ctx.driver.getChunks()) {
1114 auto *sc = dyn_cast<SectionChunk>(Val: c);
1115 if (sc && !sc->live) {
1116 if (ctx.config.verbose)
1117 sc->printDiscardedMessage();
1118 continue;
1119 }
1120 if (auto *cc = dyn_cast<CommonChunk>(Val: c)) {
1121 if (!cc->live)
1122 continue;
1123 }
1124 StringRef name = c->getSectionName();
1125 if (shouldStripSectionSuffix(sc, name, isMinGW: ctx.config.mingw))
1126 name = name.split(Separator: '$').first;
1127
1128 if (name.starts_with(Prefix: ".tls"))
1129 tlsAlignment = std::max(a: tlsAlignment, b: c->getAlignment());
1130
1131 PartialSection *pSec = createPartialSection(name,
1132 outChars: c->getOutputCharacteristics());
1133 pSec->chunks.push_back(x: c);
1134 }
1135
1136 fixPartialSectionChars(name: ".rsrc", chars: data | r);
1137 fixPartialSectionChars(name: ".edata", chars: data | r);
1138 // Even in non MinGW cases, we might need to link against GNU import
1139 // libraries.
1140 bool hasIdata = fixGnuImportChunks();
1141 if (!idata.empty())
1142 hasIdata = true;
1143
1144 if (hasIdata)
1145 addSyntheticIdata();
1146
1147 sortSections();
1148
1149 if (hasIdata)
1150 locateImportTables();
1151
1152 for (auto thunk : ctx.symtab.sameAddressThunks)
1153 wowthkSec->addChunk(c: thunk);
1154
1155 // Then create an OutputSection for each section.
1156 // '$' and all following characters in input section names are
1157 // discarded when determining output section. So, .text$foo
1158 // contributes to .text, for example. See PE/COFF spec 3.2.
1159 for (auto it : partialSections) {
1160 PartialSection *pSec = it.second;
1161 StringRef name = getOutputSectionName(name: pSec->name, isMinGW: ctx.config.mingw);
1162 uint32_t outChars = pSec->characteristics;
1163
1164 if (name == ".CRT") {
1165 // In link.exe, there is a special case for the I386 target where .CRT
1166 // sections are treated as if they have output characteristics DATA | R if
1167 // their characteristics are DATA | R | W. This implements the same
1168 // special case for all architectures.
1169 outChars = data | r;
1170
1171 Log(ctx) << "Processing section " << pSec->name << " -> " << name;
1172
1173 sortCRTSectionChunks(chunks&: pSec->chunks);
1174 }
1175
1176 // ARM64EC has specific placement and alignment requirements for the IAT.
1177 // Delay adding its chunks until appendECImportTables.
1178 if (isArm64EC(Machine: ctx.config.machine) &&
1179 (pSec->name == ".idata$5" || pSec->name == ".idata$9"))
1180 continue;
1181
1182 OutputSection *sec = createSection(name, outChars);
1183 for (Chunk *c : pSec->chunks)
1184 sec->addChunk(c);
1185
1186 sec->addContributingPartialSection(sec: pSec);
1187 }
1188
1189 if (ctx.hybridSymtab) {
1190 if (OutputSection *sec = findSection(name: ".CRT"))
1191 sec->splitECChunks();
1192 }
1193
1194 // Finally, move some output sections to the end.
1195 auto sectionOrder = [&](const OutputSection *s) {
1196 // Move DISCARDABLE (or non-memory-mapped) sections to the end of file
1197 // because the loader cannot handle holes. Stripping can remove other
1198 // discardable ones than .reloc, which is first of them (created early).
1199 if (s->header.Characteristics & IMAGE_SCN_MEM_DISCARDABLE) {
1200 // Move discardable sections named .debug_ to the end, after other
1201 // discardable sections. Stripping only removes the sections named
1202 // .debug_* - thus try to avoid leaving holes after stripping.
1203 if (s->name.starts_with(Prefix: ".debug_"))
1204 return 3;
1205 return 2;
1206 }
1207 // .rsrc should come at the end of the non-discardable sections because its
1208 // size may change by the Win32 UpdateResources() function, causing
1209 // subsequent sections to move (see https://crbug.com/827082).
1210 if (s == rsrcSec)
1211 return 1;
1212 return 0;
1213 };
1214 llvm::stable_sort(Range&: ctx.outputSections,
1215 C: [&](const OutputSection *s, const OutputSection *t) {
1216 return sectionOrder(s) < sectionOrder(t);
1217 });
1218}
1219
1220void Writer::createMiscChunks() {
1221 llvm::TimeTraceScope timeScope("Misc chunks");
1222 Configuration *config = &ctx.config;
1223
1224 for (MergeChunk *p : ctx.mergeChunkInstances) {
1225 if (p) {
1226 p->finalizeContents();
1227 rdataSec->addChunk(c: p);
1228 }
1229 }
1230
1231 // Create thunks for locally-dllimported symbols.
1232 ctx.forEachSymtab(f: [&](SymbolTable &symtab) {
1233 if (!symtab.localImportChunks.empty()) {
1234 for (Chunk *c : symtab.localImportChunks)
1235 rdataSec->addChunk(c);
1236 }
1237 });
1238
1239 // Create Debug Information Chunks
1240 if (config->mingw) {
1241 debugInfoSec = buildidSec;
1242 } else if (!config->mergeDebugDirectory) {
1243 debugInfoSec = cvinfoSec;
1244 } else {
1245 debugInfoSec = rdataSec;
1246 }
1247 if (config->buildIDHash != BuildIDHash::None || config->debug ||
1248 config->repro || config->cetCompat || config->cetCompatStrict ||
1249 config->cetCompatIpValidationRelaxed ||
1250 config->cetCompatDynamicApisInProcOnly || config->hotpatchCompat) {
1251 debugDirectory =
1252 make<DebugDirectoryChunk>(args&: ctx, args&: debugRecords, args&: config->repro);
1253 debugDirectory->setAlignment(4);
1254 debugInfoSec->addChunk(c: debugDirectory);
1255 }
1256
1257 if (config->debug || config->buildIDHash != BuildIDHash::None) {
1258 // Make a CVDebugRecordChunk even when /DEBUG:CV is not specified. We
1259 // output a PDB no matter what, and this chunk provides the only means of
1260 // allowing a debugger to match a PDB and an executable. So we need it even
1261 // if we're ultimately not going to write CodeView data to the PDB.
1262 buildId = make<CVDebugRecordChunk>(args&: ctx);
1263 debugRecords.emplace_back(args: COFF::IMAGE_DEBUG_TYPE_CODEVIEW, args&: buildId);
1264 ctx.forEachSymtab(f: [&](SymbolTable &symtab) {
1265 if (Symbol *buildidSym = symtab.findUnderscore(name: "__buildid"))
1266 replaceSymbol<DefinedSynthetic>(s: buildidSym, arg: buildidSym->getName(),
1267 arg&: buildId, arg: 4);
1268 });
1269 }
1270
1271 uint16_t ex_characteristics_flags = 0;
1272 if (config->cetCompat)
1273 ex_characteristics_flags |= IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT;
1274 if (config->cetCompatStrict)
1275 ex_characteristics_flags |=
1276 IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT_STRICT_MODE;
1277 if (config->cetCompatIpValidationRelaxed)
1278 ex_characteristics_flags |=
1279 IMAGE_DLL_CHARACTERISTICS_EX_CET_SET_CONTEXT_IP_VALIDATION_RELAXED_MODE;
1280 if (config->cetCompatDynamicApisInProcOnly)
1281 ex_characteristics_flags |=
1282 IMAGE_DLL_CHARACTERISTICS_EX_CET_DYNAMIC_APIS_ALLOW_IN_PROC_ONLY;
1283 if (config->hotpatchCompat)
1284 ex_characteristics_flags |=
1285 IMAGE_DLL_CHARACTERISTICS_EX_HOTPATCH_COMPATIBLE;
1286
1287 if (ex_characteristics_flags) {
1288 debugRecords.emplace_back(
1289 args: COFF::IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS,
1290 args: make<ExtendedDllCharacteristicsChunk>(args&: ex_characteristics_flags));
1291 }
1292
1293 // Align and add each chunk referenced by the debug data directory.
1294 for (std::pair<COFF::DebugType, Chunk *> r : debugRecords) {
1295 r.second->setAlignment(4);
1296 debugInfoSec->addChunk(c: r.second);
1297 }
1298
1299 // Create SEH table. x86-only.
1300 if (config->safeSEH)
1301 createSEHTable();
1302
1303 // Create /guard:cf tables if requested.
1304 createGuardCFTables();
1305
1306 createECChunks();
1307
1308 if (config->autoImport)
1309 createRuntimePseudoRelocs();
1310
1311 if (config->mingw) {
1312 insertCtorDtorSymbols();
1313 insertBssDataStartEndSymbols();
1314 }
1315}
1316
1317// Create .idata section for the DLL-imported symbol table.
1318// The format of this section is inherently Windows-specific.
1319// IdataContents class abstracted away the details for us,
1320// so we just let it create chunks and add them to the section.
1321void Writer::createImportTables() {
1322 llvm::TimeTraceScope timeScope("Import tables");
1323 // Initialize DLLOrder so that import entries are ordered in
1324 // the same order as in the command line. (That affects DLL
1325 // initialization order, and this ordering is MSVC-compatible.)
1326 for (ImportFile *file : ctx.importFileInstances) {
1327 if (!file->live)
1328 continue;
1329
1330 std::string dll = StringRef(file->dllName).lower();
1331 ctx.config.dllOrder.try_emplace(k: dll, args: ctx.config.dllOrder.size());
1332
1333 if (file->impSym && !isa<DefinedImportData>(Val: file->impSym))
1334 Fatal(ctx) << file->symtab.printSymbol(sym: file->impSym) << " was replaced";
1335 DefinedImportData *impSym = cast_or_null<DefinedImportData>(Val: file->impSym);
1336 if (ctx.config.delayLoads.contains(key: StringRef(file->dllName).lower())) {
1337 if (!file->thunkSym)
1338 Fatal(ctx) << "cannot delay-load " << toString(file)
1339 << " due to import of data: "
1340 << file->symtab.printSymbol(sym: impSym);
1341 delayIdata.add(sym: impSym);
1342 } else {
1343 idata.add(sym: impSym);
1344 }
1345 }
1346}
1347
1348void Writer::appendImportThunks() {
1349 if (ctx.importFileInstances.empty())
1350 return;
1351
1352 llvm::TimeTraceScope timeScope("Import thunks");
1353 for (ImportFile *file : ctx.importFileInstances) {
1354 if (!file->live)
1355 continue;
1356
1357 if (file->thunkSym) {
1358 if (!isa<DefinedImportThunk>(Val: file->thunkSym))
1359 Fatal(ctx) << file->symtab.printSymbol(sym: file->thunkSym)
1360 << " was replaced";
1361 auto *chunk = cast<DefinedImportThunk>(Val: file->thunkSym)->getChunk();
1362 if (chunk->live)
1363 textSec->addChunk(c: chunk);
1364 }
1365
1366 if (file->auxThunkSym) {
1367 if (!isa<DefinedImportThunk>(Val: file->auxThunkSym))
1368 Fatal(ctx) << file->symtab.printSymbol(sym: file->auxThunkSym)
1369 << " was replaced";
1370 auto *chunk = cast<DefinedImportThunk>(Val: file->auxThunkSym)->getChunk();
1371 if (chunk->live)
1372 textSec->addChunk(c: chunk);
1373 }
1374
1375 if (file->impchkThunk)
1376 textSec->addChunk(c: file->impchkThunk);
1377 }
1378
1379 if (!delayIdata.empty()) {
1380 delayIdata.create();
1381 for (Chunk *c : delayIdata.getChunks())
1382 didatSec->addChunk(c);
1383 for (Chunk *c : delayIdata.getDataChunks())
1384 dataSec->addChunk(c);
1385 for (Chunk *c : delayIdata.getCodeChunks())
1386 textSec->addChunk(c);
1387 for (Chunk *c : delayIdata.getCodePData())
1388 pdataSec->addChunk(c);
1389 for (Chunk *c : delayIdata.getAuxIatCopy())
1390 rdataSec->addChunk(c);
1391 for (Chunk *c : delayIdata.getCodeUnwindInfo())
1392 rdataSec->addChunk(c);
1393 }
1394}
1395
1396void Writer::createExportTable() {
1397 llvm::TimeTraceScope timeScope("Export table");
1398 if (!edataSec->chunks.empty()) {
1399 // Allow using a custom built export table from input object files, instead
1400 // of having the linker synthesize the tables.
1401 if (!ctx.hybridSymtab) {
1402 ctx.symtab.edataStart = edataSec->chunks.front();
1403 ctx.symtab.edataEnd = edataSec->chunks.back();
1404 } else {
1405 // On hybrid target, split EC and native chunks.
1406 llvm::stable_sort(Range&: edataSec->chunks, C: [=](const Chunk *a, const Chunk *b) {
1407 return (a->getMachine() != ARM64) < (b->getMachine() != ARM64);
1408 });
1409
1410 for (auto chunk : edataSec->chunks) {
1411 if (chunk->getMachine() != ARM64) {
1412 ctx.symtab.edataStart = chunk;
1413 ctx.symtab.edataEnd = edataSec->chunks.back();
1414 break;
1415 }
1416
1417 if (!ctx.hybridSymtab->edataStart)
1418 ctx.hybridSymtab->edataStart = chunk;
1419 ctx.hybridSymtab->edataEnd = chunk;
1420 }
1421 }
1422 }
1423 ctx.forEachActiveSymtab(f: [&](SymbolTable &symtab) {
1424 if (symtab.edataStart) {
1425 if (symtab.hadExplicitExports)
1426 Warn(ctx) << "literal .edata sections override exports";
1427 } else if (!symtab.exports.empty()) {
1428 std::vector<Chunk *> edataChunks;
1429 createEdataChunks(symtab, chunks&: edataChunks);
1430 for (Chunk *c : edataChunks)
1431 edataSec->addChunk(c);
1432 symtab.edataStart = edataChunks.front();
1433 symtab.edataEnd = edataChunks.back();
1434 }
1435
1436 // Warn on exported deleting destructor.
1437 for (auto e : symtab.exports)
1438 if (e.sym && e.sym->getName().starts_with(Prefix: "??_G"))
1439 Warn(ctx) << "export of deleting dtor: " << toString(ctx, b&: *e.sym);
1440 });
1441}
1442
1443void Writer::removeUnusedSections() {
1444 llvm::TimeTraceScope timeScope("Remove unused sections");
1445 // Remove sections that we can be sure won't get content, to avoid
1446 // allocating space for their section headers.
1447 auto isUnused = [this](OutputSection *s) {
1448 if (s == relocSec)
1449 return false; // This section is populated later.
1450 // MergeChunks have zero size at this point, as their size is finalized
1451 // later. Only remove sections that have no Chunks at all.
1452 return s->chunks.empty();
1453 };
1454 llvm::erase_if(C&: ctx.outputSections, P: isUnused);
1455}
1456
1457void Writer::layoutSections() {
1458 llvm::TimeTraceScope timeScope("Layout sections");
1459 if (ctx.config.sectionOrder.empty())
1460 return;
1461
1462 llvm::stable_sort(Range&: ctx.outputSections,
1463 C: [this](const OutputSection *a, const OutputSection *b) {
1464 auto itA = ctx.config.sectionOrder.find(x: a->name.str());
1465 auto itB = ctx.config.sectionOrder.find(x: b->name.str());
1466 bool aInOrder = itA != ctx.config.sectionOrder.end();
1467 bool bInOrder = itB != ctx.config.sectionOrder.end();
1468
1469 // Put unspecified sections after all specified sections
1470 if (aInOrder && bInOrder) {
1471 return itA->second < itB->second;
1472 } else if (aInOrder && !bInOrder) {
1473 return true; // ordered sections come before unordered
1474 } else {
1475 // (!aInOrder && bInOrder): unordered comes after
1476 // ordered
1477 // (!aInOrder && !bInOrder): both unspecified, preserve
1478 // the original order
1479 return false;
1480 }
1481 });
1482}
1483
1484// The Windows loader doesn't seem to like empty sections,
1485// so we remove them if any.
1486void Writer::removeEmptySections() {
1487 llvm::TimeTraceScope timeScope("Remove empty sections");
1488 auto isEmpty = [](OutputSection *s) { return s->getVirtualSize() == 0; };
1489 llvm::erase_if(C&: ctx.outputSections, P: isEmpty);
1490}
1491
1492void Writer::assignOutputSectionIndices() {
1493 llvm::TimeTraceScope timeScope("Output sections indices");
1494 // Assign final output section indices, and assign each chunk to its output
1495 // section.
1496 uint32_t idx = 1;
1497 for (OutputSection *os : ctx.outputSections) {
1498 os->sectionIndex = idx;
1499 for (Chunk *c : os->chunks)
1500 c->setOutputSectionIdx(idx);
1501 ++idx;
1502 }
1503
1504 // Merge chunks are containers of chunks, so assign those an output section
1505 // too.
1506 for (MergeChunk *mc : ctx.mergeChunkInstances)
1507 if (mc)
1508 for (SectionChunk *sc : mc->sections)
1509 if (sc && sc->live)
1510 sc->setOutputSectionIdx(mc->getOutputSectionIdx());
1511}
1512
1513std::optional<coff_symbol16> Writer::createSymbol(Defined *def) {
1514 coff_symbol16 sym;
1515 switch (def->kind()) {
1516 case Symbol::DefinedAbsoluteKind: {
1517 auto *da = dyn_cast<DefinedAbsolute>(Val: def);
1518 // Note: COFF symbol can only store 32-bit values, so 64-bit absolute
1519 // values will be truncated.
1520 sym.Value = da->getVA();
1521 sym.SectionNumber = IMAGE_SYM_ABSOLUTE;
1522 break;
1523 }
1524 default: {
1525 // Don't write symbols that won't be written to the output to the symbol
1526 // table.
1527 // We also try to write DefinedSynthetic as a normal symbol. Some of these
1528 // symbols do point to an actual chunk, like __safe_se_handler_table. Others
1529 // like __ImageBase are outside of sections and thus cannot be represented.
1530 Chunk *c = def->getChunk();
1531 if (!c)
1532 return std::nullopt;
1533 OutputSection *os = ctx.getOutputSection(c);
1534 if (!os)
1535 return std::nullopt;
1536
1537 sym.Value = def->getRVA() - os->getRVA();
1538 sym.SectionNumber = os->sectionIndex;
1539 break;
1540 }
1541 }
1542
1543 // Symbols that are runtime pseudo relocations don't point to the actual
1544 // symbol data itself (as they are imported), but points to the IAT entry
1545 // instead. Avoid emitting them to the symbol table, as they can confuse
1546 // debuggers.
1547 if (def->isRuntimePseudoReloc)
1548 return std::nullopt;
1549
1550 StringRef name = def->getName();
1551 if (name.size() > COFF::NameSize) {
1552 sym.Name.Offset.Zeroes = 0;
1553 sym.Name.Offset.Offset = 0; // Filled in later.
1554 strtab.add(S: name);
1555 } else {
1556 memset(s: sym.Name.ShortName, c: 0, n: COFF::NameSize);
1557 memcpy(dest: sym.Name.ShortName, src: name.data(), n: name.size());
1558 }
1559
1560 if (auto *d = dyn_cast<DefinedCOFF>(Val: def)) {
1561 COFFSymbolRef ref = d->getCOFFSymbol();
1562 sym.Type = ref.getType();
1563 sym.StorageClass = ref.getStorageClass();
1564 } else if (def->kind() == Symbol::DefinedImportThunkKind) {
1565 sym.Type = (IMAGE_SYM_DTYPE_FUNCTION << SCT_COMPLEX_TYPE_SHIFT) |
1566 IMAGE_SYM_TYPE_NULL;
1567 sym.StorageClass = IMAGE_SYM_CLASS_EXTERNAL;
1568 } else {
1569 sym.Type = IMAGE_SYM_TYPE_NULL;
1570 sym.StorageClass = IMAGE_SYM_CLASS_EXTERNAL;
1571 }
1572 sym.NumberOfAuxSymbols = 0;
1573 return sym;
1574}
1575
1576void Writer::createSymbolAndStringTable() {
1577 llvm::TimeTraceScope timeScope("Symbol and string table");
1578 // PE/COFF images are limited to 8 byte section names. Longer names can be
1579 // supported by writing a non-standard string table, but this string table is
1580 // not mapped at runtime and the long names will therefore be inaccessible.
1581 // link.exe always truncates section names to 8 bytes, whereas binutils always
1582 // preserves long section names via the string table. LLD adopts a hybrid
1583 // solution where discardable sections have long names preserved and
1584 // non-discardable sections have their names truncated, to ensure that any
1585 // section which is mapped at runtime also has its name mapped at runtime.
1586 SmallVector<OutputSection *> longNameSections;
1587 for (OutputSection *sec : ctx.outputSections) {
1588 if (sec->name.size() <= COFF::NameSize)
1589 continue;
1590 if ((sec->header.Characteristics & IMAGE_SCN_MEM_DISCARDABLE) == 0)
1591 continue;
1592 if (ctx.config.warnLongSectionNames) {
1593 Warn(ctx)
1594 << "section name " << sec->name
1595 << " is longer than 8 characters and will use a non-standard string "
1596 "table";
1597 }
1598 // Put the section name in the begin of strtab so that its offset is less
1599 // than Max7DecimalOffset otherwise lldb/gdb will not read it.
1600 strtab.add(S: sec->name, /*Priority=*/UINT8_MAX);
1601 longNameSections.push_back(Elt: sec);
1602 }
1603
1604 std::vector<std::pair<size_t, StringRef>> longNameSymbols;
1605 if (ctx.config.writeSymtab) {
1606 for (ObjFile *file : ctx.objFileInstances) {
1607 for (Symbol *b : file->getSymbols()) {
1608 auto *d = dyn_cast_or_null<Defined>(Val: b);
1609 if (!d || d->writtenToSymtab)
1610 continue;
1611 d->writtenToSymtab = true;
1612 if (auto *dc = dyn_cast_or_null<DefinedCOFF>(Val: d)) {
1613 COFFSymbolRef symRef = dc->getCOFFSymbol();
1614 if (symRef.isSectionDefinition() ||
1615 symRef.getStorageClass() == COFF::IMAGE_SYM_CLASS_LABEL)
1616 continue;
1617 }
1618
1619 if (std::optional<coff_symbol16> sym = createSymbol(def: d)) {
1620 if (d->getName().size() > COFF::NameSize)
1621 longNameSymbols.emplace_back(args: outputSymtab.size(), args: d->getName());
1622 outputSymtab.push_back(x: *sym);
1623 }
1624
1625 if (auto *dthunk = dyn_cast<DefinedImportThunk>(Val: d)) {
1626 if (!dthunk->wrappedSym->writtenToSymtab) {
1627 dthunk->wrappedSym->writtenToSymtab = true;
1628 if (std::optional<coff_symbol16> sym =
1629 createSymbol(def: dthunk->wrappedSym)) {
1630 if (dthunk->wrappedSym->getName().size() > COFF::NameSize)
1631 longNameSymbols.emplace_back(args: outputSymtab.size(),
1632 args: dthunk->wrappedSym->getName());
1633 outputSymtab.push_back(x: *sym);
1634 }
1635 }
1636 }
1637 }
1638 }
1639 }
1640
1641 if (outputSymtab.empty() && strtab.empty())
1642 return;
1643
1644 strtab.finalize();
1645 for (OutputSection *sec : longNameSections)
1646 sec->setStringTableOff(strtab.getOffset(S: sec->name));
1647 for (auto P : longNameSymbols) {
1648 coff_symbol16 &sym = outputSymtab[P.first];
1649 sym.Name.Offset.Offset = strtab.getOffset(S: P.second);
1650 }
1651
1652 // We position the symbol table to be adjacent to the end of the last section.
1653 uint64_t fileOff = fileSize;
1654 pointerToSymbolTable = fileOff;
1655 fileOff += outputSymtab.size() * sizeof(coff_symbol16);
1656 fileOff += strtab.getSize();
1657 fileSize = alignTo(Value: fileOff, Align: ctx.config.fileAlign);
1658}
1659
1660StringRef Writer::getMergeDestination(StringRef fromSection,
1661 StringRef toSection) {
1662 StringSet<> names;
1663 while (true) {
1664 if (!names.insert(key: toSection).second)
1665 Fatal(ctx) << "/merge: cycle found for section '" << fromSection << "'";
1666 auto i = ctx.config.merge.find(x: toSection);
1667 if (i == ctx.config.merge.end())
1668 break;
1669 toSection = i->second;
1670 }
1671 return toSection;
1672}
1673
1674void Writer::mergeSection(const std::map<StringRef, StringRef>::value_type &p) {
1675 if (p.first == p.second)
1676 return;
1677
1678 StringRef toSection = getMergeDestination(fromSection: p.first, toSection: p.second);
1679
1680 OutputSection *from = findSection(name: p.first);
1681 OutputSection *to = findSection(name: toSection);
1682 if (!from)
1683 return;
1684 if (!to) {
1685 from->name = toSection;
1686 return;
1687 }
1688 to->merge(other: from);
1689}
1690
1691void Writer::mergeSections() {
1692 llvm::TimeTraceScope timeScope("Merge sections");
1693 if (!pdataSec->chunks.empty()) {
1694 if (isArm64EC(Machine: ctx.config.machine)) {
1695 // On ARM64EC .pdata may contain both ARM64 and X64 data. Split them by
1696 // sorting and store their regions separately.
1697 llvm::stable_sort(Range&: pdataSec->chunks, C: [=](const Chunk *a, const Chunk *b) {
1698 return (a->getMachine() == AMD64) < (b->getMachine() == AMD64);
1699 });
1700
1701 for (auto chunk : pdataSec->chunks) {
1702 if (chunk->getMachine() == AMD64) {
1703 hybridPdata.first = chunk;
1704 hybridPdata.last = pdataSec->chunks.back();
1705 break;
1706 }
1707
1708 if (!pdata.first)
1709 pdata.first = chunk;
1710 pdata.last = chunk;
1711 }
1712 } else {
1713 pdata.first = pdataSec->chunks.front();
1714 pdata.last = pdataSec->chunks.back();
1715 }
1716 }
1717
1718 for (auto &p : ctx.config.merge) {
1719 if (p.first != ".bss")
1720 mergeSection(p);
1721 }
1722
1723 // Because .bss contains all zeros, it should be merged at the end of
1724 // whatever section it is being merged into (usually .data) so that the image
1725 // need not actually contain all of the zeros.
1726 auto it = ctx.config.merge.find(x: ".bss");
1727 if (it != ctx.config.merge.end()) {
1728 // Resolve the final merge target name following the chain.
1729 StringRef toSection = getMergeDestination(fromSection: it->first, toSection: it->second);
1730 // Don't merge .bss into a shared section. MSVC link.exe keeps .bss
1731 // separate when the target has IMAGE_SCN_MEM_SHARED, preventing unexpected
1732 // sharing across processes.
1733 auto secIt = ctx.config.section.find(x: toSection);
1734 if (secIt == ctx.config.section.end() ||
1735 !(secIt->second & IMAGE_SCN_MEM_SHARED))
1736 mergeSection(p: {it->first, toSection});
1737 }
1738}
1739
1740// EC targets may have chunks of various architectures mixed together at this
1741// point. Group code chunks of the same architecture together by sorting chunks
1742// by their EC range type.
1743void Writer::sortECChunks() {
1744 if (!isArm64EC(Machine: ctx.config.machine))
1745 return;
1746
1747 for (OutputSection *sec : ctx.outputSections) {
1748 if (sec->isCodeSection())
1749 llvm::stable_sort(Range&: sec->chunks, C: [=](const Chunk *a, const Chunk *b) {
1750 std::optional<chpe_range_type> aType = a->getArm64ECRangeType(),
1751 bType = b->getArm64ECRangeType();
1752 return bType && (!aType || *aType < *bType);
1753 });
1754 }
1755}
1756
1757// Visits all sections to assign incremental, non-overlapping RVAs and
1758// file offsets.
1759void Writer::assignAddresses() {
1760 llvm::TimeTraceScope timeScope("Assign addresses");
1761 Configuration *config = &ctx.config;
1762
1763 // We need to create EC code map so that ECCodeMapChunk knows its size.
1764 // We do it here to make sure that we account for range extension chunks.
1765 createECCodeMap();
1766
1767 sizeOfHeaders = dosStubSize + sizeof(PEMagic) + sizeof(coff_file_header) +
1768 sizeof(data_directory) * numberOfDataDirectory +
1769 sizeof(coff_section) * ctx.outputSections.size();
1770 sizeOfHeaders +=
1771 config->is64() ? sizeof(pe32plus_header) : sizeof(pe32_header);
1772 sizeOfHeaders = alignTo(Value: sizeOfHeaders, Align: config->fileAlign);
1773 fileSize = sizeOfHeaders;
1774
1775 // The first page is kept unmapped.
1776 uint64_t rva = alignTo(Value: sizeOfHeaders, Align: config->align);
1777
1778 for (OutputSection *sec : ctx.outputSections) {
1779 llvm::TimeTraceScope timeScope("Section: ", sec->name);
1780 if (sec == relocSec) {
1781 sec->chunks.clear();
1782 addBaserels();
1783 if (ctx.dynamicRelocs) {
1784 ctx.dynamicRelocs->finalize();
1785 relocSec->addChunk(c: ctx.dynamicRelocs);
1786 }
1787 }
1788 uint64_t rawSize = 0, virtualSize = 0;
1789 sec->header.VirtualAddress = rva;
1790
1791 // If /FUNCTIONPADMIN is used, functions are padded in order to create a
1792 // hotpatchable image.
1793 uint32_t padding = sec->isCodeSection() ? config->functionPadMin : 0;
1794 std::optional<chpe_range_type> prevECRange;
1795
1796 for (Chunk *c : sec->chunks) {
1797 // Alignment EC code range baudaries.
1798 if (isArm64EC(Machine: ctx.config.machine) && sec->isCodeSection()) {
1799 std::optional<chpe_range_type> rangeType = c->getArm64ECRangeType();
1800 if (rangeType != prevECRange) {
1801 virtualSize = alignTo(Value: virtualSize, Align: 4096);
1802 prevECRange = rangeType;
1803 }
1804 }
1805 if (padding && c->isHotPatchable())
1806 virtualSize += padding;
1807 // If chunk has EC entry thunk, reserve a space for an offset to the
1808 // thunk.
1809 if (c->getEntryThunk())
1810 virtualSize += sizeof(uint32_t);
1811 virtualSize = alignTo(Value: virtualSize, Align: c->getAlignment());
1812 c->setRVA(rva + virtualSize);
1813 virtualSize += c->getSize();
1814 if (c->hasData)
1815 rawSize = alignTo(Value: virtualSize, Align: config->fileAlign);
1816 }
1817 if (virtualSize > UINT32_MAX)
1818 Err(ctx) << "section larger than 4 GiB: " << sec->name;
1819 sec->header.VirtualSize = virtualSize;
1820 sec->header.SizeOfRawData = rawSize;
1821 if (rawSize != 0)
1822 sec->header.PointerToRawData = fileSize;
1823 rva += alignTo(Value: virtualSize, Align: config->align);
1824 fileSize += alignTo(Value: rawSize, Align: config->fileAlign);
1825 }
1826 sizeOfImage = alignTo(Value: rva, Align: config->align);
1827
1828 // Assign addresses to sections in MergeChunks.
1829 for (MergeChunk *mc : ctx.mergeChunkInstances)
1830 if (mc)
1831 mc->assignSubsectionRVAs();
1832}
1833
1834template <typename PEHeaderTy> void Writer::writeHeader() {
1835 // Write DOS header. For backwards compatibility, the first part of a PE/COFF
1836 // executable consists of an MS-DOS MZ executable. If the executable is run
1837 // under DOS, that program gets run (usually to just print an error message).
1838 // When run under Windows, the loader looks at AddressOfNewExeHeader and uses
1839 // the PE header instead.
1840 Configuration *config = &ctx.config;
1841
1842 uint8_t *buf = buffer->getBufferStart();
1843 auto *dos = reinterpret_cast<dos_header *>(buf);
1844
1845 // Write DOS program.
1846 if (config->dosStub) {
1847 memcpy(dest: buf, src: config->dosStub->getBufferStart(),
1848 n: config->dosStub->getBufferSize());
1849 // MS link.exe accepts an invalid `e_lfanew` (AddressOfNewExeHeader) and
1850 // updates it automatically. Replicate the same behaviour.
1851 dos->AddressOfNewExeHeader = alignTo(Value: config->dosStub->getBufferSize(), Align: 8);
1852 // Unlike MS link.exe, LLD accepts non-8-byte-aligned stubs.
1853 // In that case, we add zero paddings ourselves.
1854 buf += alignTo(Value: config->dosStub->getBufferSize(), Align: 8);
1855 } else {
1856 buf += sizeof(dos_header);
1857 dos->Magic[0] = 'M';
1858 dos->Magic[1] = 'Z';
1859 dos->UsedBytesInTheLastPage = dosStubSize % 512;
1860 dos->FileSizeInPages = divideCeil(Numerator: dosStubSize, Denominator: 512);
1861 dos->HeaderSizeInParagraphs = sizeof(dos_header) / 16;
1862
1863 dos->AddressOfRelocationTable = sizeof(dos_header);
1864 dos->AddressOfNewExeHeader = dosStubSize;
1865
1866 memcpy(dest: buf, src: dosProgram, n: sizeof(dosProgram));
1867 buf += sizeof(dosProgram);
1868 }
1869
1870 // Make sure DOS stub is aligned to 8 bytes at this point
1871 assert((buf - buffer->getBufferStart()) % 8 == 0);
1872
1873 // Write PE magic
1874 memcpy(dest: buf, src: PEMagic, n: sizeof(PEMagic));
1875 buf += sizeof(PEMagic);
1876
1877 // Write COFF header
1878 assert(coffHeaderOffset ==
1879 static_cast<size_t>(buf - buffer->getBufferStart()));
1880 auto *coff = reinterpret_cast<coff_file_header *>(buf);
1881 buf += sizeof(*coff);
1882 SymbolTable &symtab =
1883 ctx.config.machine == ARM64X ? *ctx.hybridSymtab : ctx.symtab;
1884 coff->Machine = symtab.isEC() ? AMD64 : symtab.machine;
1885 coff->NumberOfSections = ctx.outputSections.size();
1886 coff->Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE;
1887 if (config->largeAddressAware)
1888 coff->Characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE;
1889 if (!config->is64())
1890 coff->Characteristics |= IMAGE_FILE_32BIT_MACHINE;
1891 if (config->dll)
1892 coff->Characteristics |= IMAGE_FILE_DLL;
1893 if (config->driverUponly)
1894 coff->Characteristics |= IMAGE_FILE_UP_SYSTEM_ONLY;
1895 if (!config->relocatable)
1896 coff->Characteristics |= IMAGE_FILE_RELOCS_STRIPPED;
1897 if (config->swaprunCD)
1898 coff->Characteristics |= IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP;
1899 if (config->swaprunNet)
1900 coff->Characteristics |= IMAGE_FILE_NET_RUN_FROM_SWAP;
1901 coff->SizeOfOptionalHeader =
1902 sizeof(PEHeaderTy) + sizeof(data_directory) * numberOfDataDirectory;
1903
1904 // Write PE header
1905 assert(peHeaderOffset == static_cast<size_t>(buf - buffer->getBufferStart()));
1906 auto *pe = reinterpret_cast<PEHeaderTy *>(buf);
1907 buf += sizeof(*pe);
1908 pe->Magic = config->is64() ? PE32Header::PE32_PLUS : PE32Header::PE32;
1909
1910 // If {Major,Minor}LinkerVersion is left at 0.0, then for some
1911 // reason signing the resulting PE file with Authenticode produces a
1912 // signature that fails to validate on Windows 7 (but is OK on 10).
1913 // Set it to 14.0, which is what VS2015 outputs, and which avoids
1914 // that problem.
1915 pe->MajorLinkerVersion = 14;
1916 pe->MinorLinkerVersion = 0;
1917
1918 pe->ImageBase = config->imageBase;
1919 pe->SectionAlignment = config->align;
1920 pe->FileAlignment = config->fileAlign;
1921 pe->MajorImageVersion = config->majorImageVersion;
1922 pe->MinorImageVersion = config->minorImageVersion;
1923 pe->MajorOperatingSystemVersion = config->majorOSVersion;
1924 pe->MinorOperatingSystemVersion = config->minorOSVersion;
1925 pe->MajorSubsystemVersion = config->majorSubsystemVersion;
1926 pe->MinorSubsystemVersion = config->minorSubsystemVersion;
1927 pe->Subsystem = config->subsystem;
1928 pe->SizeOfImage = sizeOfImage;
1929 pe->SizeOfHeaders = sizeOfHeaders;
1930 if (!config->noEntry) {
1931 Defined *entry = cast<Defined>(Val: symtab.entry);
1932 pe->AddressOfEntryPoint = entry->getRVA();
1933 // Pointer to thumb code must have the LSB set, so adjust it.
1934 if (config->machine == ARMNT)
1935 pe->AddressOfEntryPoint |= 1;
1936 }
1937 pe->SizeOfStackReserve = config->stackReserve;
1938 pe->SizeOfStackCommit = config->stackCommit;
1939 pe->SizeOfHeapReserve = config->heapReserve;
1940 pe->SizeOfHeapCommit = config->heapCommit;
1941 if (config->appContainer)
1942 pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_APPCONTAINER;
1943 if (config->driverWdm)
1944 pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER;
1945 if (config->dynamicBase)
1946 pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE;
1947 if (config->highEntropyVA)
1948 pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA;
1949 if (!config->allowBind)
1950 pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_BIND;
1951 if (config->nxCompat)
1952 pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NX_COMPAT;
1953 if (!config->allowIsolation)
1954 pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION;
1955 if (config->guardCF != GuardCFLevel::Off)
1956 pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_GUARD_CF;
1957 if (config->integrityCheck)
1958 pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY;
1959 if (setNoSEHCharacteristic || config->noSEH)
1960 pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_SEH;
1961 if (config->terminalServerAware)
1962 pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE;
1963 pe->NumberOfRvaAndSize = numberOfDataDirectory;
1964 if (textSec->getVirtualSize()) {
1965 pe->BaseOfCode = textSec->getRVA();
1966 pe->SizeOfCode = textSec->getRawSize();
1967 }
1968 pe->SizeOfInitializedData = getSizeOfInitializedData();
1969
1970 // Write data directory
1971 assert(!ctx.config.is64() ||
1972 dataDirOffset64 ==
1973 static_cast<size_t>(buf - buffer->getBufferStart()));
1974 auto *dir = reinterpret_cast<data_directory *>(buf);
1975 buf += sizeof(*dir) * numberOfDataDirectory;
1976 if (symtab.edataStart) {
1977 dir[EXPORT_TABLE].RelativeVirtualAddress = symtab.edataStart->getRVA();
1978 dir[EXPORT_TABLE].Size = symtab.edataEnd->getRVA() +
1979 symtab.edataEnd->getSize() -
1980 symtab.edataStart->getRVA();
1981 }
1982 if (importTableStart) {
1983 dir[IMPORT_TABLE].RelativeVirtualAddress = importTableStart->getRVA();
1984 dir[IMPORT_TABLE].Size = importTableSize;
1985 }
1986 if (iatStart) {
1987 dir[IAT].RelativeVirtualAddress = iatStart->getRVA();
1988 dir[IAT].Size = iatSize;
1989 }
1990 if (rsrcSec->getVirtualSize()) {
1991 dir[RESOURCE_TABLE].RelativeVirtualAddress = rsrcSec->getRVA();
1992 dir[RESOURCE_TABLE].Size = rsrcSec->getVirtualSize();
1993 }
1994 // ARM64EC (but not ARM64X) contains x86_64 exception table in data directory.
1995 ChunkRange &exceptionTable =
1996 ctx.config.machine == ARM64EC ? hybridPdata : pdata;
1997 if (exceptionTable.first) {
1998 dir[EXCEPTION_TABLE].RelativeVirtualAddress =
1999 exceptionTable.first->getRVA();
2000 dir[EXCEPTION_TABLE].Size = exceptionTable.last->getRVA() +
2001 exceptionTable.last->getSize() -
2002 exceptionTable.first->getRVA();
2003 }
2004 size_t relocSize = relocSec->getVirtualSize();
2005 if (ctx.dynamicRelocs)
2006 relocSize -= ctx.dynamicRelocs->getSize();
2007 if (relocSize) {
2008 dir[BASE_RELOCATION_TABLE].RelativeVirtualAddress = relocSec->getRVA();
2009 dir[BASE_RELOCATION_TABLE].Size = relocSize;
2010 }
2011 if (Symbol *sym = symtab.findUnderscore(name: "_tls_used")) {
2012 if (Defined *b = dyn_cast<Defined>(Val: sym)) {
2013 dir[TLS_TABLE].RelativeVirtualAddress = b->getRVA();
2014 dir[TLS_TABLE].Size = config->is64()
2015 ? sizeof(object::coff_tls_directory64)
2016 : sizeof(object::coff_tls_directory32);
2017 }
2018 }
2019 if (debugDirectory) {
2020 dir[DEBUG_DIRECTORY].RelativeVirtualAddress = debugDirectory->getRVA();
2021 dir[DEBUG_DIRECTORY].Size = debugDirectory->getSize();
2022 }
2023 if (symtab.loadConfigSym) {
2024 dir[LOAD_CONFIG_TABLE].RelativeVirtualAddress =
2025 symtab.loadConfigSym->getRVA();
2026 dir[LOAD_CONFIG_TABLE].Size = symtab.loadConfigSize;
2027 }
2028 if (!delayIdata.empty()) {
2029 dir[DELAY_IMPORT_DESCRIPTOR].RelativeVirtualAddress =
2030 delayIdata.getDirRVA();
2031 dir[DELAY_IMPORT_DESCRIPTOR].Size = delayIdata.getDirSize();
2032 }
2033
2034 // Write section table
2035 for (OutputSection *sec : ctx.outputSections) {
2036 sec->writeHeaderTo(buf, isDebug: config->debug);
2037 buf += sizeof(coff_section);
2038 }
2039 sectionTable = ArrayRef<uint8_t>(
2040 buf - ctx.outputSections.size() * sizeof(coff_section), buf);
2041
2042 if (outputSymtab.empty() && strtab.empty())
2043 return;
2044
2045 coff->PointerToSymbolTable = pointerToSymbolTable;
2046 uint32_t numberOfSymbols = outputSymtab.size();
2047 coff->NumberOfSymbols = numberOfSymbols;
2048 auto *symbolTable = reinterpret_cast<coff_symbol16 *>(
2049 buffer->getBufferStart() + coff->PointerToSymbolTable);
2050 for (size_t i = 0; i != numberOfSymbols; ++i)
2051 symbolTable[i] = outputSymtab[i];
2052 // Create the string table, it follows immediately after the symbol table.
2053 // The first 4 bytes is length including itself.
2054 buf = reinterpret_cast<uint8_t *>(&symbolTable[numberOfSymbols]);
2055 strtab.write(Buf: buf);
2056}
2057
2058void Writer::openFile(StringRef path) {
2059 buffer = CHECK(
2060 FileOutputBuffer::create(path, fileSize, FileOutputBuffer::F_executable),
2061 "failed to open " + path);
2062}
2063
2064void Writer::createSEHTable() {
2065 SymbolRVASet handlers;
2066 for (ObjFile *file : ctx.objFileInstances) {
2067 if (!file->hasSafeSEH())
2068 Err(ctx) << "/safeseh: " << file->getName()
2069 << " is not compatible with SEH";
2070 markSymbolsForRVATable(file, symIdxChunks: file->getSXDataChunks(), tableSymbols&: handlers);
2071 }
2072
2073 // Set the "no SEH" characteristic if there really were no handlers, or if
2074 // there is no load config object to point to the table of handlers.
2075 setNoSEHCharacteristic =
2076 handlers.empty() || !ctx.symtab.findUnderscore(name: "_load_config_used");
2077
2078 maybeAddRVATable(tableSymbols: std::move(handlers), tableSym: "__safe_se_handler_table",
2079 countSym: "__safe_se_handler_count");
2080}
2081
2082// Add a symbol to an RVA set. Two symbols may have the same RVA, but an RVA set
2083// cannot contain duplicates. Therefore, the set is uniqued by Chunk and the
2084// symbol's offset into that Chunk.
2085static void addSymbolToRVASet(SymbolRVASet &rvaSet, Defined *s) {
2086 Chunk *c = s->getChunk();
2087 if (!c)
2088 return;
2089 if (auto *sc = dyn_cast<SectionChunk>(Val: c))
2090 c = sc->repl; // Look through ICF replacement.
2091 uint32_t off = s->getRVA() - (c ? c->getRVA() : 0);
2092 rvaSet.insert(V: {.inputChunk: c, .offset: off});
2093}
2094
2095// Given a symbol, add it to the GFIDs table if it is a live, defined, function
2096// symbol in an executable section.
2097static void maybeAddAddressTakenFunction(SymbolRVASet &addressTakenSyms,
2098 Symbol *s) {
2099 if (!s)
2100 return;
2101
2102 switch (s->kind()) {
2103 case Symbol::DefinedLocalImportKind:
2104 case Symbol::DefinedImportDataKind:
2105 // Defines an __imp_ pointer, so it is data, so it is ignored.
2106 break;
2107 case Symbol::DefinedCommonKind:
2108 // Common is always data, so it is ignored.
2109 break;
2110 case Symbol::DefinedAbsoluteKind:
2111 // Absolute is never code, synthetic generally isn't and usually isn't
2112 // determinable.
2113 break;
2114 case Symbol::DefinedSyntheticKind:
2115 // For EC export thunks, mark both the thunk itself and its target.
2116 if (auto expChunk = dyn_cast_or_null<ECExportThunkChunk>(
2117 Val: cast<Defined>(Val: s)->getChunk())) {
2118 addSymbolToRVASet(rvaSet&: addressTakenSyms, s: cast<Defined>(Val: s));
2119 addSymbolToRVASet(rvaSet&: addressTakenSyms, s: expChunk->target);
2120 }
2121 break;
2122 case Symbol::LazyArchiveKind:
2123 case Symbol::LazyObjectKind:
2124 case Symbol::LazyDLLSymbolKind:
2125 case Symbol::UndefinedKind:
2126 // Undefined symbols resolve to zero, so they don't have an RVA. Lazy
2127 // symbols shouldn't have relocations.
2128 break;
2129
2130 case Symbol::DefinedImportThunkKind:
2131 // Thunks are always code, include them.
2132 addSymbolToRVASet(rvaSet&: addressTakenSyms, s: cast<Defined>(Val: s));
2133 break;
2134
2135 case Symbol::DefinedRegularKind: {
2136 // This is a regular, defined, symbol from a COFF file. Mark the symbol as
2137 // address taken if the symbol type is function and it's in an executable
2138 // section.
2139 auto *d = cast<DefinedRegular>(Val: s);
2140 if (d->getCOFFSymbol().getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION) {
2141 SectionChunk *sc = dyn_cast<SectionChunk>(Val: d->getChunk());
2142 if (sc && sc->live &&
2143 sc->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE)
2144 addSymbolToRVASet(rvaSet&: addressTakenSyms, s: d);
2145 }
2146 break;
2147 }
2148 }
2149}
2150
2151// Visit all relocations from all section contributions of this object file and
2152// mark the relocation target as address-taken.
2153void Writer::markSymbolsWithRelocations(ObjFile *file,
2154 SymbolRVASet &usedSymbols) {
2155 for (Chunk *c : file->getChunks()) {
2156 // We only care about live section chunks. Common chunks and other chunks
2157 // don't generally contain relocations.
2158 SectionChunk *sc = dyn_cast<SectionChunk>(Val: c);
2159 if (!sc || !sc->live)
2160 continue;
2161
2162 for (const coff_relocation &reloc : sc->getRelocs()) {
2163 if (ctx.config.machine == I386 &&
2164 reloc.Type == COFF::IMAGE_REL_I386_REL32)
2165 // Ignore relative relocations on x86. On x86_64 they can't be ignored
2166 // since they're also used to compute absolute addresses.
2167 continue;
2168
2169 Symbol *ref = sc->file->getSymbol(symbolIndex: reloc.SymbolTableIndex);
2170 maybeAddAddressTakenFunction(addressTakenSyms&: usedSymbols, s: ref);
2171 }
2172 }
2173}
2174
2175// Create the guard function id table. This is a table of RVAs of all
2176// address-taken functions. It is sorted and uniqued, just like the safe SEH
2177// table.
2178void Writer::createGuardCFTables() {
2179 Configuration *config = &ctx.config;
2180
2181 if (config->guardCF == GuardCFLevel::Off) {
2182 // MSVC marks the entire image as instrumented if any input object was built
2183 // with /guard:cf.
2184 for (ObjFile *file : ctx.objFileInstances) {
2185 if (file->hasGuardCF()) {
2186 ctx.forEachSymtab(f: [&](SymbolTable &symtab) {
2187 Symbol *flagSym = symtab.findUnderscore(name: "__guard_flags");
2188 cast<DefinedAbsolute>(Val: flagSym)->setVA(
2189 uint32_t(GuardFlags::CF_INSTRUMENTED));
2190 });
2191 break;
2192 }
2193 }
2194 return;
2195 }
2196
2197 SymbolRVASet addressTakenSyms;
2198 SymbolRVASet giatsRVASet;
2199 std::vector<Symbol *> giatsSymbols;
2200 SymbolRVASet longJmpTargets;
2201 SymbolRVASet ehContTargets;
2202 for (ObjFile *file : ctx.objFileInstances) {
2203 // If the object was compiled with /guard:cf, the address taken symbols
2204 // are in .gfids$y sections, and the longjmp targets are in .gljmp$y
2205 // sections. If the object was not compiled with /guard:cf, we assume there
2206 // were no setjmp targets, and that all code symbols with relocations are
2207 // possibly address-taken.
2208 if (file->hasGuardCF()) {
2209 markSymbolsForRVATable(file, symIdxChunks: file->getGuardFidChunks(), tableSymbols&: addressTakenSyms);
2210 markSymbolsForRVATable(file, symIdxChunks: file->getGuardIATChunks(), tableSymbols&: giatsRVASet);
2211 getSymbolsFromSections(file, symIdxChunks: file->getGuardIATChunks(), symbols&: giatsSymbols);
2212 markSymbolsForRVATable(file, symIdxChunks: file->getGuardLJmpChunks(), tableSymbols&: longJmpTargets);
2213 } else {
2214 markSymbolsWithRelocations(file, usedSymbols&: addressTakenSyms);
2215 }
2216 // If the object was compiled with /guard:ehcont, the ehcont targets are in
2217 // .gehcont$y sections.
2218 if (file->hasGuardEHCont())
2219 markSymbolsForRVATable(file, symIdxChunks: file->getGuardEHContChunks(), tableSymbols&: ehContTargets);
2220 }
2221
2222 // Mark the image entry as address-taken.
2223 ctx.forEachSymtab(f: [&](SymbolTable &symtab) {
2224 if (symtab.entry)
2225 maybeAddAddressTakenFunction(addressTakenSyms, s: symtab.entry);
2226
2227 // Mark exported symbols in executable sections as address-taken.
2228 for (Export &e : symtab.exports)
2229 maybeAddAddressTakenFunction(addressTakenSyms, s: e.sym);
2230 });
2231
2232 // For each entry in the .giats table, check if it has a corresponding load
2233 // thunk (e.g. because the DLL that defines it will be delay-loaded) and, if
2234 // so, add the load thunk to the address taken (.gfids) table.
2235 for (Symbol *s : giatsSymbols) {
2236 if (auto *di = dyn_cast<DefinedImportData>(Val: s)) {
2237 if (di->loadThunkSym)
2238 addSymbolToRVASet(rvaSet&: addressTakenSyms, s: di->loadThunkSym);
2239 }
2240 }
2241
2242 // Ensure sections referenced in the gfid table are 16-byte aligned.
2243 for (const ChunkAndOffset &c : addressTakenSyms)
2244 if (c.inputChunk->getAlignment() < 16)
2245 c.inputChunk->setAlignment(16);
2246
2247 maybeAddRVATable(tableSymbols: std::move(addressTakenSyms), tableSym: "__guard_fids_table",
2248 countSym: "__guard_fids_count");
2249
2250 // Add the Guard Address Taken IAT Entry Table (.giats).
2251 maybeAddRVATable(tableSymbols: std::move(giatsRVASet), tableSym: "__guard_iat_table",
2252 countSym: "__guard_iat_count");
2253
2254 // Add the longjmp target table unless the user told us not to.
2255 if (config->guardCF & GuardCFLevel::LongJmp)
2256 maybeAddRVATable(tableSymbols: std::move(longJmpTargets), tableSym: "__guard_longjmp_table",
2257 countSym: "__guard_longjmp_count");
2258
2259 // Add the ehcont target table unless the user told us not to.
2260 if (config->guardCF & GuardCFLevel::EHCont)
2261 maybeAddRVATable(tableSymbols: std::move(ehContTargets), tableSym: "__guard_eh_cont_table",
2262 countSym: "__guard_eh_cont_count");
2263
2264 // Set __guard_flags, which will be used in the load config to indicate that
2265 // /guard:cf was enabled.
2266 uint32_t guardFlags = uint32_t(GuardFlags::CF_INSTRUMENTED) |
2267 uint32_t(GuardFlags::CF_FUNCTION_TABLE_PRESENT);
2268 if (config->guardCF & GuardCFLevel::LongJmp)
2269 guardFlags |= uint32_t(GuardFlags::CF_LONGJUMP_TABLE_PRESENT);
2270 if (config->guardCF & GuardCFLevel::EHCont)
2271 guardFlags |= uint32_t(GuardFlags::EH_CONTINUATION_TABLE_PRESENT);
2272 ctx.forEachSymtab(f: [guardFlags](SymbolTable &symtab) {
2273 Symbol *flagSym = symtab.findUnderscore(name: "__guard_flags");
2274 cast<DefinedAbsolute>(Val: flagSym)->setVA(guardFlags);
2275 });
2276}
2277
2278// Take a list of input sections containing symbol table indices and add those
2279// symbols to a vector. The challenge is that symbol RVAs are not known and
2280// depend on the table size, so we can't directly build a set of integers.
2281void Writer::getSymbolsFromSections(ObjFile *file,
2282 ArrayRef<SectionChunk *> symIdxChunks,
2283 std::vector<Symbol *> &symbols) {
2284 for (SectionChunk *c : symIdxChunks) {
2285 // Skip sections discarded by linker GC. This comes up when a .gfids section
2286 // is associated with something like a vtable and the vtable is discarded.
2287 // In this case, the associated gfids section is discarded, and we don't
2288 // mark the virtual member functions as address-taken by the vtable.
2289 if (!c->live)
2290 continue;
2291
2292 // Validate that the contents look like symbol table indices.
2293 ArrayRef<uint8_t> data = c->getContents();
2294 if (data.size() % 4 != 0) {
2295 Warn(ctx) << "ignoring " << c->getSectionName()
2296 << " symbol table index section in object " << file;
2297 continue;
2298 }
2299
2300 // Read each symbol table index and check if that symbol was included in the
2301 // final link. If so, add it to the vector of symbols.
2302 ArrayRef<ulittle32_t> symIndices(
2303 reinterpret_cast<const ulittle32_t *>(data.data()), data.size() / 4);
2304 ArrayRef<Symbol *> objSymbols = file->getSymbols();
2305 for (uint32_t symIndex : symIndices) {
2306 if (symIndex >= objSymbols.size()) {
2307 Warn(ctx) << "ignoring invalid symbol table index in section "
2308 << c->getSectionName() << " in object " << file;
2309 continue;
2310 }
2311 if (Symbol *s = objSymbols[symIndex]) {
2312 if (s->isLive())
2313 symbols.push_back(x: cast<Symbol>(Val: s));
2314 }
2315 }
2316 }
2317}
2318
2319// Take a list of input sections containing symbol table indices and add those
2320// symbols to an RVA table.
2321void Writer::markSymbolsForRVATable(ObjFile *file,
2322 ArrayRef<SectionChunk *> symIdxChunks,
2323 SymbolRVASet &tableSymbols) {
2324 std::vector<Symbol *> syms;
2325 getSymbolsFromSections(file, symIdxChunks, symbols&: syms);
2326
2327 for (Symbol *s : syms)
2328 addSymbolToRVASet(rvaSet&: tableSymbols, s: cast<Defined>(Val: s));
2329}
2330
2331// Replace the absolute table symbol with a synthetic symbol pointing to
2332// tableChunk so that we can emit base relocations for it and resolve section
2333// relative relocations.
2334void Writer::maybeAddRVATable(SymbolRVASet tableSymbols, StringRef tableSym,
2335 StringRef countSym, bool hasFlag) {
2336 if (tableSymbols.empty())
2337 return;
2338
2339 NonSectionChunk *tableChunk;
2340 if (hasFlag)
2341 tableChunk = make<RVAFlagTableChunk>(args: std::move(tableSymbols));
2342 else
2343 tableChunk = make<RVATableChunk>(args: std::move(tableSymbols));
2344 rdataSec->addChunk(c: tableChunk);
2345
2346 ctx.forEachSymtab(f: [&](SymbolTable &symtab) {
2347 Symbol *t = symtab.findUnderscore(name: tableSym);
2348 Symbol *c = symtab.findUnderscore(name: countSym);
2349 replaceSymbol<DefinedSynthetic>(s: t, arg: t->getName(), arg&: tableChunk);
2350 cast<DefinedAbsolute>(Val: c)->setVA(tableChunk->getSize() / (hasFlag ? 5 : 4));
2351 });
2352}
2353
2354// Create CHPE metadata chunks.
2355void Writer::createECChunks() {
2356 if (!ctx.symtab.isEC())
2357 return;
2358
2359 for (Symbol *s : ctx.symtab.expSymbols) {
2360 auto sym = dyn_cast<Defined>(Val: s);
2361 if (!sym || !sym->getChunk())
2362 continue;
2363 if (auto thunk = dyn_cast<ECExportThunkChunk>(Val: sym->getChunk())) {
2364 hexpthkSec->addChunk(c: thunk);
2365 exportThunks.push_back(x: {thunk, thunk->target});
2366 } else if (auto def = dyn_cast<DefinedRegular>(Val: sym)) {
2367 // Allow section chunk to be treated as an export thunk if it looks like
2368 // one.
2369 SectionChunk *chunk = def->getChunk();
2370 if (!chunk->live || chunk->getMachine() != AMD64)
2371 continue;
2372 assert(sym->getName().starts_with("EXP+"));
2373 StringRef targetName = sym->getName().substr(Start: strlen(s: "EXP+"));
2374 // If EXP+#foo is an export thunk of a hybrid patchable function,
2375 // we should use the #foo$hp_target symbol as the redirection target.
2376 // First, try to look up the $hp_target symbol. If it can't be found,
2377 // assume it's a regular function and look for #foo instead.
2378 Symbol *targetSym = ctx.symtab.find(name: (targetName + "$hp_target").str());
2379 if (!targetSym)
2380 targetSym = ctx.symtab.find(name: targetName);
2381 Defined *t = dyn_cast_or_null<Defined>(Val: targetSym);
2382 if (t && isArm64EC(Machine: t->getChunk()->getMachine()))
2383 exportThunks.push_back(x: {chunk, t});
2384 }
2385 }
2386
2387 auto codeMapChunk = make<ECCodeMapChunk>(args&: codeMap);
2388 rdataSec->addChunk(c: codeMapChunk);
2389 Symbol *codeMapSym = ctx.symtab.findUnderscore(name: "__hybrid_code_map");
2390 replaceSymbol<DefinedSynthetic>(s: codeMapSym, arg: codeMapSym->getName(),
2391 arg&: codeMapChunk);
2392
2393 CHPECodeRangesChunk *ranges = make<CHPECodeRangesChunk>(args&: exportThunks);
2394 rdataSec->addChunk(c: ranges);
2395 Symbol *rangesSym =
2396 ctx.symtab.findUnderscore(name: "__x64_code_ranges_to_entry_points");
2397 replaceSymbol<DefinedSynthetic>(s: rangesSym, arg: rangesSym->getName(), arg&: ranges);
2398
2399 CHPERedirectionChunk *entryPoints = make<CHPERedirectionChunk>(args&: exportThunks);
2400 a64xrmSec->addChunk(c: entryPoints);
2401 Symbol *entryPointsSym =
2402 ctx.symtab.findUnderscore(name: "__arm64x_redirection_metadata");
2403 replaceSymbol<DefinedSynthetic>(s: entryPointsSym, arg: entryPointsSym->getName(),
2404 arg&: entryPoints);
2405
2406 for (auto thunk : ctx.symtab.sameAddressThunks) {
2407 // Relocation values are set later in setECSymbols.
2408 ctx.dynamicRelocs->add(type: IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE, size: sizeof(uint32_t),
2409 offset: thunk);
2410 ctx.dynamicRelocs->add(type: IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE, size: sizeof(uint32_t),
2411 offset: Arm64XRelocVal(thunk, sizeof(uint32_t)));
2412 }
2413}
2414
2415// MinGW specific. Gather all relocations that are imported from a DLL even
2416// though the code didn't expect it to, produce the table that the runtime
2417// uses for fixing them up, and provide the synthetic symbols that the
2418// runtime uses for finding the table.
2419void Writer::createRuntimePseudoRelocs() {
2420 ctx.forEachSymtab(f: [&](SymbolTable &symtab) {
2421 std::vector<RuntimePseudoReloc> rels;
2422
2423 for (Chunk *c : ctx.driver.getChunks()) {
2424 auto *sc = dyn_cast<SectionChunk>(Val: c);
2425 if (!sc || !sc->live || &sc->file->symtab != &symtab)
2426 continue;
2427 // Don't create pseudo relocations for sections that won't be
2428 // mapped at runtime.
2429 if (sc->header->Characteristics & IMAGE_SCN_MEM_DISCARDABLE)
2430 continue;
2431 sc->getRuntimePseudoRelocs(res&: rels);
2432 }
2433
2434 if (!ctx.config.pseudoRelocs) {
2435 // Not writing any pseudo relocs; if some were needed, error out and
2436 // indicate what required them.
2437 for (const RuntimePseudoReloc &rpr : rels)
2438 Err(ctx) << "automatic dllimport of " << rpr.sym->getName() << " in "
2439 << toString(file: rpr.target->file)
2440 << " requires pseudo relocations";
2441 return;
2442 }
2443
2444 if (!rels.empty()) {
2445 Log(ctx) << "Writing " << Twine(rels.size())
2446 << " runtime pseudo relocations";
2447 const char *symbolName = "_pei386_runtime_relocator";
2448 Symbol *relocator = symtab.findUnderscore(name: symbolName);
2449 if (!relocator)
2450 Err(ctx)
2451 << "output image has runtime pseudo relocations, but the function "
2452 << symbolName
2453 << " is missing; it is needed for fixing the relocations at "
2454 "runtime";
2455 }
2456
2457 PseudoRelocTableChunk *table = make<PseudoRelocTableChunk>(args&: rels);
2458 rdataSec->addChunk(c: table);
2459 EmptyChunk *endOfList = make<EmptyChunk>();
2460 rdataSec->addChunk(c: endOfList);
2461
2462 Symbol *headSym = symtab.findUnderscore(name: "__RUNTIME_PSEUDO_RELOC_LIST__");
2463 Symbol *endSym = symtab.findUnderscore(name: "__RUNTIME_PSEUDO_RELOC_LIST_END__");
2464 replaceSymbol<DefinedSynthetic>(s: headSym, arg: headSym->getName(), arg&: table);
2465 replaceSymbol<DefinedSynthetic>(s: endSym, arg: endSym->getName(), arg&: endOfList);
2466 });
2467}
2468
2469// MinGW specific.
2470// The MinGW .ctors and .dtors lists have sentinels at each end;
2471// a (uintptr_t)-1 at the start and a (uintptr_t)0 at the end.
2472// There's a symbol pointing to the start sentinel pointer, __CTOR_LIST__
2473// and __DTOR_LIST__ respectively.
2474void Writer::insertCtorDtorSymbols() {
2475 ctx.forEachSymtab(f: [&](SymbolTable &symtab) {
2476 AbsolutePointerChunk *ctorListHead = make<AbsolutePointerChunk>(args&: symtab, args: -1);
2477 AbsolutePointerChunk *ctorListEnd = make<AbsolutePointerChunk>(args&: symtab, args: 0);
2478 AbsolutePointerChunk *dtorListHead = make<AbsolutePointerChunk>(args&: symtab, args: -1);
2479 AbsolutePointerChunk *dtorListEnd = make<AbsolutePointerChunk>(args&: symtab, args: 0);
2480 ctorsSec->insertChunkAtStart(c: ctorListHead);
2481 ctorsSec->addChunk(c: ctorListEnd);
2482 dtorsSec->insertChunkAtStart(c: dtorListHead);
2483 dtorsSec->addChunk(c: dtorListEnd);
2484
2485 Symbol *ctorListSym = symtab.findUnderscore(name: "__CTOR_LIST__");
2486 Symbol *dtorListSym = symtab.findUnderscore(name: "__DTOR_LIST__");
2487 replaceSymbol<DefinedSynthetic>(s: ctorListSym, arg: ctorListSym->getName(),
2488 arg&: ctorListHead);
2489 replaceSymbol<DefinedSynthetic>(s: dtorListSym, arg: dtorListSym->getName(),
2490 arg&: dtorListHead);
2491 });
2492
2493 if (ctx.hybridSymtab) {
2494 ctorsSec->splitECChunks();
2495 dtorsSec->splitECChunks();
2496 }
2497}
2498
2499// MinGW (really, Cygwin) specific.
2500// The Cygwin startup code uses __data_start__ __data_end__ __bss_start__
2501// and __bss_end__ to know what to copy during fork emulation.
2502void Writer::insertBssDataStartEndSymbols() {
2503 if (!dataSec->chunks.empty()) {
2504 Symbol *dataStartSym = ctx.symtab.find(name: "__data_start__");
2505 Symbol *dataEndSym = ctx.symtab.find(name: "__data_end__");
2506 Chunk *endChunk = dataSec->chunks.back();
2507 replaceSymbol<DefinedSynthetic>(s: dataStartSym, arg: dataStartSym->getName(),
2508 arg&: dataSec->chunks.front());
2509 replaceSymbol<DefinedSynthetic>(s: dataEndSym, arg: dataEndSym->getName(), arg&: endChunk,
2510 arg: endChunk->getSize());
2511 }
2512
2513 if (!bssSec->chunks.empty()) {
2514 Symbol *bssStartSym = ctx.symtab.find(name: "__bss_start__");
2515 Symbol *bssEndSym = ctx.symtab.find(name: "__bss_end__");
2516 Chunk *endChunk = bssSec->chunks.back();
2517 replaceSymbol<DefinedSynthetic>(s: bssStartSym, arg: bssStartSym->getName(),
2518 arg&: bssSec->chunks.front());
2519 replaceSymbol<DefinedSynthetic>(s: bssEndSym, arg: bssEndSym->getName(), arg&: endChunk,
2520 arg: endChunk->getSize());
2521 }
2522}
2523
2524// Handles /section options to allow users to overwrite
2525// section attributes.
2526void Writer::setSectionPermissions() {
2527 llvm::TimeTraceScope timeScope("Sections permissions");
2528 for (auto &p : ctx.config.section) {
2529 StringRef name = p.first;
2530 uint32_t perm = p.second;
2531 for (OutputSection *sec : ctx.outputSections)
2532 if (sec->name == name)
2533 sec->setPermissions(perm);
2534 }
2535}
2536
2537// Set symbols used by ARM64EC metadata.
2538void Writer::setECSymbols() {
2539 if (!ctx.symtab.isEC())
2540 return;
2541
2542 llvm::stable_sort(Range&: exportThunks, C: [](const std::pair<Chunk *, Defined *> &a,
2543 const std::pair<Chunk *, Defined *> &b) {
2544 return a.first->getRVA() < b.first->getRVA();
2545 });
2546
2547 ChunkRange &chpePdata = ctx.config.machine == ARM64X ? hybridPdata : pdata;
2548 Symbol *rfeTableSym = ctx.symtab.findUnderscore(name: "__arm64x_extra_rfe_table");
2549 replaceSymbol<DefinedSynthetic>(s: rfeTableSym, arg: "__arm64x_extra_rfe_table",
2550 arg&: chpePdata.first);
2551
2552 if (chpePdata.first) {
2553 Symbol *rfeSizeSym =
2554 ctx.symtab.findUnderscore(name: "__arm64x_extra_rfe_table_size");
2555 cast<DefinedAbsolute>(Val: rfeSizeSym)
2556 ->setVA(chpePdata.last->getRVA() + chpePdata.last->getSize() -
2557 chpePdata.first->getRVA());
2558 }
2559
2560 Symbol *rangesCountSym =
2561 ctx.symtab.findUnderscore(name: "__x64_code_ranges_to_entry_points_count");
2562 cast<DefinedAbsolute>(Val: rangesCountSym)->setVA(exportThunks.size());
2563
2564 Symbol *entryPointCountSym =
2565 ctx.symtab.findUnderscore(name: "__arm64x_redirection_metadata_count");
2566 cast<DefinedAbsolute>(Val: entryPointCountSym)->setVA(exportThunks.size());
2567
2568 Symbol *iatSym = ctx.symtab.findUnderscore(name: "__hybrid_auxiliary_iat");
2569 replaceSymbol<DefinedSynthetic>(s: iatSym, arg: "__hybrid_auxiliary_iat",
2570 arg: idata.auxIat.empty() ? nullptr
2571 : idata.auxIat.front());
2572
2573 Symbol *iatCopySym = ctx.symtab.findUnderscore(name: "__hybrid_auxiliary_iat_copy");
2574 replaceSymbol<DefinedSynthetic>(
2575 s: iatCopySym, arg: "__hybrid_auxiliary_iat_copy",
2576 arg: idata.auxIatCopy.empty() ? nullptr : idata.auxIatCopy.front());
2577
2578 Symbol *delayIatSym =
2579 ctx.symtab.findUnderscore(name: "__hybrid_auxiliary_delayload_iat");
2580 replaceSymbol<DefinedSynthetic>(
2581 s: delayIatSym, arg: "__hybrid_auxiliary_delayload_iat",
2582 arg: delayIdata.getAuxIat().empty() ? nullptr
2583 : delayIdata.getAuxIat().front());
2584
2585 Symbol *delayIatCopySym =
2586 ctx.symtab.findUnderscore(name: "__hybrid_auxiliary_delayload_iat_copy");
2587 replaceSymbol<DefinedSynthetic>(
2588 s: delayIatCopySym, arg: "__hybrid_auxiliary_delayload_iat_copy",
2589 arg: delayIdata.getAuxIatCopy().empty() ? nullptr
2590 : delayIdata.getAuxIatCopy().front());
2591
2592 if (ctx.config.machine == ARM64X) {
2593 // For the hybrid image, set the alternate entry point to the EC entry
2594 // point. In the hybrid view, it is swapped to the native entry point
2595 // using ARM64X relocations.
2596 if (auto altEntrySym = cast_or_null<Defined>(Val: ctx.symtab.entry)) {
2597 // If the entry is an EC export thunk, use its target instead.
2598 if (auto thunkChunk =
2599 dyn_cast<ECExportThunkChunk>(Val: altEntrySym->getChunk()))
2600 altEntrySym = thunkChunk->target;
2601 ctx.symtab.findUnderscore(name: "__arm64x_native_entrypoint")
2602 ->replaceKeepingName(other: altEntrySym, size: sizeof(SymbolUnion));
2603 }
2604
2605 if (ctx.symtab.edataStart)
2606 ctx.dynamicRelocs->set(
2607 offset: dataDirOffset64 + EXPORT_TABLE * sizeof(data_directory) +
2608 offsetof(data_directory, Size),
2609 value: ctx.symtab.edataEnd->getRVA() - ctx.symtab.edataStart->getRVA() +
2610 ctx.symtab.edataEnd->getSize());
2611 if (hybridPdata.first)
2612 ctx.dynamicRelocs->set(
2613 offset: dataDirOffset64 + EXCEPTION_TABLE * sizeof(data_directory) +
2614 offsetof(data_directory, Size),
2615 value: hybridPdata.last->getRVA() - hybridPdata.first->getRVA() +
2616 hybridPdata.last->getSize());
2617 if (chpeSym && pdata.first)
2618 ctx.dynamicRelocs->set(
2619 offset: chpeSym->getRVA() + offsetof(chpe_metadata, ExtraRFETableSize),
2620 value: pdata.last->getRVA() + pdata.last->getSize() - pdata.first->getRVA());
2621 }
2622
2623 for (SameAddressThunkARM64EC *thunk : ctx.symtab.sameAddressThunks)
2624 thunk->setDynamicRelocs(ctx);
2625}
2626
2627// Write section contents to a mmap'ed file.
2628void Writer::writeSections() {
2629 llvm::TimeTraceScope timeScope("Write sections");
2630 uint8_t *buf = buffer->getBufferStart();
2631 for (OutputSection *sec : ctx.outputSections) {
2632 uint8_t *secBuf = buf + sec->getFileOff();
2633 // Fill gaps between functions in .text with INT3 instructions
2634 // instead of leaving as NUL bytes (which can be interpreted as
2635 // ADD instructions). Only fill the gaps between chunks. Most
2636 // chunks overwrite it anyway, but uninitialized data chunks
2637 // merged into a code section don't.
2638 if ((sec->header.Characteristics & IMAGE_SCN_CNT_CODE) &&
2639 (ctx.config.machine == AMD64 || ctx.config.machine == I386)) {
2640 uint32_t prevEnd = 0;
2641 uint32_t rawSize = sec->getRawSize();
2642 for (Chunk *c : sec->chunks) {
2643 uint32_t off = c->getRVA() - sec->getRVA();
2644 // Chunks without data (e.g., .bss) have virtual addresses beyond
2645 // rawSize; stop filling when we reach the end of raw data.
2646 if (off >= rawSize)
2647 break;
2648 memset(s: secBuf + prevEnd, c: 0xCC, n: off - prevEnd);
2649 prevEnd = std::min(a: off + static_cast<uint32_t>(c->getSize()), b: rawSize);
2650 }
2651 memset(s: secBuf + prevEnd, c: 0xCC, n: rawSize - prevEnd);
2652 }
2653
2654 parallelForEach(R&: sec->chunks, Fn: [&](Chunk *c) {
2655 uint8_t *buf = secBuf + c->getRVA() - sec->getRVA();
2656 c->writeTo(buf);
2657
2658 // Write the offset to EC entry thunk preceding section contents. The low
2659 // bit is always set, so it's effectively an offset from the last byte of
2660 // the offset.
2661 if (Defined *entryThunk = c->getEntryThunk())
2662 write32le(P: buf - sizeof(uint32_t),
2663 V: entryThunk->getRVA() - c->getRVA() + 1);
2664 });
2665 }
2666}
2667
2668void Writer::writeBuildId() {
2669 llvm::TimeTraceScope timeScope("Write build ID");
2670
2671 // There are two important parts to the build ID.
2672 // 1) If building with debug info, the COFF debug directory contains a
2673 // timestamp as well as a Guid and Age of the PDB.
2674 // 2) In all cases, the PE COFF file header also contains a timestamp.
2675 // For reproducibility, instead of a timestamp we want to use a hash of the
2676 // PE contents.
2677 Configuration *config = &ctx.config;
2678 bool generateSyntheticBuildId = config->buildIDHash == BuildIDHash::Binary;
2679 if (generateSyntheticBuildId) {
2680 assert(buildId && "BuildId is not set!");
2681 // BuildId->BuildId was filled in when the PDB was written.
2682 }
2683
2684 // At this point the only fields in the COFF file which remain unset are the
2685 // "timestamp" in the COFF file header, and the ones in the coff debug
2686 // directory. Now we can hash the file and write that hash to the various
2687 // timestamp fields in the file.
2688 StringRef outputFileData(
2689 reinterpret_cast<const char *>(buffer->getBufferStart()),
2690 buffer->getBufferSize());
2691
2692 uint32_t timestamp = config->timestamp;
2693 uint64_t hash = 0;
2694
2695 if (config->repro || generateSyntheticBuildId)
2696 hash = xxh3_64bits(data: outputFileData);
2697
2698 if (config->repro)
2699 timestamp = static_cast<uint32_t>(hash);
2700
2701 if (generateSyntheticBuildId) {
2702 buildId->buildId->PDB70.CVSignature = OMF::Signature::PDB70;
2703 buildId->buildId->PDB70.Age = 1;
2704 memcpy(dest: buildId->buildId->PDB70.Signature, src: &hash, n: 8);
2705 // xxhash only gives us 8 bytes, so put some fixed data in the other half.
2706 memcpy(dest: &buildId->buildId->PDB70.Signature[8], src: "LLD PDB.", n: 8);
2707 }
2708
2709 if (debugDirectory)
2710 debugDirectory->setTimeDateStamp(timestamp);
2711
2712 uint8_t *buf = buffer->getBufferStart();
2713 buf += dosStubSize + sizeof(PEMagic);
2714 object::coff_file_header *coffHeader =
2715 reinterpret_cast<coff_file_header *>(buf);
2716 coffHeader->TimeDateStamp = timestamp;
2717}
2718
2719// Sort .pdata section contents according to PE/COFF spec 5.5.
2720template <typename T>
2721void Writer::sortExceptionTable(ChunkRange &exceptionTable) {
2722 if (!exceptionTable.first)
2723 return;
2724
2725 // We assume .pdata contains function table entries only.
2726 auto bufAddr = [&](Chunk *c) {
2727 OutputSection *os = ctx.getOutputSection(c);
2728 return buffer->getBufferStart() + os->getFileOff() + c->getRVA() -
2729 os->getRVA();
2730 };
2731 uint8_t *begin = bufAddr(exceptionTable.first);
2732 uint8_t *end = bufAddr(exceptionTable.last) + exceptionTable.last->getSize();
2733 if ((end - begin) % sizeof(T) != 0) {
2734 Fatal(ctx) << "unexpected .pdata size: " << (end - begin)
2735 << " is not a multiple of " << sizeof(T);
2736 }
2737
2738 parallelSort(MutableArrayRef<T>(reinterpret_cast<T *>(begin),
2739 reinterpret_cast<T *>(end)),
2740 [](const T &a, const T &b) { return a.begin < b.begin; });
2741}
2742
2743// Sort .pdata section contents according to PE/COFF spec 5.5.
2744void Writer::sortExceptionTables() {
2745 llvm::TimeTraceScope timeScope("Sort exception table");
2746
2747 struct EntryX64 {
2748 ulittle32_t begin, end, unwind;
2749 };
2750 struct EntryArm {
2751 ulittle32_t begin, unwind;
2752 };
2753
2754 switch (ctx.config.machine) {
2755 case AMD64:
2756 sortExceptionTable<EntryX64>(exceptionTable&: pdata);
2757 break;
2758 case ARM64EC:
2759 case ARM64X:
2760 sortExceptionTable<EntryX64>(exceptionTable&: hybridPdata);
2761 [[fallthrough]];
2762 case ARMNT:
2763 case ARM64:
2764 sortExceptionTable<EntryArm>(exceptionTable&: pdata);
2765 break;
2766 default:
2767 if (pdata.first)
2768 ctx.e.errs() << "warning: don't know how to handle .pdata\n";
2769 break;
2770 }
2771}
2772
2773// The CRT section contains, among other things, the array of function
2774// pointers that initialize every global variable that is not trivially
2775// constructed. The CRT calls them one after the other prior to invoking
2776// main().
2777//
2778// As per C++ spec, 3.6.2/2.3,
2779// "Variables with ordered initialization defined within a single
2780// translation unit shall be initialized in the order of their definitions
2781// in the translation unit"
2782//
2783// It is therefore critical to sort the chunks containing the function
2784// pointers in the order that they are listed in the object file (top to
2785// bottom), otherwise global objects might not be initialized in the
2786// correct order.
2787void Writer::sortCRTSectionChunks(std::vector<Chunk *> &chunks) {
2788 auto sectionChunkOrder = [](const Chunk *a, const Chunk *b) {
2789 auto sa = dyn_cast<SectionChunk>(Val: a);
2790 auto sb = dyn_cast<SectionChunk>(Val: b);
2791 assert(sa && sb && "Non-section chunks in CRT section!");
2792
2793 StringRef sAObj = sa->file->mb.getBufferIdentifier();
2794 StringRef sBObj = sb->file->mb.getBufferIdentifier();
2795
2796 return sAObj == sBObj && sa->getSectionNumber() < sb->getSectionNumber();
2797 };
2798 llvm::stable_sort(Range&: chunks, C: sectionChunkOrder);
2799
2800 if (ctx.config.verbose) {
2801 for (auto &c : chunks) {
2802 auto sc = dyn_cast<SectionChunk>(Val: c);
2803 Log(ctx) << " " << sc->file->mb.getBufferIdentifier().str()
2804 << ", SectionID: " << sc->getSectionNumber();
2805 }
2806 }
2807}
2808
2809OutputSection *Writer::findSection(StringRef name) {
2810 for (OutputSection *sec : ctx.outputSections)
2811 if (sec->name == name)
2812 return sec;
2813 return nullptr;
2814}
2815
2816uint32_t Writer::getSizeOfInitializedData() {
2817 uint32_t res = 0;
2818 for (OutputSection *s : ctx.outputSections)
2819 if (s->header.Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)
2820 res += s->getRawSize();
2821 return res;
2822}
2823
2824// Add base relocations to .reloc section.
2825void Writer::addBaserels() {
2826 if (!ctx.config.relocatable)
2827 return;
2828 std::vector<Baserel> v;
2829 for (OutputSection *sec : ctx.outputSections) {
2830 if (sec->header.Characteristics & IMAGE_SCN_MEM_DISCARDABLE)
2831 continue;
2832 llvm::TimeTraceScope timeScope("Base relocations: ", sec->name);
2833 // Collect all locations for base relocations.
2834 for (Chunk *c : sec->chunks)
2835 c->getBaserels(res: &v);
2836 // Add the addresses to .reloc section.
2837 if (!v.empty())
2838 addBaserelBlocks(v);
2839 v.clear();
2840 }
2841}
2842
2843// Add addresses to .reloc section. Note that addresses are grouped by page.
2844void Writer::addBaserelBlocks(std::vector<Baserel> &v) {
2845 const uint32_t mask = ~uint32_t(pageSize - 1);
2846 uint32_t page = v[0].rva & mask;
2847 size_t i = 0, j = 1;
2848 llvm::sort(C&: v,
2849 Comp: [](const Baserel &x, const Baserel &y) { return x.rva < y.rva; });
2850 for (size_t e = v.size(); j < e; ++j) {
2851 uint32_t p = v[j].rva & mask;
2852 if (p == page)
2853 continue;
2854 relocSec->addChunk(c: make<BaserelChunk>(args&: page, args: &v[i], args: &v[0] + j));
2855 i = j;
2856 page = p;
2857 }
2858 if (i == j)
2859 return;
2860 relocSec->addChunk(c: make<BaserelChunk>(args&: page, args: &v[i], args: &v[0] + j));
2861}
2862
2863void Writer::createDynamicRelocs() {
2864 if (!ctx.dynamicRelocs)
2865 return;
2866
2867 // Adjust the Machine field in the COFF header to AMD64.
2868 ctx.dynamicRelocs->add(type: IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE, size: sizeof(uint16_t),
2869 offset: coffHeaderOffset + offsetof(coff_file_header, Machine),
2870 value: AMD64);
2871
2872 if (ctx.symtab.entry != ctx.hybridSymtab->entry ||
2873 pdata.first != hybridPdata.first) {
2874 chpeSym = cast_or_null<DefinedRegular>(
2875 Val: ctx.symtab.findUnderscore(name: "__chpe_metadata"));
2876 if (!chpeSym)
2877 Warn(ctx) << "'__chpe_metadata' is missing for ARM64X target";
2878 }
2879
2880 if (ctx.symtab.entry != ctx.hybridSymtab->entry) {
2881 ctx.dynamicRelocs->add(type: IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE, size: sizeof(uint32_t),
2882 offset: peHeaderOffset +
2883 offsetof(pe32plus_header, AddressOfEntryPoint),
2884 value: cast_or_null<Defined>(Val: ctx.symtab.entry));
2885
2886 // Swap the alternate entry point in the CHPE metadata.
2887 if (chpeSym)
2888 ctx.dynamicRelocs->add(
2889 type: IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE, size: sizeof(uint32_t),
2890 offset: Arm64XRelocVal(chpeSym, offsetof(chpe_metadata, AlternateEntryPoint)),
2891 value: cast_or_null<Defined>(Val: ctx.hybridSymtab->entry));
2892 }
2893
2894 if (ctx.symtab.edataStart != ctx.hybridSymtab->edataStart) {
2895 ctx.dynamicRelocs->add(type: IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE, size: sizeof(uint32_t),
2896 offset: dataDirOffset64 +
2897 EXPORT_TABLE * sizeof(data_directory) +
2898 offsetof(data_directory, RelativeVirtualAddress),
2899 value: ctx.symtab.edataStart);
2900 // The Size value is assigned after addresses are finalized.
2901 ctx.dynamicRelocs->add(type: IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE, size: sizeof(uint32_t),
2902 offset: dataDirOffset64 +
2903 EXPORT_TABLE * sizeof(data_directory) +
2904 offsetof(data_directory, Size));
2905 }
2906
2907 if (pdata.first != hybridPdata.first) {
2908 ctx.dynamicRelocs->add(type: IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE, size: sizeof(uint32_t),
2909 offset: dataDirOffset64 +
2910 EXCEPTION_TABLE * sizeof(data_directory) +
2911 offsetof(data_directory, RelativeVirtualAddress),
2912 value: hybridPdata.first);
2913 // The Size value is assigned after addresses are finalized.
2914 ctx.dynamicRelocs->add(type: IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE, size: sizeof(uint32_t),
2915 offset: dataDirOffset64 +
2916 EXCEPTION_TABLE * sizeof(data_directory) +
2917 offsetof(data_directory, Size));
2918
2919 // Swap ExtraRFETable in the CHPE metadata.
2920 if (chpeSym) {
2921 ctx.dynamicRelocs->add(
2922 type: IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE, size: sizeof(uint32_t),
2923 offset: Arm64XRelocVal(chpeSym, offsetof(chpe_metadata, ExtraRFETable)),
2924 value: pdata.first);
2925 // The Size value is assigned after addresses are finalized.
2926 ctx.dynamicRelocs->add(
2927 type: IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE, size: sizeof(uint32_t),
2928 offset: Arm64XRelocVal(chpeSym, offsetof(chpe_metadata, ExtraRFETableSize)));
2929 }
2930 }
2931
2932 // Set the hybrid load config to the EC load config.
2933 ctx.dynamicRelocs->add(type: IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE, size: sizeof(uint32_t),
2934 offset: dataDirOffset64 +
2935 LOAD_CONFIG_TABLE * sizeof(data_directory) +
2936 offsetof(data_directory, RelativeVirtualAddress),
2937 value: ctx.symtab.loadConfigSym);
2938 ctx.dynamicRelocs->add(type: IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE, size: sizeof(uint32_t),
2939 offset: dataDirOffset64 +
2940 LOAD_CONFIG_TABLE * sizeof(data_directory) +
2941 offsetof(data_directory, Size),
2942 value: ctx.symtab.loadConfigSize);
2943}
2944
2945PartialSection *Writer::createPartialSection(StringRef name,
2946 uint32_t outChars) {
2947 PartialSection *&pSec = partialSections[{.name: name, .characteristics: outChars}];
2948 if (pSec)
2949 return pSec;
2950 pSec = make<PartialSection>(args&: name, args&: outChars);
2951 return pSec;
2952}
2953
2954PartialSection *Writer::findPartialSection(StringRef name, uint32_t outChars) {
2955 auto it = partialSections.find(x: {.name: name, .characteristics: outChars});
2956 if (it != partialSections.end())
2957 return it->second;
2958 return nullptr;
2959}
2960
2961void Writer::fixTlsAlignment() {
2962 Defined *tlsSym =
2963 dyn_cast_or_null<Defined>(Val: ctx.symtab.findUnderscore(name: "_tls_used"));
2964 if (!tlsSym)
2965 return;
2966
2967 OutputSection *sec = ctx.getOutputSection(c: tlsSym->getChunk());
2968 assert(sec && tlsSym->getRVA() >= sec->getRVA() &&
2969 "no output section for _tls_used");
2970
2971 uint8_t *secBuf = buffer->getBufferStart() + sec->getFileOff();
2972 uint64_t tlsOffset = tlsSym->getRVA() - sec->getRVA();
2973 uint64_t directorySize = ctx.config.is64()
2974 ? sizeof(object::coff_tls_directory64)
2975 : sizeof(object::coff_tls_directory32);
2976
2977 if (tlsOffset + directorySize > sec->getRawSize())
2978 Fatal(ctx) << "_tls_used sym is malformed";
2979
2980 if (ctx.config.is64()) {
2981 object::coff_tls_directory64 *tlsDir =
2982 reinterpret_cast<object::coff_tls_directory64 *>(&secBuf[tlsOffset]);
2983 tlsDir->setAlignment(tlsAlignment);
2984 } else {
2985 object::coff_tls_directory32 *tlsDir =
2986 reinterpret_cast<object::coff_tls_directory32 *>(&secBuf[tlsOffset]);
2987 tlsDir->setAlignment(tlsAlignment);
2988 }
2989}
2990
2991void Writer::prepareLoadConfig() {
2992 ctx.forEachActiveSymtab(f: [&](SymbolTable &symtab) {
2993 if (!symtab.loadConfigSym)
2994 return;
2995
2996 OutputSection *sec = ctx.getOutputSection(c: symtab.loadConfigSym->getChunk());
2997 uint8_t *secBuf = buffer->getBufferStart() + sec->getFileOff();
2998 uint8_t *symBuf = secBuf + (symtab.loadConfigSym->getRVA() - sec->getRVA());
2999
3000 if (ctx.config.is64())
3001 prepareLoadConfig(symtab,
3002 loadConfig: reinterpret_cast<coff_load_configuration64 *>(symBuf));
3003 else
3004 prepareLoadConfig(symtab,
3005 loadConfig: reinterpret_cast<coff_load_configuration32 *>(symBuf));
3006 });
3007}
3008
3009template <typename T>
3010void Writer::prepareLoadConfig(SymbolTable &symtab, T *loadConfig) {
3011 size_t loadConfigSize = loadConfig->Size;
3012
3013#define RETURN_IF_NOT_CONTAINS(field) \
3014 if (loadConfigSize < offsetof(T, field) + sizeof(T::field)) { \
3015 Warn(ctx) << "'_load_config_used' structure too small to include " #field; \
3016 return; \
3017 }
3018
3019#define IF_CONTAINS(field) \
3020 if (loadConfigSize >= offsetof(T, field) + sizeof(T::field))
3021
3022#define CHECK_VA(field, sym) \
3023 if (auto *s = dyn_cast<DefinedSynthetic>(symtab.findUnderscore(sym))) \
3024 if (loadConfig->field != ctx.config.imageBase + s->getRVA()) \
3025 Warn(ctx) << #field " not set correctly in '_load_config_used'";
3026
3027#define CHECK_ABSOLUTE(field, sym) \
3028 if (auto *s = dyn_cast<DefinedAbsolute>(symtab.findUnderscore(sym))) \
3029 if (loadConfig->field != s->getVA()) \
3030 Warn(ctx) << #field " not set correctly in '_load_config_used'";
3031
3032 if (ctx.config.dependentLoadFlags) {
3033 RETURN_IF_NOT_CONTAINS(DependentLoadFlags)
3034 loadConfig->DependentLoadFlags = ctx.config.dependentLoadFlags;
3035 }
3036
3037 if (ctx.dynamicRelocs) {
3038 IF_CONTAINS(DynamicValueRelocTableSection) {
3039 loadConfig->DynamicValueRelocTableSection = relocSec->sectionIndex;
3040 loadConfig->DynamicValueRelocTableOffset =
3041 ctx.dynamicRelocs->getRVA() - relocSec->getRVA();
3042 }
3043 else {
3044 Warn(ctx) << "'_load_config_used' structure too small to include dynamic "
3045 "relocations";
3046 }
3047 }
3048
3049 IF_CONTAINS(CHPEMetadataPointer) {
3050 // On ARM64X, only the EC version of the load config contains
3051 // CHPEMetadataPointer. Copy its value to the native load config.
3052 if (ctx.config.machine == ARM64X && !symtab.isEC() &&
3053 ctx.symtab.loadConfigSize >=
3054 offsetof(T, CHPEMetadataPointer) + sizeof(T::CHPEMetadataPointer)) {
3055 OutputSection *sec =
3056 ctx.getOutputSection(c: ctx.symtab.loadConfigSym->getChunk());
3057 uint8_t *secBuf = buffer->getBufferStart() + sec->getFileOff();
3058 auto hybridLoadConfig =
3059 reinterpret_cast<const coff_load_configuration64 *>(
3060 secBuf + (ctx.symtab.loadConfigSym->getRVA() - sec->getRVA()));
3061 loadConfig->CHPEMetadataPointer = hybridLoadConfig->CHPEMetadataPointer;
3062 }
3063 }
3064
3065 if (ctx.config.guardCF == GuardCFLevel::Off)
3066 return;
3067 RETURN_IF_NOT_CONTAINS(GuardFlags)
3068 CHECK_VA(GuardCFFunctionTable, "__guard_fids_table")
3069 CHECK_ABSOLUTE(GuardCFFunctionCount, "__guard_fids_count")
3070 CHECK_ABSOLUTE(GuardFlags, "__guard_flags")
3071 IF_CONTAINS(GuardAddressTakenIatEntryCount) {
3072 CHECK_VA(GuardAddressTakenIatEntryTable, "__guard_iat_table")
3073 CHECK_ABSOLUTE(GuardAddressTakenIatEntryCount, "__guard_iat_count")
3074 }
3075
3076 if (!(ctx.config.guardCF & GuardCFLevel::LongJmp))
3077 return;
3078 RETURN_IF_NOT_CONTAINS(GuardLongJumpTargetCount)
3079 CHECK_VA(GuardLongJumpTargetTable, "__guard_longjmp_table")
3080 CHECK_ABSOLUTE(GuardLongJumpTargetCount, "__guard_longjmp_count")
3081
3082 if (!(ctx.config.guardCF & GuardCFLevel::EHCont))
3083 return;
3084 RETURN_IF_NOT_CONTAINS(GuardEHContinuationCount)
3085 CHECK_VA(GuardEHContinuationTable, "__guard_eh_cont_table")
3086 CHECK_ABSOLUTE(GuardEHContinuationCount, "__guard_eh_cont_count")
3087
3088#undef RETURN_IF_NOT_CONTAINS
3089#undef IF_CONTAINS
3090#undef CHECK_VA
3091#undef CHECK_ABSOLUTE
3092}
3093
3094void Writer::printSummary() {
3095 if (!ctx.config.showSummary)
3096 return;
3097
3098 SmallString<256> buffer;
3099 raw_svector_ostream stream(buffer);
3100
3101 stream << center_justify(Str: "Summary", Width: 80) << '\n'
3102 << std::string(80, '-') << '\n';
3103
3104 auto print = [&](uint64_t v, StringRef s) {
3105 stream << formatv(Fmt: "{0}",
3106 Vals: fmt_align(Item: formatv(Fmt: "{0:N}", Vals&: v), Where: AlignStyle::Right, Amount: 20))
3107 << " " << s << '\n';
3108 };
3109
3110 bool hasStats = ctx.pdbStats.has_value();
3111
3112 print(ctx.objFileInstances.size(),
3113 "Input OBJ files (expanded from all cmd-line inputs)");
3114 print(ctx.consumedInputsSize,
3115 "Size of all consumed OBJ files (non-lazy), in bytes");
3116 print(ctx.typeServerSourceMappings.size(), "PDB type server dependencies");
3117 print(ctx.precompSourceMappings.size(), "Precomp OBJ dependencies");
3118 print(hasStats ? ctx.pdbStats->nbTypeRecords : 0, "Input debug type records");
3119 print(hasStats ? ctx.pdbStats->nbTypeRecordsBytes : 0,
3120 "Size of all input debug type records, in bytes");
3121 print(hasStats ? ctx.pdbStats->nbTPIrecords : 0, "Merged TPI records");
3122 print(hasStats ? ctx.pdbStats->nbIPIrecords : 0, "Merged IPI records");
3123 print(hasStats ? ctx.pdbStats->strTabSize : 0, "Output PDB strings");
3124 print(hasStats ? ctx.pdbStats->globalSymbols : 0, "Global symbol records");
3125 print(hasStats ? ctx.pdbStats->moduleSymbols : 0, "Module symbol records");
3126 print(hasStats ? ctx.pdbStats->publicSymbols : 0, "Public symbol records");
3127
3128 if (hasStats)
3129 stream << ctx.pdbStats->largeInputTypeRecs;
3130
3131 Msg(ctx) << buffer;
3132}
3133