diff options
Diffstat (limited to 'tools/llvm-pdbdump')
| -rw-r--r-- | tools/llvm-pdbdump/C13DebugFragmentVisitor.cpp | 87 | ||||
| -rw-r--r-- | tools/llvm-pdbdump/C13DebugFragmentVisitor.h | 60 | ||||
| -rw-r--r-- | tools/llvm-pdbdump/CMakeLists.txt | 3 | ||||
| -rw-r--r-- | tools/llvm-pdbdump/CompactTypeDumpVisitor.cpp | 14 | ||||
| -rw-r--r-- | tools/llvm-pdbdump/CompactTypeDumpVisitor.h | 2 | ||||
| -rw-r--r-- | tools/llvm-pdbdump/LLVMOutputStyle.cpp | 282 | ||||
| -rw-r--r-- | tools/llvm-pdbdump/PdbYaml.cpp | 36 | ||||
| -rw-r--r-- | tools/llvm-pdbdump/PdbYaml.h | 31 | ||||
| -rw-r--r-- | tools/llvm-pdbdump/StreamUtil.cpp | 2 | ||||
| -rw-r--r-- | tools/llvm-pdbdump/YAMLOutputStyle.cpp | 171 | ||||
| -rw-r--r-- | tools/llvm-pdbdump/YAMLOutputStyle.h | 4 | ||||
| -rw-r--r-- | tools/llvm-pdbdump/fuzzer/llvm-pdbdump-fuzzer.cpp | 4 | ||||
| -rw-r--r-- | tools/llvm-pdbdump/llvm-pdbdump.cpp | 100 | ||||
| -rw-r--r-- | tools/llvm-pdbdump/llvm-pdbdump.h | 2 |
14 files changed, 597 insertions, 201 deletions
diff --git a/tools/llvm-pdbdump/C13DebugFragmentVisitor.cpp b/tools/llvm-pdbdump/C13DebugFragmentVisitor.cpp new file mode 100644 index 0000000000000..7c680ebb94cfd --- /dev/null +++ b/tools/llvm-pdbdump/C13DebugFragmentVisitor.cpp @@ -0,0 +1,87 @@ +//===- C13DebugFragmentVisitor.cpp -------------------------------*- C++-*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "C13DebugFragmentVisitor.h" + +#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h" +#include "llvm/DebugInfo/PDB/Native/PDBFile.h" +#include "llvm/DebugInfo/PDB/Native/RawError.h" +#include "llvm/DebugInfo/PDB/Native/StringTable.h" + +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::pdb; + +C13DebugFragmentVisitor::C13DebugFragmentVisitor(PDBFile &F) : F(F) {} + +C13DebugFragmentVisitor::~C13DebugFragmentVisitor() {} + +Error C13DebugFragmentVisitor::visitUnknown( + codeview::ModuleDebugUnknownFragmentRef &Fragment) { + return Error::success(); +} + +Error C13DebugFragmentVisitor::visitFileChecksums( + codeview::ModuleDebugFileChecksumFragmentRef &Checksums) { + assert(!this->Checksums.hasValue()); + this->Checksums = Checksums; + return Error::success(); +} + +Error C13DebugFragmentVisitor::visitLines( + codeview::ModuleDebugLineFragmentRef &Lines) { + this->Lines.push_back(Lines); + return Error::success(); +} + +Error C13DebugFragmentVisitor::visitInlineeLines( + codeview::ModuleDebugInlineeLineFragmentRef &Lines) { + this->InlineeLines.push_back(Lines); + return Error::success(); +} + +Error C13DebugFragmentVisitor::finished() { + if (!Checksums.hasValue()) { + assert(Lines.empty()); + return Error::success(); + } + if (auto EC = handleFileChecksums()) + return EC; + + if (auto EC = handleLines()) + return EC; + + if (auto EC = handleInlineeLines()) + return EC; + + return Error::success(); +} + +Expected<StringRef> +C13DebugFragmentVisitor::getNameFromStringTable(uint32_t Offset) { + auto ST = F.getStringTable(); + if (!ST) + return ST.takeError(); + + return ST->getStringForID(Offset); +} + +Expected<StringRef> +C13DebugFragmentVisitor::getNameFromChecksumsBuffer(uint32_t Offset) { + assert(Checksums.hasValue()); + + auto Array = Checksums->getArray(); + auto ChecksumIter = Array.at(Offset); + if (ChecksumIter == Array.end()) + return make_error<RawError>(raw_error_code::invalid_format); + const auto &Entry = *ChecksumIter; + return getNameFromStringTable(Entry.FileNameOffset); +} diff --git a/tools/llvm-pdbdump/C13DebugFragmentVisitor.h b/tools/llvm-pdbdump/C13DebugFragmentVisitor.h new file mode 100644 index 0000000000000..1054b0c9f6e0a --- /dev/null +++ b/tools/llvm-pdbdump/C13DebugFragmentVisitor.h @@ -0,0 +1,60 @@ +//===- C13DebugFragmentVisitor.h - Visitor for CodeView Info ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVMPDBDUMP_C13DEBUGFRAGMENTVISITOR_H +#define LLVM_TOOLS_LLVMPDBDUMP_C13DEBUGFRAGMENTVISITOR_H + +#include "llvm/ADT/Optional.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h" +#include "llvm/Support/Error.h" + +#include <vector> + +namespace llvm { + +namespace pdb { + +class PDBFile; + +class C13DebugFragmentVisitor : public codeview::ModuleDebugFragmentVisitor { +public: + C13DebugFragmentVisitor(PDBFile &F); + ~C13DebugFragmentVisitor(); + + Error visitUnknown(codeview::ModuleDebugUnknownFragmentRef &Fragment) final; + + Error visitFileChecksums( + codeview::ModuleDebugFileChecksumFragmentRef &Checksums) final; + + Error visitLines(codeview::ModuleDebugLineFragmentRef &Lines) final; + + Error + visitInlineeLines(codeview::ModuleDebugInlineeLineFragmentRef &Lines) final; + + Error finished() final; + +protected: + virtual Error handleFileChecksums() { return Error::success(); } + virtual Error handleLines() { return Error::success(); } + virtual Error handleInlineeLines() { return Error::success(); } + + Expected<StringRef> getNameFromStringTable(uint32_t Offset); + Expected<StringRef> getNameFromChecksumsBuffer(uint32_t Offset); + + Optional<codeview::ModuleDebugFileChecksumFragmentRef> Checksums; + std::vector<codeview::ModuleDebugInlineeLineFragmentRef> InlineeLines; + std::vector<codeview::ModuleDebugLineFragmentRef> Lines; + + PDBFile &F; +}; +} +} + +#endif diff --git a/tools/llvm-pdbdump/CMakeLists.txt b/tools/llvm-pdbdump/CMakeLists.txt index e3d7b2ef275e4..325e38c15ca73 100644 --- a/tools/llvm-pdbdump/CMakeLists.txt +++ b/tools/llvm-pdbdump/CMakeLists.txt @@ -8,8 +8,9 @@ set(LLVM_LINK_COMPONENTS add_llvm_tool(llvm-pdbdump Analyze.cpp - Diff.cpp + C13DebugFragmentVisitor.cpp CompactTypeDumpVisitor.cpp + Diff.cpp llvm-pdbdump.cpp YamlSymbolDumper.cpp YamlTypeDumper.cpp diff --git a/tools/llvm-pdbdump/CompactTypeDumpVisitor.cpp b/tools/llvm-pdbdump/CompactTypeDumpVisitor.cpp index 1fc8dd5d51f0a..5ad0bfad26c19 100644 --- a/tools/llvm-pdbdump/CompactTypeDumpVisitor.cpp +++ b/tools/llvm-pdbdump/CompactTypeDumpVisitor.cpp @@ -31,14 +31,15 @@ static StringRef getLeafName(TypeLeafKind K) { CompactTypeDumpVisitor::CompactTypeDumpVisitor(TypeDatabase &TypeDB, ScopedPrinter *W) - : W(W), TI(TypeIndex::None()), Offset(0), TypeDB(TypeDB) {} + : CompactTypeDumpVisitor(TypeDB, TypeIndex(TypeIndex::FirstNonSimpleIndex), + W) {} -Error CompactTypeDumpVisitor::visitTypeBegin(CVType &Record) { - if (TI == TypeIndex::None()) - TI.setIndex(TypeIndex::FirstNonSimpleIndex); - else - TI.setIndex(TI.getIndex() + 1); +CompactTypeDumpVisitor::CompactTypeDumpVisitor(TypeDatabase &TypeDB, + TypeIndex FirstTI, + ScopedPrinter *W) + : W(W), TI(FirstTI), Offset(0), TypeDB(TypeDB) {} +Error CompactTypeDumpVisitor::visitTypeBegin(CVType &Record) { return Error::success(); } @@ -52,6 +53,7 @@ Error CompactTypeDumpVisitor::visitTypeEnd(CVType &Record) { .str()); Offset += Record.length(); + TI.setIndex(TI.getIndex() + 1); return Error::success(); } diff --git a/tools/llvm-pdbdump/CompactTypeDumpVisitor.h b/tools/llvm-pdbdump/CompactTypeDumpVisitor.h index 180eea7b8d6a1..76fafc93e030d 100644 --- a/tools/llvm-pdbdump/CompactTypeDumpVisitor.h +++ b/tools/llvm-pdbdump/CompactTypeDumpVisitor.h @@ -27,6 +27,8 @@ namespace pdb { class CompactTypeDumpVisitor : public codeview::TypeVisitorCallbacks { public: CompactTypeDumpVisitor(codeview::TypeDatabase &TypeDB, ScopedPrinter *W); + CompactTypeDumpVisitor(codeview::TypeDatabase &TypeDB, + codeview::TypeIndex FirstTI, ScopedPrinter *W); /// Paired begin/end actions for all types. Receives all record data, /// including the fixed-length record prefix. diff --git a/tools/llvm-pdbdump/LLVMOutputStyle.cpp b/tools/llvm-pdbdump/LLVMOutputStyle.cpp index 8348751703f14..f3e28e0b08fc5 100644 --- a/tools/llvm-pdbdump/LLVMOutputStyle.cpp +++ b/tools/llvm-pdbdump/LLVMOutputStyle.cpp @@ -9,6 +9,7 @@ #include "LLVMOutputStyle.h" +#include "C13DebugFragmentVisitor.h" #include "CompactTypeDumpVisitor.h" #include "StreamUtil.h" #include "llvm-pdbdump.h" @@ -16,20 +17,25 @@ #include "llvm/DebugInfo/CodeView/CVTypeDumper.h" #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" #include "llvm/DebugInfo/CodeView/EnumTables.h" -#include "llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h" +#include "llvm/DebugInfo/CodeView/Line.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugUnknownFragment.h" #include "llvm/DebugInfo/CodeView/SymbolDumper.h" #include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h" #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" #include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h" #include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" +#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h" #include "llvm/DebugInfo/PDB/Native/DbiStream.h" #include "llvm/DebugInfo/PDB/Native/EnumTables.h" #include "llvm/DebugInfo/PDB/Native/GlobalsStream.h" #include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h" #include "llvm/DebugInfo/PDB/Native/InfoStream.h" -#include "llvm/DebugInfo/PDB/Native/ModInfo.h" -#include "llvm/DebugInfo/PDB/Native/ModStream.h" +#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h" #include "llvm/DebugInfo/PDB/Native/PublicsStream.h" #include "llvm/DebugInfo/PDB/Native/RawError.h" @@ -74,6 +80,127 @@ struct PageStats { // Pages which are marked free in the FPM but are used. BitVector UseAfterFreePages; }; + +class C13RawVisitor : public C13DebugFragmentVisitor { +public: + C13RawVisitor(ScopedPrinter &P, PDBFile &F, TypeDatabase &IPI) + : C13DebugFragmentVisitor(F), P(P), IPI(IPI) {} + + Error handleLines() override { + if (Lines.empty()) + return Error::success(); + + DictScope DD(P, "Lines"); + + for (const auto &Fragment : Lines) { + DictScope DDD(P, "Block"); + P.printNumber("RelocSegment", Fragment.header()->RelocSegment); + P.printNumber("RelocOffset", Fragment.header()->RelocOffset); + P.printNumber("CodeSize", Fragment.header()->CodeSize); + P.printBoolean("HasColumns", Fragment.hasColumnInfo()); + + for (const auto &L : Fragment) { + DictScope DDDD(P, "Lines"); + + if (auto EC = printFileName("FileName", L.NameIndex)) + return EC; + + for (const auto &N : L.LineNumbers) { + DictScope DDD(P, "Line"); + LineInfo LI(N.Flags); + P.printNumber("Offset", N.Offset); + if (LI.isAlwaysStepInto()) + P.printString("StepInto", StringRef("Always")); + else if (LI.isNeverStepInto()) + P.printString("StepInto", StringRef("Never")); + else + P.printNumber("LineNumberStart", LI.getStartLine()); + P.printNumber("EndDelta", LI.getLineDelta()); + P.printBoolean("IsStatement", LI.isStatement()); + } + for (const auto &C : L.Columns) { + DictScope DDD(P, "Column"); + P.printNumber("Start", C.StartColumn); + P.printNumber("End", C.EndColumn); + } + } + } + + return Error::success(); + } + + Error handleFileChecksums() override { + if (!Checksums.hasValue()) + return Error::success(); + + DictScope DD(P, "FileChecksums"); + for (const auto &CS : *Checksums) { + DictScope DDD(P, "Checksum"); + if (auto Result = getNameFromStringTable(CS.FileNameOffset)) + P.printString("FileName", *Result); + else + return Result.takeError(); + P.printEnum("Kind", uint8_t(CS.Kind), getFileChecksumNames()); + P.printBinaryBlock("Checksum", CS.Checksum); + } + return Error::success(); + } + + Error handleInlineeLines() override { + if (InlineeLines.empty()) + return Error::success(); + + DictScope D(P, "InlineeLines"); + for (const auto &IL : InlineeLines) { + P.printBoolean("HasExtraFiles", IL.hasExtraFiles()); + ListScope LS(P, "Lines"); + for (const auto &L : IL) { + DictScope DDD(P, "Inlinee"); + if (auto EC = printFileName("FileName", L.Header->FileID)) + return EC; + + if (auto EC = dumpTypeRecord("Function", IPI, L.Header->Inlinee)) + return EC; + P.printNumber("SourceLine", L.Header->SourceLineNum); + if (IL.hasExtraFiles()) { + ListScope DDDD(P, "ExtraFiles"); + for (const auto &EF : L.ExtraFiles) { + if (auto EC = printFileName("File", EF)) + return EC; + } + } + } + } + return Error::success(); + } + +private: + Error dumpTypeRecord(StringRef Label, TypeDatabase &DB, TypeIndex Index) { + CompactTypeDumpVisitor CTDV(DB, Index, &P); + CVTypeVisitor Visitor(CTDV); + DictScope D(P, Label); + if (DB.containsTypeIndex(Index)) { + CVType &Type = DB.getTypeRecord(Index); + if (auto EC = Visitor.visitTypeRecord(Type)) + return EC; + } else { + P.printString( + llvm::formatv("Index: {0:x} (unknown function)", Index.getIndex()) + .str()); + } + return Error::success(); + } + Error printFileName(StringRef Label, uint32_t Offset) { + if (auto Result = getNameFromChecksumsBuffer(Offset)) { + P.printString(Label, *Result); + return Error::success(); + } else + return Result.takeError(); + } + + ScopedPrinter &P; + TypeDatabase &IPI; +}; } static void recordKnownUsedPage(PageStats &Stats, uint32_t UsedIndex) { @@ -316,6 +443,27 @@ Error LLVMOutputStyle::dumpBlockRanges() { return Error::success(); } +static Error parseStreamSpec(StringRef Str, uint32_t &SI, uint32_t &Offset, + uint32_t &Size) { + if (Str.consumeInteger(0, SI)) + return make_error<RawError>(raw_error_code::invalid_format, + "Invalid Stream Specification"); + if (Str.consume_front(":")) { + if (Str.consumeInteger(0, Offset)) + return make_error<RawError>(raw_error_code::invalid_format, + "Invalid Stream Specification"); + } + if (Str.consume_front("@")) { + if (Str.consumeInteger(0, Size)) + return make_error<RawError>(raw_error_code::invalid_format, + "Invalid Stream Specification"); + } + if (!Str.empty()) + return make_error<RawError>(raw_error_code::invalid_format, + "Invalid Stream Specification"); + return Error::success(); +} + Error LLVMOutputStyle::dumpStreamBytes() { if (opts::raw::DumpStreamData.empty()) return Error::success(); @@ -324,7 +472,15 @@ Error LLVMOutputStyle::dumpStreamBytes() { discoverStreamPurposes(File, StreamPurposes); DictScope D(P, "Stream Data"); - for (uint32_t SI : opts::raw::DumpStreamData) { + for (auto &Str : opts::raw::DumpStreamData) { + uint32_t SI = 0; + uint32_t Begin = 0; + uint32_t Size = 0; + uint32_t End = 0; + + if (auto EC = parseStreamSpec(Str, SI, Begin, Size)) + return EC; + if (SI >= File.getNumStreams()) return make_error<RawError>(raw_error_code::no_stream); @@ -333,6 +489,14 @@ Error LLVMOutputStyle::dumpStreamBytes() { if (!S) continue; DictScope DD(P, "Stream"); + if (Size == 0) + End = S->getLength(); + else { + End = Begin + Size; + if (End >= S->getLength()) + return make_error<RawError>(raw_error_code::index_out_of_bounds, + "Stream is not long enough!"); + } P.printNumber("Index", SI); P.printString("Type", StreamPurposes[SI]); @@ -344,7 +508,9 @@ Error LLVMOutputStyle::dumpStreamBytes() { ArrayRef<uint8_t> StreamData; if (auto EC = R.readBytes(StreamData, S->getLength())) return EC; - P.printBinaryBlock("Data", StreamData); + Size = End - Begin; + StreamData = StreamData.slice(Begin, Size); + P.printBinaryBlock("Data", StreamData, Begin); } return Error::success(); } @@ -439,11 +605,12 @@ Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) { Label = "Type Info Stream (IPI)"; VerLabel = "IPI Version"; } - if (!DumpRecordBytes && !DumpRecords && !DumpTpiHash && - !opts::raw::DumpModuleSyms) - return Error::success(); bool IsSilentDatabaseBuild = !DumpRecordBytes && !DumpRecords && !DumpTpiHash; + if (IsSilentDatabaseBuild) { + outs().flush(); + errs() << "Building Type Information For " << Label << "\n"; + } auto Tpi = (StreamIdx == StreamTPI) ? File.getPDBTpiStream() : File.getPDBIpiStream(); @@ -502,6 +669,7 @@ Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) { if (auto EC = Visitor.visitTypeRecord(Type)) return EC; + T.setIndex(T.getIndex() + 1); } if (HadError) return make_error<RawError>(raw_error_code::corrupt_file, @@ -584,7 +752,7 @@ Error LLVMOutputStyle::dumpDbiStream() { P.printNumber("Num Files", Modi.Info.getNumberOfFiles()); P.printNumber("Source File Name Idx", Modi.Info.getSourceFileNameIndex()); P.printNumber("Pdb File Name Idx", Modi.Info.getPdbFilePathNameIndex()); - P.printNumber("Line Info Byte Size", Modi.Info.getLineInfoByteSize()); + P.printNumber("Line Info Byte Size", Modi.Info.getC11LineInfoByteSize()); P.printNumber("C13 Line Info Byte Size", Modi.Info.getC13LineInfoByteSize()); P.printNumber("Symbol Byte Size", Modi.Info.getSymbolDebugInfoByteSize()); @@ -606,7 +774,7 @@ Error LLVMOutputStyle::dumpDbiStream() { File.getMsfLayout(), File.getMsfBuffer(), Modi.Info.getModuleStreamIndex()); - ModStream ModS(Modi.Info, std::move(ModStreamData)); + ModuleDebugStreamRef ModS(Modi.Info, std::move(ModStreamData)); if (auto EC = ModS.reload()) return EC; @@ -633,97 +801,11 @@ Error LLVMOutputStyle::dumpDbiStream() { } if (opts::raw::DumpLineInfo) { ListScope SS(P, "LineInfo"); - bool HadError = false; - // Define a locally scoped visitor to print the different - // substream types types. - class RecordVisitor : public codeview::IModuleSubstreamVisitor { - public: - RecordVisitor(ScopedPrinter &P, PDBFile &F) : P(P), F(F) {} - Error visitUnknown(ModuleSubstreamKind Kind, - BinaryStreamRef Stream) override { - DictScope DD(P, "Unknown"); - ArrayRef<uint8_t> Data; - BinaryStreamReader R(Stream); - if (auto EC = R.readBytes(Data, R.bytesRemaining())) { - return make_error<RawError>( - raw_error_code::corrupt_file, - "DBI stream contained corrupt line info record"); - } - P.printBinaryBlock("Data", Data); - return Error::success(); - } - Error - visitFileChecksums(BinaryStreamRef Data, - const FileChecksumArray &Checksums) override { - DictScope DD(P, "FileChecksums"); - for (const auto &C : Checksums) { - DictScope DDD(P, "Checksum"); - if (auto Result = getFileNameForOffset(C.FileNameOffset)) - P.printString("FileName", Result.get()); - else - return Result.takeError(); - P.flush(); - P.printEnum("Kind", uint8_t(C.Kind), getFileChecksumNames()); - P.printBinaryBlock("Checksum", C.Checksum); - } - return Error::success(); - } - Error visitLines(BinaryStreamRef Data, - const LineSubstreamHeader *Header, - const LineInfoArray &Lines) override { - DictScope DD(P, "Lines"); - for (const auto &L : Lines) { - if (auto Result = getFileNameForOffset2(L.NameIndex)) - P.printString("FileName", Result.get()); - else - return Result.takeError(); - P.flush(); - for (const auto &N : L.LineNumbers) { - DictScope DDD(P, "Line"); - LineInfo LI(N.Flags); - P.printNumber("Offset", N.Offset); - if (LI.isAlwaysStepInto()) - P.printString("StepInto", StringRef("Always")); - else if (LI.isNeverStepInto()) - P.printString("StepInto", StringRef("Never")); - else - P.printNumber("LineNumberStart", LI.getStartLine()); - P.printNumber("EndDelta", LI.getLineDelta()); - P.printBoolean("IsStatement", LI.isStatement()); - } - for (const auto &C : L.Columns) { - DictScope DDD(P, "Column"); - P.printNumber("Start", C.StartColumn); - P.printNumber("End", C.EndColumn); - } - } - return Error::success(); - } - - private: - Expected<StringRef> getFileNameForOffset(uint32_t Offset) { - auto ST = F.getStringTable(); - if (!ST) - return ST.takeError(); - - return ST->getStringForID(Offset); - } - Expected<StringRef> getFileNameForOffset2(uint32_t Offset) { - auto DS = F.getPDBDbiStream(); - if (!DS) - return DS.takeError(); - return DS->getFileNameForIndex(Offset); - } - ScopedPrinter &P; - PDBFile &F; - }; - - RecordVisitor V(P, File); - for (const auto &L : ModS.lines(&HadError)) { - if (auto EC = codeview::visitModuleSubstream(L, V)) - return EC; - } + C13RawVisitor V(P, File, ItemDB); + if (auto EC = codeview::visitModuleDebugFragments( + ModS.linesAndChecksums(), V)) + return EC; } } } diff --git a/tools/llvm-pdbdump/PdbYaml.cpp b/tools/llvm-pdbdump/PdbYaml.cpp index 65a5a9142d20a..d6ba7d6454593 100644 --- a/tools/llvm-pdbdump/PdbYaml.cpp +++ b/tools/llvm-pdbdump/PdbYaml.cpp @@ -40,6 +40,9 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbSourceFileChecksumEntry) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbSourceLineEntry) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbSourceColumnEntry) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbSourceLineBlock) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbSourceLineInfo) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbInlineeSite) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbInlineeInfo) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbSymbolRecord) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbTpiRecord) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::StreamBlockList) @@ -162,8 +165,7 @@ template <> struct ScalarEnumerationTraits<llvm::codeview::FileChecksumKind> { template <> struct ScalarBitSetTraits<llvm::codeview::LineFlags> { static void bitset(IO &io, llvm::codeview::LineFlags &Flags) { - io.bitSetCase(Flags, "HasColumnInfo", - llvm::codeview::LineFlags::HaveColumns); + io.bitSetCase(Flags, "HasColumnInfo", llvm::codeview::LF_HaveColumns); io.enumFallback<Hex16>(Flags); } }; @@ -311,7 +313,7 @@ void MappingContextTraits<pdb::yaml::PdbSourceColumnEntry, pdb::yaml::SerializationContext &Context) { IO.mapRequired("StartColumn", Obj.StartColumn); IO.mapRequired("EndColumn", Obj.EndColumn); -}; +} void MappingContextTraits<pdb::yaml::PdbSourceLineBlock, pdb::yaml::SerializationContext>:: @@ -320,7 +322,7 @@ void MappingContextTraits<pdb::yaml::PdbSourceLineBlock, IO.mapRequired("FileName", Obj.FileName); IO.mapRequired("Lines", Obj.Lines, Context); IO.mapRequired("Columns", Obj.Columns, Context); -}; +} void MappingContextTraits<pdb::yaml::PdbSourceFileChecksumEntry, pdb::yaml::SerializationContext>:: @@ -329,26 +331,42 @@ void MappingContextTraits<pdb::yaml::PdbSourceFileChecksumEntry, IO.mapRequired("FileName", Obj.FileName); IO.mapRequired("Kind", Obj.Kind); IO.mapRequired("Checksum", Obj.ChecksumBytes); -}; +} void MappingContextTraits<pdb::yaml::PdbSourceLineInfo, pdb::yaml::SerializationContext>:: mapping(IO &IO, PdbSourceLineInfo &Obj, pdb::yaml::SerializationContext &Context) { IO.mapRequired("CodeSize", Obj.CodeSize); + IO.mapRequired("Flags", Obj.Flags); IO.mapRequired("RelocOffset", Obj.RelocOffset); IO.mapRequired("RelocSegment", Obj.RelocSegment); - IO.mapRequired("LineInfo", Obj.LineInfo, Context); -}; + IO.mapRequired("Blocks", Obj.Blocks, Context); +} void MappingContextTraits<pdb::yaml::PdbSourceFileInfo, pdb::yaml::SerializationContext>:: mapping(IO &IO, PdbSourceFileInfo &Obj, pdb::yaml::SerializationContext &Context) { - IO.mapOptionalWithContext("Lines", Obj.Lines, Context); IO.mapOptionalWithContext("Checksums", Obj.FileChecksums, Context); -}; + IO.mapOptionalWithContext("Lines", Obj.LineFragments, Context); + IO.mapOptionalWithContext("InlineeLines", Obj.Inlinees, Context); +} + +void MappingContextTraits<PdbInlineeSite, SerializationContext>::mapping( + IO &IO, PdbInlineeSite &Obj, SerializationContext &Context) { + IO.mapRequired("FileName", Obj.FileName); + IO.mapRequired("LineNum", Obj.SourceLineNum); + IO.mapRequired("Inlinee", Obj.Inlinee); + IO.mapOptional("ExtraFiles", Obj.ExtraFiles); +} + +void MappingContextTraits<PdbInlineeInfo, SerializationContext>::mapping( + IO &IO, PdbInlineeInfo &Obj, SerializationContext &Context) { + IO.mapRequired("HasExtraFiles", Obj.HasExtraFiles); + IO.mapRequired("Sites", Obj.Sites, Context); +} void MappingContextTraits<PdbTpiRecord, pdb::yaml::SerializationContext>:: mapping(IO &IO, pdb::yaml::PdbTpiRecord &Obj, diff --git a/tools/llvm-pdbdump/PdbYaml.h b/tools/llvm-pdbdump/PdbYaml.h index 96e0583ca23d1..423845caeb317 100644 --- a/tools/llvm-pdbdump/PdbYaml.h +++ b/tools/llvm-pdbdump/PdbYaml.h @@ -99,12 +99,25 @@ struct PdbSourceLineInfo { codeview::LineFlags Flags; uint32_t CodeSize; - std::vector<PdbSourceLineBlock> LineInfo; + std::vector<PdbSourceLineBlock> Blocks; +}; + +struct PdbInlineeSite { + codeview::TypeIndex Inlinee; + StringRef FileName; + uint32_t SourceLineNum; + std::vector<StringRef> ExtraFiles; +}; + +struct PdbInlineeInfo { + bool HasExtraFiles; + std::vector<PdbInlineeSite> Sites; }; struct PdbSourceFileInfo { - PdbSourceLineInfo Lines; std::vector<PdbSourceFileChecksumEntry> FileChecksums; + std::vector<PdbSourceLineInfo> LineFragments; + std::vector<PdbInlineeInfo> Inlinees; }; struct PdbDbiModuleInfo { @@ -259,6 +272,20 @@ struct MappingContextTraits<pdb::yaml::PdbSourceFileInfo, }; template <> +struct MappingContextTraits<pdb::yaml::PdbInlineeInfo, + pdb::yaml::SerializationContext> { + static void mapping(IO &IO, pdb::yaml::PdbInlineeInfo &Obj, + pdb::yaml::SerializationContext &Context); +}; + +template <> +struct MappingContextTraits<pdb::yaml::PdbInlineeSite, + pdb::yaml::SerializationContext> { + static void mapping(IO &IO, pdb::yaml::PdbInlineeSite &Obj, + pdb::yaml::SerializationContext &Context); +}; + +template <> struct MappingContextTraits<pdb::yaml::PdbTpiRecord, pdb::yaml::SerializationContext> { static void mapping(IO &IO, pdb::yaml::PdbTpiRecord &Obj, diff --git a/tools/llvm-pdbdump/StreamUtil.cpp b/tools/llvm-pdbdump/StreamUtil.cpp index db1e01aa01543..6577702adac88 100644 --- a/tools/llvm-pdbdump/StreamUtil.cpp +++ b/tools/llvm-pdbdump/StreamUtil.cpp @@ -11,9 +11,9 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMapInfo.h" +#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h" #include "llvm/DebugInfo/PDB/Native/DbiStream.h" #include "llvm/DebugInfo/PDB/Native/InfoStream.h" -#include "llvm/DebugInfo/PDB/Native/ModInfo.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h" #include "llvm/DebugInfo/PDB/Native/TpiStream.h" diff --git a/tools/llvm-pdbdump/YAMLOutputStyle.cpp b/tools/llvm-pdbdump/YAMLOutputStyle.cpp index b329de265e720..807d7f8b82e1e 100644 --- a/tools/llvm-pdbdump/YAMLOutputStyle.cpp +++ b/tools/llvm-pdbdump/YAMLOutputStyle.cpp @@ -9,21 +9,28 @@ #include "YAMLOutputStyle.h" +#include "C13DebugFragmentVisitor.h" #include "PdbYaml.h" #include "llvm-pdbdump.h" #include "llvm/DebugInfo/CodeView/Line.h" -#include "llvm/DebugInfo/CodeView/ModuleSubstream.h" -#include "llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugUnknownFragment.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Native/DbiStream.h" #include "llvm/DebugInfo/PDB/Native/InfoStream.h" -#include "llvm/DebugInfo/PDB/Native/ModStream.h" +#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h" #include "llvm/DebugInfo/PDB/Native/RawConstants.h" +#include "llvm/DebugInfo/PDB/Native/RawError.h" #include "llvm/DebugInfo/PDB/Native/TpiStream.h" using namespace llvm; +using namespace llvm::codeview; using namespace llvm::pdb; YAMLOutputStyle::YAMLOutputStyle(PDBFile &File) @@ -46,6 +53,12 @@ Error YAMLOutputStyle::dump() { if (opts::pdb2yaml::DbiModuleInfo) opts::pdb2yaml::DbiStream = true; + // Some names from the module source file info get pulled from the string + // table, so if we're writing module source info, we have to write the string + // table as well. + if (opts::pdb2yaml::DbiModuleSourceLineInfo) + opts::pdb2yaml::StringTable = true; + if (auto EC = dumpFileHeaders()) return EC; @@ -75,22 +88,15 @@ Error YAMLOutputStyle::dump() { } namespace { -class C13SubstreamVisitor : public codeview::IModuleSubstreamVisitor { +class C13YamlVisitor : public C13DebugFragmentVisitor { public: - C13SubstreamVisitor(llvm::pdb::yaml::PdbSourceFileInfo &Info, PDBFile &F) - : Info(Info), F(F) {} - - Error visitUnknown(codeview::ModuleSubstreamKind Kind, - BinaryStreamRef Stream) override { - return Error::success(); - } + C13YamlVisitor(llvm::pdb::yaml::PdbSourceFileInfo &Info, PDBFile &F) + : C13DebugFragmentVisitor(F), Info(Info) {} - Error - visitFileChecksums(BinaryStreamRef Data, - const codeview::FileChecksumArray &Checksums) override { - for (const auto &C : Checksums) { + Error handleFileChecksums() override { + for (const auto &C : *Checksums) { llvm::pdb::yaml::PdbSourceFileChecksumEntry Entry; - if (auto Result = getGlobalString(C.FileNameOffset)) + if (auto Result = getNameFromStringTable(C.FileNameOffset)) Entry.FileName = *Result; else return Result.takeError(); @@ -102,80 +108,94 @@ public: return Error::success(); } - Error visitLines(BinaryStreamRef Data, - const codeview::LineSubstreamHeader *Header, - const codeview::LineInfoArray &Lines) override { + Error handleLines() override { + for (const auto &LF : Lines) { + Info.LineFragments.emplace_back(); + auto &Fragment = Info.LineFragments.back(); - Info.Lines.CodeSize = Header->CodeSize; - Info.Lines.Flags = - static_cast<codeview::LineFlags>(uint16_t(Header->Flags)); - Info.Lines.RelocOffset = Header->RelocOffset; - Info.Lines.RelocSegment = Header->RelocSegment; + Fragment.CodeSize = LF.header()->CodeSize; + Fragment.Flags = + static_cast<codeview::LineFlags>(uint16_t(LF.header()->Flags)); + Fragment.RelocOffset = LF.header()->RelocOffset; + Fragment.RelocSegment = LF.header()->RelocSegment; - for (const auto &L : Lines) { - llvm::pdb::yaml::PdbSourceLineBlock Block; + for (const auto &L : LF) { + Fragment.Blocks.emplace_back(); + auto &Block = Fragment.Blocks.back(); - if (auto Result = getDbiFileName(L.NameIndex)) - Block.FileName = *Result; - else - return Result.takeError(); + if (auto Result = getNameFromChecksumsBuffer(L.NameIndex)) + Block.FileName = *Result; + else + return Result.takeError(); - for (const auto &N : L.LineNumbers) { - llvm::pdb::yaml::PdbSourceLineEntry Line; - Line.Offset = N.Offset; - codeview::LineInfo LI(N.Flags); - Line.LineStart = LI.getStartLine(); - Line.EndDelta = LI.getEndLine(); - Line.IsStatement = LI.isStatement(); - Block.Lines.push_back(Line); - } + for (const auto &N : L.LineNumbers) { + llvm::pdb::yaml::PdbSourceLineEntry Line; + Line.Offset = N.Offset; + codeview::LineInfo LI(N.Flags); + Line.LineStart = LI.getStartLine(); + Line.EndDelta = LI.getLineDelta(); + Line.IsStatement = LI.isStatement(); + Block.Lines.push_back(Line); + } - if (Info.Lines.Flags & codeview::LineFlags::HaveColumns) { - for (const auto &C : L.Columns) { - llvm::pdb::yaml::PdbSourceColumnEntry Column; - Column.StartColumn = C.StartColumn; - Column.EndColumn = C.EndColumn; - Block.Columns.push_back(Column); + if (LF.hasColumnInfo()) { + for (const auto &C : L.Columns) { + llvm::pdb::yaml::PdbSourceColumnEntry Column; + Column.StartColumn = C.StartColumn; + Column.EndColumn = C.EndColumn; + Block.Columns.push_back(Column); + } } } - - Info.Lines.LineInfo.push_back(Block); } return Error::success(); } -private: - Expected<StringRef> getGlobalString(uint32_t Offset) { - auto ST = F.getStringTable(); - if (!ST) - return ST.takeError(); + Error handleInlineeLines() override { + for (const auto &ILF : InlineeLines) { + Info.Inlinees.emplace_back(); + auto &Inlinee = Info.Inlinees.back(); - return ST->getStringForID(Offset); - } - Expected<StringRef> getDbiFileName(uint32_t Offset) { - auto DS = F.getPDBDbiStream(); - if (!DS) - return DS.takeError(); - return DS->getFileNameForIndex(Offset); + Inlinee.HasExtraFiles = ILF.hasExtraFiles(); + for (const auto &IL : ILF) { + Inlinee.Sites.emplace_back(); + auto &Site = Inlinee.Sites.back(); + if (auto Result = getNameFromChecksumsBuffer(IL.Header->FileID)) + Site.FileName = *Result; + else + return Result.takeError(); + + Site.Inlinee = IL.Header->Inlinee; + Site.SourceLineNum = IL.Header->SourceLineNum; + if (ILF.hasExtraFiles()) { + for (const auto &EF : IL.ExtraFiles) { + if (auto Result = getNameFromChecksumsBuffer(EF)) + Site.ExtraFiles.push_back(*Result); + else + return Result.takeError(); + } + } + } + } + return Error::success(); } +private: + llvm::pdb::yaml::PdbSourceFileInfo &Info; - PDBFile &F; }; } Expected<Optional<llvm::pdb::yaml::PdbSourceFileInfo>> -YAMLOutputStyle::getFileLineInfo(const pdb::ModStream &ModS) { +YAMLOutputStyle::getFileLineInfo(const pdb::ModuleDebugStreamRef &ModS) { if (!ModS.hasLineInfo()) return None; yaml::PdbSourceFileInfo Info; - bool Error = false; - C13SubstreamVisitor Visitor(Info, File); - for (auto &Substream : ModS.lines(&Error)) { - if (auto E = codeview::visitModuleSubstream(Substream, Visitor)) - return std::move(E); - } + C13YamlVisitor Visitor(Info, File); + if (auto EC = codeview::visitModuleDebugFragments(ModS.linesAndChecksums(), + Visitor)) + return std::move(EC); return Info; } @@ -283,17 +303,22 @@ Error YAMLOutputStyle::dumpDbiStream() { Obj.DbiStream->VerHeader = DS.getDbiVersion(); if (opts::pdb2yaml::DbiModuleInfo) { for (const auto &MI : DS.modules()) { - yaml::PdbDbiModuleInfo DMI; + Obj.DbiStream->ModInfos.emplace_back(); + yaml::PdbDbiModuleInfo &DMI = Obj.DbiStream->ModInfos.back(); + DMI.Mod = MI.Info.getModuleName(); DMI.Obj = MI.Info.getObjFileName(); if (opts::pdb2yaml::DbiModuleSourceFileInfo) DMI.SourceFiles = MI.SourceFiles; + uint16_t ModiStream = MI.Info.getModuleStreamIndex(); + if (ModiStream == kInvalidStreamIndex) + continue; + auto ModStreamData = msf::MappedBlockStream::createIndexedStream( - File.getMsfLayout(), File.getMsfBuffer(), - MI.Info.getModuleStreamIndex()); + File.getMsfLayout(), File.getMsfBuffer(), ModiStream); - pdb::ModStream ModS(MI.Info, std::move(ModStreamData)); + pdb::ModuleDebugStreamRef ModS(MI.Info, std::move(ModStreamData)); if (auto EC = ModS.reload()) return EC; @@ -304,8 +329,7 @@ Error YAMLOutputStyle::dumpDbiStream() { DMI.FileLineInfo = *ExpectedInfo; } - if (opts::pdb2yaml::DbiModuleSyms && - MI.Info.getModuleStreamIndex() != kInvalidStreamIndex) { + if (opts::pdb2yaml::DbiModuleSyms) { DMI.Modi.emplace(); DMI.Modi->Signature = ModS.signature(); @@ -315,7 +339,6 @@ Error YAMLOutputStyle::dumpDbiStream() { DMI.Modi->Symbols.push_back(Record); } } - Obj.DbiStream->ModInfos.push_back(DMI); } } return Error::success(); diff --git a/tools/llvm-pdbdump/YAMLOutputStyle.h b/tools/llvm-pdbdump/YAMLOutputStyle.h index 263af776fa03f..517c7d86d7ab9 100644 --- a/tools/llvm-pdbdump/YAMLOutputStyle.h +++ b/tools/llvm-pdbdump/YAMLOutputStyle.h @@ -19,7 +19,7 @@ namespace llvm { namespace pdb { -class ModStream; +class ModuleDebugStreamRef; class YAMLOutputStyle : public OutputStyle { public: @@ -29,7 +29,7 @@ public: private: Expected<Optional<llvm::pdb::yaml::PdbSourceFileInfo>> - getFileLineInfo(const pdb::ModStream &ModS); + getFileLineInfo(const pdb::ModuleDebugStreamRef &ModS); Error dumpStringTable(); Error dumpFileHeaders(); diff --git a/tools/llvm-pdbdump/fuzzer/llvm-pdbdump-fuzzer.cpp b/tools/llvm-pdbdump/fuzzer/llvm-pdbdump-fuzzer.cpp index 38eaf16c65b05..14cd222d138a2 100644 --- a/tools/llvm-pdbdump/fuzzer/llvm-pdbdump-fuzzer.cpp +++ b/tools/llvm-pdbdump/fuzzer/llvm-pdbdump-fuzzer.cpp @@ -19,7 +19,7 @@ #include "llvm/DebugInfo/PDB/Raw/DbiStream.h" #include "llvm/DebugInfo/PDB/Raw/IPDBStreamData.h" #include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h" -#include "llvm/DebugInfo/PDB/Raw/ModStream.h" +#include "llvm/DebugInfo/PDB/Raw/ModuleDebugStream.h" #include "llvm/DebugInfo/PDB/Raw/PDBFile.h" #include "llvm/DebugInfo/PDB/Raw/RawSession.h" #include "llvm/Support/MemoryBuffer.h" @@ -90,7 +90,7 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t *data, size_t size) { consumeError(ModStreamData.takeError()); return 0; } - pdb::ModStream ModS(Modi.Info, std::move(*ModStreamData)); + pdb::ModuleDebugStreamRef ModS(Modi.Info, std::move(*ModStreamData)); if (auto E = ModS.reload()) { consumeError(std::move(E)); return 0; diff --git a/tools/llvm-pdbdump/llvm-pdbdump.cpp b/tools/llvm-pdbdump/llvm-pdbdump.cpp index 7337b1d28747d..642e169613ba7 100644 --- a/tools/llvm-pdbdump/llvm-pdbdump.cpp +++ b/tools/llvm-pdbdump/llvm-pdbdump.cpp @@ -28,18 +28,22 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Config/config.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h" #include "llvm/DebugInfo/MSF/MSFBuilder.h" #include "llvm/DebugInfo/PDB/GenericError.h" #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" #include "llvm/DebugInfo/PDB/IPDBRawSymbol.h" #include "llvm/DebugInfo/PDB/IPDBSession.h" +#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h" #include "llvm/DebugInfo/PDB/Native/DbiStream.h" #include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h" #include "llvm/DebugInfo/PDB/Native/InfoStream.h" #include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h" -#include "llvm/DebugInfo/PDB/Native/ModInfoBuilder.h" #include "llvm/DebugInfo/PDB/Native/NativeSession.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h" #include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h" @@ -261,9 +265,10 @@ cl::opt<std::string> cl::cat(MsfOptions), cl::sub(RawSubcommand)); llvm::Optional<BlockRange> DumpBlockRange; -cl::list<uint32_t> +cl::list<std::string> DumpStreamData("stream-data", cl::CommaSeparated, cl::ZeroOrMore, - cl::desc("Dump binary data from specified streams."), + cl::desc("Dump binary data from specified streams. Format " + "is SN[:Start][@Size]"), cl::cat(MsfOptions), cl::sub(RawSubcommand)); // TYPE OPTIONS @@ -419,6 +424,21 @@ cl::list<std::string> InputFilename(cl::Positional, static ExitOnError ExitOnErr; +static uint32_t +getFileChecksumOffset(StringRef FileName, + ModuleDebugFileChecksumFragment &Checksums, + StringTableBuilder &Strings) { + // The offset in the line info record is the offset of the checksum + // entry for the corresponding file. That entry then contains an + // offset into the global string table of the file name. So to + // compute the proper offset to write into the line info record, we + // must first get its offset in the global string table, then ask the + // checksum builder to find the offset in its serialized buffer that + // it mapped that filename string table offset to. + uint32_t StringOffset = Strings.insert(FileName); + return Checksums.mapChecksumOffset(StringOffset); +} + static void yamlToPdb(StringRef Path) { BumpPtrAllocator Allocator; ErrorOr<std::unique_ptr<MemoryBuffer>> ErrorOrBuffer = @@ -490,6 +510,80 @@ static void yamlToPdb(StringRef Path) { for (auto Symbol : ModiStream.Symbols) ModiBuilder.addSymbol(Symbol.Record); } + if (MI.FileLineInfo.hasValue()) { + const auto &FLI = *MI.FileLineInfo; + + // File Checksums must be emitted before line information, because line + // info records use offsets into the checksum buffer to reference a file's + // source file name. + auto Checksums = llvm::make_unique<ModuleDebugFileChecksumFragment>(); + auto &ChecksumRef = *Checksums; + if (!FLI.FileChecksums.empty()) { + auto &Strings = Builder.getStringTableBuilder(); + for (auto &FC : FLI.FileChecksums) { + uint32_t STOffset = Strings.insert(FC.FileName); + Checksums->addChecksum(STOffset, FC.Kind, FC.ChecksumBytes.Bytes); + } + } + ModiBuilder.setC13FileChecksums(std::move(Checksums)); + + // FIXME: StringTable / StringTableBuilder should really be in + // DebugInfoCodeView. This would allow us to construct the + // ModuleDebugLineFragment with a reference to the string table, + // and we could just pass strings around rather than having to + // remember how to calculate the right offset. + auto &Strings = Builder.getStringTableBuilder(); + + for (const auto &Fragment : FLI.LineFragments) { + auto Lines = llvm::make_unique<ModuleDebugLineFragment>(); + Lines->setCodeSize(Fragment.CodeSize); + Lines->setRelocationAddress(Fragment.RelocSegment, + Fragment.RelocOffset); + Lines->setFlags(Fragment.Flags); + for (const auto &LC : Fragment.Blocks) { + uint32_t ChecksumOffset = + getFileChecksumOffset(LC.FileName, ChecksumRef, Strings); + + Lines->createBlock(ChecksumOffset); + if (Lines->hasColumnInfo()) { + for (const auto &Item : zip(LC.Lines, LC.Columns)) { + auto &L = std::get<0>(Item); + auto &C = std::get<1>(Item); + uint32_t LE = L.LineStart + L.EndDelta; + Lines->addLineAndColumnInfo( + L.Offset, LineInfo(L.LineStart, LE, L.IsStatement), + C.StartColumn, C.EndColumn); + } + } else { + for (const auto &L : LC.Lines) { + uint32_t LE = L.LineStart + L.EndDelta; + Lines->addLineInfo(L.Offset, + LineInfo(L.LineStart, LE, L.IsStatement)); + } + } + } + ModiBuilder.addC13Fragment(std::move(Lines)); + } + + for (const auto &Inlinee : FLI.Inlinees) { + auto Inlinees = llvm::make_unique<ModuleDebugInlineeLineFragment>( + Inlinee.HasExtraFiles); + for (const auto &Site : Inlinee.Sites) { + uint32_t FileOff = + getFileChecksumOffset(Site.FileName, ChecksumRef, Strings); + + Inlinees->addInlineSite(Site.Inlinee, FileOff, Site.SourceLineNum); + if (!Inlinee.HasExtraFiles) + continue; + + for (auto EF : Site.ExtraFiles) { + FileOff = getFileChecksumOffset(EF, ChecksumRef, Strings); + Inlinees->addExtraFile(FileOff); + } + } + ModiBuilder.addC13Fragment(std::move(Inlinees)); + } + } } auto &TpiBuilder = Builder.getTpiBuilder(); diff --git a/tools/llvm-pdbdump/llvm-pdbdump.h b/tools/llvm-pdbdump/llvm-pdbdump.h index f080d6d552501..8b1dde9399bfa 100644 --- a/tools/llvm-pdbdump/llvm-pdbdump.h +++ b/tools/llvm-pdbdump/llvm-pdbdump.h @@ -60,7 +60,7 @@ struct BlockRange { }; extern llvm::Optional<BlockRange> DumpBlockRange; -extern llvm::cl::list<uint32_t> DumpStreamData; +extern llvm::cl::list<std::string> DumpStreamData; extern llvm::cl::opt<bool> CompactRecords; extern llvm::cl::opt<bool> DumpGlobals; |
