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