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