10b57cec5SDimitry Andric //===- PDB.cpp ------------------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include "PDB.h"
10349cc55cSDimitry Andric #include "COFFLinkerContext.h"
110b57cec5SDimitry Andric #include "Chunks.h"
120b57cec5SDimitry Andric #include "Config.h"
130b57cec5SDimitry Andric #include "DebugTypes.h"
140b57cec5SDimitry Andric #include "Driver.h"
150b57cec5SDimitry Andric #include "SymbolTable.h"
160b57cec5SDimitry Andric #include "Symbols.h"
170b57cec5SDimitry Andric #include "TypeMerger.h"
180b57cec5SDimitry Andric #include "Writer.h"
19480093f4SDimitry Andric #include "lld/Common/Timer.h"
200b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h"
2181ad6265SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
2281ad6265SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
230b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
240b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h"
250b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
260b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h"
270b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/RecordName.h"
280b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
290b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h"
300b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolSerializer.h"
310b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
320b57cec5SDimitry Andric #include "llvm/DebugInfo/MSF/MSFBuilder.h"
330b57cec5SDimitry Andric #include "llvm/DebugInfo/MSF/MSFCommon.h"
3406c3fb27SDimitry Andric #include "llvm/DebugInfo/MSF/MSFError.h"
350b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/GenericError.h"
360b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h"
370b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
380b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h"
390b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h"
400b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/InfoStream.h"
410b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h"
420b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/NativeSession.h"
430b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
440b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h"
450b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h"
460b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/TpiHashing.h"
470b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
480b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h"
490b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDB.h"
500b57cec5SDimitry Andric #include "llvm/Object/COFF.h"
510b57cec5SDimitry Andric #include "llvm/Object/CVDebugRecord.h"
520b57cec5SDimitry Andric #include "llvm/Support/BinaryByteStream.h"
5385868e8aSDimitry Andric #include "llvm/Support/CRC.h"
540b57cec5SDimitry Andric #include "llvm/Support/Endian.h"
550b57cec5SDimitry Andric #include "llvm/Support/Errc.h"
56480093f4SDimitry Andric #include "llvm/Support/FormatAdapters.h"
570b57cec5SDimitry Andric #include "llvm/Support/FormatVariadic.h"
580b57cec5SDimitry Andric #include "llvm/Support/Path.h"
590b57cec5SDimitry Andric #include "llvm/Support/ScopedPrinter.h"
605f757f3fSDimitry Andric #include "llvm/Support/TimeProfiler.h"
610b57cec5SDimitry Andric #include <memory>
62bdd1243dSDimitry Andric #include <optional>
630b57cec5SDimitry Andric
640b57cec5SDimitry Andric using namespace llvm;
650b57cec5SDimitry Andric using namespace llvm::codeview;
665ffd83dbSDimitry Andric using namespace lld;
675ffd83dbSDimitry Andric using namespace lld::coff;
680b57cec5SDimitry Andric
690b57cec5SDimitry Andric using llvm::object::coff_section;
70e8d8bef9SDimitry Andric using llvm::pdb::StringTableFixup;
710b57cec5SDimitry Andric
720b57cec5SDimitry Andric namespace {
730b57cec5SDimitry Andric class DebugSHandler;
740b57cec5SDimitry Andric
750b57cec5SDimitry Andric class PDBLinker {
760b57cec5SDimitry Andric friend DebugSHandler;
770b57cec5SDimitry Andric
780b57cec5SDimitry Andric public:
PDBLinker(COFFLinkerContext & ctx)79349cc55cSDimitry Andric PDBLinker(COFFLinkerContext &ctx)
8004eeddc0SDimitry Andric : builder(bAlloc()), tMerger(ctx, bAlloc()), ctx(ctx) {
810b57cec5SDimitry Andric // This isn't strictly necessary, but link.exe usually puts an empty string
820b57cec5SDimitry Andric // as the first "valid" string in the string table, so we do the same in
830b57cec5SDimitry Andric // order to maintain as much byte-for-byte compatibility as possible.
840b57cec5SDimitry Andric pdbStrTab.insert("");
850b57cec5SDimitry Andric }
860b57cec5SDimitry Andric
870b57cec5SDimitry Andric /// Emit the basic PDB structure: initial streams, headers, etc.
880b57cec5SDimitry Andric void initialize(llvm::codeview::DebugInfo *buildId);
890b57cec5SDimitry Andric
900b57cec5SDimitry Andric /// Add natvis files specified on the command line.
910b57cec5SDimitry Andric void addNatvisFiles();
920b57cec5SDimitry Andric
935ffd83dbSDimitry Andric /// Add named streams specified on the command line.
945ffd83dbSDimitry Andric void addNamedStreams();
955ffd83dbSDimitry Andric
960b57cec5SDimitry Andric /// Link CodeView from each object file in the symbol table into the PDB.
970b57cec5SDimitry Andric void addObjectsToPDB();
980b57cec5SDimitry Andric
995ffd83dbSDimitry Andric /// Add every live, defined public symbol to the PDB.
1005ffd83dbSDimitry Andric void addPublicsToPDB();
1015ffd83dbSDimitry Andric
1020b57cec5SDimitry Andric /// Link info for each import file in the symbol table into the PDB.
103349cc55cSDimitry Andric void addImportFilesToPDB();
1040b57cec5SDimitry Andric
105e8d8bef9SDimitry Andric void createModuleDBI(ObjFile *file);
106e8d8bef9SDimitry Andric
1070b57cec5SDimitry Andric /// Link CodeView from a single object file into the target (output) PDB.
1080b57cec5SDimitry Andric /// When a precompiled headers object is linked, its TPI map might be provided
1090b57cec5SDimitry Andric /// externally.
1105ffd83dbSDimitry Andric void addDebug(TpiSource *source);
1110b57cec5SDimitry Andric
112e8d8bef9SDimitry Andric void addDebugSymbols(TpiSource *source);
1130b57cec5SDimitry Andric
114e8d8bef9SDimitry Andric // Analyze the symbol records to separate module symbols from global symbols,
115e8d8bef9SDimitry Andric // find string references, and calculate how large the symbol stream will be
116e8d8bef9SDimitry Andric // in the PDB.
117e8d8bef9SDimitry Andric void analyzeSymbolSubsection(SectionChunk *debugChunk,
118e8d8bef9SDimitry Andric uint32_t &moduleSymOffset,
119e8d8bef9SDimitry Andric uint32_t &nextRelocIndex,
120e8d8bef9SDimitry Andric std::vector<StringTableFixup> &stringTableFixups,
1210b57cec5SDimitry Andric BinaryStreamRef symData);
1220b57cec5SDimitry Andric
123bdd1243dSDimitry Andric // Write all module symbols from all live debug symbol subsections of the
124e8d8bef9SDimitry Andric // given object file into the given stream writer.
125e8d8bef9SDimitry Andric Error writeAllModuleSymbolRecords(ObjFile *file, BinaryStreamWriter &writer);
126e8d8bef9SDimitry Andric
127e8d8bef9SDimitry Andric // Callback to copy and relocate debug symbols during PDB file writing.
128e8d8bef9SDimitry Andric static Error commitSymbolsForObject(void *ctx, void *obj,
129e8d8bef9SDimitry Andric BinaryStreamWriter &writer);
130e8d8bef9SDimitry Andric
131e8d8bef9SDimitry Andric // Copy the symbol record, relocate it, and fix the alignment if necessary.
132e8d8bef9SDimitry Andric // Rewrite type indices in the record. Replace unrecognized symbol records
133e8d8bef9SDimitry Andric // with S_SKIP records.
134e8d8bef9SDimitry Andric void writeSymbolRecord(SectionChunk *debugChunk,
135e8d8bef9SDimitry Andric ArrayRef<uint8_t> sectionContents, CVSymbol sym,
136e8d8bef9SDimitry Andric size_t alignedSize, uint32_t &nextRelocIndex,
137e8d8bef9SDimitry Andric std::vector<uint8_t> &storage);
138e8d8bef9SDimitry Andric
1390b57cec5SDimitry Andric /// Add the section map and section contributions to the PDB.
140349cc55cSDimitry Andric void addSections(ArrayRef<uint8_t> sectionTable);
1410b57cec5SDimitry Andric
1420b57cec5SDimitry Andric /// Write the PDB to disk and store the Guid generated for it in *Guid.
1430b57cec5SDimitry Andric void commit(codeview::GUID *guid);
1440b57cec5SDimitry Andric
1450b57cec5SDimitry Andric // Print statistics regarding the final PDB
1460b57cec5SDimitry Andric void printStats();
1470b57cec5SDimitry Andric
1480b57cec5SDimitry Andric private:
149bdd1243dSDimitry Andric void pdbMakeAbsolute(SmallVectorImpl<char> &fileName);
150bdd1243dSDimitry Andric void translateIdSymbols(MutableArrayRef<uint8_t> &recordData,
151bdd1243dSDimitry Andric TpiSource *source);
152bdd1243dSDimitry Andric void addCommonLinkerModuleSymbols(StringRef path,
153bdd1243dSDimitry Andric pdb::DbiModuleDescriptorBuilder &mod);
1540b57cec5SDimitry Andric
1550b57cec5SDimitry Andric pdb::PDBFileBuilder builder;
1560b57cec5SDimitry Andric
1570b57cec5SDimitry Andric TypeMerger tMerger;
1580b57cec5SDimitry Andric
159349cc55cSDimitry Andric COFFLinkerContext &ctx;
160349cc55cSDimitry Andric
1610b57cec5SDimitry Andric /// PDBs use a single global string table for filenames in the file checksum
1620b57cec5SDimitry Andric /// table.
1630b57cec5SDimitry Andric DebugStringTableSubsection pdbStrTab;
1640b57cec5SDimitry Andric
1650b57cec5SDimitry Andric llvm::SmallString<128> nativePath;
1660b57cec5SDimitry Andric
1670b57cec5SDimitry Andric // For statistics
1680b57cec5SDimitry Andric uint64_t globalSymbols = 0;
1690b57cec5SDimitry Andric uint64_t moduleSymbols = 0;
1700b57cec5SDimitry Andric uint64_t publicSymbols = 0;
171e8d8bef9SDimitry Andric uint64_t nbTypeRecords = 0;
172e8d8bef9SDimitry Andric uint64_t nbTypeRecordsBytes = 0;
1730b57cec5SDimitry Andric };
1740b57cec5SDimitry Andric
175e8d8bef9SDimitry Andric /// Represents an unrelocated DEBUG_S_FRAMEDATA subsection.
176e8d8bef9SDimitry Andric struct UnrelocatedFpoData {
177e8d8bef9SDimitry Andric SectionChunk *debugChunk = nullptr;
178e8d8bef9SDimitry Andric ArrayRef<uint8_t> subsecData;
179e8d8bef9SDimitry Andric uint32_t relocIndex = 0;
180e8d8bef9SDimitry Andric };
181e8d8bef9SDimitry Andric
182e8d8bef9SDimitry Andric /// The size of the magic bytes at the beginning of a symbol section or stream.
183e8d8bef9SDimitry Andric enum : uint32_t { kSymbolStreamMagicSize = 4 };
184e8d8bef9SDimitry Andric
1850b57cec5SDimitry Andric class DebugSHandler {
1860b57cec5SDimitry Andric PDBLinker &linker;
1870b57cec5SDimitry Andric
1880b57cec5SDimitry Andric /// The object file whose .debug$S sections we're processing.
1890b57cec5SDimitry Andric ObjFile &file;
1900b57cec5SDimitry Andric
1910b57cec5SDimitry Andric /// The DEBUG_S_STRINGTABLE subsection. These strings are referred to by
1920b57cec5SDimitry Andric /// index from other records in the .debug$S section. All of these strings
1930b57cec5SDimitry Andric /// need to be added to the global PDB string table, and all references to
1940b57cec5SDimitry Andric /// these strings need to have their indices re-written to refer to the
1950b57cec5SDimitry Andric /// global PDB string table.
1965ffd83dbSDimitry Andric DebugStringTableSubsectionRef cvStrTab;
1970b57cec5SDimitry Andric
1980b57cec5SDimitry Andric /// The DEBUG_S_FILECHKSMS subsection. As above, these are referred to
1990b57cec5SDimitry Andric /// by other records in the .debug$S section and need to be merged into the
2000b57cec5SDimitry Andric /// PDB.
2010b57cec5SDimitry Andric DebugChecksumsSubsectionRef checksums;
2020b57cec5SDimitry Andric
2030b57cec5SDimitry Andric /// The DEBUG_S_FRAMEDATA subsection(s). There can be more than one of
2040b57cec5SDimitry Andric /// these and they need not appear in any specific order. However, they
2050b57cec5SDimitry Andric /// contain string table references which need to be re-written, so we
2060b57cec5SDimitry Andric /// collect them all here and re-write them after all subsections have been
2070b57cec5SDimitry Andric /// discovered and processed.
208e8d8bef9SDimitry Andric std::vector<UnrelocatedFpoData> frameDataSubsecs;
2090b57cec5SDimitry Andric
210e8d8bef9SDimitry Andric /// List of string table references in symbol records. Later they will be
211e8d8bef9SDimitry Andric /// applied to the symbols during PDB writing.
212e8d8bef9SDimitry Andric std::vector<StringTableFixup> stringTableFixups;
2130b57cec5SDimitry Andric
214e8d8bef9SDimitry Andric /// Sum of the size of all module symbol records across all .debug$S sections.
215e8d8bef9SDimitry Andric /// Includes record realignment and the size of the symbol stream magic
216e8d8bef9SDimitry Andric /// prefix.
217e8d8bef9SDimitry Andric uint32_t moduleStreamSize = kSymbolStreamMagicSize;
218e8d8bef9SDimitry Andric
219e8d8bef9SDimitry Andric /// Next relocation index in the current .debug$S section. Resets every
220e8d8bef9SDimitry Andric /// handleDebugS call.
221e8d8bef9SDimitry Andric uint32_t nextRelocIndex = 0;
222e8d8bef9SDimitry Andric
223e8d8bef9SDimitry Andric void advanceRelocIndex(SectionChunk *debugChunk, ArrayRef<uint8_t> subsec);
224e8d8bef9SDimitry Andric
225e8d8bef9SDimitry Andric void addUnrelocatedSubsection(SectionChunk *debugChunk,
226e8d8bef9SDimitry Andric const DebugSubsectionRecord &ss);
227e8d8bef9SDimitry Andric
228e8d8bef9SDimitry Andric void addFrameDataSubsection(SectionChunk *debugChunk,
229e8d8bef9SDimitry Andric const DebugSubsectionRecord &ss);
230e8d8bef9SDimitry Andric
2310b57cec5SDimitry Andric public:
DebugSHandler(PDBLinker & linker,ObjFile & file)2325f757f3fSDimitry Andric DebugSHandler(PDBLinker &linker, ObjFile &file)
2335f757f3fSDimitry Andric : linker(linker), file(file) {}
2340b57cec5SDimitry Andric
235e8d8bef9SDimitry Andric void handleDebugS(SectionChunk *debugChunk);
2360b57cec5SDimitry Andric
2370b57cec5SDimitry Andric void finish();
2380b57cec5SDimitry Andric };
2390b57cec5SDimitry Andric }
2400b57cec5SDimitry Andric
2410b57cec5SDimitry Andric // Visual Studio's debugger requires absolute paths in various places in the
2420b57cec5SDimitry Andric // PDB to work without additional configuration:
2430b57cec5SDimitry Andric // https://docs.microsoft.com/en-us/visualstudio/debugger/debug-source-files-common-properties-solution-property-pages-dialog-box
pdbMakeAbsolute(SmallVectorImpl<char> & fileName)244bdd1243dSDimitry Andric void PDBLinker::pdbMakeAbsolute(SmallVectorImpl<char> &fileName) {
2450b57cec5SDimitry Andric // The default behavior is to produce paths that are valid within the context
2460b57cec5SDimitry Andric // of the machine that you perform the link on. If the linker is running on
2470b57cec5SDimitry Andric // a POSIX system, we will output absolute POSIX paths. If the linker is
2480b57cec5SDimitry Andric // running on a Windows system, we will output absolute Windows paths. If the
2490b57cec5SDimitry Andric // user desires any other kind of behavior, they should explicitly pass
2500b57cec5SDimitry Andric // /pdbsourcepath, in which case we will treat the exact string the user
2510b57cec5SDimitry Andric // passed in as the gospel and not normalize, canonicalize it.
2520b57cec5SDimitry Andric if (sys::path::is_absolute(fileName, sys::path::Style::windows) ||
2530b57cec5SDimitry Andric sys::path::is_absolute(fileName, sys::path::Style::posix))
2540b57cec5SDimitry Andric return;
2550b57cec5SDimitry Andric
2560b57cec5SDimitry Andric // It's not absolute in any path syntax. Relative paths necessarily refer to
2570b57cec5SDimitry Andric // the local file system, so we can make it native without ending up with a
2580b57cec5SDimitry Andric // nonsensical path.
259bdd1243dSDimitry Andric if (ctx.config.pdbSourcePath.empty()) {
2600b57cec5SDimitry Andric sys::path::native(fileName);
2610b57cec5SDimitry Andric sys::fs::make_absolute(fileName);
262349cc55cSDimitry Andric sys::path::remove_dots(fileName, true);
2630b57cec5SDimitry Andric return;
2640b57cec5SDimitry Andric }
2650b57cec5SDimitry Andric
2660b57cec5SDimitry Andric // Try to guess whether /PDBSOURCEPATH is a unix path or a windows path.
2670b57cec5SDimitry Andric // Since PDB's are more of a Windows thing, we make this conservative and only
2680b57cec5SDimitry Andric // decide that it's a unix path if we're fairly certain. Specifically, if
2690b57cec5SDimitry Andric // it starts with a forward slash.
270bdd1243dSDimitry Andric SmallString<128> absoluteFileName = ctx.config.pdbSourcePath;
2715f757f3fSDimitry Andric sys::path::Style guessedStyle = absoluteFileName.starts_with("/")
2720b57cec5SDimitry Andric ? sys::path::Style::posix
2730b57cec5SDimitry Andric : sys::path::Style::windows;
2740b57cec5SDimitry Andric sys::path::append(absoluteFileName, guessedStyle, fileName);
2750b57cec5SDimitry Andric sys::path::native(absoluteFileName, guessedStyle);
2760b57cec5SDimitry Andric sys::path::remove_dots(absoluteFileName, true, guessedStyle);
2770b57cec5SDimitry Andric
2780b57cec5SDimitry Andric fileName = std::move(absoluteFileName);
2790b57cec5SDimitry Andric }
2800b57cec5SDimitry Andric
addTypeInfo(pdb::TpiStreamBuilder & tpiBuilder,TypeCollection & typeTable)2810b57cec5SDimitry Andric static void addTypeInfo(pdb::TpiStreamBuilder &tpiBuilder,
2820b57cec5SDimitry Andric TypeCollection &typeTable) {
2830b57cec5SDimitry Andric // Start the TPI or IPI stream header.
2840b57cec5SDimitry Andric tpiBuilder.setVersionHeader(pdb::PdbTpiV80);
2850b57cec5SDimitry Andric
2860b57cec5SDimitry Andric // Flatten the in memory type table and hash each type.
2870b57cec5SDimitry Andric typeTable.ForEachRecord([&](TypeIndex ti, const CVType &type) {
2880b57cec5SDimitry Andric auto hash = pdb::hashTypeRecord(type);
2890b57cec5SDimitry Andric if (auto e = hash.takeError())
2900b57cec5SDimitry Andric fatal("type hashing error");
2910b57cec5SDimitry Andric tpiBuilder.addTypeRecord(type.RecordData, *hash);
2920b57cec5SDimitry Andric });
2930b57cec5SDimitry Andric }
2940b57cec5SDimitry Andric
addGHashTypeInfo(COFFLinkerContext & ctx,pdb::PDBFileBuilder & builder)295349cc55cSDimitry Andric static void addGHashTypeInfo(COFFLinkerContext &ctx,
296349cc55cSDimitry Andric pdb::PDBFileBuilder &builder) {
297e8d8bef9SDimitry Andric // Start the TPI or IPI stream header.
298e8d8bef9SDimitry Andric builder.getTpiBuilder().setVersionHeader(pdb::PdbTpiV80);
299e8d8bef9SDimitry Andric builder.getIpiBuilder().setVersionHeader(pdb::PdbTpiV80);
300fcaf7f86SDimitry Andric for (TpiSource *source : ctx.tpiSourceList) {
301e8d8bef9SDimitry Andric builder.getTpiBuilder().addTypeRecords(source->mergedTpi.recs,
302e8d8bef9SDimitry Andric source->mergedTpi.recSizes,
303e8d8bef9SDimitry Andric source->mergedTpi.recHashes);
304e8d8bef9SDimitry Andric builder.getIpiBuilder().addTypeRecords(source->mergedIpi.recs,
305e8d8bef9SDimitry Andric source->mergedIpi.recSizes,
306e8d8bef9SDimitry Andric source->mergedIpi.recHashes);
307fcaf7f86SDimitry Andric }
3080b57cec5SDimitry Andric }
3090b57cec5SDimitry Andric
3100b57cec5SDimitry Andric static void
recordStringTableReferences(CVSymbol sym,uint32_t symOffset,std::vector<StringTableFixup> & stringTableFixups)311e8d8bef9SDimitry Andric recordStringTableReferences(CVSymbol sym, uint32_t symOffset,
312e8d8bef9SDimitry Andric std::vector<StringTableFixup> &stringTableFixups) {
3130b57cec5SDimitry Andric // For now we only handle S_FILESTATIC, but we may need the same logic for
3140b57cec5SDimitry Andric // S_DEFRANGE and S_DEFRANGE_SUBFIELD. However, I cannot seem to generate any
3150b57cec5SDimitry Andric // PDBs that contain these types of records, so because of the uncertainty
3160b57cec5SDimitry Andric // they are omitted here until we can prove that it's necessary.
317e8d8bef9SDimitry Andric switch (sym.kind()) {
318e8d8bef9SDimitry Andric case SymbolKind::S_FILESTATIC: {
3190b57cec5SDimitry Andric // FileStaticSym::ModFileOffset
320e8d8bef9SDimitry Andric uint32_t ref = *reinterpret_cast<const ulittle32_t *>(&sym.data()[8]);
321e8d8bef9SDimitry Andric stringTableFixups.push_back({ref, symOffset + 8});
3220b57cec5SDimitry Andric break;
323e8d8bef9SDimitry Andric }
3240b57cec5SDimitry Andric case SymbolKind::S_DEFRANGE:
3250b57cec5SDimitry Andric case SymbolKind::S_DEFRANGE_SUBFIELD:
3260b57cec5SDimitry Andric log("Not fixing up string table reference in S_DEFRANGE / "
3270b57cec5SDimitry Andric "S_DEFRANGE_SUBFIELD record");
3280b57cec5SDimitry Andric break;
3290b57cec5SDimitry Andric default:
3300b57cec5SDimitry Andric break;
3310b57cec5SDimitry Andric }
3320b57cec5SDimitry Andric }
3330b57cec5SDimitry Andric
symbolKind(ArrayRef<uint8_t> recordData)3340b57cec5SDimitry Andric static SymbolKind symbolKind(ArrayRef<uint8_t> recordData) {
3350b57cec5SDimitry Andric const RecordPrefix *prefix =
3360b57cec5SDimitry Andric reinterpret_cast<const RecordPrefix *>(recordData.data());
3370b57cec5SDimitry Andric return static_cast<SymbolKind>(uint16_t(prefix->RecordKind));
3380b57cec5SDimitry Andric }
3390b57cec5SDimitry Andric
3400b57cec5SDimitry Andric /// MSVC translates S_PROC_ID_END to S_END, and S_[LG]PROC32_ID to S_[LG]PROC32
translateIdSymbols(MutableArrayRef<uint8_t> & recordData,TpiSource * source)341bdd1243dSDimitry Andric void PDBLinker::translateIdSymbols(MutableArrayRef<uint8_t> &recordData,
342bdd1243dSDimitry Andric TpiSource *source) {
3430b57cec5SDimitry Andric RecordPrefix *prefix = reinterpret_cast<RecordPrefix *>(recordData.data());
3440b57cec5SDimitry Andric
3450b57cec5SDimitry Andric SymbolKind kind = symbolKind(recordData);
3460b57cec5SDimitry Andric
3470b57cec5SDimitry Andric if (kind == SymbolKind::S_PROC_ID_END) {
3480b57cec5SDimitry Andric prefix->RecordKind = SymbolKind::S_END;
3490b57cec5SDimitry Andric return;
3500b57cec5SDimitry Andric }
3510b57cec5SDimitry Andric
3520b57cec5SDimitry Andric // In an object file, GPROC32_ID has an embedded reference which refers to the
3530b57cec5SDimitry Andric // single object file type index namespace. This has already been translated
3540b57cec5SDimitry Andric // to the PDB file's ID stream index space, but we need to convert this to a
3550b57cec5SDimitry Andric // symbol that refers to the type stream index space. So we remap again from
3560b57cec5SDimitry Andric // ID index space to type index space.
3570b57cec5SDimitry Andric if (kind == SymbolKind::S_GPROC32_ID || kind == SymbolKind::S_LPROC32_ID) {
3580b57cec5SDimitry Andric SmallVector<TiReference, 1> refs;
3590b57cec5SDimitry Andric auto content = recordData.drop_front(sizeof(RecordPrefix));
3600b57cec5SDimitry Andric CVSymbol sym(recordData);
3610b57cec5SDimitry Andric discoverTypeIndicesInSymbol(sym, refs);
3620b57cec5SDimitry Andric assert(refs.size() == 1);
3630b57cec5SDimitry Andric assert(refs.front().Count == 1);
3640b57cec5SDimitry Andric
3650b57cec5SDimitry Andric TypeIndex *ti =
3660b57cec5SDimitry Andric reinterpret_cast<TypeIndex *>(content.data() + refs[0].Offset);
3670b57cec5SDimitry Andric // `ti` is the index of a FuncIdRecord or MemberFuncIdRecord which lives in
3680b57cec5SDimitry Andric // the IPI stream, whose `FunctionType` member refers to the TPI stream.
369e8d8bef9SDimitry Andric // Note that LF_FUNC_ID and LF_MFUNC_ID have the same record layout, and
3700b57cec5SDimitry Andric // in both cases we just need the second type index.
3710b57cec5SDimitry Andric if (!ti->isSimple() && !ti->isNoneType()) {
372fe6060f1SDimitry Andric TypeIndex newType = TypeIndex(SimpleTypeKind::NotTranslated);
373bdd1243dSDimitry Andric if (ctx.config.debugGHashes) {
374e8d8bef9SDimitry Andric auto idToType = tMerger.funcIdToType.find(*ti);
375fe6060f1SDimitry Andric if (idToType != tMerger.funcIdToType.end())
376fe6060f1SDimitry Andric newType = idToType->second;
377e8d8bef9SDimitry Andric } else {
378fe6060f1SDimitry Andric if (tMerger.getIDTable().contains(*ti)) {
379e8d8bef9SDimitry Andric CVType funcIdData = tMerger.getIDTable().getType(*ti);
380fe6060f1SDimitry Andric if (funcIdData.length() >= 8 && (funcIdData.kind() == LF_FUNC_ID ||
381fe6060f1SDimitry Andric funcIdData.kind() == LF_MFUNC_ID)) {
382fe6060f1SDimitry Andric newType = *reinterpret_cast<const TypeIndex *>(&funcIdData.data()[8]);
3830b57cec5SDimitry Andric }
384e8d8bef9SDimitry Andric }
385fe6060f1SDimitry Andric }
386fe6060f1SDimitry Andric if (newType == TypeIndex(SimpleTypeKind::NotTranslated)) {
387fe6060f1SDimitry Andric warn(formatv("procedure symbol record for `{0}` in {1} refers to PDB "
388fe6060f1SDimitry Andric "item index {2:X} which is not a valid function ID record",
389fe6060f1SDimitry Andric getSymbolName(CVSymbol(recordData)),
390fe6060f1SDimitry Andric source->file->getName(), ti->getIndex()));
391fe6060f1SDimitry Andric }
392fe6060f1SDimitry Andric *ti = newType;
393fe6060f1SDimitry Andric }
3940b57cec5SDimitry Andric
3950b57cec5SDimitry Andric kind = (kind == SymbolKind::S_GPROC32_ID) ? SymbolKind::S_GPROC32
3960b57cec5SDimitry Andric : SymbolKind::S_LPROC32;
3970b57cec5SDimitry Andric prefix->RecordKind = uint16_t(kind);
3980b57cec5SDimitry Andric }
3990b57cec5SDimitry Andric }
4000b57cec5SDimitry Andric
401e8d8bef9SDimitry Andric namespace {
4020b57cec5SDimitry Andric struct ScopeRecord {
4030b57cec5SDimitry Andric ulittle32_t ptrParent;
4040b57cec5SDimitry Andric ulittle32_t ptrEnd;
4050b57cec5SDimitry Andric };
406e8d8bef9SDimitry Andric } // namespace
4070b57cec5SDimitry Andric
408e8d8bef9SDimitry Andric /// Given a pointer to a symbol record that opens a scope, return a pointer to
409e8d8bef9SDimitry Andric /// the scope fields.
getSymbolScopeFields(void * sym)410e8d8bef9SDimitry Andric static ScopeRecord *getSymbolScopeFields(void *sym) {
411e8d8bef9SDimitry Andric return reinterpret_cast<ScopeRecord *>(reinterpret_cast<char *>(sym) +
412e8d8bef9SDimitry Andric sizeof(RecordPrefix));
4130b57cec5SDimitry Andric }
4140b57cec5SDimitry Andric
415e8d8bef9SDimitry Andric // To open a scope, push the offset of the current symbol record onto the
416e8d8bef9SDimitry Andric // stack.
scopeStackOpen(SmallVectorImpl<uint32_t> & stack,std::vector<uint8_t> & storage)417e8d8bef9SDimitry Andric static void scopeStackOpen(SmallVectorImpl<uint32_t> &stack,
418e8d8bef9SDimitry Andric std::vector<uint8_t> &storage) {
419e8d8bef9SDimitry Andric stack.push_back(storage.size());
420e8d8bef9SDimitry Andric }
421e8d8bef9SDimitry Andric
422e8d8bef9SDimitry Andric // To close a scope, update the record that opened the scope.
scopeStackClose(SmallVectorImpl<uint32_t> & stack,std::vector<uint8_t> & storage,uint32_t storageBaseOffset,ObjFile * file)423e8d8bef9SDimitry Andric static void scopeStackClose(SmallVectorImpl<uint32_t> &stack,
424e8d8bef9SDimitry Andric std::vector<uint8_t> &storage,
425e8d8bef9SDimitry Andric uint32_t storageBaseOffset, ObjFile *file) {
4260b57cec5SDimitry Andric if (stack.empty()) {
4270b57cec5SDimitry Andric warn("symbol scopes are not balanced in " + file->getName());
4280b57cec5SDimitry Andric return;
4290b57cec5SDimitry Andric }
430e8d8bef9SDimitry Andric
431e8d8bef9SDimitry Andric // Update ptrEnd of the record that opened the scope to point to the
432e8d8bef9SDimitry Andric // current record, if we are writing into the module symbol stream.
433e8d8bef9SDimitry Andric uint32_t offOpen = stack.pop_back_val();
434e8d8bef9SDimitry Andric uint32_t offEnd = storageBaseOffset + storage.size();
435e8d8bef9SDimitry Andric uint32_t offParent = stack.empty() ? 0 : (stack.back() + storageBaseOffset);
436e8d8bef9SDimitry Andric ScopeRecord *scopeRec = getSymbolScopeFields(&(storage)[offOpen]);
437e8d8bef9SDimitry Andric scopeRec->ptrParent = offParent;
438e8d8bef9SDimitry Andric scopeRec->ptrEnd = offEnd;
4390b57cec5SDimitry Andric }
4400b57cec5SDimitry Andric
symbolGoesInModuleStream(const CVSymbol & sym,unsigned symbolScopeDepth)441e8d8bef9SDimitry Andric static bool symbolGoesInModuleStream(const CVSymbol &sym,
442e8d8bef9SDimitry Andric unsigned symbolScopeDepth) {
4430b57cec5SDimitry Andric switch (sym.kind()) {
4440b57cec5SDimitry Andric case SymbolKind::S_GDATA32:
4455ffd83dbSDimitry Andric case SymbolKind::S_GTHREAD32:
4460b57cec5SDimitry Andric // We really should not be seeing S_PROCREF and S_LPROCREF in the first place
4470b57cec5SDimitry Andric // since they are synthesized by the linker in response to S_GPROC32 and
4480b57cec5SDimitry Andric // S_LPROC32, but if we do see them, don't put them in the module stream I
4490b57cec5SDimitry Andric // guess.
4500b57cec5SDimitry Andric case SymbolKind::S_PROCREF:
4510b57cec5SDimitry Andric case SymbolKind::S_LPROCREF:
4520b57cec5SDimitry Andric return false;
453bdd1243dSDimitry Andric // S_UDT and S_CONSTANT records go in the module stream if it is not a global record.
4540b57cec5SDimitry Andric case SymbolKind::S_UDT:
455bdd1243dSDimitry Andric case SymbolKind::S_CONSTANT:
456e8d8bef9SDimitry Andric return symbolScopeDepth > 0;
4570b57cec5SDimitry Andric // S_GDATA32 does not go in the module stream, but S_LDATA32 does.
4580b57cec5SDimitry Andric case SymbolKind::S_LDATA32:
4595ffd83dbSDimitry Andric case SymbolKind::S_LTHREAD32:
4600b57cec5SDimitry Andric default:
4610b57cec5SDimitry Andric return true;
4620b57cec5SDimitry Andric }
4630b57cec5SDimitry Andric }
4640b57cec5SDimitry Andric
symbolGoesInGlobalsStream(const CVSymbol & sym,unsigned symbolScopeDepth)4655ffd83dbSDimitry Andric static bool symbolGoesInGlobalsStream(const CVSymbol &sym,
466e8d8bef9SDimitry Andric unsigned symbolScopeDepth) {
4670b57cec5SDimitry Andric switch (sym.kind()) {
4680b57cec5SDimitry Andric case SymbolKind::S_GDATA32:
4695ffd83dbSDimitry Andric case SymbolKind::S_GTHREAD32:
4700b57cec5SDimitry Andric case SymbolKind::S_GPROC32:
4710b57cec5SDimitry Andric case SymbolKind::S_LPROC32:
472e8d8bef9SDimitry Andric case SymbolKind::S_GPROC32_ID:
473e8d8bef9SDimitry Andric case SymbolKind::S_LPROC32_ID:
4740b57cec5SDimitry Andric // We really should not be seeing S_PROCREF and S_LPROCREF in the first place
4750b57cec5SDimitry Andric // since they are synthesized by the linker in response to S_GPROC32 and
4760b57cec5SDimitry Andric // S_LPROC32, but if we do see them, copy them straight through.
4770b57cec5SDimitry Andric case SymbolKind::S_PROCREF:
4780b57cec5SDimitry Andric case SymbolKind::S_LPROCREF:
4790b57cec5SDimitry Andric return true;
4805ffd83dbSDimitry Andric // Records that go in the globals stream, unless they are function-local.
4810b57cec5SDimitry Andric case SymbolKind::S_UDT:
4825ffd83dbSDimitry Andric case SymbolKind::S_LDATA32:
4835ffd83dbSDimitry Andric case SymbolKind::S_LTHREAD32:
484bdd1243dSDimitry Andric case SymbolKind::S_CONSTANT:
485e8d8bef9SDimitry Andric return symbolScopeDepth == 0;
4860b57cec5SDimitry Andric default:
4870b57cec5SDimitry Andric return false;
4880b57cec5SDimitry Andric }
4890b57cec5SDimitry Andric }
4900b57cec5SDimitry Andric
addGlobalSymbol(pdb::GSIStreamBuilder & builder,uint16_t modIndex,unsigned symOffset,std::vector<uint8_t> & symStorage)4910b57cec5SDimitry Andric static void addGlobalSymbol(pdb::GSIStreamBuilder &builder, uint16_t modIndex,
492e8d8bef9SDimitry Andric unsigned symOffset,
493e8d8bef9SDimitry Andric std::vector<uint8_t> &symStorage) {
494bdd1243dSDimitry Andric CVSymbol sym{ArrayRef(symStorage)};
4950b57cec5SDimitry Andric switch (sym.kind()) {
4960b57cec5SDimitry Andric case SymbolKind::S_CONSTANT:
4970b57cec5SDimitry Andric case SymbolKind::S_UDT:
4980b57cec5SDimitry Andric case SymbolKind::S_GDATA32:
4995ffd83dbSDimitry Andric case SymbolKind::S_GTHREAD32:
5005ffd83dbSDimitry Andric case SymbolKind::S_LTHREAD32:
5010b57cec5SDimitry Andric case SymbolKind::S_LDATA32:
5020b57cec5SDimitry Andric case SymbolKind::S_PROCREF:
503e8d8bef9SDimitry Andric case SymbolKind::S_LPROCREF: {
504e8d8bef9SDimitry Andric // sym is a temporary object, so we have to copy and reallocate the record
505e8d8bef9SDimitry Andric // to stabilize it.
50604eeddc0SDimitry Andric uint8_t *mem = bAlloc().Allocate<uint8_t>(sym.length());
507e8d8bef9SDimitry Andric memcpy(mem, sym.data().data(), sym.length());
508bdd1243dSDimitry Andric builder.addGlobalSymbol(CVSymbol(ArrayRef(mem, sym.length())));
5090b57cec5SDimitry Andric break;
510e8d8bef9SDimitry Andric }
5110b57cec5SDimitry Andric case SymbolKind::S_GPROC32:
5120b57cec5SDimitry Andric case SymbolKind::S_LPROC32: {
5130b57cec5SDimitry Andric SymbolRecordKind k = SymbolRecordKind::ProcRefSym;
5140b57cec5SDimitry Andric if (sym.kind() == SymbolKind::S_LPROC32)
5150b57cec5SDimitry Andric k = SymbolRecordKind::LocalProcRef;
5160b57cec5SDimitry Andric ProcRefSym ps(k);
5170b57cec5SDimitry Andric ps.Module = modIndex;
5180b57cec5SDimitry Andric // For some reason, MSVC seems to add one to this value.
5190b57cec5SDimitry Andric ++ps.Module;
5200b57cec5SDimitry Andric ps.Name = getSymbolName(sym);
5210b57cec5SDimitry Andric ps.SumName = 0;
5220b57cec5SDimitry Andric ps.SymOffset = symOffset;
5230b57cec5SDimitry Andric builder.addGlobalSymbol(ps);
5240b57cec5SDimitry Andric break;
5250b57cec5SDimitry Andric }
5260b57cec5SDimitry Andric default:
5270b57cec5SDimitry Andric llvm_unreachable("Invalid symbol kind!");
5280b57cec5SDimitry Andric }
5290b57cec5SDimitry Andric }
5300b57cec5SDimitry Andric
531e8d8bef9SDimitry Andric // Check if the given symbol record was padded for alignment. If so, zero out
532e8d8bef9SDimitry Andric // the padding bytes and update the record prefix with the new size.
fixRecordAlignment(MutableArrayRef<uint8_t> recordBytes,size_t oldSize)533e8d8bef9SDimitry Andric static void fixRecordAlignment(MutableArrayRef<uint8_t> recordBytes,
534e8d8bef9SDimitry Andric size_t oldSize) {
535e8d8bef9SDimitry Andric size_t alignedSize = recordBytes.size();
536e8d8bef9SDimitry Andric if (oldSize == alignedSize)
5370b57cec5SDimitry Andric return;
538e8d8bef9SDimitry Andric reinterpret_cast<RecordPrefix *>(recordBytes.data())->RecordLen =
539e8d8bef9SDimitry Andric alignedSize - 2;
540e8d8bef9SDimitry Andric memset(recordBytes.data() + oldSize, 0, alignedSize - oldSize);
5410b57cec5SDimitry Andric }
5420b57cec5SDimitry Andric
543e8d8bef9SDimitry Andric // Replace any record with a skip record of the same size. This is useful when
544e8d8bef9SDimitry Andric // we have reserved size for a symbol record, but type index remapping fails.
replaceWithSkipRecord(MutableArrayRef<uint8_t> recordBytes)545e8d8bef9SDimitry Andric static void replaceWithSkipRecord(MutableArrayRef<uint8_t> recordBytes) {
546e8d8bef9SDimitry Andric memset(recordBytes.data(), 0, recordBytes.size());
547e8d8bef9SDimitry Andric auto *prefix = reinterpret_cast<RecordPrefix *>(recordBytes.data());
548e8d8bef9SDimitry Andric prefix->RecordKind = SymbolKind::S_SKIP;
549e8d8bef9SDimitry Andric prefix->RecordLen = recordBytes.size() - 2;
5500b57cec5SDimitry Andric }
5510b57cec5SDimitry Andric
552e8d8bef9SDimitry Andric // Copy the symbol record, relocate it, and fix the alignment if necessary.
553e8d8bef9SDimitry Andric // Rewrite type indices in the record. Replace unrecognized symbol records with
554e8d8bef9SDimitry Andric // S_SKIP records.
writeSymbolRecord(SectionChunk * debugChunk,ArrayRef<uint8_t> sectionContents,CVSymbol sym,size_t alignedSize,uint32_t & nextRelocIndex,std::vector<uint8_t> & storage)555e8d8bef9SDimitry Andric void PDBLinker::writeSymbolRecord(SectionChunk *debugChunk,
556e8d8bef9SDimitry Andric ArrayRef<uint8_t> sectionContents,
557e8d8bef9SDimitry Andric CVSymbol sym, size_t alignedSize,
558e8d8bef9SDimitry Andric uint32_t &nextRelocIndex,
559e8d8bef9SDimitry Andric std::vector<uint8_t> &storage) {
560e8d8bef9SDimitry Andric // Allocate space for the new record at the end of the storage.
561e8d8bef9SDimitry Andric storage.resize(storage.size() + alignedSize);
562e8d8bef9SDimitry Andric auto recordBytes = MutableArrayRef<uint8_t>(storage).take_back(alignedSize);
5630b57cec5SDimitry Andric
564e8d8bef9SDimitry Andric // Copy the symbol record and relocate it.
565e8d8bef9SDimitry Andric debugChunk->writeAndRelocateSubsection(sectionContents, sym.data(),
566e8d8bef9SDimitry Andric nextRelocIndex, recordBytes.data());
567e8d8bef9SDimitry Andric fixRecordAlignment(recordBytes, sym.length());
5680b57cec5SDimitry Andric
5690b57cec5SDimitry Andric // Re-map all the type index references.
570e8d8bef9SDimitry Andric TpiSource *source = debugChunk->file->debugTypesObj;
571e8d8bef9SDimitry Andric if (!source->remapTypesInSymbolRecord(recordBytes)) {
572e8d8bef9SDimitry Andric log("ignoring unknown symbol record with kind 0x" + utohexstr(sym.kind()));
573e8d8bef9SDimitry Andric replaceWithSkipRecord(recordBytes);
574e8d8bef9SDimitry Andric }
5750b57cec5SDimitry Andric
5760b57cec5SDimitry Andric // An object file may have S_xxx_ID symbols, but these get converted to
5770b57cec5SDimitry Andric // "real" symbols in a PDB.
578bdd1243dSDimitry Andric translateIdSymbols(recordBytes, source);
579e8d8bef9SDimitry Andric }
5800b57cec5SDimitry Andric
analyzeSymbolSubsection(SectionChunk * debugChunk,uint32_t & moduleSymOffset,uint32_t & nextRelocIndex,std::vector<StringTableFixup> & stringTableFixups,BinaryStreamRef symData)581e8d8bef9SDimitry Andric void PDBLinker::analyzeSymbolSubsection(
582e8d8bef9SDimitry Andric SectionChunk *debugChunk, uint32_t &moduleSymOffset,
583e8d8bef9SDimitry Andric uint32_t &nextRelocIndex, std::vector<StringTableFixup> &stringTableFixups,
584e8d8bef9SDimitry Andric BinaryStreamRef symData) {
585e8d8bef9SDimitry Andric ObjFile *file = debugChunk->file;
586e8d8bef9SDimitry Andric uint32_t moduleSymStart = moduleSymOffset;
5870b57cec5SDimitry Andric
588e8d8bef9SDimitry Andric uint32_t scopeLevel = 0;
589e8d8bef9SDimitry Andric std::vector<uint8_t> storage;
590e8d8bef9SDimitry Andric ArrayRef<uint8_t> sectionContents = debugChunk->getContents();
591e8d8bef9SDimitry Andric
592e8d8bef9SDimitry Andric ArrayRef<uint8_t> symsBuffer;
593e8d8bef9SDimitry Andric cantFail(symData.readBytes(0, symData.getLength(), symsBuffer));
594e8d8bef9SDimitry Andric
595e8d8bef9SDimitry Andric if (symsBuffer.empty())
596e8d8bef9SDimitry Andric warn("empty symbols subsection in " + file->getName());
597e8d8bef9SDimitry Andric
598e8d8bef9SDimitry Andric Error ec = forEachCodeViewRecord<CVSymbol>(
599e8d8bef9SDimitry Andric symsBuffer, [&](CVSymbol sym) -> llvm::Error {
600e8d8bef9SDimitry Andric // Track the current scope.
6010b57cec5SDimitry Andric if (symbolOpensScope(sym.kind()))
602e8d8bef9SDimitry Andric ++scopeLevel;
6030b57cec5SDimitry Andric else if (symbolEndsScope(sym.kind()))
604e8d8bef9SDimitry Andric --scopeLevel;
6050b57cec5SDimitry Andric
606e8d8bef9SDimitry Andric uint32_t alignedSize =
607e8d8bef9SDimitry Andric alignTo(sym.length(), alignOf(CodeViewContainer::Pdb));
608e8d8bef9SDimitry Andric
609e8d8bef9SDimitry Andric // Copy global records. Some global records (mainly procedures)
610e8d8bef9SDimitry Andric // reference the current offset into the module stream.
611e8d8bef9SDimitry Andric if (symbolGoesInGlobalsStream(sym, scopeLevel)) {
612e8d8bef9SDimitry Andric storage.clear();
613e8d8bef9SDimitry Andric writeSymbolRecord(debugChunk, sectionContents, sym, alignedSize,
614e8d8bef9SDimitry Andric nextRelocIndex, storage);
6150b57cec5SDimitry Andric addGlobalSymbol(builder.getGsiBuilder(),
616e8d8bef9SDimitry Andric file->moduleDBI->getModuleIndex(), moduleSymOffset,
617e8d8bef9SDimitry Andric storage);
6180b57cec5SDimitry Andric ++globalSymbols;
6190b57cec5SDimitry Andric }
6200b57cec5SDimitry Andric
621e8d8bef9SDimitry Andric // Update the module stream offset and record any string table index
622e8d8bef9SDimitry Andric // references. There are very few of these and they will be rewritten
623e8d8bef9SDimitry Andric // later during PDB writing.
624e8d8bef9SDimitry Andric if (symbolGoesInModuleStream(sym, scopeLevel)) {
625e8d8bef9SDimitry Andric recordStringTableReferences(sym, moduleSymOffset, stringTableFixups);
626e8d8bef9SDimitry Andric moduleSymOffset += alignedSize;
6270b57cec5SDimitry Andric ++moduleSymbols;
6280b57cec5SDimitry Andric }
6290b57cec5SDimitry Andric
630e8d8bef9SDimitry Andric return Error::success();
631e8d8bef9SDimitry Andric });
632e8d8bef9SDimitry Andric
633e8d8bef9SDimitry Andric // If we encountered corrupt records, ignore the whole subsection. If we wrote
634e8d8bef9SDimitry Andric // any partial records, undo that. For globals, we just keep what we have and
635e8d8bef9SDimitry Andric // continue.
636e8d8bef9SDimitry Andric if (ec) {
637e8d8bef9SDimitry Andric warn("corrupt symbol records in " + file->getName());
638e8d8bef9SDimitry Andric moduleSymOffset = moduleSymStart;
639e8d8bef9SDimitry Andric consumeError(std::move(ec));
640e8d8bef9SDimitry Andric }
641e8d8bef9SDimitry Andric }
642e8d8bef9SDimitry Andric
writeAllModuleSymbolRecords(ObjFile * file,BinaryStreamWriter & writer)643e8d8bef9SDimitry Andric Error PDBLinker::writeAllModuleSymbolRecords(ObjFile *file,
644e8d8bef9SDimitry Andric BinaryStreamWriter &writer) {
645bdd1243dSDimitry Andric ExitOnError exitOnErr;
646e8d8bef9SDimitry Andric std::vector<uint8_t> storage;
647e8d8bef9SDimitry Andric SmallVector<uint32_t, 4> scopes;
648e8d8bef9SDimitry Andric
649e8d8bef9SDimitry Andric // Visit all live .debug$S sections a second time, and write them to the PDB.
650e8d8bef9SDimitry Andric for (SectionChunk *debugChunk : file->getDebugChunks()) {
651e8d8bef9SDimitry Andric if (!debugChunk->live || debugChunk->getSize() == 0 ||
652e8d8bef9SDimitry Andric debugChunk->getSectionName() != ".debug$S")
653e8d8bef9SDimitry Andric continue;
654e8d8bef9SDimitry Andric
655e8d8bef9SDimitry Andric ArrayRef<uint8_t> sectionContents = debugChunk->getContents();
656e8d8bef9SDimitry Andric auto contents =
657e8d8bef9SDimitry Andric SectionChunk::consumeDebugMagic(sectionContents, ".debug$S");
658e8d8bef9SDimitry Andric DebugSubsectionArray subsections;
6595f757f3fSDimitry Andric BinaryStreamReader reader(contents, llvm::endianness::little);
660e8d8bef9SDimitry Andric exitOnErr(reader.readArray(subsections, contents.size()));
661e8d8bef9SDimitry Andric
662e8d8bef9SDimitry Andric uint32_t nextRelocIndex = 0;
663e8d8bef9SDimitry Andric for (const DebugSubsectionRecord &ss : subsections) {
664e8d8bef9SDimitry Andric if (ss.kind() != DebugSubsectionKind::Symbols)
665e8d8bef9SDimitry Andric continue;
666e8d8bef9SDimitry Andric
667e8d8bef9SDimitry Andric uint32_t moduleSymStart = writer.getOffset();
668e8d8bef9SDimitry Andric scopes.clear();
669e8d8bef9SDimitry Andric storage.clear();
670e8d8bef9SDimitry Andric ArrayRef<uint8_t> symsBuffer;
671e8d8bef9SDimitry Andric BinaryStreamRef sr = ss.getRecordData();
672e8d8bef9SDimitry Andric cantFail(sr.readBytes(0, sr.getLength(), symsBuffer));
673e8d8bef9SDimitry Andric auto ec = forEachCodeViewRecord<CVSymbol>(
674e8d8bef9SDimitry Andric symsBuffer, [&](CVSymbol sym) -> llvm::Error {
675e8d8bef9SDimitry Andric // Track the current scope. Only update records in the postmerge
676e8d8bef9SDimitry Andric // pass.
677e8d8bef9SDimitry Andric if (symbolOpensScope(sym.kind()))
678e8d8bef9SDimitry Andric scopeStackOpen(scopes, storage);
679e8d8bef9SDimitry Andric else if (symbolEndsScope(sym.kind()))
680e8d8bef9SDimitry Andric scopeStackClose(scopes, storage, moduleSymStart, file);
681e8d8bef9SDimitry Andric
682e8d8bef9SDimitry Andric // Copy, relocate, and rewrite each module symbol.
683e8d8bef9SDimitry Andric if (symbolGoesInModuleStream(sym, scopes.size())) {
684e8d8bef9SDimitry Andric uint32_t alignedSize =
685e8d8bef9SDimitry Andric alignTo(sym.length(), alignOf(CodeViewContainer::Pdb));
686e8d8bef9SDimitry Andric writeSymbolRecord(debugChunk, sectionContents, sym, alignedSize,
687e8d8bef9SDimitry Andric nextRelocIndex, storage);
688e8d8bef9SDimitry Andric }
689e8d8bef9SDimitry Andric return Error::success();
690e8d8bef9SDimitry Andric });
691e8d8bef9SDimitry Andric
692e8d8bef9SDimitry Andric // If we encounter corrupt records in the second pass, ignore them. We
693e8d8bef9SDimitry Andric // already warned about them in the first analysis pass.
694e8d8bef9SDimitry Andric if (ec) {
695e8d8bef9SDimitry Andric consumeError(std::move(ec));
696e8d8bef9SDimitry Andric storage.clear();
697e8d8bef9SDimitry Andric }
698e8d8bef9SDimitry Andric
699e8d8bef9SDimitry Andric // Writing bytes has a very high overhead, so write the entire subsection
700e8d8bef9SDimitry Andric // at once.
701e8d8bef9SDimitry Andric // TODO: Consider buffering symbols for the entire object file to reduce
702e8d8bef9SDimitry Andric // overhead even further.
703e8d8bef9SDimitry Andric if (Error e = writer.writeBytes(storage))
704e8d8bef9SDimitry Andric return e;
705e8d8bef9SDimitry Andric }
706e8d8bef9SDimitry Andric }
707e8d8bef9SDimitry Andric
708e8d8bef9SDimitry Andric return Error::success();
709e8d8bef9SDimitry Andric }
710e8d8bef9SDimitry Andric
commitSymbolsForObject(void * ctx,void * obj,BinaryStreamWriter & writer)711e8d8bef9SDimitry Andric Error PDBLinker::commitSymbolsForObject(void *ctx, void *obj,
712e8d8bef9SDimitry Andric BinaryStreamWriter &writer) {
713e8d8bef9SDimitry Andric return static_cast<PDBLinker *>(ctx)->writeAllModuleSymbolRecords(
714e8d8bef9SDimitry Andric static_cast<ObjFile *>(obj), writer);
7150b57cec5SDimitry Andric }
7160b57cec5SDimitry Andric
createSectionContrib(COFFLinkerContext & ctx,const Chunk * c,uint32_t modi)717349cc55cSDimitry Andric static pdb::SectionContrib createSectionContrib(COFFLinkerContext &ctx,
718349cc55cSDimitry Andric const Chunk *c, uint32_t modi) {
719349cc55cSDimitry Andric OutputSection *os = c ? ctx.getOutputSection(c) : nullptr;
7200b57cec5SDimitry Andric pdb::SectionContrib sc;
7210b57cec5SDimitry Andric memset(&sc, 0, sizeof(sc));
7220b57cec5SDimitry Andric sc.ISect = os ? os->sectionIndex : llvm::pdb::kInvalidStreamIndex;
7230b57cec5SDimitry Andric sc.Off = c && os ? c->getRVA() - os->getRVA() : 0;
7240b57cec5SDimitry Andric sc.Size = c ? c->getSize() : -1;
7250b57cec5SDimitry Andric if (auto *secChunk = dyn_cast_or_null<SectionChunk>(c)) {
7260b57cec5SDimitry Andric sc.Characteristics = secChunk->header->Characteristics;
7270b57cec5SDimitry Andric sc.Imod = secChunk->file->moduleDBI->getModuleIndex();
7280b57cec5SDimitry Andric ArrayRef<uint8_t> contents = secChunk->getContents();
7290b57cec5SDimitry Andric JamCRC crc(0);
73085868e8aSDimitry Andric crc.update(contents);
7310b57cec5SDimitry Andric sc.DataCrc = crc.getCRC();
7320b57cec5SDimitry Andric } else {
7330b57cec5SDimitry Andric sc.Characteristics = os ? os->header.Characteristics : 0;
7340b57cec5SDimitry Andric sc.Imod = modi;
7350b57cec5SDimitry Andric }
7360b57cec5SDimitry Andric sc.RelocCrc = 0; // FIXME
7370b57cec5SDimitry Andric
7380b57cec5SDimitry Andric return sc;
7390b57cec5SDimitry Andric }
7400b57cec5SDimitry Andric
7410b57cec5SDimitry Andric static uint32_t
translateStringTableIndex(uint32_t objIndex,const DebugStringTableSubsectionRef & objStrTable,DebugStringTableSubsection & pdbStrTable)7420b57cec5SDimitry Andric translateStringTableIndex(uint32_t objIndex,
7430b57cec5SDimitry Andric const DebugStringTableSubsectionRef &objStrTable,
7440b57cec5SDimitry Andric DebugStringTableSubsection &pdbStrTable) {
7450b57cec5SDimitry Andric auto expectedString = objStrTable.getString(objIndex);
7460b57cec5SDimitry Andric if (!expectedString) {
7470b57cec5SDimitry Andric warn("Invalid string table reference");
7480b57cec5SDimitry Andric consumeError(expectedString.takeError());
7490b57cec5SDimitry Andric return 0;
7500b57cec5SDimitry Andric }
7510b57cec5SDimitry Andric
7520b57cec5SDimitry Andric return pdbStrTable.insert(*expectedString);
7530b57cec5SDimitry Andric }
7540b57cec5SDimitry Andric
handleDebugS(SectionChunk * debugChunk)755e8d8bef9SDimitry Andric void DebugSHandler::handleDebugS(SectionChunk *debugChunk) {
756e8d8bef9SDimitry Andric // Note that we are processing the *unrelocated* section contents. They will
757e8d8bef9SDimitry Andric // be relocated later during PDB writing.
758e8d8bef9SDimitry Andric ArrayRef<uint8_t> contents = debugChunk->getContents();
759e8d8bef9SDimitry Andric contents = SectionChunk::consumeDebugMagic(contents, ".debug$S");
7600b57cec5SDimitry Andric DebugSubsectionArray subsections;
7615f757f3fSDimitry Andric BinaryStreamReader reader(contents, llvm::endianness::little);
762bdd1243dSDimitry Andric ExitOnError exitOnErr;
763e8d8bef9SDimitry Andric exitOnErr(reader.readArray(subsections, contents.size()));
764e8d8bef9SDimitry Andric debugChunk->sortRelocations();
7650b57cec5SDimitry Andric
766e8d8bef9SDimitry Andric // Reset the relocation index, since this is a new section.
767e8d8bef9SDimitry Andric nextRelocIndex = 0;
7685ffd83dbSDimitry Andric
7690b57cec5SDimitry Andric for (const DebugSubsectionRecord &ss : subsections) {
7700b57cec5SDimitry Andric // Ignore subsections with the 'ignore' bit. Some versions of the Visual C++
7710b57cec5SDimitry Andric // runtime have subsections with this bit set.
7720b57cec5SDimitry Andric if (uint32_t(ss.kind()) & codeview::SubsectionIgnoreFlag)
7730b57cec5SDimitry Andric continue;
7740b57cec5SDimitry Andric
7750b57cec5SDimitry Andric switch (ss.kind()) {
7760b57cec5SDimitry Andric case DebugSubsectionKind::StringTable: {
7775ffd83dbSDimitry Andric assert(!cvStrTab.valid() &&
7780b57cec5SDimitry Andric "Encountered multiple string table subsections!");
7795ffd83dbSDimitry Andric exitOnErr(cvStrTab.initialize(ss.getRecordData()));
7800b57cec5SDimitry Andric break;
7810b57cec5SDimitry Andric }
7820b57cec5SDimitry Andric case DebugSubsectionKind::FileChecksums:
7830b57cec5SDimitry Andric assert(!checksums.valid() &&
7840b57cec5SDimitry Andric "Encountered multiple checksum subsections!");
7850b57cec5SDimitry Andric exitOnErr(checksums.initialize(ss.getRecordData()));
7860b57cec5SDimitry Andric break;
7870b57cec5SDimitry Andric case DebugSubsectionKind::Lines:
7880b57cec5SDimitry Andric case DebugSubsectionKind::InlineeLines:
789e8d8bef9SDimitry Andric addUnrelocatedSubsection(debugChunk, ss);
7900b57cec5SDimitry Andric break;
791e8d8bef9SDimitry Andric case DebugSubsectionKind::FrameData:
792e8d8bef9SDimitry Andric addFrameDataSubsection(debugChunk, ss);
7930b57cec5SDimitry Andric break;
794e8d8bef9SDimitry Andric case DebugSubsectionKind::Symbols:
795e8d8bef9SDimitry Andric linker.analyzeSymbolSubsection(debugChunk, moduleStreamSize,
796e8d8bef9SDimitry Andric nextRelocIndex, stringTableFixups,
7970b57cec5SDimitry Andric ss.getRecordData());
7980b57cec5SDimitry Andric break;
7990b57cec5SDimitry Andric
8000b57cec5SDimitry Andric case DebugSubsectionKind::CrossScopeImports:
8010b57cec5SDimitry Andric case DebugSubsectionKind::CrossScopeExports:
8020b57cec5SDimitry Andric // These appear to relate to cross-module optimization, so we might use
8030b57cec5SDimitry Andric // these for ThinLTO.
8040b57cec5SDimitry Andric break;
8050b57cec5SDimitry Andric
8060b57cec5SDimitry Andric case DebugSubsectionKind::ILLines:
8070b57cec5SDimitry Andric case DebugSubsectionKind::FuncMDTokenMap:
8080b57cec5SDimitry Andric case DebugSubsectionKind::TypeMDTokenMap:
8090b57cec5SDimitry Andric case DebugSubsectionKind::MergedAssemblyInput:
8100b57cec5SDimitry Andric // These appear to relate to .Net assembly info.
8110b57cec5SDimitry Andric break;
8120b57cec5SDimitry Andric
8130b57cec5SDimitry Andric case DebugSubsectionKind::CoffSymbolRVA:
8140b57cec5SDimitry Andric // Unclear what this is for.
8150b57cec5SDimitry Andric break;
8160b57cec5SDimitry Andric
81761cfbce3SDimitry Andric case DebugSubsectionKind::XfgHashType:
81861cfbce3SDimitry Andric case DebugSubsectionKind::XfgHashVirtual:
81961cfbce3SDimitry Andric break;
82061cfbce3SDimitry Andric
8210b57cec5SDimitry Andric default:
8220b57cec5SDimitry Andric warn("ignoring unknown debug$S subsection kind 0x" +
8230b57cec5SDimitry Andric utohexstr(uint32_t(ss.kind())) + " in file " + toString(&file));
8240b57cec5SDimitry Andric break;
8250b57cec5SDimitry Andric }
8260b57cec5SDimitry Andric }
8270b57cec5SDimitry Andric }
8280b57cec5SDimitry Andric
advanceRelocIndex(SectionChunk * sc,ArrayRef<uint8_t> subsec)829e8d8bef9SDimitry Andric void DebugSHandler::advanceRelocIndex(SectionChunk *sc,
830e8d8bef9SDimitry Andric ArrayRef<uint8_t> subsec) {
831e8d8bef9SDimitry Andric ptrdiff_t vaBegin = subsec.data() - sc->getContents().data();
832e8d8bef9SDimitry Andric assert(vaBegin > 0);
833e8d8bef9SDimitry Andric auto relocs = sc->getRelocs();
834e8d8bef9SDimitry Andric for (; nextRelocIndex < relocs.size(); ++nextRelocIndex) {
835*0fca6ea1SDimitry Andric if (relocs[nextRelocIndex].VirtualAddress >= (uint32_t)vaBegin)
836e8d8bef9SDimitry Andric break;
837e8d8bef9SDimitry Andric }
838e8d8bef9SDimitry Andric }
839e8d8bef9SDimitry Andric
840e8d8bef9SDimitry Andric namespace {
841e8d8bef9SDimitry Andric /// Wrapper class for unrelocated line and inlinee line subsections, which
842e8d8bef9SDimitry Andric /// require only relocation and type index remapping to add to the PDB.
843e8d8bef9SDimitry Andric class UnrelocatedDebugSubsection : public DebugSubsection {
844e8d8bef9SDimitry Andric public:
UnrelocatedDebugSubsection(DebugSubsectionKind k,SectionChunk * debugChunk,ArrayRef<uint8_t> subsec,uint32_t relocIndex)845e8d8bef9SDimitry Andric UnrelocatedDebugSubsection(DebugSubsectionKind k, SectionChunk *debugChunk,
846e8d8bef9SDimitry Andric ArrayRef<uint8_t> subsec, uint32_t relocIndex)
847e8d8bef9SDimitry Andric : DebugSubsection(k), debugChunk(debugChunk), subsec(subsec),
848e8d8bef9SDimitry Andric relocIndex(relocIndex) {}
849e8d8bef9SDimitry Andric
850e8d8bef9SDimitry Andric Error commit(BinaryStreamWriter &writer) const override;
calculateSerializedSize() const851e8d8bef9SDimitry Andric uint32_t calculateSerializedSize() const override { return subsec.size(); }
852e8d8bef9SDimitry Andric
853e8d8bef9SDimitry Andric SectionChunk *debugChunk;
854e8d8bef9SDimitry Andric ArrayRef<uint8_t> subsec;
855e8d8bef9SDimitry Andric uint32_t relocIndex;
856e8d8bef9SDimitry Andric };
857e8d8bef9SDimitry Andric } // namespace
858e8d8bef9SDimitry Andric
commit(BinaryStreamWriter & writer) const859e8d8bef9SDimitry Andric Error UnrelocatedDebugSubsection::commit(BinaryStreamWriter &writer) const {
860e8d8bef9SDimitry Andric std::vector<uint8_t> relocatedBytes(subsec.size());
861e8d8bef9SDimitry Andric uint32_t tmpRelocIndex = relocIndex;
862e8d8bef9SDimitry Andric debugChunk->writeAndRelocateSubsection(debugChunk->getContents(), subsec,
863e8d8bef9SDimitry Andric tmpRelocIndex, relocatedBytes.data());
864e8d8bef9SDimitry Andric
865e8d8bef9SDimitry Andric // Remap type indices in inlinee line records in place. Skip the remapping if
866e8d8bef9SDimitry Andric // there is no type source info.
867e8d8bef9SDimitry Andric if (kind() == DebugSubsectionKind::InlineeLines &&
868e8d8bef9SDimitry Andric debugChunk->file->debugTypesObj) {
869e8d8bef9SDimitry Andric TpiSource *source = debugChunk->file->debugTypesObj;
870e8d8bef9SDimitry Andric DebugInlineeLinesSubsectionRef inlineeLines;
8715f757f3fSDimitry Andric BinaryStreamReader storageReader(relocatedBytes, llvm::endianness::little);
872bdd1243dSDimitry Andric ExitOnError exitOnErr;
873e8d8bef9SDimitry Andric exitOnErr(inlineeLines.initialize(storageReader));
874e8d8bef9SDimitry Andric for (const InlineeSourceLine &line : inlineeLines) {
875e8d8bef9SDimitry Andric TypeIndex &inlinee = *const_cast<TypeIndex *>(&line.Header->Inlinee);
876e8d8bef9SDimitry Andric if (!source->remapTypeIndex(inlinee, TiRefKind::IndexRef)) {
877e8d8bef9SDimitry Andric log("bad inlinee line record in " + debugChunk->file->getName() +
878e8d8bef9SDimitry Andric " with bad inlinee index 0x" + utohexstr(inlinee.getIndex()));
879e8d8bef9SDimitry Andric }
880e8d8bef9SDimitry Andric }
881e8d8bef9SDimitry Andric }
882e8d8bef9SDimitry Andric
883e8d8bef9SDimitry Andric return writer.writeBytes(relocatedBytes);
884e8d8bef9SDimitry Andric }
885e8d8bef9SDimitry Andric
addUnrelocatedSubsection(SectionChunk * debugChunk,const DebugSubsectionRecord & ss)886e8d8bef9SDimitry Andric void DebugSHandler::addUnrelocatedSubsection(SectionChunk *debugChunk,
887e8d8bef9SDimitry Andric const DebugSubsectionRecord &ss) {
888e8d8bef9SDimitry Andric ArrayRef<uint8_t> subsec;
889e8d8bef9SDimitry Andric BinaryStreamRef sr = ss.getRecordData();
890e8d8bef9SDimitry Andric cantFail(sr.readBytes(0, sr.getLength(), subsec));
891e8d8bef9SDimitry Andric advanceRelocIndex(debugChunk, subsec);
892e8d8bef9SDimitry Andric file.moduleDBI->addDebugSubsection(
893e8d8bef9SDimitry Andric std::make_shared<UnrelocatedDebugSubsection>(ss.kind(), debugChunk,
894e8d8bef9SDimitry Andric subsec, nextRelocIndex));
895e8d8bef9SDimitry Andric }
896e8d8bef9SDimitry Andric
addFrameDataSubsection(SectionChunk * debugChunk,const DebugSubsectionRecord & ss)897e8d8bef9SDimitry Andric void DebugSHandler::addFrameDataSubsection(SectionChunk *debugChunk,
898e8d8bef9SDimitry Andric const DebugSubsectionRecord &ss) {
899e8d8bef9SDimitry Andric // We need to re-write string table indices here, so save off all
900e8d8bef9SDimitry Andric // frame data subsections until we've processed the entire list of
901e8d8bef9SDimitry Andric // subsections so that we can be sure we have the string table.
902e8d8bef9SDimitry Andric ArrayRef<uint8_t> subsec;
903e8d8bef9SDimitry Andric BinaryStreamRef sr = ss.getRecordData();
904e8d8bef9SDimitry Andric cantFail(sr.readBytes(0, sr.getLength(), subsec));
905e8d8bef9SDimitry Andric advanceRelocIndex(debugChunk, subsec);
906e8d8bef9SDimitry Andric frameDataSubsecs.push_back({debugChunk, subsec, nextRelocIndex});
907e8d8bef9SDimitry Andric }
908e8d8bef9SDimitry Andric
9090b57cec5SDimitry Andric static Expected<StringRef>
getFileName(const DebugStringTableSubsectionRef & strings,const DebugChecksumsSubsectionRef & checksums,uint32_t fileID)9100b57cec5SDimitry Andric getFileName(const DebugStringTableSubsectionRef &strings,
9110b57cec5SDimitry Andric const DebugChecksumsSubsectionRef &checksums, uint32_t fileID) {
9120b57cec5SDimitry Andric auto iter = checksums.getArray().at(fileID);
9130b57cec5SDimitry Andric if (iter == checksums.getArray().end())
9140b57cec5SDimitry Andric return make_error<CodeViewError>(cv_error_code::no_records);
9150b57cec5SDimitry Andric uint32_t offset = iter->FileNameOffset;
9160b57cec5SDimitry Andric return strings.getString(offset);
9170b57cec5SDimitry Andric }
9180b57cec5SDimitry Andric
finish()9190b57cec5SDimitry Andric void DebugSHandler::finish() {
9200b57cec5SDimitry Andric pdb::DbiStreamBuilder &dbiBuilder = linker.builder.getDbiBuilder();
9210b57cec5SDimitry Andric
922e8d8bef9SDimitry Andric // If we found any symbol records for the module symbol stream, defer them.
923e8d8bef9SDimitry Andric if (moduleStreamSize > kSymbolStreamMagicSize)
924e8d8bef9SDimitry Andric file.moduleDBI->addUnmergedSymbols(&file, moduleStreamSize -
925e8d8bef9SDimitry Andric kSymbolStreamMagicSize);
926e8d8bef9SDimitry Andric
9270b57cec5SDimitry Andric // We should have seen all debug subsections across the entire object file now
9280b57cec5SDimitry Andric // which means that if a StringTable subsection and Checksums subsection were
9290b57cec5SDimitry Andric // present, now is the time to handle them.
9305ffd83dbSDimitry Andric if (!cvStrTab.valid()) {
9310b57cec5SDimitry Andric if (checksums.valid())
9320b57cec5SDimitry Andric fatal(".debug$S sections with a checksums subsection must also contain a "
9330b57cec5SDimitry Andric "string table subsection");
9340b57cec5SDimitry Andric
935e8d8bef9SDimitry Andric if (!stringTableFixups.empty())
9360b57cec5SDimitry Andric warn("No StringTable subsection was encountered, but there are string "
9370b57cec5SDimitry Andric "table references");
9380b57cec5SDimitry Andric return;
9390b57cec5SDimitry Andric }
9400b57cec5SDimitry Andric
941bdd1243dSDimitry Andric ExitOnError exitOnErr;
942bdd1243dSDimitry Andric
943e8d8bef9SDimitry Andric // Handle FPO data. Each subsection begins with a single image base
944e8d8bef9SDimitry Andric // relocation, which is then added to the RvaStart of each frame data record
945e8d8bef9SDimitry Andric // when it is added to the PDB. The string table indices for the FPO program
946e8d8bef9SDimitry Andric // must also be rewritten to use the PDB string table.
947e8d8bef9SDimitry Andric for (const UnrelocatedFpoData &subsec : frameDataSubsecs) {
948e8d8bef9SDimitry Andric // Relocate the first four bytes of the subection and reinterpret them as a
94906c3fb27SDimitry Andric // 32 bit little-endian integer.
950e8d8bef9SDimitry Andric SectionChunk *debugChunk = subsec.debugChunk;
951e8d8bef9SDimitry Andric ArrayRef<uint8_t> subsecData = subsec.subsecData;
952e8d8bef9SDimitry Andric uint32_t relocIndex = subsec.relocIndex;
953e8d8bef9SDimitry Andric auto unrelocatedRvaStart = subsecData.take_front(sizeof(uint32_t));
954e8d8bef9SDimitry Andric uint8_t relocatedRvaStart[sizeof(uint32_t)];
955e8d8bef9SDimitry Andric debugChunk->writeAndRelocateSubsection(debugChunk->getContents(),
956e8d8bef9SDimitry Andric unrelocatedRvaStart, relocIndex,
957e8d8bef9SDimitry Andric &relocatedRvaStart[0]);
95806c3fb27SDimitry Andric // Use of memcpy here avoids violating type-based aliasing rules.
95906c3fb27SDimitry Andric support::ulittle32_t rvaStart;
96006c3fb27SDimitry Andric memcpy(&rvaStart, &relocatedRvaStart[0], sizeof(support::ulittle32_t));
961e8d8bef9SDimitry Andric
962e8d8bef9SDimitry Andric // Copy each frame data record, add in rvaStart, translate string table
963e8d8bef9SDimitry Andric // indices, and add the record to the PDB.
964e8d8bef9SDimitry Andric DebugFrameDataSubsectionRef fds;
9655f757f3fSDimitry Andric BinaryStreamReader reader(subsecData, llvm::endianness::little);
966e8d8bef9SDimitry Andric exitOnErr(fds.initialize(reader));
9670b57cec5SDimitry Andric for (codeview::FrameData fd : fds) {
968e8d8bef9SDimitry Andric fd.RvaStart += rvaStart;
9690b57cec5SDimitry Andric fd.FrameFunc =
9705ffd83dbSDimitry Andric translateStringTableIndex(fd.FrameFunc, cvStrTab, linker.pdbStrTab);
9710b57cec5SDimitry Andric dbiBuilder.addNewFpoData(fd);
9720b57cec5SDimitry Andric }
9730b57cec5SDimitry Andric }
9740b57cec5SDimitry Andric
975e8d8bef9SDimitry Andric // Translate the fixups and pass them off to the module builder so they will
976e8d8bef9SDimitry Andric // be applied during writing.
977e8d8bef9SDimitry Andric for (StringTableFixup &ref : stringTableFixups) {
978e8d8bef9SDimitry Andric ref.StrTabOffset =
979e8d8bef9SDimitry Andric translateStringTableIndex(ref.StrTabOffset, cvStrTab, linker.pdbStrTab);
980e8d8bef9SDimitry Andric }
981e8d8bef9SDimitry Andric file.moduleDBI->setStringTableFixups(std::move(stringTableFixups));
9820b57cec5SDimitry Andric
9830b57cec5SDimitry Andric // Make a new file checksum table that refers to offsets in the PDB-wide
9840b57cec5SDimitry Andric // string table. Generally the string table subsection appears after the
9850b57cec5SDimitry Andric // checksum table, so we have to do this after looping over all the
9865ffd83dbSDimitry Andric // subsections. The new checksum table must have the exact same layout and
9875ffd83dbSDimitry Andric // size as the original. Otherwise, the file references in the line and
9885ffd83dbSDimitry Andric // inlinee line tables will be incorrect.
98985868e8aSDimitry Andric auto newChecksums = std::make_unique<DebugChecksumsSubsection>(linker.pdbStrTab);
990349cc55cSDimitry Andric for (const FileChecksumEntry &fc : checksums) {
9910b57cec5SDimitry Andric SmallString<128> filename =
9925ffd83dbSDimitry Andric exitOnErr(cvStrTab.getString(fc.FileNameOffset));
993bdd1243dSDimitry Andric linker.pdbMakeAbsolute(filename);
9940b57cec5SDimitry Andric exitOnErr(dbiBuilder.addModuleSourceFile(*file.moduleDBI, filename));
9950b57cec5SDimitry Andric newChecksums->addChecksum(filename, fc.Kind, fc.Checksum);
9960b57cec5SDimitry Andric }
9975ffd83dbSDimitry Andric assert(checksums.getArray().getUnderlyingStream().getLength() ==
9985ffd83dbSDimitry Andric newChecksums->calculateSerializedSize() &&
9995ffd83dbSDimitry Andric "file checksum table must have same layout");
10000b57cec5SDimitry Andric
10010b57cec5SDimitry Andric file.moduleDBI->addDebugSubsection(std::move(newChecksums));
10020b57cec5SDimitry Andric }
10030b57cec5SDimitry Andric
warnUnusable(InputFile * f,Error e,bool shouldWarn)1004bdd1243dSDimitry Andric static void warnUnusable(InputFile *f, Error e, bool shouldWarn) {
1005bdd1243dSDimitry Andric if (!shouldWarn) {
10065ffd83dbSDimitry Andric consumeError(std::move(e));
10070b57cec5SDimitry Andric return;
10085ffd83dbSDimitry Andric }
10095ffd83dbSDimitry Andric auto msg = "Cannot use debug info for '" + toString(f) + "' [LNK4099]";
10105ffd83dbSDimitry Andric if (e)
10115ffd83dbSDimitry Andric warn(msg + "\n>>> failed to load reference " + toString(std::move(e)));
10125ffd83dbSDimitry Andric else
10135ffd83dbSDimitry Andric warn(msg);
10145ffd83dbSDimitry Andric }
10150b57cec5SDimitry Andric
10165ffd83dbSDimitry Andric // Allocate memory for a .debug$S / .debug$F section and relocate it.
relocateDebugChunk(SectionChunk & debugChunk)10175ffd83dbSDimitry Andric static ArrayRef<uint8_t> relocateDebugChunk(SectionChunk &debugChunk) {
101804eeddc0SDimitry Andric uint8_t *buffer = bAlloc().Allocate<uint8_t>(debugChunk.getSize());
10195ffd83dbSDimitry Andric assert(debugChunk.getOutputSectionIdx() == 0 &&
10205ffd83dbSDimitry Andric "debug sections should not be in output sections");
10215ffd83dbSDimitry Andric debugChunk.writeTo(buffer);
1022bdd1243dSDimitry Andric return ArrayRef(buffer, debugChunk.getSize());
10235ffd83dbSDimitry Andric }
10245ffd83dbSDimitry Andric
addDebugSymbols(TpiSource * source)1025e8d8bef9SDimitry Andric void PDBLinker::addDebugSymbols(TpiSource *source) {
1026e8d8bef9SDimitry Andric // If this TpiSource doesn't have an object file, it must be from a type
1027e8d8bef9SDimitry Andric // server PDB. Type server PDBs do not contain symbols, so stop here.
1028e8d8bef9SDimitry Andric if (!source->file)
1029e8d8bef9SDimitry Andric return;
1030e8d8bef9SDimitry Andric
10315f757f3fSDimitry Andric llvm::TimeTraceScope timeScope("Merge symbols");
1032349cc55cSDimitry Andric ScopedTimer t(ctx.symbolMergingTimer);
1033bdd1243dSDimitry Andric ExitOnError exitOnErr;
10340b57cec5SDimitry Andric pdb::DbiStreamBuilder &dbiBuilder = builder.getDbiBuilder();
10355f757f3fSDimitry Andric DebugSHandler dsh(*this, *source->file);
10360b57cec5SDimitry Andric // Now do all live .debug$S and .debug$F sections.
1037e8d8bef9SDimitry Andric for (SectionChunk *debugChunk : source->file->getDebugChunks()) {
10380b57cec5SDimitry Andric if (!debugChunk->live || debugChunk->getSize() == 0)
10390b57cec5SDimitry Andric continue;
10400b57cec5SDimitry Andric
10415ffd83dbSDimitry Andric bool isDebugS = debugChunk->getSectionName() == ".debug$S";
10425ffd83dbSDimitry Andric bool isDebugF = debugChunk->getSectionName() == ".debug$F";
10435ffd83dbSDimitry Andric if (!isDebugS && !isDebugF)
10440b57cec5SDimitry Andric continue;
10450b57cec5SDimitry Andric
10465ffd83dbSDimitry Andric if (isDebugS) {
1047e8d8bef9SDimitry Andric dsh.handleDebugS(debugChunk);
10485ffd83dbSDimitry Andric } else if (isDebugF) {
1049e8d8bef9SDimitry Andric // Handle old FPO data .debug$F sections. These are relatively rare.
1050e8d8bef9SDimitry Andric ArrayRef<uint8_t> relocatedDebugContents =
1051e8d8bef9SDimitry Andric relocateDebugChunk(*debugChunk);
10520b57cec5SDimitry Andric FixedStreamArray<object::FpoData> fpoRecords;
10535f757f3fSDimitry Andric BinaryStreamReader reader(relocatedDebugContents,
10545f757f3fSDimitry Andric llvm::endianness::little);
10550b57cec5SDimitry Andric uint32_t count = relocatedDebugContents.size() / sizeof(object::FpoData);
10560b57cec5SDimitry Andric exitOnErr(reader.readArray(fpoRecords, count));
10570b57cec5SDimitry Andric
10580b57cec5SDimitry Andric // These are already relocated and don't refer to the string table, so we
10590b57cec5SDimitry Andric // can just copy it.
10600b57cec5SDimitry Andric for (const object::FpoData &fd : fpoRecords)
10610b57cec5SDimitry Andric dbiBuilder.addOldFpoData(fd);
10620b57cec5SDimitry Andric }
10630b57cec5SDimitry Andric }
10640b57cec5SDimitry Andric
10650b57cec5SDimitry Andric // Do any post-processing now that all .debug$S sections have been processed.
10660b57cec5SDimitry Andric dsh.finish();
10670b57cec5SDimitry Andric }
10680b57cec5SDimitry Andric
10690b57cec5SDimitry Andric // Add a module descriptor for every object file. We need to put an absolute
10700b57cec5SDimitry Andric // path to the object into the PDB. If this is a plain object, we make its
10710b57cec5SDimitry Andric // path absolute. If it's an object in an archive, we make the archive path
10720b57cec5SDimitry Andric // absolute.
createModuleDBI(ObjFile * file)1073e8d8bef9SDimitry Andric void PDBLinker::createModuleDBI(ObjFile *file) {
10740b57cec5SDimitry Andric pdb::DbiStreamBuilder &dbiBuilder = builder.getDbiBuilder();
10750b57cec5SDimitry Andric SmallString<128> objName;
1076bdd1243dSDimitry Andric ExitOnError exitOnErr;
10770b57cec5SDimitry Andric
10780b57cec5SDimitry Andric bool inArchive = !file->parentName.empty();
10790b57cec5SDimitry Andric objName = inArchive ? file->parentName : file->getName();
10800b57cec5SDimitry Andric pdbMakeAbsolute(objName);
1081fe6060f1SDimitry Andric StringRef modName = inArchive ? file->getName() : objName.str();
10820b57cec5SDimitry Andric
10830b57cec5SDimitry Andric file->moduleDBI = &exitOnErr(dbiBuilder.addModuleInfo(modName));
10840b57cec5SDimitry Andric file->moduleDBI->setObjFileName(objName);
1085e8d8bef9SDimitry Andric file->moduleDBI->setMergeSymbolsCallback(this, &commitSymbolsForObject);
10860b57cec5SDimitry Andric
10870b57cec5SDimitry Andric ArrayRef<Chunk *> chunks = file->getChunks();
10880b57cec5SDimitry Andric uint32_t modi = file->moduleDBI->getModuleIndex();
10890b57cec5SDimitry Andric
10900b57cec5SDimitry Andric for (Chunk *c : chunks) {
10910b57cec5SDimitry Andric auto *secChunk = dyn_cast<SectionChunk>(c);
10920b57cec5SDimitry Andric if (!secChunk || !secChunk->live)
10930b57cec5SDimitry Andric continue;
1094349cc55cSDimitry Andric pdb::SectionContrib sc = createSectionContrib(ctx, secChunk, modi);
10950b57cec5SDimitry Andric file->moduleDBI->setFirstSectionContrib(sc);
10960b57cec5SDimitry Andric break;
10970b57cec5SDimitry Andric }
10980b57cec5SDimitry Andric }
10995ffd83dbSDimitry Andric
addDebug(TpiSource * source)11005ffd83dbSDimitry Andric void PDBLinker::addDebug(TpiSource *source) {
1101e8d8bef9SDimitry Andric // Before we can process symbol substreams from .debug$S, we need to process
1102e8d8bef9SDimitry Andric // type information, file checksums, and the string table. Add type info to
1103e8d8bef9SDimitry Andric // the PDB first, so that we can get the map from object file type and item
1104e8d8bef9SDimitry Andric // indices to PDB type and item indices. If we are using ghashes, types have
1105e8d8bef9SDimitry Andric // already been merged.
1106bdd1243dSDimitry Andric if (!ctx.config.debugGHashes) {
11075f757f3fSDimitry Andric llvm::TimeTraceScope timeScope("Merge types (Non-GHASH)");
1108349cc55cSDimitry Andric ScopedTimer t(ctx.typeMergingTimer);
1109e8d8bef9SDimitry Andric if (Error e = source->mergeDebugT(&tMerger)) {
1110e8d8bef9SDimitry Andric // If type merging failed, ignore the symbols.
1111bdd1243dSDimitry Andric warnUnusable(source->file, std::move(e),
1112bdd1243dSDimitry Andric ctx.config.warnDebugInfoUnusable);
1113e8d8bef9SDimitry Andric return;
1114e8d8bef9SDimitry Andric }
1115e8d8bef9SDimitry Andric }
11165ffd83dbSDimitry Andric
1117e8d8bef9SDimitry Andric // If type merging failed, ignore the symbols.
1118e8d8bef9SDimitry Andric Error typeError = std::move(source->typeMergingError);
1119e8d8bef9SDimitry Andric if (typeError) {
1120bdd1243dSDimitry Andric warnUnusable(source->file, std::move(typeError),
1121bdd1243dSDimitry Andric ctx.config.warnDebugInfoUnusable);
1122e8d8bef9SDimitry Andric return;
1123e8d8bef9SDimitry Andric }
11245ffd83dbSDimitry Andric
1125e8d8bef9SDimitry Andric addDebugSymbols(source);
11260b57cec5SDimitry Andric }
11270b57cec5SDimitry Andric
createPublic(COFFLinkerContext & ctx,Defined * def)1128349cc55cSDimitry Andric static pdb::BulkPublic createPublic(COFFLinkerContext &ctx, Defined *def) {
11295ffd83dbSDimitry Andric pdb::BulkPublic pub;
11305ffd83dbSDimitry Andric pub.Name = def->getName().data();
11315ffd83dbSDimitry Andric pub.NameLen = def->getName().size();
11325ffd83dbSDimitry Andric
11335ffd83dbSDimitry Andric PublicSymFlags flags = PublicSymFlags::None;
11340b57cec5SDimitry Andric if (auto *d = dyn_cast<DefinedCOFF>(def)) {
11350b57cec5SDimitry Andric if (d->getCOFFSymbol().isFunctionDefinition())
11365ffd83dbSDimitry Andric flags = PublicSymFlags::Function;
11370b57cec5SDimitry Andric } else if (isa<DefinedImportThunk>(def)) {
11385ffd83dbSDimitry Andric flags = PublicSymFlags::Function;
11390b57cec5SDimitry Andric }
11405ffd83dbSDimitry Andric pub.setFlags(flags);
11410b57cec5SDimitry Andric
1142349cc55cSDimitry Andric OutputSection *os = ctx.getOutputSection(def->getChunk());
11430b57cec5SDimitry Andric assert(os && "all publics should be in final image");
11440b57cec5SDimitry Andric pub.Offset = def->getRVA() - os->getRVA();
11450b57cec5SDimitry Andric pub.Segment = os->sectionIndex;
11460b57cec5SDimitry Andric return pub;
11470b57cec5SDimitry Andric }
11480b57cec5SDimitry Andric
11490b57cec5SDimitry Andric // Add all object files to the PDB. Merge .debug$T sections into IpiData and
11500b57cec5SDimitry Andric // TpiData.
addObjectsToPDB()11510b57cec5SDimitry Andric void PDBLinker::addObjectsToPDB() {
11525f757f3fSDimitry Andric {
11535f757f3fSDimitry Andric llvm::TimeTraceScope timeScope("Add objects to PDB");
1154349cc55cSDimitry Andric ScopedTimer t1(ctx.addObjectsTimer);
11550b57cec5SDimitry Andric
11565ffd83dbSDimitry Andric // Create module descriptors
1157fcaf7f86SDimitry Andric for (ObjFile *obj : ctx.objFileInstances)
1158fcaf7f86SDimitry Andric createModuleDBI(obj);
11590b57cec5SDimitry Andric
1160e8d8bef9SDimitry Andric // Reorder dependency type sources to come first.
1161349cc55cSDimitry Andric tMerger.sortDependencies();
11625ffd83dbSDimitry Andric
1163e8d8bef9SDimitry Andric // Merge type information from input files using global type hashing.
1164bdd1243dSDimitry Andric if (ctx.config.debugGHashes)
1165e8d8bef9SDimitry Andric tMerger.mergeTypesWithGHash();
11665ffd83dbSDimitry Andric
1167e8d8bef9SDimitry Andric // Merge dependencies and then regular objects.
11685f757f3fSDimitry Andric {
11695f757f3fSDimitry Andric llvm::TimeTraceScope timeScope("Merge debug info (dependencies)");
1170fcaf7f86SDimitry Andric for (TpiSource *source : tMerger.dependencySources)
1171fcaf7f86SDimitry Andric addDebug(source);
11725f757f3fSDimitry Andric }
11735f757f3fSDimitry Andric {
11745f757f3fSDimitry Andric llvm::TimeTraceScope timeScope("Merge debug info (objects)");
1175fcaf7f86SDimitry Andric for (TpiSource *source : tMerger.objectSources)
1176fcaf7f86SDimitry Andric addDebug(source);
11775f757f3fSDimitry Andric }
11780b57cec5SDimitry Andric
11790b57cec5SDimitry Andric builder.getStringTableBuilder().setStrings(pdbStrTab);
11805f757f3fSDimitry Andric }
11810b57cec5SDimitry Andric
11820b57cec5SDimitry Andric // Construct TPI and IPI stream contents.
11835f757f3fSDimitry Andric {
11845f757f3fSDimitry Andric llvm::TimeTraceScope timeScope("TPI/IPI stream layout");
1185349cc55cSDimitry Andric ScopedTimer t2(ctx.tpiStreamLayoutTimer);
1186bdd1243dSDimitry Andric
1187e8d8bef9SDimitry Andric // Collect all the merged types.
1188bdd1243dSDimitry Andric if (ctx.config.debugGHashes) {
1189349cc55cSDimitry Andric addGHashTypeInfo(ctx, builder);
1190e8d8bef9SDimitry Andric } else {
11910b57cec5SDimitry Andric addTypeInfo(builder.getTpiBuilder(), tMerger.getTypeTable());
11920b57cec5SDimitry Andric addTypeInfo(builder.getIpiBuilder(), tMerger.getIDTable());
1193e8d8bef9SDimitry Andric }
11945f757f3fSDimitry Andric }
1195e8d8bef9SDimitry Andric
1196bdd1243dSDimitry Andric if (ctx.config.showSummary) {
1197fcaf7f86SDimitry Andric for (TpiSource *source : ctx.tpiSourceList) {
1198e8d8bef9SDimitry Andric nbTypeRecords += source->nbTypeRecords;
1199e8d8bef9SDimitry Andric nbTypeRecordsBytes += source->nbTypeRecordsBytes;
1200fcaf7f86SDimitry Andric }
1201e8d8bef9SDimitry Andric }
12025ffd83dbSDimitry Andric }
12030b57cec5SDimitry Andric
addPublicsToPDB()12045ffd83dbSDimitry Andric void PDBLinker::addPublicsToPDB() {
12055f757f3fSDimitry Andric llvm::TimeTraceScope timeScope("Publics layout");
1206349cc55cSDimitry Andric ScopedTimer t3(ctx.publicsLayoutTimer);
12075ffd83dbSDimitry Andric // Compute the public symbols.
12080b57cec5SDimitry Andric auto &gsiBuilder = builder.getGsiBuilder();
12095ffd83dbSDimitry Andric std::vector<pdb::BulkPublic> publics;
1210349cc55cSDimitry Andric ctx.symtab.forEachSymbol([&publics, this](Symbol *s) {
12115ffd83dbSDimitry Andric // Only emit external, defined, live symbols that have a chunk. Static,
12125ffd83dbSDimitry Andric // non-external symbols do not appear in the symbol table.
12130b57cec5SDimitry Andric auto *def = dyn_cast<Defined>(s);
1214fe6060f1SDimitry Andric if (def && def->isLive() && def->getChunk()) {
1215fe6060f1SDimitry Andric // Don't emit a public symbol for coverage data symbols. LLVM code
1216fe6060f1SDimitry Andric // coverage (and PGO) create a __profd_ and __profc_ symbol for every
1217fe6060f1SDimitry Andric // function. C++ mangled names are long, and tend to dominate symbol size.
1218fe6060f1SDimitry Andric // Including these names triples the size of the public stream, which
1219fe6060f1SDimitry Andric // results in bloated PDB files. These symbols generally are not helpful
1220fe6060f1SDimitry Andric // for debugging, so suppress them.
1221fe6060f1SDimitry Andric StringRef name = def->getName();
1222fe6060f1SDimitry Andric if (name.data()[0] == '_' && name.data()[1] == '_') {
1223fe6060f1SDimitry Andric // Drop the '_' prefix for x86.
1224bdd1243dSDimitry Andric if (ctx.config.machine == I386)
1225fe6060f1SDimitry Andric name = name.drop_front(1);
122606c3fb27SDimitry Andric if (name.starts_with("__profd_") || name.starts_with("__profc_") ||
122706c3fb27SDimitry Andric name.starts_with("__covrec_")) {
1228fe6060f1SDimitry Andric return;
1229fe6060f1SDimitry Andric }
1230fe6060f1SDimitry Andric }
1231349cc55cSDimitry Andric publics.push_back(createPublic(ctx, def));
1232fe6060f1SDimitry Andric }
12330b57cec5SDimitry Andric });
12340b57cec5SDimitry Andric
12350b57cec5SDimitry Andric if (!publics.empty()) {
12360b57cec5SDimitry Andric publicSymbols = publics.size();
12375ffd83dbSDimitry Andric gsiBuilder.addPublicSymbols(std::move(publics));
12380b57cec5SDimitry Andric }
12390b57cec5SDimitry Andric }
12400b57cec5SDimitry Andric
printStats()12410b57cec5SDimitry Andric void PDBLinker::printStats() {
1242bdd1243dSDimitry Andric if (!ctx.config.showSummary)
12430b57cec5SDimitry Andric return;
12440b57cec5SDimitry Andric
12450b57cec5SDimitry Andric SmallString<256> buffer;
12460b57cec5SDimitry Andric raw_svector_ostream stream(buffer);
12470b57cec5SDimitry Andric
12480b57cec5SDimitry Andric stream << center_justify("Summary", 80) << '\n'
12490b57cec5SDimitry Andric << std::string(80, '-') << '\n';
12500b57cec5SDimitry Andric
12510b57cec5SDimitry Andric auto print = [&](uint64_t v, StringRef s) {
12520b57cec5SDimitry Andric stream << format_decimal(v, 15) << " " << s << '\n';
12530b57cec5SDimitry Andric };
12540b57cec5SDimitry Andric
1255349cc55cSDimitry Andric print(ctx.objFileInstances.size(),
12560b57cec5SDimitry Andric "Input OBJ files (expanded from all cmd-line inputs)");
1257349cc55cSDimitry Andric print(ctx.typeServerSourceMappings.size(), "PDB type server dependencies");
1258349cc55cSDimitry Andric print(ctx.precompSourceMappings.size(), "Precomp OBJ dependencies");
1259e8d8bef9SDimitry Andric print(nbTypeRecords, "Input type records");
1260e8d8bef9SDimitry Andric print(nbTypeRecordsBytes, "Input type records bytes");
1261e8d8bef9SDimitry Andric print(builder.getTpiBuilder().getRecordCount(), "Merged TPI records");
1262e8d8bef9SDimitry Andric print(builder.getIpiBuilder().getRecordCount(), "Merged IPI records");
12630b57cec5SDimitry Andric print(pdbStrTab.size(), "Output PDB strings");
12640b57cec5SDimitry Andric print(globalSymbols, "Global symbol records");
12650b57cec5SDimitry Andric print(moduleSymbols, "Module symbol records");
12660b57cec5SDimitry Andric print(publicSymbols, "Public symbol records");
12670b57cec5SDimitry Andric
1268480093f4SDimitry Andric auto printLargeInputTypeRecs = [&](StringRef name,
1269480093f4SDimitry Andric ArrayRef<uint32_t> recCounts,
1270480093f4SDimitry Andric TypeCollection &records) {
1271480093f4SDimitry Andric // Figure out which type indices were responsible for the most duplicate
1272480093f4SDimitry Andric // bytes in the input files. These should be frequently emitted LF_CLASS and
1273480093f4SDimitry Andric // LF_FIELDLIST records.
1274480093f4SDimitry Andric struct TypeSizeInfo {
1275480093f4SDimitry Andric uint32_t typeSize;
1276480093f4SDimitry Andric uint32_t dupCount;
1277480093f4SDimitry Andric TypeIndex typeIndex;
1278480093f4SDimitry Andric uint64_t totalInputSize() const { return uint64_t(dupCount) * typeSize; }
1279480093f4SDimitry Andric bool operator<(const TypeSizeInfo &rhs) const {
12805ffd83dbSDimitry Andric if (totalInputSize() == rhs.totalInputSize())
12815ffd83dbSDimitry Andric return typeIndex < rhs.typeIndex;
1282480093f4SDimitry Andric return totalInputSize() < rhs.totalInputSize();
1283480093f4SDimitry Andric }
1284480093f4SDimitry Andric };
1285480093f4SDimitry Andric SmallVector<TypeSizeInfo, 0> tsis;
1286480093f4SDimitry Andric for (auto e : enumerate(recCounts)) {
1287480093f4SDimitry Andric TypeIndex typeIndex = TypeIndex::fromArrayIndex(e.index());
1288480093f4SDimitry Andric uint32_t typeSize = records.getType(typeIndex).length();
1289480093f4SDimitry Andric uint32_t dupCount = e.value();
1290480093f4SDimitry Andric tsis.push_back({typeSize, dupCount, typeIndex});
1291480093f4SDimitry Andric }
1292480093f4SDimitry Andric
1293480093f4SDimitry Andric if (!tsis.empty()) {
1294480093f4SDimitry Andric stream << "\nTop 10 types responsible for the most " << name
1295480093f4SDimitry Andric << " input:\n";
1296480093f4SDimitry Andric stream << " index total bytes count size\n";
1297480093f4SDimitry Andric llvm::sort(tsis);
1298480093f4SDimitry Andric unsigned i = 0;
1299480093f4SDimitry Andric for (const auto &tsi : reverse(tsis)) {
1300480093f4SDimitry Andric stream << formatv(" {0,10:X}: {1,14:N} = {2,5:N} * {3,6:N}\n",
1301480093f4SDimitry Andric tsi.typeIndex.getIndex(), tsi.totalInputSize(),
1302480093f4SDimitry Andric tsi.dupCount, tsi.typeSize);
1303480093f4SDimitry Andric if (++i >= 10)
1304480093f4SDimitry Andric break;
1305480093f4SDimitry Andric }
1306480093f4SDimitry Andric stream
1307480093f4SDimitry Andric << "Run llvm-pdbutil to print details about a particular record:\n";
1308480093f4SDimitry Andric stream << formatv("llvm-pdbutil dump -{0}s -{0}-index {1:X} {2}\n",
1309480093f4SDimitry Andric (name == "TPI" ? "type" : "id"),
1310bdd1243dSDimitry Andric tsis.back().typeIndex.getIndex(), ctx.config.pdbPath);
1311480093f4SDimitry Andric }
1312480093f4SDimitry Andric };
1313480093f4SDimitry Andric
1314bdd1243dSDimitry Andric if (!ctx.config.debugGHashes) {
1315e8d8bef9SDimitry Andric // FIXME: Reimplement for ghash.
13165ffd83dbSDimitry Andric printLargeInputTypeRecs("TPI", tMerger.tpiCounts, tMerger.getTypeTable());
13175ffd83dbSDimitry Andric printLargeInputTypeRecs("IPI", tMerger.ipiCounts, tMerger.getIDTable());
1318e8d8bef9SDimitry Andric }
1319480093f4SDimitry Andric
13200b57cec5SDimitry Andric message(buffer);
13210b57cec5SDimitry Andric }
13220b57cec5SDimitry Andric
addNatvisFiles()13230b57cec5SDimitry Andric void PDBLinker::addNatvisFiles() {
13245f757f3fSDimitry Andric llvm::TimeTraceScope timeScope("Natvis files");
1325bdd1243dSDimitry Andric for (StringRef file : ctx.config.natvisFiles) {
13260b57cec5SDimitry Andric ErrorOr<std::unique_ptr<MemoryBuffer>> dataOrErr =
13270b57cec5SDimitry Andric MemoryBuffer::getFile(file);
13280b57cec5SDimitry Andric if (!dataOrErr) {
13290b57cec5SDimitry Andric warn("Cannot open input file: " + file);
13300b57cec5SDimitry Andric continue;
13310b57cec5SDimitry Andric }
1332fe6060f1SDimitry Andric std::unique_ptr<MemoryBuffer> data = std::move(*dataOrErr);
1333fe6060f1SDimitry Andric
1334fe6060f1SDimitry Andric // Can't use takeBuffer() here since addInjectedSource() takes ownership.
1335bdd1243dSDimitry Andric if (ctx.driver.tar)
1336bdd1243dSDimitry Andric ctx.driver.tar->append(relativeToRoot(data->getBufferIdentifier()),
1337fe6060f1SDimitry Andric data->getBuffer());
1338fe6060f1SDimitry Andric
1339fe6060f1SDimitry Andric builder.addInjectedSource(file, std::move(data));
13400b57cec5SDimitry Andric }
13410b57cec5SDimitry Andric }
13420b57cec5SDimitry Andric
addNamedStreams()13435ffd83dbSDimitry Andric void PDBLinker::addNamedStreams() {
13445f757f3fSDimitry Andric llvm::TimeTraceScope timeScope("Named streams");
1345bdd1243dSDimitry Andric ExitOnError exitOnErr;
1346bdd1243dSDimitry Andric for (const auto &streamFile : ctx.config.namedStreams) {
13475ffd83dbSDimitry Andric const StringRef stream = streamFile.getKey(), file = streamFile.getValue();
13485ffd83dbSDimitry Andric ErrorOr<std::unique_ptr<MemoryBuffer>> dataOrErr =
13495ffd83dbSDimitry Andric MemoryBuffer::getFile(file);
13505ffd83dbSDimitry Andric if (!dataOrErr) {
13515ffd83dbSDimitry Andric warn("Cannot open input file: " + file);
13525ffd83dbSDimitry Andric continue;
13535ffd83dbSDimitry Andric }
1354fe6060f1SDimitry Andric std::unique_ptr<MemoryBuffer> data = std::move(*dataOrErr);
1355fe6060f1SDimitry Andric exitOnErr(builder.addNamedStream(stream, data->getBuffer()));
1356bdd1243dSDimitry Andric ctx.driver.takeBuffer(std::move(data));
13575ffd83dbSDimitry Andric }
13585ffd83dbSDimitry Andric }
13595ffd83dbSDimitry Andric
toCodeViewMachine(COFF::MachineTypes machine)13600b57cec5SDimitry Andric static codeview::CPUType toCodeViewMachine(COFF::MachineTypes machine) {
13610b57cec5SDimitry Andric switch (machine) {
13620b57cec5SDimitry Andric case COFF::IMAGE_FILE_MACHINE_AMD64:
13630b57cec5SDimitry Andric return codeview::CPUType::X64;
13640b57cec5SDimitry Andric case COFF::IMAGE_FILE_MACHINE_ARM:
13650b57cec5SDimitry Andric return codeview::CPUType::ARM7;
13660b57cec5SDimitry Andric case COFF::IMAGE_FILE_MACHINE_ARM64:
13670b57cec5SDimitry Andric return codeview::CPUType::ARM64;
13680b57cec5SDimitry Andric case COFF::IMAGE_FILE_MACHINE_ARMNT:
13690b57cec5SDimitry Andric return codeview::CPUType::ARMNT;
13700b57cec5SDimitry Andric case COFF::IMAGE_FILE_MACHINE_I386:
13710b57cec5SDimitry Andric return codeview::CPUType::Intel80386;
13720b57cec5SDimitry Andric default:
13730b57cec5SDimitry Andric llvm_unreachable("Unsupported CPU Type");
13740b57cec5SDimitry Andric }
13750b57cec5SDimitry Andric }
13760b57cec5SDimitry Andric
13770b57cec5SDimitry Andric // Mimic MSVC which surrounds arguments containing whitespace with quotes.
13780b57cec5SDimitry Andric // Double double-quotes are handled, so that the resulting string can be
13790b57cec5SDimitry Andric // executed again on the cmd-line.
quote(ArrayRef<StringRef> args)13800b57cec5SDimitry Andric static std::string quote(ArrayRef<StringRef> args) {
13810b57cec5SDimitry Andric std::string r;
13820b57cec5SDimitry Andric r.reserve(256);
13830b57cec5SDimitry Andric for (StringRef a : args) {
13840b57cec5SDimitry Andric if (!r.empty())
13850b57cec5SDimitry Andric r.push_back(' ');
1386349cc55cSDimitry Andric bool hasWS = a.contains(' ');
1387349cc55cSDimitry Andric bool hasQ = a.contains('"');
13880b57cec5SDimitry Andric if (hasWS || hasQ)
13890b57cec5SDimitry Andric r.push_back('"');
13900b57cec5SDimitry Andric if (hasQ) {
13910b57cec5SDimitry Andric SmallVector<StringRef, 4> s;
13920b57cec5SDimitry Andric a.split(s, '"');
13930b57cec5SDimitry Andric r.append(join(s, "\"\""));
13940b57cec5SDimitry Andric } else {
13955ffd83dbSDimitry Andric r.append(std::string(a));
13960b57cec5SDimitry Andric }
13970b57cec5SDimitry Andric if (hasWS || hasQ)
13980b57cec5SDimitry Andric r.push_back('"');
13990b57cec5SDimitry Andric }
14000b57cec5SDimitry Andric return r;
14010b57cec5SDimitry Andric }
14020b57cec5SDimitry Andric
fillLinkerVerRecord(Compile3Sym & cs,MachineTypes machine)1403bdd1243dSDimitry Andric static void fillLinkerVerRecord(Compile3Sym &cs, MachineTypes machine) {
1404bdd1243dSDimitry Andric cs.Machine = toCodeViewMachine(machine);
14050b57cec5SDimitry Andric // Interestingly, if we set the string to 0.0.0.0, then when trying to view
14060b57cec5SDimitry Andric // local variables WinDbg emits an error that private symbols are not present.
14070b57cec5SDimitry Andric // By setting this to a valid MSVC linker version string, local variables are
14080b57cec5SDimitry Andric // displayed properly. As such, even though it is not representative of
14090b57cec5SDimitry Andric // LLVM's version information, we need this for compatibility.
14100b57cec5SDimitry Andric cs.Flags = CompileSym3Flags::None;
14110b57cec5SDimitry Andric cs.VersionBackendBuild = 25019;
14120b57cec5SDimitry Andric cs.VersionBackendMajor = 14;
14130b57cec5SDimitry Andric cs.VersionBackendMinor = 10;
14140b57cec5SDimitry Andric cs.VersionBackendQFE = 0;
14150b57cec5SDimitry Andric
14160b57cec5SDimitry Andric // MSVC also sets the frontend to 0.0.0.0 since this is specifically for the
14170b57cec5SDimitry Andric // linker module (which is by definition a backend), so we don't need to do
14180b57cec5SDimitry Andric // anything here. Also, it seems we can use "LLVM Linker" for the linker name
14190b57cec5SDimitry Andric // without any problems. Only the backend version has to be hardcoded to a
14200b57cec5SDimitry Andric // magic number.
14210b57cec5SDimitry Andric cs.VersionFrontendBuild = 0;
14220b57cec5SDimitry Andric cs.VersionFrontendMajor = 0;
14230b57cec5SDimitry Andric cs.VersionFrontendMinor = 0;
14240b57cec5SDimitry Andric cs.VersionFrontendQFE = 0;
14250b57cec5SDimitry Andric cs.Version = "LLVM Linker";
14260b57cec5SDimitry Andric cs.setLanguage(SourceLanguage::Link);
14270b57cec5SDimitry Andric }
14280b57cec5SDimitry Andric
addCommonLinkerModuleSymbols(StringRef path,pdb::DbiModuleDescriptorBuilder & mod)1429bdd1243dSDimitry Andric void PDBLinker::addCommonLinkerModuleSymbols(
1430bdd1243dSDimitry Andric StringRef path, pdb::DbiModuleDescriptorBuilder &mod) {
14310b57cec5SDimitry Andric ObjNameSym ons(SymbolRecordKind::ObjNameSym);
14320b57cec5SDimitry Andric EnvBlockSym ebs(SymbolRecordKind::EnvBlockSym);
14330b57cec5SDimitry Andric Compile3Sym cs(SymbolRecordKind::Compile3Sym);
1434bdd1243dSDimitry Andric fillLinkerVerRecord(cs, ctx.config.machine);
14350b57cec5SDimitry Andric
14360b57cec5SDimitry Andric ons.Name = "* Linker *";
14370b57cec5SDimitry Andric ons.Signature = 0;
14380b57cec5SDimitry Andric
1439bdd1243dSDimitry Andric ArrayRef<StringRef> args = ArrayRef(ctx.config.argv).drop_front();
14400b57cec5SDimitry Andric std::string argStr = quote(args);
14410b57cec5SDimitry Andric ebs.Fields.push_back("cwd");
14420b57cec5SDimitry Andric SmallString<64> cwd;
1443bdd1243dSDimitry Andric if (ctx.config.pdbSourcePath.empty())
14440b57cec5SDimitry Andric sys::fs::current_path(cwd);
14450b57cec5SDimitry Andric else
1446bdd1243dSDimitry Andric cwd = ctx.config.pdbSourcePath;
14470b57cec5SDimitry Andric ebs.Fields.push_back(cwd);
14480b57cec5SDimitry Andric ebs.Fields.push_back("exe");
1449bdd1243dSDimitry Andric SmallString<64> exe = ctx.config.argv[0];
14500b57cec5SDimitry Andric pdbMakeAbsolute(exe);
14510b57cec5SDimitry Andric ebs.Fields.push_back(exe);
14520b57cec5SDimitry Andric ebs.Fields.push_back("pdb");
14530b57cec5SDimitry Andric ebs.Fields.push_back(path);
14540b57cec5SDimitry Andric ebs.Fields.push_back("cmd");
14550b57cec5SDimitry Andric ebs.Fields.push_back(argStr);
145604eeddc0SDimitry Andric llvm::BumpPtrAllocator &bAlloc = lld::bAlloc();
14570b57cec5SDimitry Andric mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol(
14585ffd83dbSDimitry Andric ons, bAlloc, CodeViewContainer::Pdb));
14590b57cec5SDimitry Andric mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol(
14605ffd83dbSDimitry Andric cs, bAlloc, CodeViewContainer::Pdb));
14610b57cec5SDimitry Andric mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol(
14625ffd83dbSDimitry Andric ebs, bAlloc, CodeViewContainer::Pdb));
14630b57cec5SDimitry Andric }
14640b57cec5SDimitry Andric
addLinkerModuleCoffGroup(PartialSection * sec,pdb::DbiModuleDescriptorBuilder & mod,OutputSection & os)14650b57cec5SDimitry Andric static void addLinkerModuleCoffGroup(PartialSection *sec,
14660b57cec5SDimitry Andric pdb::DbiModuleDescriptorBuilder &mod,
14675ffd83dbSDimitry Andric OutputSection &os) {
14680b57cec5SDimitry Andric // If there's a section, there's at least one chunk
14690b57cec5SDimitry Andric assert(!sec->chunks.empty());
14700b57cec5SDimitry Andric const Chunk *firstChunk = *sec->chunks.begin();
14710b57cec5SDimitry Andric const Chunk *lastChunk = *sec->chunks.rbegin();
14720b57cec5SDimitry Andric
14730b57cec5SDimitry Andric // Emit COFF group
14740b57cec5SDimitry Andric CoffGroupSym cgs(SymbolRecordKind::CoffGroupSym);
14750b57cec5SDimitry Andric cgs.Name = sec->name;
14760b57cec5SDimitry Andric cgs.Segment = os.sectionIndex;
14770b57cec5SDimitry Andric cgs.Offset = firstChunk->getRVA() - os.getRVA();
14780b57cec5SDimitry Andric cgs.Size = lastChunk->getRVA() + lastChunk->getSize() - firstChunk->getRVA();
14790b57cec5SDimitry Andric cgs.Characteristics = sec->characteristics;
14800b57cec5SDimitry Andric
14810b57cec5SDimitry Andric // Somehow .idata sections & sections groups in the debug symbol stream have
14820b57cec5SDimitry Andric // the "write" flag set. However the section header for the corresponding
14830b57cec5SDimitry Andric // .idata section doesn't have it.
148406c3fb27SDimitry Andric if (cgs.Name.starts_with(".idata"))
14850b57cec5SDimitry Andric cgs.Characteristics |= llvm::COFF::IMAGE_SCN_MEM_WRITE;
14860b57cec5SDimitry Andric
14870b57cec5SDimitry Andric mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol(
148804eeddc0SDimitry Andric cgs, bAlloc(), CodeViewContainer::Pdb));
14890b57cec5SDimitry Andric }
14900b57cec5SDimitry Andric
addLinkerModuleSectionSymbol(pdb::DbiModuleDescriptorBuilder & mod,OutputSection & os,bool isMinGW)14910b57cec5SDimitry Andric static void addLinkerModuleSectionSymbol(pdb::DbiModuleDescriptorBuilder &mod,
1492bdd1243dSDimitry Andric OutputSection &os, bool isMinGW) {
14930b57cec5SDimitry Andric SectionSym sym(SymbolRecordKind::SectionSym);
14940b57cec5SDimitry Andric sym.Alignment = 12; // 2^12 = 4KB
14950b57cec5SDimitry Andric sym.Characteristics = os.header.Characteristics;
14960b57cec5SDimitry Andric sym.Length = os.getVirtualSize();
14970b57cec5SDimitry Andric sym.Name = os.name;
14980b57cec5SDimitry Andric sym.Rva = os.getRVA();
14990b57cec5SDimitry Andric sym.SectionNumber = os.sectionIndex;
15000b57cec5SDimitry Andric mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol(
150104eeddc0SDimitry Andric sym, bAlloc(), CodeViewContainer::Pdb));
15020b57cec5SDimitry Andric
15030b57cec5SDimitry Andric // Skip COFF groups in MinGW because it adds a significant footprint to the
15040b57cec5SDimitry Andric // PDB, due to each function being in its own section
1505bdd1243dSDimitry Andric if (isMinGW)
15060b57cec5SDimitry Andric return;
15070b57cec5SDimitry Andric
15080b57cec5SDimitry Andric // Output COFF groups for individual chunks of this section.
15090b57cec5SDimitry Andric for (PartialSection *sec : os.contribSections) {
15105ffd83dbSDimitry Andric addLinkerModuleCoffGroup(sec, mod, os);
15110b57cec5SDimitry Andric }
15120b57cec5SDimitry Andric }
15130b57cec5SDimitry Andric
15140b57cec5SDimitry Andric // Add all import files as modules to the PDB.
addImportFilesToPDB()1515349cc55cSDimitry Andric void PDBLinker::addImportFilesToPDB() {
1516349cc55cSDimitry Andric if (ctx.importFileInstances.empty())
15170b57cec5SDimitry Andric return;
15180b57cec5SDimitry Andric
15195f757f3fSDimitry Andric llvm::TimeTraceScope timeScope("Import files");
1520bdd1243dSDimitry Andric ExitOnError exitOnErr;
15210b57cec5SDimitry Andric std::map<std::string, llvm::pdb::DbiModuleDescriptorBuilder *> dllToModuleDbi;
15220b57cec5SDimitry Andric
1523349cc55cSDimitry Andric for (ImportFile *file : ctx.importFileInstances) {
15240b57cec5SDimitry Andric if (!file->live)
15250b57cec5SDimitry Andric continue;
15260b57cec5SDimitry Andric
15270b57cec5SDimitry Andric if (!file->thunkSym)
15280b57cec5SDimitry Andric continue;
15290b57cec5SDimitry Andric
15300b57cec5SDimitry Andric if (!file->thunkLive)
15310b57cec5SDimitry Andric continue;
15320b57cec5SDimitry Andric
15330b57cec5SDimitry Andric std::string dll = StringRef(file->dllName).lower();
15340b57cec5SDimitry Andric llvm::pdb::DbiModuleDescriptorBuilder *&mod = dllToModuleDbi[dll];
15350b57cec5SDimitry Andric if (!mod) {
15360b57cec5SDimitry Andric pdb::DbiStreamBuilder &dbiBuilder = builder.getDbiBuilder();
15370b57cec5SDimitry Andric SmallString<128> libPath = file->parentName;
15380b57cec5SDimitry Andric pdbMakeAbsolute(libPath);
15390b57cec5SDimitry Andric sys::path::native(libPath);
15400b57cec5SDimitry Andric
15410b57cec5SDimitry Andric // Name modules similar to MSVC's link.exe.
15420b57cec5SDimitry Andric // The first module is the simple dll filename
15430b57cec5SDimitry Andric llvm::pdb::DbiModuleDescriptorBuilder &firstMod =
15440b57cec5SDimitry Andric exitOnErr(dbiBuilder.addModuleInfo(file->dllName));
15450b57cec5SDimitry Andric firstMod.setObjFileName(libPath);
15460b57cec5SDimitry Andric pdb::SectionContrib sc =
1547349cc55cSDimitry Andric createSectionContrib(ctx, nullptr, llvm::pdb::kInvalidStreamIndex);
15480b57cec5SDimitry Andric firstMod.setFirstSectionContrib(sc);
15490b57cec5SDimitry Andric
15500b57cec5SDimitry Andric // The second module is where the import stream goes.
15510b57cec5SDimitry Andric mod = &exitOnErr(dbiBuilder.addModuleInfo("Import:" + file->dllName));
15520b57cec5SDimitry Andric mod->setObjFileName(libPath);
15530b57cec5SDimitry Andric }
15540b57cec5SDimitry Andric
15550b57cec5SDimitry Andric DefinedImportThunk *thunk = cast<DefinedImportThunk>(file->thunkSym);
15560b57cec5SDimitry Andric Chunk *thunkChunk = thunk->getChunk();
1557349cc55cSDimitry Andric OutputSection *thunkOS = ctx.getOutputSection(thunkChunk);
15580b57cec5SDimitry Andric
15590b57cec5SDimitry Andric ObjNameSym ons(SymbolRecordKind::ObjNameSym);
15600b57cec5SDimitry Andric Compile3Sym cs(SymbolRecordKind::Compile3Sym);
15610b57cec5SDimitry Andric Thunk32Sym ts(SymbolRecordKind::Thunk32Sym);
15620b57cec5SDimitry Andric ScopeEndSym es(SymbolRecordKind::ScopeEndSym);
15630b57cec5SDimitry Andric
15640b57cec5SDimitry Andric ons.Name = file->dllName;
15650b57cec5SDimitry Andric ons.Signature = 0;
15660b57cec5SDimitry Andric
1567bdd1243dSDimitry Andric fillLinkerVerRecord(cs, ctx.config.machine);
15680b57cec5SDimitry Andric
15690b57cec5SDimitry Andric ts.Name = thunk->getName();
15700b57cec5SDimitry Andric ts.Parent = 0;
15710b57cec5SDimitry Andric ts.End = 0;
15720b57cec5SDimitry Andric ts.Next = 0;
15730b57cec5SDimitry Andric ts.Thunk = ThunkOrdinal::Standard;
15740b57cec5SDimitry Andric ts.Length = thunkChunk->getSize();
15750b57cec5SDimitry Andric ts.Segment = thunkOS->sectionIndex;
15760b57cec5SDimitry Andric ts.Offset = thunkChunk->getRVA() - thunkOS->getRVA();
15770b57cec5SDimitry Andric
157804eeddc0SDimitry Andric llvm::BumpPtrAllocator &bAlloc = lld::bAlloc();
15790b57cec5SDimitry Andric mod->addSymbol(codeview::SymbolSerializer::writeOneSymbol(
15805ffd83dbSDimitry Andric ons, bAlloc, CodeViewContainer::Pdb));
15810b57cec5SDimitry Andric mod->addSymbol(codeview::SymbolSerializer::writeOneSymbol(
15825ffd83dbSDimitry Andric cs, bAlloc, CodeViewContainer::Pdb));
15830b57cec5SDimitry Andric
15840b57cec5SDimitry Andric CVSymbol newSym = codeview::SymbolSerializer::writeOneSymbol(
15855ffd83dbSDimitry Andric ts, bAlloc, CodeViewContainer::Pdb);
1586e8d8bef9SDimitry Andric
1587e8d8bef9SDimitry Andric // Write ptrEnd for the S_THUNK32.
1588e8d8bef9SDimitry Andric ScopeRecord *thunkSymScope =
1589e8d8bef9SDimitry Andric getSymbolScopeFields(const_cast<uint8_t *>(newSym.data().data()));
15900b57cec5SDimitry Andric
15910b57cec5SDimitry Andric mod->addSymbol(newSym);
15920b57cec5SDimitry Andric
15935ffd83dbSDimitry Andric newSym = codeview::SymbolSerializer::writeOneSymbol(es, bAlloc,
15940b57cec5SDimitry Andric CodeViewContainer::Pdb);
1595e8d8bef9SDimitry Andric thunkSymScope->ptrEnd = mod->getNextSymbolOffset();
15960b57cec5SDimitry Andric
15970b57cec5SDimitry Andric mod->addSymbol(newSym);
15980b57cec5SDimitry Andric
15990b57cec5SDimitry Andric pdb::SectionContrib sc =
1600349cc55cSDimitry Andric createSectionContrib(ctx, thunk->getChunk(), mod->getModuleIndex());
16010b57cec5SDimitry Andric mod->setFirstSectionContrib(sc);
16020b57cec5SDimitry Andric }
16030b57cec5SDimitry Andric }
16040b57cec5SDimitry Andric
16050b57cec5SDimitry Andric // Creates a PDB file.
createPDB(COFFLinkerContext & ctx,ArrayRef<uint8_t> sectionTable,llvm::codeview::DebugInfo * buildId)1606349cc55cSDimitry Andric void lld::coff::createPDB(COFFLinkerContext &ctx,
16070b57cec5SDimitry Andric ArrayRef<uint8_t> sectionTable,
16080b57cec5SDimitry Andric llvm::codeview::DebugInfo *buildId) {
16095f757f3fSDimitry Andric llvm::TimeTraceScope timeScope("PDB file");
1610349cc55cSDimitry Andric ScopedTimer t1(ctx.totalPdbLinkTimer);
16115f757f3fSDimitry Andric {
1612349cc55cSDimitry Andric PDBLinker pdb(ctx);
16130b57cec5SDimitry Andric
16140b57cec5SDimitry Andric pdb.initialize(buildId);
16150b57cec5SDimitry Andric pdb.addObjectsToPDB();
1616349cc55cSDimitry Andric pdb.addImportFilesToPDB();
1617349cc55cSDimitry Andric pdb.addSections(sectionTable);
16180b57cec5SDimitry Andric pdb.addNatvisFiles();
16195ffd83dbSDimitry Andric pdb.addNamedStreams();
16205ffd83dbSDimitry Andric pdb.addPublicsToPDB();
16210b57cec5SDimitry Andric
16225f757f3fSDimitry Andric {
16235f757f3fSDimitry Andric llvm::TimeTraceScope timeScope("Commit PDB file to disk");
1624349cc55cSDimitry Andric ScopedTimer t2(ctx.diskCommitTimer);
16250b57cec5SDimitry Andric codeview::GUID guid;
16260b57cec5SDimitry Andric pdb.commit(&guid);
16270b57cec5SDimitry Andric memcpy(&buildId->PDB70.Signature, &guid, 16);
16285f757f3fSDimitry Andric }
16290b57cec5SDimitry Andric
16300b57cec5SDimitry Andric t1.stop();
16310b57cec5SDimitry Andric pdb.printStats();
16325f757f3fSDimitry Andric
16335f757f3fSDimitry Andric // Manually start this profile point to measure ~PDBLinker().
16345f757f3fSDimitry Andric if (getTimeTraceProfilerInstance() != nullptr)
16355f757f3fSDimitry Andric timeTraceProfilerBegin("PDBLinker destructor", StringRef(""));
16365f757f3fSDimitry Andric }
16375f757f3fSDimitry Andric // Manually end this profile point to measure ~PDBLinker().
16385f757f3fSDimitry Andric if (getTimeTraceProfilerInstance() != nullptr)
16395f757f3fSDimitry Andric timeTraceProfilerEnd();
16400b57cec5SDimitry Andric }
16410b57cec5SDimitry Andric
initialize(llvm::codeview::DebugInfo * buildId)16420b57cec5SDimitry Andric void PDBLinker::initialize(llvm::codeview::DebugInfo *buildId) {
1643bdd1243dSDimitry Andric ExitOnError exitOnErr;
1644bdd1243dSDimitry Andric exitOnErr(builder.initialize(ctx.config.pdbPageSize));
16450b57cec5SDimitry Andric
16460b57cec5SDimitry Andric buildId->Signature.CVSignature = OMF::Signature::PDB70;
16470b57cec5SDimitry Andric // Signature is set to a hash of the PDB contents when the PDB is done.
16480b57cec5SDimitry Andric memset(buildId->PDB70.Signature, 0, 16);
16490b57cec5SDimitry Andric buildId->PDB70.Age = 1;
16500b57cec5SDimitry Andric
16510b57cec5SDimitry Andric // Create streams in MSF for predefined streams, namely
16520b57cec5SDimitry Andric // PDB, TPI, DBI and IPI.
16530b57cec5SDimitry Andric for (int i = 0; i < (int)pdb::kSpecialStreamCount; ++i)
16540b57cec5SDimitry Andric exitOnErr(builder.getMsfBuilder().addStream(0));
16550b57cec5SDimitry Andric
16560b57cec5SDimitry Andric // Add an Info stream.
16570b57cec5SDimitry Andric auto &infoBuilder = builder.getInfoBuilder();
16580b57cec5SDimitry Andric infoBuilder.setVersion(pdb::PdbRaw_ImplVer::PdbImplVC70);
16590b57cec5SDimitry Andric infoBuilder.setHashPDBContentsToGUID(true);
16600b57cec5SDimitry Andric
16610b57cec5SDimitry Andric // Add an empty DBI stream.
16620b57cec5SDimitry Andric pdb::DbiStreamBuilder &dbiBuilder = builder.getDbiBuilder();
16630b57cec5SDimitry Andric dbiBuilder.setAge(buildId->PDB70.Age);
16640b57cec5SDimitry Andric dbiBuilder.setVersionHeader(pdb::PdbDbiV70);
1665bdd1243dSDimitry Andric dbiBuilder.setMachineType(ctx.config.machine);
16660b57cec5SDimitry Andric // Technically we are not link.exe 14.11, but there are known cases where
16670b57cec5SDimitry Andric // debugging tools on Windows expect Microsoft-specific version numbers or
16680b57cec5SDimitry Andric // they fail to work at all. Since we know we produce PDBs that are
16690b57cec5SDimitry Andric // compatible with LINK 14.11, we set that version number here.
16700b57cec5SDimitry Andric dbiBuilder.setBuildNumber(14, 11);
16710b57cec5SDimitry Andric }
16720b57cec5SDimitry Andric
addSections(ArrayRef<uint8_t> sectionTable)1673349cc55cSDimitry Andric void PDBLinker::addSections(ArrayRef<uint8_t> sectionTable) {
16745f757f3fSDimitry Andric llvm::TimeTraceScope timeScope("PDB output sections");
1675bdd1243dSDimitry Andric ExitOnError exitOnErr;
16760b57cec5SDimitry Andric // It's not entirely clear what this is, but the * Linker * module uses it.
16770b57cec5SDimitry Andric pdb::DbiStreamBuilder &dbiBuilder = builder.getDbiBuilder();
1678bdd1243dSDimitry Andric nativePath = ctx.config.pdbPath;
16790b57cec5SDimitry Andric pdbMakeAbsolute(nativePath);
16800b57cec5SDimitry Andric uint32_t pdbFilePathNI = dbiBuilder.addECName(nativePath);
16810b57cec5SDimitry Andric auto &linkerModule = exitOnErr(dbiBuilder.addModuleInfo("* Linker *"));
16820b57cec5SDimitry Andric linkerModule.setPdbFilePathNI(pdbFilePathNI);
16835ffd83dbSDimitry Andric addCommonLinkerModuleSymbols(nativePath, linkerModule);
16840b57cec5SDimitry Andric
16850b57cec5SDimitry Andric // Add section contributions. They must be ordered by ascending RVA.
1686349cc55cSDimitry Andric for (OutputSection *os : ctx.outputSections) {
1687bdd1243dSDimitry Andric addLinkerModuleSectionSymbol(linkerModule, *os, ctx.config.mingw);
16880b57cec5SDimitry Andric for (Chunk *c : os->chunks) {
16890b57cec5SDimitry Andric pdb::SectionContrib sc =
1690349cc55cSDimitry Andric createSectionContrib(ctx, c, linkerModule.getModuleIndex());
16910b57cec5SDimitry Andric builder.getDbiBuilder().addSectionContrib(sc);
16920b57cec5SDimitry Andric }
16930b57cec5SDimitry Andric }
16940b57cec5SDimitry Andric
16950b57cec5SDimitry Andric // The * Linker * first section contrib is only used along with /INCREMENTAL,
16960b57cec5SDimitry Andric // to provide trampolines thunks for incremental function patching. Set this
16970b57cec5SDimitry Andric // as "unused" because LLD doesn't support /INCREMENTAL link.
16980b57cec5SDimitry Andric pdb::SectionContrib sc =
1699349cc55cSDimitry Andric createSectionContrib(ctx, nullptr, llvm::pdb::kInvalidStreamIndex);
17000b57cec5SDimitry Andric linkerModule.setFirstSectionContrib(sc);
17010b57cec5SDimitry Andric
17020b57cec5SDimitry Andric // Add Section Map stream.
17030b57cec5SDimitry Andric ArrayRef<object::coff_section> sections = {
17040b57cec5SDimitry Andric (const object::coff_section *)sectionTable.data(),
17050b57cec5SDimitry Andric sectionTable.size() / sizeof(object::coff_section)};
17065ffd83dbSDimitry Andric dbiBuilder.createSectionMap(sections);
17070b57cec5SDimitry Andric
17080b57cec5SDimitry Andric // Add COFF section header stream.
17090b57cec5SDimitry Andric exitOnErr(
17100b57cec5SDimitry Andric dbiBuilder.addDbgStream(pdb::DbgHeaderType::SectionHdr, sectionTable));
17110b57cec5SDimitry Andric }
17120b57cec5SDimitry Andric
commit(codeview::GUID * guid)17130b57cec5SDimitry Andric void PDBLinker::commit(codeview::GUID *guid) {
1714fe6060f1SDimitry Andric // Print an error and continue if PDB writing fails. This is done mainly so
1715fe6060f1SDimitry Andric // the user can see the output of /time and /summary, which is very helpful
1716fe6060f1SDimitry Andric // when trying to figure out why a PDB file is too large.
1717bdd1243dSDimitry Andric if (Error e = builder.commit(ctx.config.pdbPath, guid)) {
171806c3fb27SDimitry Andric e = handleErrors(std::move(e),
171906c3fb27SDimitry Andric [](const llvm::msf::MSFError &me) {
172006c3fb27SDimitry Andric error(me.message());
172106c3fb27SDimitry Andric if (me.isPageOverflow())
172206c3fb27SDimitry Andric error("try setting a larger /pdbpagesize");
172306c3fb27SDimitry Andric });
1724fe6060f1SDimitry Andric checkError(std::move(e));
1725bdd1243dSDimitry Andric error("failed to write PDB file " + Twine(ctx.config.pdbPath));
1726fe6060f1SDimitry Andric }
17270b57cec5SDimitry Andric }
17280b57cec5SDimitry Andric
getSecrelReloc(Triple::ArchType arch)1729*0fca6ea1SDimitry Andric static uint32_t getSecrelReloc(Triple::ArchType arch) {
1730*0fca6ea1SDimitry Andric switch (arch) {
1731*0fca6ea1SDimitry Andric case Triple::x86_64:
17320b57cec5SDimitry Andric return COFF::IMAGE_REL_AMD64_SECREL;
1733*0fca6ea1SDimitry Andric case Triple::x86:
17340b57cec5SDimitry Andric return COFF::IMAGE_REL_I386_SECREL;
1735*0fca6ea1SDimitry Andric case Triple::thumb:
17360b57cec5SDimitry Andric return COFF::IMAGE_REL_ARM_SECREL;
1737*0fca6ea1SDimitry Andric case Triple::aarch64:
17380b57cec5SDimitry Andric return COFF::IMAGE_REL_ARM64_SECREL;
17390b57cec5SDimitry Andric default:
17400b57cec5SDimitry Andric llvm_unreachable("unknown machine type");
17410b57cec5SDimitry Andric }
17420b57cec5SDimitry Andric }
17430b57cec5SDimitry Andric
17440b57cec5SDimitry Andric // Try to find a line table for the given offset Addr into the given chunk C.
17450b57cec5SDimitry Andric // If a line table was found, the line table, the string and checksum tables
17460b57cec5SDimitry Andric // that are used to interpret the line table, and the offset of Addr in the line
17470b57cec5SDimitry Andric // table are stored in the output arguments. Returns whether a line table was
17480b57cec5SDimitry Andric // found.
findLineTable(const SectionChunk * c,uint32_t addr,DebugStringTableSubsectionRef & cvStrTab,DebugChecksumsSubsectionRef & checksums,DebugLinesSubsectionRef & lines,uint32_t & offsetInLinetable)17490b57cec5SDimitry Andric static bool findLineTable(const SectionChunk *c, uint32_t addr,
17505ffd83dbSDimitry Andric DebugStringTableSubsectionRef &cvStrTab,
17510b57cec5SDimitry Andric DebugChecksumsSubsectionRef &checksums,
17520b57cec5SDimitry Andric DebugLinesSubsectionRef &lines,
17530b57cec5SDimitry Andric uint32_t &offsetInLinetable) {
17540b57cec5SDimitry Andric ExitOnError exitOnErr;
1755*0fca6ea1SDimitry Andric const uint32_t secrelReloc = getSecrelReloc(c->getArch());
17560b57cec5SDimitry Andric
17570b57cec5SDimitry Andric for (SectionChunk *dbgC : c->file->getDebugChunks()) {
17580b57cec5SDimitry Andric if (dbgC->getSectionName() != ".debug$S")
17590b57cec5SDimitry Andric continue;
17600b57cec5SDimitry Andric
17610b57cec5SDimitry Andric // Build a mapping of SECREL relocations in dbgC that refer to `c`.
17620b57cec5SDimitry Andric DenseMap<uint32_t, uint32_t> secrels;
17630b57cec5SDimitry Andric for (const coff_relocation &r : dbgC->getRelocs()) {
17640b57cec5SDimitry Andric if (r.Type != secrelReloc)
17650b57cec5SDimitry Andric continue;
17660b57cec5SDimitry Andric
17670b57cec5SDimitry Andric if (auto *s = dyn_cast_or_null<DefinedRegular>(
17680b57cec5SDimitry Andric c->file->getSymbols()[r.SymbolTableIndex]))
17690b57cec5SDimitry Andric if (s->getChunk() == c)
17700b57cec5SDimitry Andric secrels[r.VirtualAddress] = s->getValue();
17710b57cec5SDimitry Andric }
17720b57cec5SDimitry Andric
17730b57cec5SDimitry Andric ArrayRef<uint8_t> contents =
17740b57cec5SDimitry Andric SectionChunk::consumeDebugMagic(dbgC->getContents(), ".debug$S");
17750b57cec5SDimitry Andric DebugSubsectionArray subsections;
17765f757f3fSDimitry Andric BinaryStreamReader reader(contents, llvm::endianness::little);
17770b57cec5SDimitry Andric exitOnErr(reader.readArray(subsections, contents.size()));
17780b57cec5SDimitry Andric
17790b57cec5SDimitry Andric for (const DebugSubsectionRecord &ss : subsections) {
17800b57cec5SDimitry Andric switch (ss.kind()) {
17810b57cec5SDimitry Andric case DebugSubsectionKind::StringTable: {
17825ffd83dbSDimitry Andric assert(!cvStrTab.valid() &&
17830b57cec5SDimitry Andric "Encountered multiple string table subsections!");
17845ffd83dbSDimitry Andric exitOnErr(cvStrTab.initialize(ss.getRecordData()));
17850b57cec5SDimitry Andric break;
17860b57cec5SDimitry Andric }
17870b57cec5SDimitry Andric case DebugSubsectionKind::FileChecksums:
17880b57cec5SDimitry Andric assert(!checksums.valid() &&
17890b57cec5SDimitry Andric "Encountered multiple checksum subsections!");
17900b57cec5SDimitry Andric exitOnErr(checksums.initialize(ss.getRecordData()));
17910b57cec5SDimitry Andric break;
17920b57cec5SDimitry Andric case DebugSubsectionKind::Lines: {
17930b57cec5SDimitry Andric ArrayRef<uint8_t> bytes;
17940b57cec5SDimitry Andric auto ref = ss.getRecordData();
17950b57cec5SDimitry Andric exitOnErr(ref.readLongestContiguousChunk(0, bytes));
17960b57cec5SDimitry Andric size_t offsetInDbgC = bytes.data() - dbgC->getContents().data();
17970b57cec5SDimitry Andric
17980b57cec5SDimitry Andric // Check whether this line table refers to C.
17990b57cec5SDimitry Andric auto i = secrels.find(offsetInDbgC);
18000b57cec5SDimitry Andric if (i == secrels.end())
18010b57cec5SDimitry Andric break;
18020b57cec5SDimitry Andric
18030b57cec5SDimitry Andric // Check whether this line table covers Addr in C.
18040b57cec5SDimitry Andric DebugLinesSubsectionRef linesTmp;
18050b57cec5SDimitry Andric exitOnErr(linesTmp.initialize(BinaryStreamReader(ref)));
18060b57cec5SDimitry Andric uint32_t offsetInC = i->second + linesTmp.header()->RelocOffset;
18070b57cec5SDimitry Andric if (addr < offsetInC || addr >= offsetInC + linesTmp.header()->CodeSize)
18080b57cec5SDimitry Andric break;
18090b57cec5SDimitry Andric
18100b57cec5SDimitry Andric assert(!lines.header() &&
18110b57cec5SDimitry Andric "Encountered multiple line tables for function!");
18120b57cec5SDimitry Andric exitOnErr(lines.initialize(BinaryStreamReader(ref)));
18130b57cec5SDimitry Andric offsetInLinetable = addr - offsetInC;
18140b57cec5SDimitry Andric break;
18150b57cec5SDimitry Andric }
18160b57cec5SDimitry Andric default:
18170b57cec5SDimitry Andric break;
18180b57cec5SDimitry Andric }
18190b57cec5SDimitry Andric
18205ffd83dbSDimitry Andric if (cvStrTab.valid() && checksums.valid() && lines.header())
18210b57cec5SDimitry Andric return true;
18220b57cec5SDimitry Andric }
18230b57cec5SDimitry Andric }
18240b57cec5SDimitry Andric
18250b57cec5SDimitry Andric return false;
18260b57cec5SDimitry Andric }
18270b57cec5SDimitry Andric
18280b57cec5SDimitry Andric // Use CodeView line tables to resolve a file and line number for the given
1829bdd1243dSDimitry Andric // offset into the given chunk and return them, or std::nullopt if a line table
1830bdd1243dSDimitry Andric // was not found.
1831bdd1243dSDimitry Andric std::optional<std::pair<StringRef, uint32_t>>
getFileLineCodeView(const SectionChunk * c,uint32_t addr)18325ffd83dbSDimitry Andric lld::coff::getFileLineCodeView(const SectionChunk *c, uint32_t addr) {
18330b57cec5SDimitry Andric ExitOnError exitOnErr;
18340b57cec5SDimitry Andric
18355ffd83dbSDimitry Andric DebugStringTableSubsectionRef cvStrTab;
18360b57cec5SDimitry Andric DebugChecksumsSubsectionRef checksums;
18370b57cec5SDimitry Andric DebugLinesSubsectionRef lines;
18380b57cec5SDimitry Andric uint32_t offsetInLinetable;
18390b57cec5SDimitry Andric
18405ffd83dbSDimitry Andric if (!findLineTable(c, addr, cvStrTab, checksums, lines, offsetInLinetable))
1841bdd1243dSDimitry Andric return std::nullopt;
18420b57cec5SDimitry Andric
1843bdd1243dSDimitry Andric std::optional<uint32_t> nameIndex;
1844bdd1243dSDimitry Andric std::optional<uint32_t> lineNumber;
1845349cc55cSDimitry Andric for (const LineColumnEntry &entry : lines) {
18460b57cec5SDimitry Andric for (const LineNumberEntry &ln : entry.LineNumbers) {
18470b57cec5SDimitry Andric LineInfo li(ln.Flags);
18480b57cec5SDimitry Andric if (ln.Offset > offsetInLinetable) {
18490b57cec5SDimitry Andric if (!nameIndex) {
18500b57cec5SDimitry Andric nameIndex = entry.NameIndex;
18510b57cec5SDimitry Andric lineNumber = li.getStartLine();
18520b57cec5SDimitry Andric }
18530b57cec5SDimitry Andric StringRef filename =
18545ffd83dbSDimitry Andric exitOnErr(getFileName(cvStrTab, checksums, *nameIndex));
185585868e8aSDimitry Andric return std::make_pair(filename, *lineNumber);
18560b57cec5SDimitry Andric }
18570b57cec5SDimitry Andric nameIndex = entry.NameIndex;
18580b57cec5SDimitry Andric lineNumber = li.getStartLine();
18590b57cec5SDimitry Andric }
18600b57cec5SDimitry Andric }
18610b57cec5SDimitry Andric if (!nameIndex)
1862bdd1243dSDimitry Andric return std::nullopt;
18635ffd83dbSDimitry Andric StringRef filename = exitOnErr(getFileName(cvStrTab, checksums, *nameIndex));
186485868e8aSDimitry Andric return std::make_pair(filename, *lineNumber);
18650b57cec5SDimitry Andric }
1866