Lines Matching +full:dll +full:- +full:config
1 //===- Writer.cpp ---------------------------------------------------------===//
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
12 #include "Config.h"
13 #include "DLL.h"
50 /* To re-generate DOSProgram:
56 ; Point ds:dx at the $-terminated string.
67 $ nasm -fbin /tmp/DOSProgram.asm -o /tmp/DOSProgram.bin
68 $ xxd -i /tmp/DOSProgram.bin
104 uint64_t offs = os->getFileOff() + (c->getRVA() - os->getRVA()); in writeTo()
105 fillEntry(d, record.first, c->getSize(), c->getRVA(), offs); in writeTo()
110 // FIXME: The COFF spec allows either a 0-sized entry to just say in writeTo()
111 // "the timestamp field is really a hash", or a 4-byte size field in writeTo()
113 // lowest 4 bytes usually being the timestamp in little-endian order). in writeTo()
127 d->Characteristics = 0; in fillEntry()
128 d->TimeDateStamp = 0; in fillEntry()
129 d->MajorVersion = 0; in fillEntry()
130 d->MinorVersion = 0; in fillEntry()
131 d->Type = debugType; in fillEntry()
132 d->SizeOfData = size; in fillEntry()
133 d->AddressOfRawData = rva; in fillEntry()
134 d->PointerToRawData = offs; in fillEntry()
136 timeDateStamps.push_back(&d->TimeDateStamp); in fillEntry()
150 return sizeof(codeview::DebugInfo) + ctx.config.pdbAltPath.size() + 1; in getSize()
160 if (!ctx.config.pdbAltPath.empty()) in writeTo()
161 memcpy(p, ctx.config.pdbAltPath.data(), ctx.config.pdbAltPath.size()); in writeTo()
162 p[ctx.config.pdbAltPath.size()] = '\0'; in writeTo()
327 // are entirely linker-generated we can keep track of their locations using
358 chunks.insert(chunks.end(), other->chunks.begin(), other->chunks.end()); in merge()
359 other->chunks.clear(); in merge()
360 contribSections.insert(contribSections.end(), other->contribSections.begin(), in merge()
361 other->contribSections.end()); in merge()
362 other->contribSections.clear(); in merge()
366 if (other->header.Characteristics & IMAGE_SCN_CNT_CODE) { in merge()
379 encodeSectionName(hdr->Name, stringTableOff); in writeHeaderTo()
382 (hdr->Characteristics & IMAGE_SCN_MEM_DISCARDABLE) == 0); in writeHeaderTo()
383 strncpy(hdr->Name, name.data(), in writeHeaderTo()
395 if (ctx.config.machine == ARMNT) { in isInRange()
406 } else if (ctx.config.machine == ARM64) { in isInRange()
428 Defined *&lastThunk = lastThunks[target->getRVA()]; in getThunk()
429 if (lastThunk && isInRange(type, lastThunk->getRVA(), p, margin)) in getThunk()
432 switch (ctx.config.machine) { in getThunk()
452 // range, but only barely, also get thunks - in case other added thunks makes
465 for (size_t i = 0; i != os->chunks.size(); ++i) { in createThunks()
466 SectionChunk *sc = dyn_cast_or_null<SectionChunk>(os->chunks[i]); in createThunks()
474 size_t thunkInsertionRVA = sc->getRVA() + sc->getSize() + thunksSize; in createThunks()
475 ObjFile *file = sc->file; in createThunks()
478 file->getCOFFObj()->getRelocations(sc->header); in createThunks()
481 Symbol *relocTarget = file->getSymbol(rel.SymbolTableIndex); in createThunks()
487 uint64_t p = sc->getRVA() + rel.VirtualAddress + thunksSize; in createThunks()
493 uint64_t s = sym->getRVA(); in createThunks()
501 Chunk *thunkChunk = thunk->getChunk(); in createThunks()
502 thunkChunk->setRVA( in createThunks()
504 os->chunks.insert(os->chunks.begin() + thunkInsertionSpot, thunkChunk); in createThunks()
506 thunksSize += thunkChunk->getSize(); in createThunks()
507 thunkInsertionRVA += thunkChunk->getSize(); in createThunks()
515 uint32_t &thunkSymbolIndex = insertion.first->second; in createThunks()
517 thunkSymbolIndex = file->addRangeThunkSymbol(thunk); in createThunks()
525 ArrayRef<coff_relocation> curRelocs = sc->getRelocs(); in createThunks()
542 if (nextReplacement != endReplacement && nextReplacement->first == i) { in createThunks()
543 newRelocs[i].SymbolTableIndex = nextReplacement->second; in createThunks()
548 sc->setRelocs(newRelocs); in createThunks()
555 if (!isArm64EC(ctx.config.machine)) in createECCodeMap()
573 for (Chunk *c : sec->chunks) { in createECCodeMap()
576 if (isa<SectionChunk>(c) && !c->getSize()) in createECCodeMap()
579 std::optional<chpe_range_type> chunkType = c->getArm64ECRangeType(); in createECCodeMap()
592 cast<DefinedAbsolute>(tableCountSym)->setVA(codeMap.size()); in createECCodeMap()
602 ArrayRef<coff_relocation> relocs = sc->getRelocs(); in verifyRanges()
604 Symbol *relocTarget = sc->file->getSymbol(rel.SymbolTableIndex); in verifyRanges()
610 uint64_t p = sc->getRVA() + rel.VirtualAddress; in verifyRanges()
611 uint64_t s = sym->getRVA(); in verifyRanges()
623 if (ctx.config.machine != ARMNT && ctx.config.machine != ARM64) in finalizeAddresses()
628 sec->origChunks = sec->chunks; in finalizeAddresses()
629 origNumChunks += sec->chunks.size(); in finalizeAddresses()
644 if (!verifyRanges(sec->chunks)) { in finalizeAddresses()
648 numChunks += sec->chunks.size(); in finalizeAddresses()
653 log("Added " + Twine(numChunks - origNumChunks) + " thunks with " + in finalizeAddresses()
666 sec->chunks = sec->origChunks; in finalizeAddresses()
692 if (!ctx.config.writeCheckSum) { in writePEChecksum()
698 // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#checksum in writePEChecksum()
699 uint32_t *buf = (uint32_t *)buffer->getBufferStart(); in writePEChecksum()
700 uint32_t size = (uint32_t)(buffer->getBufferSize()); in writePEChecksum()
714 count -= 2; in writePEChecksum()
717 // Add left-over byte, if any in writePEChecksum()
721 // Fold 32-bit sum to 16 bits in writePEChecksum()
727 peHeader->CheckSum = sum; in writePEChecksum()
757 openFile(ctx.config.outputFile); in run()
758 if (ctx.config.is64()) { in run()
773 if (!ctx.config.pdbPath.empty() && ctx.config.debug) { in run()
775 createPDB(ctx, sectionTable, buildId->buildId); in run()
789 if (auto e = buffer->commit()) in run()
790 fatal("failed to write output '" + buffer->getPath() + in run()
806 if (sec->sym) in sortBySectionOrder()
807 return ctx.config.order.lookup(sec->sym->getName()); in sortBySectionOrder()
821 StringRef curName = pSec->name; in fixPartialSectionChars()
825 if (pSec->characteristics == chars) in fixPartialSectionChars()
827 PartialSection *destSec = createPartialSection(pSec->name, chars); in fixPartialSectionChars()
828 destSec->chunks.insert(destSec->chunks.end(), pSec->chunks.begin(), in fixPartialSectionChars()
829 pSec->chunks.end()); in fixPartialSectionChars()
830 pSec->chunks.clear(); in fixPartialSectionChars()
856 if (!pSec->name.starts_with(".idata")) in fixGnuImportChunks()
859 if (!pSec->chunks.empty()) in fixGnuImportChunks()
861 llvm::stable_sort(pSec->chunks, [&](Chunk *s, Chunk *t) { in fixGnuImportChunks()
873 (sc1->file->parentName + "/" + sc1->file->getName()).str(); in fixGnuImportChunks()
875 (sc2->file->parentName + "/" + sc2->file->getName()).str(); in fixGnuImportChunks()
893 pSec->chunks.insert(pSec->chunks.end(), v.begin(), v.end()); in addSyntheticIdata()
912 if (!importDirs->chunks.empty()) in locateImportTables()
913 importTableStart = importDirs->chunks.front(); in locateImportTables()
914 for (Chunk *c : importDirs->chunks) in locateImportTables()
915 importTableSize += c->getSize(); in locateImportTables()
919 if (!importAddresses->chunks.empty()) in locateImportTables()
920 iatStart = importAddresses->chunks.front(); in locateImportTables()
921 for (Chunk *c : importAddresses->chunks) in locateImportTables()
922 iatSize += c->getSize(); in locateImportTables()
935 // .tls$$<symbol> (where non-comdat .tls symbols are otherwise stored in in shouldStripSectionSuffix()
942 if (!sc || !sc->isCOMDAT()) in shouldStripSectionSuffix()
950 if (!ctx.config.callGraphProfile.empty()) { in sortSections()
954 if (DefinedRegular *sym = it.first->sym) in sortSections()
955 ctx.config.order[sym->getName()] = it.second; in sortSections()
958 if (!ctx.config.order.empty()) in sortSections()
960 sortBySectionOrder(it.second->chunks); in sortSections()
1003 if (sc && !sc->live) { in createSections()
1004 if (ctx.config.verbose) in createSections()
1005 sc->printDiscardedMessage(); in createSections()
1008 StringRef name = c->getSectionName(); in createSections()
1009 if (shouldStripSectionSuffix(sc, name, ctx.config.mingw)) in createSections()
1013 tlsAlignment = std::max(tlsAlignment, c->getAlignment()); in createSections()
1016 c->getOutputCharacteristics()); in createSections()
1017 pSec->chunks.push_back(c); in createSections()
1042 StringRef name = getOutputSectionName(pSec->name); in createSections()
1043 uint32_t outChars = pSec->characteristics; in createSections()
1052 log("Processing section " + pSec->name + " -> " + name); in createSections()
1054 sortCRTSectionChunks(pSec->chunks); in createSections()
1058 for (Chunk *c : pSec->chunks) in createSections()
1059 sec->addChunk(c); in createSections()
1061 sec->addContributingPartialSection(pSec); in createSections()
1066 // Move DISCARDABLE (or non-memory-mapped) sections to the end of file in createSections()
1069 if (s->header.Characteristics & IMAGE_SCN_MEM_DISCARDABLE) { in createSections()
1072 // .debug_* - thus try to avoid leaving holes after stripping. in createSections()
1073 if (s->name.starts_with(".debug_")) in createSections()
1077 // .rsrc should come at the end of the non-discardable sections because its in createSections()
1092 Configuration *config = &ctx.config; in createMiscChunks() local
1096 p->finalizeContents(); in createMiscChunks()
1097 rdataSec->addChunk(p); in createMiscChunks()
1101 // Create thunks for locally-dllimported symbols. in createMiscChunks()
1104 rdataSec->addChunk(c); in createMiscChunks()
1108 debugInfoSec = config->mingw ? buildidSec : rdataSec; in createMiscChunks()
1109 if (config->buildIDHash != BuildIDHash::None || config->debug || in createMiscChunks()
1110 config->repro || config->cetCompat) { in createMiscChunks()
1112 make<DebugDirectoryChunk>(ctx, debugRecords, config->repro); in createMiscChunks()
1113 debugDirectory->setAlignment(4); in createMiscChunks()
1114 debugInfoSec->addChunk(debugDirectory); in createMiscChunks()
1117 if (config->debug || config->buildIDHash != BuildIDHash::None) { in createMiscChunks()
1125 replaceSymbol<DefinedSynthetic>(buildidSym, buildidSym->getName(), in createMiscChunks()
1129 if (config->cetCompat) { in createMiscChunks()
1137 r.second->setAlignment(4); in createMiscChunks()
1138 debugInfoSec->addChunk(r.second); in createMiscChunks()
1141 // Create SEH table. x86-only. in createMiscChunks()
1142 if (config->safeSEH) in createMiscChunks()
1146 if (config->guardCF != GuardCFLevel::Off) in createMiscChunks()
1149 if (isArm64EC(config->machine)) in createMiscChunks()
1152 if (config->autoImport) in createMiscChunks()
1155 if (config->mingw) in createMiscChunks()
1159 // Create .idata section for the DLL-imported symbol table.
1160 // The format of this section is inherently Windows-specific.
1166 // the same order as in the command line. (That affects DLL in createImportTables()
1167 // initialization order, and this ordering is MSVC-compatible.) in createImportTables()
1169 if (!file->live) in createImportTables()
1172 std::string dll = StringRef(file->dllName).lower(); in createImportTables() local
1173 if (ctx.config.dllOrder.count(dll) == 0) in createImportTables()
1174 ctx.config.dllOrder[dll] = ctx.config.dllOrder.size(); in createImportTables()
1176 if (file->impSym && !isa<DefinedImportData>(file->impSym)) in createImportTables()
1177 fatal(toString(ctx, *file->impSym) + " was replaced"); in createImportTables()
1178 DefinedImportData *impSym = cast_or_null<DefinedImportData>(file->impSym); in createImportTables()
1179 if (ctx.config.delayLoads.count(StringRef(file->dllName).lower())) { in createImportTables()
1180 if (!file->thunkSym) in createImportTables()
1181 fatal("cannot delay-load " + toString(file) + in createImportTables()
1196 if (!file->live) in appendImportThunks()
1199 if (!file->thunkSym) in appendImportThunks()
1202 if (!isa<DefinedImportThunk>(file->thunkSym)) in appendImportThunks()
1203 fatal(toString(ctx, *file->thunkSym) + " was replaced"); in appendImportThunks()
1204 DefinedImportThunk *thunk = cast<DefinedImportThunk>(file->thunkSym); in appendImportThunks()
1205 if (file->thunkLive) in appendImportThunks()
1206 textSec->addChunk(thunk->getChunk()); in appendImportThunks()
1210 Defined *helper = cast<Defined>(ctx.config.delayLoadHelper); in appendImportThunks()
1213 didatSec->addChunk(c); in appendImportThunks()
1215 dataSec->addChunk(c); in appendImportThunks()
1217 textSec->addChunk(c); in appendImportThunks()
1219 pdataSec->addChunk(c); in appendImportThunks()
1221 rdataSec->addChunk(c); in appendImportThunks()
1227 if (!edataSec->chunks.empty()) { in createExportTable()
1230 if (ctx.config.hadExplicitExports) in createExportTable()
1232 } else if (!ctx.config.exports.empty()) { in createExportTable()
1234 edataSec->addChunk(c); in createExportTable()
1236 if (!edataSec->chunks.empty()) { in createExportTable()
1237 edataStart = edataSec->chunks.front(); in createExportTable()
1238 edataEnd = edataSec->chunks.back(); in createExportTable()
1241 for (auto e : ctx.config.exports) in createExportTable()
1242 if (e.sym && e.sym->getName().starts_with("??_G")) in createExportTable()
1255 return s->chunks.empty(); in removeUnusedSections()
1264 auto isEmpty = [](OutputSection *s) { return s->getVirtualSize() == 0; }; in removeEmptySections()
1274 os->sectionIndex = idx; in assignOutputSectionIndices()
1275 for (Chunk *c : os->chunks) in assignOutputSectionIndices()
1276 c->setOutputSectionIdx(idx); in assignOutputSectionIndices()
1284 for (SectionChunk *sc : mc->sections) in assignOutputSectionIndices()
1285 if (sc && sc->live) in assignOutputSectionIndices()
1286 sc->setOutputSectionIdx(mc->getOutputSectionIdx()); in assignOutputSectionIndices()
1299 switch (def->kind()) { in createSymbol()
1302 // Note: COFF symbol can only store 32-bit values, so 64-bit absolute in createSymbol()
1304 sym.Value = da->getVA(); in createSymbol()
1314 Chunk *c = def->getChunk(); in createSymbol()
1321 sym.Value = def->getRVA() - os->getRVA(); in createSymbol()
1322 sym.SectionNumber = os->sectionIndex; in createSymbol()
1331 if (def->isRuntimePseudoReloc) in createSymbol()
1334 StringRef name = def->getName(); in createSymbol()
1344 COFFSymbolRef ref = d->getCOFFSymbol(); in createSymbol()
1347 } else if (def->kind() == Symbol::DefinedImportThunkKind) { in createSymbol()
1362 // supported by writing a non-standard string table, but this string table is in createSymbolAndStringTable()
1367 // non-discardable sections have their names truncated, to ensure that any in createSymbolAndStringTable()
1370 if (sec->name.size() <= COFF::NameSize) in createSymbolAndStringTable()
1372 if ((sec->header.Characteristics & IMAGE_SCN_MEM_DISCARDABLE) == 0) in createSymbolAndStringTable()
1374 if (ctx.config.warnLongSectionNames) { in createSymbolAndStringTable()
1375 warn("section name " + sec->name + in createSymbolAndStringTable()
1376 " is longer than 8 characters and will use a non-standard string " in createSymbolAndStringTable()
1379 sec->setStringTableOff(addEntryToStringTable(sec->name)); in createSymbolAndStringTable()
1382 if (ctx.config.writeSymtab) { in createSymbolAndStringTable()
1384 for (Symbol *b : file->getSymbols()) { in createSymbolAndStringTable()
1386 if (!d || d->writtenToSymtab) in createSymbolAndStringTable()
1388 d->writtenToSymtab = true; in createSymbolAndStringTable()
1390 COFFSymbolRef symRef = dc->getCOFFSymbol(); in createSymbolAndStringTable()
1400 if (!dthunk->wrappedSym->writtenToSymtab) { in createSymbolAndStringTable()
1401 dthunk->wrappedSym->writtenToSymtab = true; in createSymbolAndStringTable()
1403 createSymbol(dthunk->wrappedSym)) in createSymbolAndStringTable()
1419 fileSize = alignTo(fileOff, ctx.config.fileAlign); in createSymbolAndStringTable()
1424 if (!pdataSec->chunks.empty()) { in mergeSections()
1425 if (isArm64EC(ctx.config.machine)) { in mergeSections()
1428 llvm::stable_sort(pdataSec->chunks, [=](const Chunk *a, const Chunk *b) { in mergeSections()
1429 return (a->getMachine() == AMD64) < (b->getMachine() == AMD64); in mergeSections()
1432 for (auto chunk : pdataSec->chunks) { in mergeSections()
1433 if (chunk->getMachine() == AMD64) { in mergeSections()
1435 hybridPdata.last = pdataSec->chunks.back(); in mergeSections()
1444 pdata.first = pdataSec->chunks.front(); in mergeSections()
1445 pdata.last = pdataSec->chunks.back(); in mergeSections()
1449 for (auto &p : ctx.config.merge) { in mergeSections()
1457 auto i = ctx.config.merge.find(toName); in mergeSections()
1458 if (i == ctx.config.merge.end()) in mergeSections()
1460 toName = i->second; in mergeSections()
1467 from->name = toName; in mergeSections()
1470 to->merge(from); in mergeSections()
1478 if (!isArm64EC(ctx.config.machine)) in sortECChunks()
1482 if (sec->isCodeSection()) in sortECChunks()
1483 llvm::stable_sort(sec->chunks, [=](const Chunk *a, const Chunk *b) { in sortECChunks()
1484 std::optional<chpe_range_type> aType = a->getArm64ECRangeType(), in sortECChunks()
1485 bType = b->getArm64ECRangeType(); in sortECChunks()
1491 // Visits all sections to assign incremental, non-overlapping RVAs and
1495 Configuration *config = &ctx.config; in assignAddresses() local
1505 config->is64() ? sizeof(pe32plus_header) : sizeof(pe32_header); in assignAddresses()
1506 sizeOfHeaders = alignTo(sizeOfHeaders, config->fileAlign); in assignAddresses()
1510 uint64_t rva = alignTo(sizeOfHeaders, config->align); in assignAddresses()
1513 llvm::TimeTraceScope timeScope("Section: ", sec->name); in assignAddresses()
1517 sec->header.VirtualAddress = rva; in assignAddresses()
1521 uint32_t padding = sec->isCodeSection() ? config->functionPadMin : 0; in assignAddresses()
1524 for (Chunk *c : sec->chunks) { in assignAddresses()
1526 if (isArm64EC(ctx.config.machine) && sec->isCodeSection()) { in assignAddresses()
1527 std::optional<chpe_range_type> rangeType = c->getArm64ECRangeType(); in assignAddresses()
1533 if (padding && c->isHotPatchable()) in assignAddresses()
1537 if (c->getEntryThunk()) in assignAddresses()
1539 virtualSize = alignTo(virtualSize, c->getAlignment()); in assignAddresses()
1540 c->setRVA(rva + virtualSize); in assignAddresses()
1541 virtualSize += c->getSize(); in assignAddresses()
1542 if (c->hasData) in assignAddresses()
1543 rawSize = alignTo(virtualSize, config->fileAlign); in assignAddresses()
1546 error("section larger than 4 GiB: " + sec->name); in assignAddresses()
1547 sec->header.VirtualSize = virtualSize; in assignAddresses()
1548 sec->header.SizeOfRawData = rawSize; in assignAddresses()
1550 sec->header.PointerToRawData = fileSize; in assignAddresses()
1551 rva += alignTo(virtualSize, config->align); in assignAddresses()
1552 fileSize += alignTo(rawSize, config->fileAlign); in assignAddresses()
1554 sizeOfImage = alignTo(rva, config->align); in assignAddresses()
1559 mc->assignSubsectionRVAs(); in assignAddresses()
1564 // executable consists of an MS-DOS MZ executable. If the executable is run in writeHeader()
1568 Configuration *config = &ctx.config; in writeHeader() local
1569 uint8_t *buf = buffer->getBufferStart(); in writeHeader()
1572 dos->Magic[0] = 'M'; in writeHeader()
1573 dos->Magic[1] = 'Z'; in writeHeader()
1574 dos->UsedBytesInTheLastPage = dosStubSize % 512; in writeHeader()
1575 dos->FileSizeInPages = divideCeil(dosStubSize, 512); in writeHeader()
1576 dos->HeaderSizeInParagraphs = sizeof(dos_header) / 16; in writeHeader()
1578 dos->AddressOfRelocationTable = sizeof(dos_header); in writeHeader()
1579 dos->AddressOfNewExeHeader = dosStubSize; in writeHeader()
1592 switch (config->machine) { in writeHeader()
1594 coff->Machine = AMD64; in writeHeader()
1597 coff->Machine = ARM64; in writeHeader()
1600 coff->Machine = config->machine; in writeHeader()
1602 coff->NumberOfSections = ctx.outputSections.size(); in writeHeader()
1603 coff->Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE; in writeHeader()
1604 if (config->largeAddressAware) in writeHeader()
1605 coff->Characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE; in writeHeader()
1606 if (!config->is64()) in writeHeader()
1607 coff->Characteristics |= IMAGE_FILE_32BIT_MACHINE; in writeHeader()
1608 if (config->dll) in writeHeader()
1609 coff->Characteristics |= IMAGE_FILE_DLL; in writeHeader()
1610 if (config->driverUponly) in writeHeader()
1611 coff->Characteristics |= IMAGE_FILE_UP_SYSTEM_ONLY; in writeHeader()
1612 if (!config->relocatable) in writeHeader()
1613 coff->Characteristics |= IMAGE_FILE_RELOCS_STRIPPED; in writeHeader()
1614 if (config->swaprunCD) in writeHeader()
1615 coff->Characteristics |= IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP; in writeHeader()
1616 if (config->swaprunNet) in writeHeader()
1617 coff->Characteristics |= IMAGE_FILE_NET_RUN_FROM_SWAP; in writeHeader()
1618 coff->SizeOfOptionalHeader = in writeHeader()
1624 pe->Magic = config->is64() ? PE32Header::PE32_PLUS : PE32Header::PE32; in writeHeader()
1631 pe->MajorLinkerVersion = 14; in writeHeader()
1632 pe->MinorLinkerVersion = 0; in writeHeader()
1634 pe->ImageBase = config->imageBase; in writeHeader()
1635 pe->SectionAlignment = config->align; in writeHeader()
1636 pe->FileAlignment = config->fileAlign; in writeHeader()
1637 pe->MajorImageVersion = config->majorImageVersion; in writeHeader()
1638 pe->MinorImageVersion = config->minorImageVersion; in writeHeader()
1639 pe->MajorOperatingSystemVersion = config->majorOSVersion; in writeHeader()
1640 pe->MinorOperatingSystemVersion = config->minorOSVersion; in writeHeader()
1641 pe->MajorSubsystemVersion = config->majorSubsystemVersion; in writeHeader()
1642 pe->MinorSubsystemVersion = config->minorSubsystemVersion; in writeHeader()
1643 pe->Subsystem = config->subsystem; in writeHeader()
1644 pe->SizeOfImage = sizeOfImage; in writeHeader()
1645 pe->SizeOfHeaders = sizeOfHeaders; in writeHeader()
1646 if (!config->noEntry) { in writeHeader()
1647 Defined *entry = cast<Defined>(config->entry); in writeHeader()
1648 pe->AddressOfEntryPoint = entry->getRVA(); in writeHeader()
1650 if (config->machine == ARMNT) in writeHeader()
1651 pe->AddressOfEntryPoint |= 1; in writeHeader()
1653 pe->SizeOfStackReserve = config->stackReserve; in writeHeader()
1654 pe->SizeOfStackCommit = config->stackCommit; in writeHeader()
1655 pe->SizeOfHeapReserve = config->heapReserve; in writeHeader()
1656 pe->SizeOfHeapCommit = config->heapCommit; in writeHeader()
1657 if (config->appContainer) in writeHeader()
1658 pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_APPCONTAINER; in writeHeader()
1659 if (config->driverWdm) in writeHeader()
1660 pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER; in writeHeader()
1661 if (config->dynamicBase) in writeHeader()
1662 pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE; in writeHeader()
1663 if (config->highEntropyVA) in writeHeader()
1664 pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA; in writeHeader()
1665 if (!config->allowBind) in writeHeader()
1666 pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_BIND; in writeHeader()
1667 if (config->nxCompat) in writeHeader()
1668 pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NX_COMPAT; in writeHeader()
1669 if (!config->allowIsolation) in writeHeader()
1670 pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION; in writeHeader()
1671 if (config->guardCF != GuardCFLevel::Off) in writeHeader()
1672 pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_GUARD_CF; in writeHeader()
1673 if (config->integrityCheck) in writeHeader()
1674 pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY; in writeHeader()
1675 if (setNoSEHCharacteristic || config->noSEH) in writeHeader()
1676 pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_SEH; in writeHeader()
1677 if (config->terminalServerAware) in writeHeader()
1678 pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE; in writeHeader()
1679 pe->NumberOfRvaAndSize = numberOfDataDirectory; in writeHeader()
1680 if (textSec->getVirtualSize()) { in writeHeader()
1681 pe->BaseOfCode = textSec->getRVA(); in writeHeader()
1682 pe->SizeOfCode = textSec->getRawSize(); in writeHeader()
1684 pe->SizeOfInitializedData = getSizeOfInitializedData(); in writeHeader()
1690 dir[EXPORT_TABLE].RelativeVirtualAddress = edataStart->getRVA(); in writeHeader()
1692 edataEnd->getRVA() + edataEnd->getSize() - edataStart->getRVA(); in writeHeader()
1695 dir[IMPORT_TABLE].RelativeVirtualAddress = importTableStart->getRVA(); in writeHeader()
1699 dir[IAT].RelativeVirtualAddress = iatStart->getRVA(); in writeHeader()
1702 if (rsrcSec->getVirtualSize()) { in writeHeader()
1703 dir[RESOURCE_TABLE].RelativeVirtualAddress = rsrcSec->getRVA(); in writeHeader()
1704 dir[RESOURCE_TABLE].Size = rsrcSec->getVirtualSize(); in writeHeader()
1708 ctx.config.machine == ARM64EC ? hybridPdata : pdata; in writeHeader()
1711 exceptionTable.first->getRVA(); in writeHeader()
1712 dir[EXCEPTION_TABLE].Size = exceptionTable.last->getRVA() + in writeHeader()
1713 exceptionTable.last->getSize() - in writeHeader()
1714 exceptionTable.first->getRVA(); in writeHeader()
1716 if (relocSec->getVirtualSize()) { in writeHeader()
1717 dir[BASE_RELOCATION_TABLE].RelativeVirtualAddress = relocSec->getRVA(); in writeHeader()
1718 dir[BASE_RELOCATION_TABLE].Size = relocSec->getVirtualSize(); in writeHeader()
1722 dir[TLS_TABLE].RelativeVirtualAddress = b->getRVA(); in writeHeader()
1723 dir[TLS_TABLE].Size = config->is64() in writeHeader()
1729 dir[DEBUG_DIRECTORY].RelativeVirtualAddress = debugDirectory->getRVA(); in writeHeader()
1730 dir[DEBUG_DIRECTORY].Size = debugDirectory->getSize(); in writeHeader()
1734 SectionChunk *sc = b->getChunk(); in writeHeader()
1735 assert(b->getRVA() >= sc->getRVA()); in writeHeader()
1736 uint64_t offsetInChunk = b->getRVA() - sc->getRVA(); in writeHeader()
1737 if (!sc->hasData || offsetInChunk + 4 > sc->getSize()) in writeHeader()
1740 ArrayRef<uint8_t> secContents = sc->getContents(); in writeHeader()
1743 if (offsetInChunk + loadConfigSize > sc->getSize()) in writeHeader()
1745 dir[LOAD_CONFIG_TABLE].RelativeVirtualAddress = b->getRVA(); in writeHeader()
1757 sec->writeHeaderTo(buf, config->debug); in writeHeader()
1761 buf - ctx.outputSections.size() * sizeof(coff_section), buf); in writeHeader()
1766 coff->PointerToSymbolTable = pointerToSymbolTable; in writeHeader()
1768 coff->NumberOfSymbols = numberOfSymbols; in writeHeader()
1770 buffer->getBufferStart() + coff->PointerToSymbolTable); in writeHeader()
1790 if (!file->hasSafeSEH()) in createSEHTable()
1791 error("/safeseh: " + file->getName() + " is not compatible with SEH"); in createSEHTable()
1792 markSymbolsForRVATable(file, file->getSXDataChunks(), handlers); in createSEHTable()
1796 // there is no load config object to point to the table of handlers. in createSEHTable()
1808 Chunk *c = s->getChunk(); in addSymbolToRVASet()
1812 c = sc->repl; // Look through ICF replacement. in addSymbolToRVASet()
1813 uint32_t off = s->getRVA() - (c ? c->getRVA() : 0); in addSymbolToRVASet()
1824 switch (s->kind()) { in maybeAddAddressTakenFunction()
1855 if (d->getCOFFSymbol().getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION) { in maybeAddAddressTakenFunction()
1856 SectionChunk *sc = dyn_cast<SectionChunk>(d->getChunk()); in maybeAddAddressTakenFunction()
1857 if (sc && sc->live && in maybeAddAddressTakenFunction()
1858 sc->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE) in maybeAddAddressTakenFunction()
1867 // mark the relocation target as address-taken.
1870 for (Chunk *c : file->getChunks()) { in markSymbolsWithRelocations()
1874 if (!sc || !sc->live) in markSymbolsWithRelocations()
1877 for (const coff_relocation &reloc : sc->getRelocs()) { in markSymbolsWithRelocations()
1878 if (ctx.config.machine == I386 && in markSymbolsWithRelocations()
1884 Symbol *ref = sc->file->getSymbol(reloc.SymbolTableIndex); in markSymbolsWithRelocations()
1891 // address-taken functions. It is sorted and uniqued, just like the safe SEH
1894 Configuration *config = &ctx.config; in createGuardCFTables() local
1906 // possibly address-taken. in createGuardCFTables()
1907 if (file->hasGuardCF()) { in createGuardCFTables()
1908 markSymbolsForRVATable(file, file->getGuardFidChunks(), addressTakenSyms); in createGuardCFTables()
1909 markSymbolsForRVATable(file, file->getGuardIATChunks(), giatsRVASet); in createGuardCFTables()
1910 getSymbolsFromSections(file, file->getGuardIATChunks(), giatsSymbols); in createGuardCFTables()
1911 markSymbolsForRVATable(file, file->getGuardLJmpChunks(), longJmpTargets); in createGuardCFTables()
1917 if (file->hasGuardEHCont()) in createGuardCFTables()
1918 markSymbolsForRVATable(file, file->getGuardEHContChunks(), ehContTargets); in createGuardCFTables()
1921 // Mark the image entry as address-taken. in createGuardCFTables()
1922 if (config->entry) in createGuardCFTables()
1923 maybeAddAddressTakenFunction(addressTakenSyms, config->entry); in createGuardCFTables()
1925 // Mark exported symbols in executable sections as address-taken. in createGuardCFTables()
1926 for (Export &e : config->exports) in createGuardCFTables()
1930 // thunk (e.g. because the DLL that defines it will be delay-loaded) and, if in createGuardCFTables()
1934 if (di->loadThunkSym) in createGuardCFTables()
1935 addSymbolToRVASet(addressTakenSyms, di->loadThunkSym); in createGuardCFTables()
1939 // Ensure sections referenced in the gfid table are 16-byte aligned. in createGuardCFTables()
1941 if (c.inputChunk->getAlignment() < 16) in createGuardCFTables()
1942 c.inputChunk->setAlignment(16); in createGuardCFTables()
1952 if (config->guardCF & GuardCFLevel::LongJmp) in createGuardCFTables()
1957 if (config->guardCF & GuardCFLevel::EHCont) in createGuardCFTables()
1961 // Set __guard_flags, which will be used in the load config to indicate that in createGuardCFTables()
1965 if (config->guardCF & GuardCFLevel::LongJmp) in createGuardCFTables()
1967 if (config->guardCF & GuardCFLevel::EHCont) in createGuardCFTables()
1970 cast<DefinedAbsolute>(flagSym)->setVA(guardFlags); in createGuardCFTables()
1983 // mark the virtual member functions as address-taken by the vtable. in getSymbolsFromSections()
1984 if (!c->live) in getSymbolsFromSections()
1988 ArrayRef<uint8_t> data = c->getContents(); in getSymbolsFromSections()
1990 warn("ignoring " + c->getSectionName() + in getSymbolsFromSections()
1999 ArrayRef<Symbol *> objSymbols = file->getSymbols(); in getSymbolsFromSections()
2003 c->getSectionName() + " in object " + toString(file)); in getSymbolsFromSections()
2007 if (s->isLive()) in getSymbolsFromSections()
2039 rdataSec->addChunk(tableChunk); in maybeAddRVATable()
2043 replaceSymbol<DefinedSynthetic>(t, t->getName(), tableChunk); in maybeAddRVATable()
2044 cast<DefinedAbsolute>(c)->setVA(tableChunk->getSize() / (hasFlag ? 5 : 4)); in maybeAddRVATable()
2050 rdataSec->addChunk(codeMapChunk); in createECChunks()
2052 replaceSymbol<DefinedSynthetic>(codeMapSym, codeMapSym->getName(), in createECChunks()
2056 // MinGW specific. Gather all relocations that are imported from a DLL even
2065 if (!sc || !sc->live) in createRuntimePseudoRelocs()
2069 if (sc->header->Characteristics & IMAGE_SCN_MEM_DISCARDABLE) in createRuntimePseudoRelocs()
2071 sc->getRuntimePseudoRelocs(rels); in createRuntimePseudoRelocs()
2074 if (!ctx.config.pseudoRelocs) { in createRuntimePseudoRelocs()
2078 error("automatic dllimport of " + rpr.sym->getName() + " in " + in createRuntimePseudoRelocs()
2079 toString(rpr.target->file) + " requires pseudo relocations"); in createRuntimePseudoRelocs()
2094 rdataSec->addChunk(table); in createRuntimePseudoRelocs()
2096 rdataSec->addChunk(endOfList); in createRuntimePseudoRelocs()
2101 replaceSymbol<DefinedSynthetic>(headSym, headSym->getName(), table); in createRuntimePseudoRelocs()
2102 replaceSymbol<DefinedSynthetic>(endSym, endSym->getName(), endOfList); in createRuntimePseudoRelocs()
2107 // a (uintptr_t)-1 at the start and a (uintptr_t)0 at the end.
2111 AbsolutePointerChunk *ctorListHead = make<AbsolutePointerChunk>(ctx, -1); in insertCtorDtorSymbols()
2113 AbsolutePointerChunk *dtorListHead = make<AbsolutePointerChunk>(ctx, -1); in insertCtorDtorSymbols()
2115 ctorsSec->insertChunkAtStart(ctorListHead); in insertCtorDtorSymbols()
2116 ctorsSec->addChunk(ctorListEnd); in insertCtorDtorSymbols()
2117 dtorsSec->insertChunkAtStart(dtorListHead); in insertCtorDtorSymbols()
2118 dtorsSec->addChunk(dtorListEnd); in insertCtorDtorSymbols()
2122 replaceSymbol<DefinedSynthetic>(ctorListSym, ctorListSym->getName(), in insertCtorDtorSymbols()
2124 replaceSymbol<DefinedSynthetic>(dtorListSym, dtorListSym->getName(), in insertCtorDtorSymbols()
2132 for (auto &p : ctx.config.section) { in setSectionPermissions()
2136 if (sec->name == name) in setSectionPermissions()
2137 sec->setPermissions(perm); in setSectionPermissions()
2143 if (!isArm64EC(ctx.config.machine)) in setECSymbols()
2154 ->setVA(pdata.last->getRVA() + pdata.last->getSize() - in setECSymbols()
2155 pdata.first->getRVA()); in setECSymbols()
2162 uint8_t *buf = buffer->getBufferStart(); in writeSections()
2164 uint8_t *secBuf = buf + sec->getFileOff(); in writeSections()
2170 if ((sec->header.Characteristics & IMAGE_SCN_CNT_CODE) && in writeSections()
2171 (ctx.config.machine == AMD64 || ctx.config.machine == I386)) { in writeSections()
2173 for (Chunk *c : sec->chunks) { in writeSections()
2174 uint32_t off = c->getRVA() - sec->getRVA(); in writeSections()
2175 memset(secBuf + prevEnd, 0xCC, off - prevEnd); in writeSections()
2176 prevEnd = off + c->getSize(); in writeSections()
2178 memset(secBuf + prevEnd, 0xCC, sec->getRawSize() - prevEnd); in writeSections()
2181 parallelForEach(sec->chunks, [&](Chunk *c) { in writeSections()
2182 c->writeTo(secBuf + c->getRVA() - sec->getRVA()); in writeSections()
2196 Configuration *config = &ctx.config; in writeBuildId() local
2197 bool generateSyntheticBuildId = config->buildIDHash == BuildIDHash::Binary; in writeBuildId()
2200 // BuildId->BuildId was filled in when the PDB was written. in writeBuildId()
2208 reinterpret_cast<const char *>(buffer->getBufferStart()), in writeBuildId()
2209 buffer->getBufferSize()); in writeBuildId()
2211 uint32_t timestamp = config->timestamp; in writeBuildId()
2214 if (config->repro || generateSyntheticBuildId) in writeBuildId()
2217 if (config->repro) in writeBuildId()
2221 buildId->buildId->PDB70.CVSignature = OMF::Signature::PDB70; in writeBuildId()
2222 buildId->buildId->PDB70.Age = 1; in writeBuildId()
2223 memcpy(buildId->buildId->PDB70.Signature, &hash, 8); in writeBuildId()
2225 memcpy(&buildId->buildId->PDB70.Signature[8], "LLD PDB.", 8); in writeBuildId()
2229 debugDirectory->setTimeDateStamp(timestamp); in writeBuildId()
2231 uint8_t *buf = buffer->getBufferStart(); in writeBuildId()
2235 coffHeader->TimeDateStamp = timestamp; in writeBuildId()
2247 return buffer->getBufferStart() + os->getFileOff() + c->getRVA() - in sortExceptionTable()
2248 os->getRVA(); in sortExceptionTable()
2251 uint8_t *end = bufAddr(exceptionTable.last) + exceptionTable.last->getSize(); in sortExceptionTable()
2252 if ((end - begin) % sizeof(T) != 0) { in sortExceptionTable()
2253 fatal("unexpected .pdata size: " + Twine(end - begin) + in sortExceptionTable()
2273 switch (ctx.config.machine) { in sortExceptionTables()
2310 assert(sa && sb && "Non-section chunks in CRT section!"); in sortCRTSectionChunks()
2312 StringRef sAObj = sa->file->mb.getBufferIdentifier(); in sortCRTSectionChunks()
2313 StringRef sBObj = sb->file->mb.getBufferIdentifier(); in sortCRTSectionChunks()
2315 return sAObj == sBObj && sa->getSectionNumber() < sb->getSectionNumber(); in sortCRTSectionChunks()
2319 if (ctx.config.verbose) { in sortCRTSectionChunks()
2322 log(" " + sc->file->mb.getBufferIdentifier().str() + in sortCRTSectionChunks()
2323 ", SectionID: " + Twine(sc->getSectionNumber())); in sortCRTSectionChunks()
2330 if (sec->name == name) in findSection()
2338 if (s->header.Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) in getSizeOfInitializedData()
2339 res += s->getRawSize(); in getSizeOfInitializedData()
2345 if (!ctx.config.relocatable) in addBaserels()
2347 relocSec->chunks.clear(); in addBaserels()
2350 if (sec->header.Characteristics & IMAGE_SCN_MEM_DISCARDABLE) in addBaserels()
2352 llvm::TimeTraceScope timeScope("Base relocations: ", sec->name); in addBaserels()
2354 for (Chunk *c : sec->chunks) in addBaserels()
2355 c->getBaserels(&v); in addBaserels()
2365 const uint32_t mask = ~uint32_t(pageSize - 1); in addBaserelBlocks()
2372 relocSec->addChunk(make<BaserelChunk>(page, &v[i], &v[0] + j)); in addBaserelBlocks()
2378 relocSec->addChunk(make<BaserelChunk>(page, &v[i], &v[0] + j)); in addBaserelBlocks()
2393 return it->second; in findPartialSection()
2403 OutputSection *sec = ctx.getOutputSection(tlsSym->getChunk()); in fixTlsAlignment()
2404 assert(sec && tlsSym->getRVA() >= sec->getRVA() && in fixTlsAlignment()
2407 uint8_t *secBuf = buffer->getBufferStart() + sec->getFileOff(); in fixTlsAlignment()
2408 uint64_t tlsOffset = tlsSym->getRVA() - sec->getRVA(); in fixTlsAlignment()
2409 uint64_t directorySize = ctx.config.is64() in fixTlsAlignment()
2413 if (tlsOffset + directorySize > sec->getRawSize()) in fixTlsAlignment()
2416 if (ctx.config.is64()) { in fixTlsAlignment()
2419 tlsDir->setAlignment(tlsAlignment); in fixTlsAlignment()
2423 tlsDir->setAlignment(tlsAlignment); in fixTlsAlignment()
2431 if (ctx.config.guardCF != GuardCFLevel::Off) in prepareLoadConfig()
2436 OutputSection *sec = ctx.getOutputSection(b->getChunk()); in prepareLoadConfig()
2437 uint8_t *buf = buffer->getBufferStart(); in prepareLoadConfig()
2438 uint8_t *secBuf = buf + sec->getFileOff(); in prepareLoadConfig()
2439 uint8_t *symBuf = secBuf + (b->getRVA() - sec->getRVA()); in prepareLoadConfig()
2440 uint32_t expectedAlign = ctx.config.is64() ? 8 : 4; in prepareLoadConfig()
2441 if (b->getChunk()->getAlignment() < expectedAlign) in prepareLoadConfig()
2444 Twine(b->getChunk()->getAlignment()) + " instead)"); in prepareLoadConfig()
2445 else if (!isAligned(Align(expectedAlign), b->getRVA())) in prepareLoadConfig()
2447 Twine::utohexstr(b->getRVA()) + " not aligned to " + in prepareLoadConfig()
2450 if (ctx.config.is64()) in prepareLoadConfig()
2457 if (ctx.config.dependentLoadFlags) in prepareLoadConfig()
2458 loadConfig->DependentLoadFlags = ctx.config.dependentLoadFlags; in prepareLoadConfig()
2465 size_t loadConfigSize = loadConfig->Size; in checkLoadConfigGuardData()
2478 if (loadConfig->field != ctx.config.imageBase + s->getRVA()) \ in checkLoadConfigGuardData()
2483 if (loadConfig->field != s->getVA()) \ in checkLoadConfigGuardData()
2486 if (ctx.config.guardCF == GuardCFLevel::Off) in checkLoadConfigGuardData()
2497 if (!(ctx.config.guardCF & GuardCFLevel::LongJmp)) in checkLoadConfigGuardData()
2503 if (!(ctx.config.guardCF & GuardCFLevel::EHCont)) in checkLoadConfigGuardData()