diff options
author | Zachary Turner <zturner@google.com> | 2018-03-30 17:16:50 +0000 |
---|---|---|
committer | Zachary Turner <zturner@google.com> | 2018-03-30 17:16:50 +0000 |
commit | d5cf5cf637918664c6de75c0685786acb2a2b92c (patch) | |
tree | da6a5622ec4166360922f051c7b09b7ec892d1be /llvm/tools/llvm-pdbutil/ExplainOutputStyle.cpp | |
parent | 0945ad6643e240bb9fb5c89b3abdfa0f9b9bfac2 (diff) | |
download | bcm5719-llvm-d5cf5cf637918664c6de75c0685786acb2a2b92c.tar.gz bcm5719-llvm-d5cf5cf637918664c6de75c0685786acb2a2b92c.zip |
[llvm-pdbutil] Dig deeper into the PDB and DBI streams when explaining.
This will show more detail when using `llvm-pdbutil explain` on an
offset in the DBI or PDB streams. Specifically, it will dig into
individual header fields and substreams to give a more precise
description of what the byte represents.
llvm-svn: 328878
Diffstat (limited to 'llvm/tools/llvm-pdbutil/ExplainOutputStyle.cpp')
-rw-r--r-- | llvm/tools/llvm-pdbutil/ExplainOutputStyle.cpp | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/llvm/tools/llvm-pdbutil/ExplainOutputStyle.cpp b/llvm/tools/llvm-pdbutil/ExplainOutputStyle.cpp index c4fbde22e75..70deb2e7277 100644 --- a/llvm/tools/llvm-pdbutil/ExplainOutputStyle.cpp +++ b/llvm/tools/llvm-pdbutil/ExplainOutputStyle.cpp @@ -13,8 +13,14 @@ #include "StreamUtil.h" #include "llvm-pdbutil.h" +#include "llvm/DebugInfo/CodeView/Formatters.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/PDBFile.h" +#include "llvm/DebugInfo/PDB/Native/RawTypes.h" +#include "llvm/Support/BinaryStreamArray.h" +#include "llvm/Support/Error.h" using namespace llvm; using namespace llvm::codeview; @@ -201,6 +207,20 @@ void ExplainOutputStyle::explainStreamOffset(uint32_t Stream) { P.formatLine("Address is at offset {0}/{1} of Stream {2} ({3}){4}.", StreamOff, Layout.Length, Stream, S.getLongName(), (StreamOff > Layout.Length) ? " in unused space" : ""); + switch (S.getPurpose()) { + case StreamPurpose::DBI: + explainDbiStream(Stream, StreamOff); + break; + case StreamPurpose::PDB: + explainPdbStream(Stream, StreamOff); + break; + case StreamPurpose::IPI: + case StreamPurpose::TPI: + case StreamPurpose::ModuleStream: + case StreamPurpose::NamedStream: + default: + break; + } } void ExplainOutputStyle::explainStreamDirectoryOffset() { @@ -218,3 +238,183 @@ void ExplainOutputStyle::explainStreamDirectoryOffset() { void ExplainOutputStyle::explainUnknownBlock() { P.formatLine("Address has unknown purpose."); } + +template <typename T> +static void printStructField(LinePrinter &P, StringRef Label, T Value) { + P.formatLine("which contains {0}.", Label); + P.formatLine("The current value is {0}.", Value); +} + +static void explainDbiHeaderOffset(LinePrinter &P, DbiStream &Dbi, + uint32_t Offset) { + const DbiStreamHeader *Header = Dbi.getHeader(); + assert(Header != nullptr); + + if (Offset < endof(DbiStreamHeader, VersionSignature)) + printStructField(P, "the DBI Stream Version Signature", + int32_t(Header->VersionSignature)); + else if (Offset < endof(DbiStreamHeader, VersionHeader)) + printStructField(P, "the DBI Stream Version Header", + uint32_t(Header->VersionHeader)); + else if (Offset < endof(DbiStreamHeader, Age)) + printStructField(P, "the age of the DBI Stream", uint32_t(Header->Age)); + else if (Offset < endof(DbiStreamHeader, GlobalSymbolStreamIndex)) + printStructField(P, "the index of the Global Symbol Stream", + uint16_t(Header->GlobalSymbolStreamIndex)); + else if (Offset < endof(DbiStreamHeader, BuildNumber)) + printStructField(P, "the build number", uint16_t(Header->BuildNumber)); + else if (Offset < endof(DbiStreamHeader, PublicSymbolStreamIndex)) + printStructField(P, "the index of the Public Symbol Stream", + uint16_t(Header->PublicSymbolStreamIndex)); + else if (Offset < endof(DbiStreamHeader, PdbDllVersion)) + printStructField(P, "the version of mspdb.dll", + uint16_t(Header->PdbDllVersion)); + else if (Offset < endof(DbiStreamHeader, SymRecordStreamIndex)) + printStructField(P, "the index of the Symbol Record Stream", + uint16_t(Header->SymRecordStreamIndex)); + else if (Offset < endof(DbiStreamHeader, PdbDllRbld)) + printStructField(P, "the rbld of mspdb.dll", uint16_t(Header->PdbDllRbld)); + else if (Offset < endof(DbiStreamHeader, ModiSubstreamSize)) + printStructField(P, "the size of the Module Info Substream", + int32_t(Header->ModiSubstreamSize)); + else if (Offset < endof(DbiStreamHeader, SecContrSubstreamSize)) + printStructField(P, "the size of the Section Contribution Substream", + int32_t(Header->SecContrSubstreamSize)); + else if (Offset < endof(DbiStreamHeader, SectionMapSize)) + printStructField(P, "the size of the Section Map Substream", + int32_t(Header->SectionMapSize)); + else if (Offset < endof(DbiStreamHeader, FileInfoSize)) + printStructField(P, "the size of the File Info Substream", + int32_t(Header->FileInfoSize)); + else if (Offset < endof(DbiStreamHeader, TypeServerSize)) + printStructField(P, "the size of the Type Server Map", + int32_t(Header->TypeServerSize)); + else if (Offset < endof(DbiStreamHeader, MFCTypeServerIndex)) + printStructField(P, "the index of the MFC Type Server stream", + uint32_t(Header->MFCTypeServerIndex)); + else if (Offset < endof(DbiStreamHeader, OptionalDbgHdrSize)) + printStructField(P, "the size of the Optional Debug Stream array", + int32_t(Header->OptionalDbgHdrSize)); + else if (Offset < endof(DbiStreamHeader, ECSubstreamSize)) + printStructField(P, "the size of the Edit & Continue Substream", + int32_t(Header->ECSubstreamSize)); + else if (Offset < endof(DbiStreamHeader, Flags)) + printStructField(P, "the DBI Stream flags", uint16_t(Header->Flags)); + else if (Offset < endof(DbiStreamHeader, MachineType)) + printStructField(P, "the machine type", uint16_t(Header->MachineType)); + else if (Offset < endof(DbiStreamHeader, Reserved)) + printStructField(P, "reserved data", uint32_t(Header->Reserved)); +} + +static void explainDbiModiSubstreamOffset(LinePrinter &P, DbiStream &Dbi, + uint32_t Offset) { + VarStreamArray<DbiModuleDescriptor> ModuleDescriptors; + BinaryStreamRef ModiSubstreamData = Dbi.getModiSubstreamData().StreamData; + BinaryStreamReader Reader(ModiSubstreamData); + + cantFail(Reader.readArray(ModuleDescriptors, ModiSubstreamData.getLength())); + auto Prev = ModuleDescriptors.begin(); + assert(Prev.offset() == 0); + auto Current = Prev; + uint32_t Index = 0; + while (true) { + Prev = Current; + ++Current; + if (Current == ModuleDescriptors.end() || Offset < Current.offset()) + break; + ++Index; + } + + DbiModuleDescriptor &Descriptor = *Prev; + P.formatLine("which contains the descriptor for module {0} ({1}).", Index, + Descriptor.getModuleName()); +} + +template <typename T> +static void dontExplain(LinePrinter &Printer, T &Stream, uint32_t Offset) {} + +template <typename T, typename SubstreamRangeT> +static void explainSubstreamOffset(LinePrinter &P, uint32_t OffsetInStream, + T &Stream, + const SubstreamRangeT &Substreams) { + uint32_t SubOffset = OffsetInStream; + for (const auto &Entry : Substreams) { + if (Entry.Size == 0) + continue; + if (SubOffset < Entry.Size) { + P.formatLine("address is at offset {0}/{1} of the {2}.", SubOffset, + Entry.Size, Entry.Label); + Entry.Explain(P, Stream, SubOffset); + return; + } + SubOffset -= Entry.Size; + } +} + +void ExplainOutputStyle::explainDbiStream(uint32_t StreamIdx, + uint32_t OffsetInStream) { + P.printLine("Within the DBI stream:"); + DbiStream &Dbi = cantFail(File.getPDBDbiStream()); + AutoIndent Indent(P); + const DbiStreamHeader *Header = Dbi.getHeader(); + assert(Header != nullptr); + + struct SubstreamInfo { + uint32_t Size; + StringRef Label; + void (*Explain)(LinePrinter &, DbiStream &, uint32_t); + } Substreams[] = { + {sizeof(DbiStreamHeader), "DBI Stream Header", explainDbiHeaderOffset}, + {Header->ModiSubstreamSize, "Module Info Substream", + explainDbiModiSubstreamOffset}, + {Header->SecContrSubstreamSize, "Section Contribution Substream", + dontExplain<DbiStream>}, + {Header->SectionMapSize, "Section Map", dontExplain<DbiStream>}, + {Header->FileInfoSize, "File Info Substream", dontExplain<DbiStream>}, + {Header->TypeServerSize, "Type Server Map Substream", + dontExplain<DbiStream>}, + {Header->ECSubstreamSize, "Edit & Continue Substream", + dontExplain<DbiStream>}, + {Header->OptionalDbgHdrSize, "Optional Debug Stream Array", + dontExplain<DbiStream>}, + }; + + explainSubstreamOffset(P, OffsetInStream, Dbi, Substreams); +} + +static void explainPdbStreamHeaderOffset(LinePrinter &P, InfoStream &Info, + uint32_t Offset) { + const InfoStreamHeader *Header = Info.getHeader(); + assert(Header != nullptr); + + if (Offset < endof(InfoStreamHeader, Version)) + printStructField(P, "the PDB Stream Version Signature", + uint32_t(Header->Version)); + else if (Offset < endof(InfoStreamHeader, Signature)) + printStructField(P, "the signature of the PDB Stream", + uint32_t(Header->Signature)); + else if (Offset < endof(InfoStreamHeader, Age)) + printStructField(P, "the age of the PDB", uint32_t(Header->Age)); + else if (Offset < endof(InfoStreamHeader, Guid)) + printStructField(P, "the guid of the PDB", fmt_guid(Header->Guid.Guid)); +} + +void ExplainOutputStyle::explainPdbStream(uint32_t StreamIdx, + uint32_t OffsetInStream) { + P.printLine("Within the PDB stream:"); + InfoStream &Info = cantFail(File.getPDBInfoStream()); + AutoIndent Indent(P); + + struct SubstreamInfo { + uint32_t Size; + StringRef Label; + void (*Explain)(LinePrinter &, InfoStream &, uint32_t); + } Substreams[] = {{sizeof(InfoStreamHeader), "PDB Stream Header", + explainPdbStreamHeaderOffset}, + {Info.getNamedStreamMapByteSize(), "Named Stream Map", + dontExplain<InfoStream>}, + {Info.getStreamSize(), "PDB Feature Signatures", + dontExplain<InfoStream>}}; + + explainSubstreamOffset(P, OffsetInStream, Info, Substreams); +} |