xref: /llvm-project/llvm/tools/llvm-pdbutil/BytesOutputStyle.cpp (revision e0e687a615c1fdb6ba034fc2e48b0834a372706f)
19940203aSZachary Turner //===- BytesOutputStyle.cpp ----------------------------------- *- C++ --*-===//
29940203aSZachary Turner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
69940203aSZachary Turner //
79940203aSZachary Turner //===----------------------------------------------------------------------===//
89940203aSZachary Turner 
99940203aSZachary Turner #include "BytesOutputStyle.h"
109940203aSZachary Turner 
119940203aSZachary Turner #include "StreamUtil.h"
129940203aSZachary Turner #include "llvm-pdbutil.h"
139940203aSZachary Turner 
14c2f5b4bfSZachary Turner #include "llvm/DebugInfo/CodeView/Formatters.h"
15c2f5b4bfSZachary Turner #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
16c3d8eec9SZachary Turner #include "llvm/DebugInfo/MSF/MSFCommon.h"
179940203aSZachary Turner #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
18dd739682SZachary Turner #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
1975112133SCarlos Alberto Enciso #include "llvm/DebugInfo/PDB/Native/FormatUtil.h"
206c3e41bbSZachary Turner #include "llvm/DebugInfo/PDB/Native/InfoStream.h"
21fa332827SZachary Turner #include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
229940203aSZachary Turner #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
239940203aSZachary Turner #include "llvm/DebugInfo/PDB/Native/RawError.h"
24c2f5b4bfSZachary Turner #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
259940203aSZachary Turner #include "llvm/Support/BinaryStreamReader.h"
269940203aSZachary Turner #include "llvm/Support/FormatAdapters.h"
279940203aSZachary Turner #include "llvm/Support/FormatVariadic.h"
289940203aSZachary Turner 
299940203aSZachary Turner using namespace llvm;
30c2f5b4bfSZachary Turner using namespace llvm::codeview;
319940203aSZachary Turner using namespace llvm::msf;
329940203aSZachary Turner using namespace llvm::pdb;
339940203aSZachary Turner 
349940203aSZachary Turner namespace {
359940203aSZachary Turner struct StreamSpec {
369940203aSZachary Turner   uint32_t SI = 0;
379940203aSZachary Turner   uint32_t Begin = 0;
389940203aSZachary Turner   uint32_t Size = 0;
399940203aSZachary Turner };
409940203aSZachary Turner } // namespace
419940203aSZachary Turner 
parseStreamSpec(StringRef Str)429940203aSZachary Turner static Expected<StreamSpec> parseStreamSpec(StringRef Str) {
439940203aSZachary Turner   StreamSpec Result;
449940203aSZachary Turner   if (Str.consumeInteger(0, Result.SI))
459940203aSZachary Turner     return make_error<RawError>(raw_error_code::invalid_format,
469940203aSZachary Turner                                 "Invalid Stream Specification");
479940203aSZachary Turner   if (Str.consume_front(":")) {
489940203aSZachary Turner     if (Str.consumeInteger(0, Result.Begin))
499940203aSZachary Turner       return make_error<RawError>(raw_error_code::invalid_format,
509940203aSZachary Turner                                   "Invalid Stream Specification");
519940203aSZachary Turner   }
529940203aSZachary Turner   if (Str.consume_front("@")) {
539940203aSZachary Turner     if (Str.consumeInteger(0, Result.Size))
549940203aSZachary Turner       return make_error<RawError>(raw_error_code::invalid_format,
559940203aSZachary Turner                                   "Invalid Stream Specification");
569940203aSZachary Turner   }
579940203aSZachary Turner 
589940203aSZachary Turner   if (!Str.empty())
599940203aSZachary Turner     return make_error<RawError>(raw_error_code::invalid_format,
609940203aSZachary Turner                                 "Invalid Stream Specification");
619940203aSZachary Turner   return Result;
629940203aSZachary Turner }
639940203aSZachary Turner 
parseStreamSpecs(LinePrinter & P)649940203aSZachary Turner static SmallVector<StreamSpec, 2> parseStreamSpecs(LinePrinter &P) {
659940203aSZachary Turner   SmallVector<StreamSpec, 2> Result;
669940203aSZachary Turner 
679940203aSZachary Turner   for (auto &Str : opts::bytes::DumpStreamData) {
689940203aSZachary Turner     auto ESS = parseStreamSpec(Str);
699940203aSZachary Turner     if (!ESS) {
709940203aSZachary Turner       P.formatLine("Error parsing stream spec {0}: {1}", Str,
719940203aSZachary Turner                    toString(ESS.takeError()));
729940203aSZachary Turner       continue;
739940203aSZachary Turner     }
749940203aSZachary Turner     Result.push_back(*ESS);
759940203aSZachary Turner   }
769940203aSZachary Turner   return Result;
779940203aSZachary Turner }
789940203aSZachary Turner 
printHeader(LinePrinter & P,const Twine & S)799940203aSZachary Turner static void printHeader(LinePrinter &P, const Twine &S) {
809940203aSZachary Turner   P.NewLine();
819940203aSZachary Turner   P.formatLine("{0,=60}", S);
829940203aSZachary Turner   P.formatLine("{0}", fmt_repeat('=', 60));
839940203aSZachary Turner }
849940203aSZachary Turner 
BytesOutputStyle(PDBFile & File)859940203aSZachary Turner BytesOutputStyle::BytesOutputStyle(PDBFile &File)
8675112133SCarlos Alberto Enciso     : File(File), P(2, false, outs(), opts::Filters) {}
879940203aSZachary Turner 
dump()889940203aSZachary Turner Error BytesOutputStyle::dump() {
899940203aSZachary Turner 
90*e0e687a6SKazu Hirata   if (opts::bytes::DumpBlockRange) {
919940203aSZachary Turner     auto &R = *opts::bytes::DumpBlockRange;
92129b531cSKazu Hirata     uint32_t Max = R.Max.value_or(R.Min);
939940203aSZachary Turner 
949940203aSZachary Turner     if (Max < R.Min)
959940203aSZachary Turner       return make_error<StringError>(
969940203aSZachary Turner           "Invalid block range specified.  Max < Min",
979940203aSZachary Turner           inconvertibleErrorCode());
989940203aSZachary Turner     if (Max >= File.getBlockCount())
999940203aSZachary Turner       return make_error<StringError>(
1009940203aSZachary Turner           "Invalid block range specified.  Requested block out of bounds",
1019940203aSZachary Turner           inconvertibleErrorCode());
1029940203aSZachary Turner 
1039940203aSZachary Turner     dumpBlockRanges(R.Min, Max);
1049940203aSZachary Turner     P.NewLine();
1059940203aSZachary Turner   }
1069940203aSZachary Turner 
107*e0e687a6SKazu Hirata   if (opts::bytes::DumpByteRange) {
1086b124f29SZachary Turner     auto &R = *opts::bytes::DumpByteRange;
109129b531cSKazu Hirata     uint32_t Max = R.Max.value_or(File.getFileSize());
1106b124f29SZachary Turner 
1116b124f29SZachary Turner     if (Max < R.Min)
1126b124f29SZachary Turner       return make_error<StringError>("Invalid byte range specified.  Max < Min",
1136b124f29SZachary Turner                                      inconvertibleErrorCode());
1146b124f29SZachary Turner     if (Max >= File.getFileSize())
1156b124f29SZachary Turner       return make_error<StringError>(
1166b124f29SZachary Turner           "Invalid byte range specified.  Requested byte larger than file size",
1176b124f29SZachary Turner           inconvertibleErrorCode());
1186b124f29SZachary Turner 
1196b124f29SZachary Turner     dumpByteRanges(R.Min, Max);
1206b124f29SZachary Turner     P.NewLine();
1216b124f29SZachary Turner   }
1226b124f29SZachary Turner 
123c3d8eec9SZachary Turner   if (opts::bytes::Fpm) {
124c3d8eec9SZachary Turner     dumpFpm();
125c3d8eec9SZachary Turner     P.NewLine();
126c3d8eec9SZachary Turner   }
127c3d8eec9SZachary Turner 
1289940203aSZachary Turner   if (!opts::bytes::DumpStreamData.empty()) {
1299940203aSZachary Turner     dumpStreamBytes();
1309940203aSZachary Turner     P.NewLine();
1319940203aSZachary Turner   }
1326c3e41bbSZachary Turner 
1336c3e41bbSZachary Turner   if (opts::bytes::NameMap) {
1346c3e41bbSZachary Turner     dumpNameMap();
1356c3e41bbSZachary Turner     P.NewLine();
1366c3e41bbSZachary Turner   }
137dd739682SZachary Turner 
138dd739682SZachary Turner   if (opts::bytes::SectionContributions) {
139dd739682SZachary Turner     dumpSectionContributions();
140dd739682SZachary Turner     P.NewLine();
141dd739682SZachary Turner   }
142dd739682SZachary Turner 
143dd739682SZachary Turner   if (opts::bytes::SectionMap) {
144dd739682SZachary Turner     dumpSectionMap();
145dd739682SZachary Turner     P.NewLine();
146dd739682SZachary Turner   }
147dd739682SZachary Turner 
148dd739682SZachary Turner   if (opts::bytes::ModuleInfos) {
149dd739682SZachary Turner     dumpModuleInfos();
150dd739682SZachary Turner     P.NewLine();
151dd739682SZachary Turner   }
152dd739682SZachary Turner 
153dd739682SZachary Turner   if (opts::bytes::FileInfo) {
154dd739682SZachary Turner     dumpFileInfo();
155dd739682SZachary Turner     P.NewLine();
156dd739682SZachary Turner   }
157dd739682SZachary Turner 
158dd739682SZachary Turner   if (opts::bytes::TypeServerMap) {
159dd739682SZachary Turner     dumpTypeServerMap();
160dd739682SZachary Turner     P.NewLine();
161dd739682SZachary Turner   }
162dd739682SZachary Turner 
163dd739682SZachary Turner   if (opts::bytes::ECData) {
164dd739682SZachary Turner     dumpECData();
165dd739682SZachary Turner     P.NewLine();
166dd739682SZachary Turner   }
167dd739682SZachary Turner 
168c2f5b4bfSZachary Turner   if (!opts::bytes::TypeIndex.empty()) {
169c2f5b4bfSZachary Turner     dumpTypeIndex(StreamTPI, opts::bytes::TypeIndex);
170c2f5b4bfSZachary Turner     P.NewLine();
171c2f5b4bfSZachary Turner   }
172c2f5b4bfSZachary Turner 
173c2f5b4bfSZachary Turner   if (!opts::bytes::IdIndex.empty()) {
174c2f5b4bfSZachary Turner     dumpTypeIndex(StreamIPI, opts::bytes::IdIndex);
175c2f5b4bfSZachary Turner     P.NewLine();
176c2f5b4bfSZachary Turner   }
177c2f5b4bfSZachary Turner 
178fa332827SZachary Turner   if (opts::bytes::ModuleSyms) {
179fa332827SZachary Turner     dumpModuleSyms();
180fa332827SZachary Turner     P.NewLine();
181fa332827SZachary Turner   }
182fa332827SZachary Turner 
183fa332827SZachary Turner   if (opts::bytes::ModuleC11) {
184fa332827SZachary Turner     dumpModuleC11();
185fa332827SZachary Turner     P.NewLine();
186fa332827SZachary Turner   }
187fa332827SZachary Turner 
188fa332827SZachary Turner   if (opts::bytes::ModuleC13) {
189fa332827SZachary Turner     dumpModuleC13();
190fa332827SZachary Turner     P.NewLine();
191fa332827SZachary Turner   }
192fa332827SZachary Turner 
1939940203aSZachary Turner   return Error::success();
1949940203aSZachary Turner }
1959940203aSZachary Turner 
dumpNameMap()1966c3e41bbSZachary Turner void BytesOutputStyle::dumpNameMap() {
1976c3e41bbSZachary Turner   printHeader(P, "Named Stream Map");
1986c3e41bbSZachary Turner 
1996c3e41bbSZachary Turner   AutoIndent Indent(P);
2006c3e41bbSZachary Turner 
2016c3e41bbSZachary Turner   auto &InfoS = Err(File.getPDBInfoStream());
2026c3e41bbSZachary Turner   BinarySubstreamRef NS = InfoS.getNamedStreamsBuffer();
2036c3e41bbSZachary Turner   auto Layout = File.getStreamLayout(StreamPDB);
2046c3e41bbSZachary Turner   P.formatMsfStreamData("Named Stream Map", File, Layout, NS);
2056c3e41bbSZachary Turner }
2066c3e41bbSZachary Turner 
dumpBlockRanges(uint32_t Min,uint32_t Max)2079940203aSZachary Turner void BytesOutputStyle::dumpBlockRanges(uint32_t Min, uint32_t Max) {
2089940203aSZachary Turner   printHeader(P, "MSF Blocks");
2099940203aSZachary Turner 
2109940203aSZachary Turner   AutoIndent Indent(P);
2119940203aSZachary Turner   for (uint32_t I = Min; I <= Max; ++I) {
2129940203aSZachary Turner     uint64_t Base = I;
2139940203aSZachary Turner     Base *= File.getBlockSize();
2149940203aSZachary Turner 
2159940203aSZachary Turner     auto ExpectedData = File.getBlockData(I, File.getBlockSize());
2169940203aSZachary Turner     if (!ExpectedData) {
2179940203aSZachary Turner       P.formatLine("Could not get block {0}.  Reason = {1}", I,
2189940203aSZachary Turner                    toString(ExpectedData.takeError()));
2199940203aSZachary Turner       continue;
2209940203aSZachary Turner     }
2219940203aSZachary Turner     std::string Label = formatv("Block {0}", I).str();
2229940203aSZachary Turner     P.formatBinary(Label, *ExpectedData, Base, 0);
2239940203aSZachary Turner   }
2249940203aSZachary Turner }
2259940203aSZachary Turner 
dumpSectionContributions()226dd739682SZachary Turner void BytesOutputStyle::dumpSectionContributions() {
227dd739682SZachary Turner   printHeader(P, "Section Contributions");
228dd739682SZachary Turner 
229dd739682SZachary Turner   AutoIndent Indent(P);
230dd739682SZachary Turner 
231dd739682SZachary Turner   auto &DbiS = Err(File.getPDBDbiStream());
232dd739682SZachary Turner   BinarySubstreamRef NS = DbiS.getSectionContributionData();
233dd739682SZachary Turner   auto Layout = File.getStreamLayout(StreamDBI);
234dd739682SZachary Turner   P.formatMsfStreamData("Section Contributions", File, Layout, NS);
235dd739682SZachary Turner }
236dd739682SZachary Turner 
dumpSectionMap()237dd739682SZachary Turner void BytesOutputStyle::dumpSectionMap() {
238dd739682SZachary Turner   printHeader(P, "Section Map");
239dd739682SZachary Turner 
240dd739682SZachary Turner   AutoIndent Indent(P);
241dd739682SZachary Turner 
242dd739682SZachary Turner   auto &DbiS = Err(File.getPDBDbiStream());
243dd739682SZachary Turner   BinarySubstreamRef NS = DbiS.getSecMapSubstreamData();
244dd739682SZachary Turner   auto Layout = File.getStreamLayout(StreamDBI);
245dd739682SZachary Turner   P.formatMsfStreamData("Section Map", File, Layout, NS);
246dd739682SZachary Turner }
247dd739682SZachary Turner 
dumpModuleInfos()248dd739682SZachary Turner void BytesOutputStyle::dumpModuleInfos() {
249dd739682SZachary Turner   printHeader(P, "Module Infos");
250dd739682SZachary Turner 
251dd739682SZachary Turner   AutoIndent Indent(P);
252dd739682SZachary Turner 
253dd739682SZachary Turner   auto &DbiS = Err(File.getPDBDbiStream());
254dd739682SZachary Turner   BinarySubstreamRef NS = DbiS.getModiSubstreamData();
255dd739682SZachary Turner   auto Layout = File.getStreamLayout(StreamDBI);
256dd739682SZachary Turner   P.formatMsfStreamData("Module Infos", File, Layout, NS);
257dd739682SZachary Turner }
258dd739682SZachary Turner 
dumpFileInfo()259dd739682SZachary Turner void BytesOutputStyle::dumpFileInfo() {
260dd739682SZachary Turner   printHeader(P, "File Info");
261dd739682SZachary Turner 
262dd739682SZachary Turner   AutoIndent Indent(P);
263dd739682SZachary Turner 
264dd739682SZachary Turner   auto &DbiS = Err(File.getPDBDbiStream());
265dd739682SZachary Turner   BinarySubstreamRef NS = DbiS.getFileInfoSubstreamData();
266dd739682SZachary Turner   auto Layout = File.getStreamLayout(StreamDBI);
267dd739682SZachary Turner   P.formatMsfStreamData("File Info", File, Layout, NS);
268dd739682SZachary Turner }
269dd739682SZachary Turner 
dumpTypeServerMap()270dd739682SZachary Turner void BytesOutputStyle::dumpTypeServerMap() {
271dd739682SZachary Turner   printHeader(P, "Type Server Map");
272dd739682SZachary Turner 
273dd739682SZachary Turner   AutoIndent Indent(P);
274dd739682SZachary Turner 
275dd739682SZachary Turner   auto &DbiS = Err(File.getPDBDbiStream());
276dd739682SZachary Turner   BinarySubstreamRef NS = DbiS.getTypeServerMapSubstreamData();
277dd739682SZachary Turner   auto Layout = File.getStreamLayout(StreamDBI);
278dd739682SZachary Turner   P.formatMsfStreamData("Type Server Map", File, Layout, NS);
279dd739682SZachary Turner }
280dd739682SZachary Turner 
dumpECData()281dd739682SZachary Turner void BytesOutputStyle::dumpECData() {
282dd739682SZachary Turner   printHeader(P, "Edit and Continue Data");
283dd739682SZachary Turner 
284dd739682SZachary Turner   AutoIndent Indent(P);
285dd739682SZachary Turner 
286dd739682SZachary Turner   auto &DbiS = Err(File.getPDBDbiStream());
287dd739682SZachary Turner   BinarySubstreamRef NS = DbiS.getECSubstreamData();
288dd739682SZachary Turner   auto Layout = File.getStreamLayout(StreamDBI);
289dd739682SZachary Turner   P.formatMsfStreamData("Edit and Continue Data", File, Layout, NS);
290dd739682SZachary Turner }
291dd739682SZachary Turner 
dumpTypeIndex(uint32_t StreamIdx,ArrayRef<uint32_t> Indices)292c2f5b4bfSZachary Turner void BytesOutputStyle::dumpTypeIndex(uint32_t StreamIdx,
293c2f5b4bfSZachary Turner                                      ArrayRef<uint32_t> Indices) {
294c2f5b4bfSZachary Turner   assert(StreamIdx == StreamTPI || StreamIdx == StreamIPI);
295c2f5b4bfSZachary Turner   assert(!Indices.empty());
296c2f5b4bfSZachary Turner 
297c2f5b4bfSZachary Turner   bool IsTpi = (StreamIdx == StreamTPI);
298c2f5b4bfSZachary Turner 
299c2f5b4bfSZachary Turner   StringRef Label = IsTpi ? "Type (TPI) Records" : "Index (IPI) Records";
300c2f5b4bfSZachary Turner   printHeader(P, Label);
301c2f5b4bfSZachary Turner   auto &Stream = Err(IsTpi ? File.getPDBTpiStream() : File.getPDBIpiStream());
302c2f5b4bfSZachary Turner 
303c2f5b4bfSZachary Turner   AutoIndent Indent(P);
304c2f5b4bfSZachary Turner 
305c2f5b4bfSZachary Turner   auto Substream = Stream.getTypeRecordsSubstream();
306c2f5b4bfSZachary Turner   auto &Types = Err(initializeTypes(StreamIdx));
307c2f5b4bfSZachary Turner   auto Layout = File.getStreamLayout(StreamIdx);
308c2f5b4bfSZachary Turner   for (const auto &Id : Indices) {
309c2f5b4bfSZachary Turner     TypeIndex TI(Id);
310c2f5b4bfSZachary Turner     if (TI.toArrayIndex() >= Types.capacity()) {
311c2f5b4bfSZachary Turner       P.formatLine("Error: TypeIndex {0} does not exist", TI);
312c2f5b4bfSZachary Turner       continue;
313c2f5b4bfSZachary Turner     }
314c2f5b4bfSZachary Turner 
315c2f5b4bfSZachary Turner     auto Type = Types.getType(TI);
316c2f5b4bfSZachary Turner     uint32_t Offset = Types.getOffsetOfType(TI);
317c2f5b4bfSZachary Turner     auto OneType = Substream.slice(Offset, Type.length());
318c2f5b4bfSZachary Turner     P.formatMsfStreamData(formatv("Type {0}", TI).str(), File, Layout, OneType);
319c2f5b4bfSZachary Turner   }
320c2f5b4bfSZachary Turner }
321c2f5b4bfSZachary Turner 
322fa332827SZachary Turner template <typename CallbackT>
iterateOneModule(PDBFile & File,LinePrinter & P,const DbiModuleList & Modules,uint32_t I,uint32_t Digits,uint32_t IndentLevel,CallbackT Callback)323fa332827SZachary Turner static void iterateOneModule(PDBFile &File, LinePrinter &P,
324fa332827SZachary Turner                              const DbiModuleList &Modules, uint32_t I,
325fa332827SZachary Turner                              uint32_t Digits, uint32_t IndentLevel,
326fa332827SZachary Turner                              CallbackT Callback) {
327e79b07e4SZachary Turner   if (I >= Modules.getModuleCount()) {
328e79b07e4SZachary Turner     P.formatLine("Mod {0:4} | Invalid module index ",
329e79b07e4SZachary Turner                  fmt_align(I, AlignStyle::Right, std::max(Digits, 4U)));
330e79b07e4SZachary Turner     return;
331e79b07e4SZachary Turner   }
332e79b07e4SZachary Turner 
333fa332827SZachary Turner   auto Modi = Modules.getModuleDescriptor(I);
334fa332827SZachary Turner   P.formatLine("Mod {0:4} | `{1}`: ",
335fa332827SZachary Turner                fmt_align(I, AlignStyle::Right, std::max(Digits, 4U)),
336fa332827SZachary Turner                Modi.getModuleName());
337fa332827SZachary Turner 
338fa332827SZachary Turner   uint16_t ModiStream = Modi.getModuleStreamIndex();
339fa332827SZachary Turner   AutoIndent Indent2(P, IndentLevel);
340e79b07e4SZachary Turner   if (ModiStream == kInvalidStreamIndex)
341e79b07e4SZachary Turner     return;
342e79b07e4SZachary Turner 
34313f7ddffSNico Weber   auto ModStreamData = File.createIndexedStream(ModiStream);
344fa332827SZachary Turner   ModuleDebugStreamRef ModStream(Modi, std::move(ModStreamData));
345fa332827SZachary Turner   if (auto EC = ModStream.reload()) {
346fa332827SZachary Turner     P.formatLine("Could not parse debug information.");
347fa332827SZachary Turner     return;
348fa332827SZachary Turner   }
349fa332827SZachary Turner   auto Layout = File.getStreamLayout(ModiStream);
350fa332827SZachary Turner   Callback(I, ModStream, Layout);
351fa332827SZachary Turner }
352fa332827SZachary Turner 
353fa332827SZachary Turner template <typename CallbackT>
iterateModules(PDBFile & File,LinePrinter & P,uint32_t IndentLevel,CallbackT Callback)354fa332827SZachary Turner static void iterateModules(PDBFile &File, LinePrinter &P, uint32_t IndentLevel,
355fa332827SZachary Turner                            CallbackT Callback) {
356fa332827SZachary Turner   AutoIndent Indent(P);
357fa332827SZachary Turner   if (!File.hasPDBDbiStream()) {
358fa332827SZachary Turner     P.formatLine("DBI Stream not present");
359fa332827SZachary Turner     return;
360fa332827SZachary Turner   }
361fa332827SZachary Turner 
362fa332827SZachary Turner   ExitOnError Err("Unexpected error processing modules");
363fa332827SZachary Turner 
364fa332827SZachary Turner   auto &Stream = Err(File.getPDBDbiStream());
365fa332827SZachary Turner 
366fa332827SZachary Turner   const DbiModuleList &Modules = Stream.modules();
367fa332827SZachary Turner 
368fa332827SZachary Turner   if (opts::bytes::ModuleIndex.getNumOccurrences() > 0) {
369fa332827SZachary Turner     iterateOneModule(File, P, Modules, opts::bytes::ModuleIndex, 1, IndentLevel,
370fa332827SZachary Turner                      Callback);
371fa332827SZachary Turner   } else {
372fa332827SZachary Turner     uint32_t Count = Modules.getModuleCount();
373fa332827SZachary Turner     uint32_t Digits = NumDigits(Count);
374fa332827SZachary Turner     for (uint32_t I = 0; I < Count; ++I) {
375fa332827SZachary Turner       iterateOneModule(File, P, Modules, I, Digits, IndentLevel, Callback);
376fa332827SZachary Turner     }
377fa332827SZachary Turner   }
378fa332827SZachary Turner }
379fa332827SZachary Turner 
dumpModuleSyms()380fa332827SZachary Turner void BytesOutputStyle::dumpModuleSyms() {
381fa332827SZachary Turner   printHeader(P, "Module Symbols");
382fa332827SZachary Turner 
383fa332827SZachary Turner   AutoIndent Indent(P);
384fa332827SZachary Turner 
385fa332827SZachary Turner   iterateModules(File, P, 2,
386fa332827SZachary Turner                  [this](uint32_t Modi, const ModuleDebugStreamRef &Stream,
387fa332827SZachary Turner                         const MSFStreamLayout &Layout) {
388fa332827SZachary Turner                    auto Symbols = Stream.getSymbolsSubstream();
389fa332827SZachary Turner                    P.formatMsfStreamData("Symbols", File, Layout, Symbols);
390fa332827SZachary Turner                  });
391fa332827SZachary Turner }
392fa332827SZachary Turner 
dumpModuleC11()393fa332827SZachary Turner void BytesOutputStyle::dumpModuleC11() {
394fa332827SZachary Turner   printHeader(P, "C11 Debug Chunks");
395fa332827SZachary Turner 
396fa332827SZachary Turner   AutoIndent Indent(P);
397fa332827SZachary Turner 
398fa332827SZachary Turner   iterateModules(File, P, 2,
399fa332827SZachary Turner                  [this](uint32_t Modi, const ModuleDebugStreamRef &Stream,
400fa332827SZachary Turner                         const MSFStreamLayout &Layout) {
401fa332827SZachary Turner                    auto Chunks = Stream.getC11LinesSubstream();
402fa332827SZachary Turner                    P.formatMsfStreamData("C11 Debug Chunks", File, Layout,
403fa332827SZachary Turner                                          Chunks);
404fa332827SZachary Turner                  });
405fa332827SZachary Turner }
406fa332827SZachary Turner 
dumpModuleC13()407fa332827SZachary Turner void BytesOutputStyle::dumpModuleC13() {
408fa332827SZachary Turner   printHeader(P, "Debug Chunks");
409fa332827SZachary Turner 
410fa332827SZachary Turner   AutoIndent Indent(P);
411fa332827SZachary Turner 
412e79b07e4SZachary Turner   iterateModules(
413e79b07e4SZachary Turner       File, P, 2,
414fa332827SZachary Turner       [this](uint32_t Modi, const ModuleDebugStreamRef &Stream,
415fa332827SZachary Turner              const MSFStreamLayout &Layout) {
416fa332827SZachary Turner         auto Chunks = Stream.getC13LinesSubstream();
417e79b07e4SZachary Turner         if (opts::bytes::SplitChunks) {
418e79b07e4SZachary Turner           for (const auto &SS : Stream.subsections()) {
419e79b07e4SZachary Turner             BinarySubstreamRef ThisChunk;
420e79b07e4SZachary Turner             std::tie(ThisChunk, Chunks) = Chunks.split(SS.getRecordLength());
421e79b07e4SZachary Turner             P.formatMsfStreamData(formatChunkKind(SS.kind()), File, Layout,
422e79b07e4SZachary Turner                                   ThisChunk);
423e79b07e4SZachary Turner           }
424e79b07e4SZachary Turner         } else {
425fa332827SZachary Turner           P.formatMsfStreamData("Debug Chunks", File, Layout, Chunks);
426e79b07e4SZachary Turner         }
427fa332827SZachary Turner       });
428fa332827SZachary Turner }
429fa332827SZachary Turner 
dumpByteRanges(uint32_t Min,uint32_t Max)4306b124f29SZachary Turner void BytesOutputStyle::dumpByteRanges(uint32_t Min, uint32_t Max) {
4316b124f29SZachary Turner   printHeader(P, "MSF Bytes");
4326b124f29SZachary Turner 
4336b124f29SZachary Turner   AutoIndent Indent(P);
4346b124f29SZachary Turner 
4356b124f29SZachary Turner   BinaryStreamReader Reader(File.getMsfBuffer());
4366b124f29SZachary Turner   ArrayRef<uint8_t> Data;
4376b124f29SZachary Turner   consumeError(Reader.skip(Min));
4386b124f29SZachary Turner   uint32_t Size = Max - Min + 1;
4396b124f29SZachary Turner   auto EC = Reader.readBytes(Data, Size);
4406b124f29SZachary Turner   assert(!EC);
4416b124f29SZachary Turner   consumeError(std::move(EC));
4426b124f29SZachary Turner   P.formatBinary("Bytes", Data, Min);
4436b124f29SZachary Turner }
4446b124f29SZachary Turner 
445c2f5b4bfSZachary Turner Expected<codeview::LazyRandomTypeCollection &>
initializeTypes(uint32_t StreamIdx)446c2f5b4bfSZachary Turner BytesOutputStyle::initializeTypes(uint32_t StreamIdx) {
447c2f5b4bfSZachary Turner   auto &TypeCollection = (StreamIdx == StreamTPI) ? TpiTypes : IpiTypes;
448c2f5b4bfSZachary Turner   if (TypeCollection)
449c2f5b4bfSZachary Turner     return *TypeCollection;
450c2f5b4bfSZachary Turner 
451c2f5b4bfSZachary Turner   auto Tpi = (StreamIdx == StreamTPI) ? File.getPDBTpiStream()
452c2f5b4bfSZachary Turner                                       : File.getPDBIpiStream();
453c2f5b4bfSZachary Turner   if (!Tpi)
454c2f5b4bfSZachary Turner     return Tpi.takeError();
455c2f5b4bfSZachary Turner 
456c2f5b4bfSZachary Turner   auto &Types = Tpi->typeArray();
457c2f5b4bfSZachary Turner   uint32_t Count = Tpi->getNumTypeRecords();
458c2f5b4bfSZachary Turner   auto Offsets = Tpi->getTypeIndexOffsets();
459c2f5b4bfSZachary Turner   TypeCollection =
4600eaee545SJonas Devlieghere       std::make_unique<LazyRandomTypeCollection>(Types, Count, Offsets);
461c2f5b4bfSZachary Turner 
462c2f5b4bfSZachary Turner   return *TypeCollection;
463c2f5b4bfSZachary Turner }
464c2f5b4bfSZachary Turner 
dumpFpm()465c3d8eec9SZachary Turner void BytesOutputStyle::dumpFpm() {
466c3d8eec9SZachary Turner   printHeader(P, "Free Page Map");
467c3d8eec9SZachary Turner 
468c3d8eec9SZachary Turner   msf::MSFStreamLayout FpmLayout = File.getFpmStreamLayout();
469c3d8eec9SZachary Turner   P.formatMsfStreamBlocks(File, FpmLayout);
470c3d8eec9SZachary Turner }
471c3d8eec9SZachary Turner 
dumpStreamBytes()4729940203aSZachary Turner void BytesOutputStyle::dumpStreamBytes() {
4739940203aSZachary Turner   if (StreamPurposes.empty())
4749940203aSZachary Turner     discoverStreamPurposes(File, StreamPurposes);
4759940203aSZachary Turner 
4769940203aSZachary Turner   printHeader(P, "Stream Data");
4779940203aSZachary Turner   ExitOnError Err("Unexpected error reading stream data");
4789940203aSZachary Turner 
4799940203aSZachary Turner   auto Specs = parseStreamSpecs(P);
4809940203aSZachary Turner 
4819940203aSZachary Turner   for (const auto &Spec : Specs) {
4829940203aSZachary Turner     AutoIndent Indent(P);
4830b36c3ebSZachary Turner     if (Spec.SI >= StreamPurposes.size()) {
4849940203aSZachary Turner       P.formatLine("Stream {0}: Not present", Spec.SI);
4859940203aSZachary Turner       continue;
4869940203aSZachary Turner     }
487d1de2f4fSZachary Turner     P.formatMsfStreamData("Data", File, Spec.SI,
488d1de2f4fSZachary Turner                           StreamPurposes[Spec.SI].getShortName(), Spec.Begin,
489d1de2f4fSZachary Turner                           Spec.Size);
4909940203aSZachary Turner   }
4919940203aSZachary Turner }
492