summaryrefslogtreecommitdiffstats
path: root/llvm/tools/llvm-pdbutil/ExplainOutputStyle.cpp
diff options
context:
space:
mode:
authorZachary Turner <zturner@google.com>2018-03-30 17:16:50 +0000
committerZachary Turner <zturner@google.com>2018-03-30 17:16:50 +0000
commitd5cf5cf637918664c6de75c0685786acb2a2b92c (patch)
treeda6a5622ec4166360922f051c7b09b7ec892d1be /llvm/tools/llvm-pdbutil/ExplainOutputStyle.cpp
parent0945ad6643e240bb9fb5c89b3abdfa0f9b9bfac2 (diff)
downloadbcm5719-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.cpp200
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);
+}
OpenPOWER on IntegriCloud