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