diff options
Diffstat (limited to 'tools/llvm-pdbdump/LLVMOutputStyle.cpp')
| -rw-r--r-- | tools/llvm-pdbdump/LLVMOutputStyle.cpp | 282 |
1 files changed, 182 insertions, 100 deletions
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; } } } |
