]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp
Merge llvm, clang, lld and lldb trunk r291274, and resolve conflicts.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / llvm-pdbdump / LLVMOutputStyle.cpp
1 //===- LLVMOutputStyle.cpp ------------------------------------ *- C++ --*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "LLVMOutputStyle.h"
11
12 #include "llvm-pdbdump.h"
13 #include "llvm/DebugInfo/CodeView/EnumTables.h"
14 #include "llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h"
15 #include "llvm/DebugInfo/CodeView/SymbolDumper.h"
16 #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
17 #include "llvm/DebugInfo/MSF/StreamReader.h"
18 #include "llvm/DebugInfo/PDB/PDBExtras.h"
19 #include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
20 #include "llvm/DebugInfo/PDB/Raw/EnumTables.h"
21 #include "llvm/DebugInfo/PDB/Raw/GlobalsStream.h"
22 #include "llvm/DebugInfo/PDB/Raw/ISectionContribVisitor.h"
23 #include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
24 #include "llvm/DebugInfo/PDB/Raw/ModInfo.h"
25 #include "llvm/DebugInfo/PDB/Raw/ModStream.h"
26 #include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
27 #include "llvm/DebugInfo/PDB/Raw/PublicsStream.h"
28 #include "llvm/DebugInfo/PDB/Raw/RawError.h"
29 #include "llvm/DebugInfo/PDB/Raw/TpiStream.h"
30 #include "llvm/Object/COFF.h"
31
32 #include <unordered_map>
33
34 using namespace llvm;
35 using namespace llvm::codeview;
36 using namespace llvm::msf;
37 using namespace llvm::pdb;
38
39 namespace {
40 struct PageStats {
41   explicit PageStats(const BitVector &FreePages)
42       : Upm(FreePages), ActualUsedPages(FreePages.size()),
43         MultiUsePages(FreePages.size()), UseAfterFreePages(FreePages.size()) {
44     const_cast<BitVector &>(Upm).flip();
45     // To calculate orphaned pages, we start with the set of pages that the
46     // MSF thinks are used.  Each time we find one that actually *is* used,
47     // we unset it.  Whichever bits remain set at the end are orphaned.
48     OrphanedPages = Upm;
49   }
50
51   // The inverse of the MSF File's copy of the Fpm.  The basis for which we
52   // determine the allocation status of each page.
53   const BitVector Upm;
54
55   // Pages which are marked as used in the FPM and are used at least once.
56   BitVector ActualUsedPages;
57
58   // Pages which are marked as used in the FPM but are used more than once.
59   BitVector MultiUsePages;
60
61   // Pages which are marked as used in the FPM but are not used at all.
62   BitVector OrphanedPages;
63
64   // Pages which are marked free in the FPM but are used.
65   BitVector UseAfterFreePages;
66 };
67 }
68
69 static void recordKnownUsedPage(PageStats &Stats, uint32_t UsedIndex) {
70   if (Stats.Upm.test(UsedIndex)) {
71     if (Stats.ActualUsedPages.test(UsedIndex))
72       Stats.MultiUsePages.set(UsedIndex);
73     Stats.ActualUsedPages.set(UsedIndex);
74     Stats.OrphanedPages.reset(UsedIndex);
75   } else {
76     // The MSF doesn't think this page is used, but it is.
77     Stats.UseAfterFreePages.set(UsedIndex);
78   }
79 }
80
81 static void printSectionOffset(llvm::raw_ostream &OS,
82                                const SectionOffset &Off) {
83   OS << Off.Off << ", " << Off.Isect;
84 }
85
86 LLVMOutputStyle::LLVMOutputStyle(PDBFile &File)
87     : File(File), P(outs()), Dumper(&P, false) {}
88
89 Error LLVMOutputStyle::dump() {
90   if (auto EC = dumpFileHeaders())
91     return EC;
92
93   if (auto EC = dumpStreamSummary())
94     return EC;
95
96   if (auto EC = dumpFreePageMap())
97     return EC;
98
99   if (auto EC = dumpStreamBlocks())
100     return EC;
101
102   if (auto EC = dumpBlockRanges())
103     return EC;
104
105   if (auto EC = dumpStreamBytes())
106     return EC;
107
108   if (auto EC = dumpInfoStream())
109     return EC;
110
111   if (auto EC = dumpTpiStream(StreamTPI))
112     return EC;
113
114   if (auto EC = dumpTpiStream(StreamIPI))
115     return EC;
116
117   if (auto EC = dumpDbiStream())
118     return EC;
119
120   if (auto EC = dumpSectionContribs())
121     return EC;
122
123   if (auto EC = dumpSectionMap())
124     return EC;
125
126   if (auto EC = dumpGlobalsStream())
127     return EC;
128
129   if (auto EC = dumpPublicsStream())
130     return EC;
131
132   if (auto EC = dumpSectionHeaders())
133     return EC;
134
135   if (auto EC = dumpFpoStream())
136     return EC;
137
138   flush();
139
140   return Error::success();
141 }
142
143 Error LLVMOutputStyle::dumpFileHeaders() {
144   if (!opts::raw::DumpHeaders)
145     return Error::success();
146
147   DictScope D(P, "FileHeaders");
148   P.printNumber("BlockSize", File.getBlockSize());
149   P.printNumber("FreeBlockMap", File.getFreeBlockMapBlock());
150   P.printNumber("NumBlocks", File.getBlockCount());
151   P.printNumber("NumDirectoryBytes", File.getNumDirectoryBytes());
152   P.printNumber("Unknown1", File.getUnknown1());
153   P.printNumber("BlockMapAddr", File.getBlockMapIndex());
154   P.printNumber("NumDirectoryBlocks", File.getNumDirectoryBlocks());
155
156   // The directory is not contiguous.  Instead, the block map contains a
157   // contiguous list of block numbers whose contents, when concatenated in
158   // order, make up the directory.
159   P.printList("DirectoryBlocks", File.getDirectoryBlockArray());
160   P.printNumber("NumStreams", File.getNumStreams());
161   return Error::success();
162 }
163
164 void LLVMOutputStyle::discoverStreamPurposes() {
165   if (!StreamPurposes.empty())
166     return;
167
168   // It's OK if we fail to load some of these streams, we still attempt to print
169   // what we can.
170   auto Dbi = File.getPDBDbiStream();
171   auto Tpi = File.getPDBTpiStream();
172   auto Ipi = File.getPDBIpiStream();
173   auto Info = File.getPDBInfoStream();
174
175   uint32_t StreamCount = File.getNumStreams();
176   std::unordered_map<uint16_t, const ModuleInfoEx *> ModStreams;
177   std::unordered_map<uint16_t, std::string> NamedStreams;
178
179   if (Dbi) {
180     for (auto &ModI : Dbi->modules()) {
181       uint16_t SN = ModI.Info.getModuleStreamIndex();
182       ModStreams[SN] = &ModI;
183     }
184   }
185   if (Info) {
186     for (auto &NSE : Info->named_streams()) {
187       NamedStreams[NSE.second] = NSE.first();
188     }
189   }
190
191   StreamPurposes.resize(StreamCount);
192   for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
193     std::string Value;
194     if (StreamIdx == OldMSFDirectory)
195       Value = "Old MSF Directory";
196     else if (StreamIdx == StreamPDB)
197       Value = "PDB Stream";
198     else if (StreamIdx == StreamDBI)
199       Value = "DBI Stream";
200     else if (StreamIdx == StreamTPI)
201       Value = "TPI Stream";
202     else if (StreamIdx == StreamIPI)
203       Value = "IPI Stream";
204     else if (Dbi && StreamIdx == Dbi->getGlobalSymbolStreamIndex())
205       Value = "Global Symbol Hash";
206     else if (Dbi && StreamIdx == Dbi->getPublicSymbolStreamIndex())
207       Value = "Public Symbol Hash";
208     else if (Dbi && StreamIdx == Dbi->getSymRecordStreamIndex())
209       Value = "Public Symbol Records";
210     else if (Tpi && StreamIdx == Tpi->getTypeHashStreamIndex())
211       Value = "TPI Hash";
212     else if (Tpi && StreamIdx == Tpi->getTypeHashStreamAuxIndex())
213       Value = "TPI Aux Hash";
214     else if (Ipi && StreamIdx == Ipi->getTypeHashStreamIndex())
215       Value = "IPI Hash";
216     else if (Ipi && StreamIdx == Ipi->getTypeHashStreamAuxIndex())
217       Value = "IPI Aux Hash";
218     else if (Dbi &&
219              StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Exception))
220       Value = "Exception Data";
221     else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Fixup))
222       Value = "Fixup Data";
223     else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::FPO))
224       Value = "FPO Data";
225     else if (Dbi &&
226              StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::NewFPO))
227       Value = "New FPO Data";
228     else if (Dbi &&
229              StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::OmapFromSrc))
230       Value = "Omap From Source Data";
231     else if (Dbi &&
232              StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::OmapToSrc))
233       Value = "Omap To Source Data";
234     else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Pdata))
235       Value = "Pdata";
236     else if (Dbi &&
237              StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::SectionHdr))
238       Value = "Section Header Data";
239     else if (Dbi &&
240              StreamIdx ==
241                  Dbi->getDebugStreamIndex(DbgHeaderType::SectionHdrOrig))
242       Value = "Section Header Original Data";
243     else if (Dbi &&
244              StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::TokenRidMap))
245       Value = "Token Rid Data";
246     else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Xdata))
247       Value = "Xdata";
248     else {
249       auto ModIter = ModStreams.find(StreamIdx);
250       auto NSIter = NamedStreams.find(StreamIdx);
251       if (ModIter != ModStreams.end()) {
252         Value = "Module \"";
253         Value += ModIter->second->Info.getModuleName().str();
254         Value += "\"";
255       } else if (NSIter != NamedStreams.end()) {
256         Value = "Named Stream \"";
257         Value += NSIter->second;
258         Value += "\"";
259       } else {
260         Value = "???";
261       }
262     }
263     StreamPurposes[StreamIdx] = Value;
264   }
265
266   // Consume errors from missing streams.
267   if (!Dbi)
268     consumeError(Dbi.takeError());
269   if (!Tpi)
270     consumeError(Tpi.takeError());
271   if (!Ipi)
272     consumeError(Ipi.takeError());
273   if (!Info)
274     consumeError(Info.takeError());
275 }
276
277 Error LLVMOutputStyle::dumpStreamSummary() {
278   if (!opts::raw::DumpStreamSummary)
279     return Error::success();
280
281   discoverStreamPurposes();
282
283   uint32_t StreamCount = File.getNumStreams();
284
285   ListScope L(P, "Streams");
286   for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
287     std::string Label("Stream ");
288     Label += to_string(StreamIdx);
289
290     std::string Value = "[" + StreamPurposes[StreamIdx] + "] (";
291     Value += to_string(File.getStreamByteSize(StreamIdx));
292     Value += " bytes)";
293
294     P.printString(Label, Value);
295   }
296
297   P.flush();
298   return Error::success();
299 }
300
301 Error LLVMOutputStyle::dumpFreePageMap() {
302   if (!opts::raw::DumpPageStats)
303     return Error::success();
304
305   // Start with used pages instead of free pages because
306   // the number of free pages is far larger than used pages.
307   BitVector FPM = File.getMsfLayout().FreePageMap;
308
309   PageStats PS(FPM);
310
311   recordKnownUsedPage(PS, 0); // MSF Super Block
312
313   uint32_t BlocksPerSection = msf::getFpmIntervalLength(File.getMsfLayout());
314   uint32_t NumSections = msf::getNumFpmIntervals(File.getMsfLayout());
315   for (uint32_t I = 0; I < NumSections; ++I) {
316     uint32_t Fpm0 = 1 + BlocksPerSection * I;
317     // 2 Fpm blocks spaced at `getBlockSize()` block intervals
318     recordKnownUsedPage(PS, Fpm0);
319     recordKnownUsedPage(PS, Fpm0 + 1);
320   }
321
322   recordKnownUsedPage(PS, File.getBlockMapIndex()); // Stream Table
323
324   for (auto DB : File.getDirectoryBlockArray())
325     recordKnownUsedPage(PS, DB);
326
327   // Record pages used by streams. Note that pages for stream 0
328   // are considered being unused because that's what MSVC tools do.
329   // Stream 0 doesn't contain actual data, so it makes some sense,
330   // though it's a bit confusing to us.
331   for (auto &SE : File.getStreamMap().drop_front(1))
332     for (auto &S : SE)
333       recordKnownUsedPage(PS, S);
334
335   dumpBitVector("Msf Free Pages", FPM);
336   dumpBitVector("Orphaned Pages", PS.OrphanedPages);
337   dumpBitVector("Multiply Used Pages", PS.MultiUsePages);
338   dumpBitVector("Use After Free Pages", PS.UseAfterFreePages);
339   return Error::success();
340 }
341
342 void LLVMOutputStyle::dumpBitVector(StringRef Name, const BitVector &V) {
343   std::vector<uint32_t> Vec;
344   for (uint32_t I = 0, E = V.size(); I != E; ++I)
345     if (V[I])
346       Vec.push_back(I);
347   P.printList(Name, Vec);
348 }
349
350 Error LLVMOutputStyle::dumpGlobalsStream() {
351   if (!opts::raw::DumpGlobals)
352     return Error::success();
353   if (!File.hasPDBGlobalsStream()) {
354     P.printString("Globals Stream not present");
355     return Error::success();
356   }
357
358   auto Globals = File.getPDBGlobalsStream();
359   if (!Globals)
360     return Globals.takeError();
361   DictScope D(P, "Globals Stream");
362
363   auto Dbi = File.getPDBDbiStream();
364   if (!Dbi)
365     return Dbi.takeError();
366
367   P.printNumber("Stream number", Dbi->getGlobalSymbolStreamIndex());
368   P.printNumber("Number of buckets", Globals->getNumBuckets());
369   P.printList("Hash Buckets", Globals->getHashBuckets());
370
371   return Error::success();
372 }
373
374 Error LLVMOutputStyle::dumpStreamBlocks() {
375   if (!opts::raw::DumpStreamBlocks)
376     return Error::success();
377
378   ListScope L(P, "StreamBlocks");
379   uint32_t StreamCount = File.getNumStreams();
380   for (uint32_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
381     std::string Name("Stream ");
382     Name += to_string(StreamIdx);
383     auto StreamBlocks = File.getStreamBlockList(StreamIdx);
384     P.printList(Name, StreamBlocks);
385   }
386   return Error::success();
387 }
388
389 Error LLVMOutputStyle::dumpBlockRanges() {
390   if (!opts::raw::DumpBlockRange.hasValue())
391     return Error::success();
392   auto &R = *opts::raw::DumpBlockRange;
393   uint32_t Max = R.Max.getValueOr(R.Min);
394
395   if (Max < R.Min)
396     return make_error<StringError>(
397         "Invalid block range specified.  Max < Min",
398         std::make_error_code(std::errc::bad_address));
399   if (Max >= File.getBlockCount())
400     return make_error<StringError>(
401         "Invalid block range specified.  Requested block out of bounds",
402         std::make_error_code(std::errc::bad_address));
403
404   DictScope D(P, "Block Data");
405   for (uint32_t I = R.Min; I <= Max; ++I) {
406     auto ExpectedData = File.getBlockData(I, File.getBlockSize());
407     if (!ExpectedData)
408       return ExpectedData.takeError();
409     std::string Label;
410     llvm::raw_string_ostream S(Label);
411     S << "Block " << I;
412     S.flush();
413     P.printBinaryBlock(Label, *ExpectedData);
414   }
415
416   return Error::success();
417 }
418
419 Error LLVMOutputStyle::dumpStreamBytes() {
420   if (opts::raw::DumpStreamData.empty())
421     return Error::success();
422
423   discoverStreamPurposes();
424
425   DictScope D(P, "Stream Data");
426   for (uint32_t SI : opts::raw::DumpStreamData) {
427     if (SI >= File.getNumStreams())
428       return make_error<RawError>(raw_error_code::no_stream);
429
430     auto S = MappedBlockStream::createIndexedStream(File.getMsfLayout(),
431                                                     File.getMsfBuffer(), SI);
432     if (!S)
433       continue;
434     DictScope DD(P, "Stream");
435
436     P.printNumber("Index", SI);
437     P.printString("Type", StreamPurposes[SI]);
438     P.printNumber("Size", S->getLength());
439     auto Blocks = File.getMsfLayout().StreamMap[SI];
440     P.printList("Blocks", Blocks);
441
442     StreamReader R(*S);
443     ArrayRef<uint8_t> StreamData;
444     if (auto EC = R.readBytes(StreamData, S->getLength()))
445       return EC;
446     P.printBinaryBlock("Data", StreamData);
447   }
448   return Error::success();
449 }
450
451 Error LLVMOutputStyle::dumpInfoStream() {
452   if (!opts::raw::DumpHeaders)
453     return Error::success();
454   if (!File.hasPDBInfoStream()) {
455     P.printString("PDB Stream not present");
456     return Error::success();
457   }
458   auto IS = File.getPDBInfoStream();
459   if (!IS)
460     return IS.takeError();
461
462   DictScope D(P, "PDB Stream");
463   P.printNumber("Version", IS->getVersion());
464   P.printHex("Signature", IS->getSignature());
465   P.printNumber("Age", IS->getAge());
466   P.printObject("Guid", IS->getGuid());
467   return Error::success();
468 }
469
470 static void printTypeIndexOffset(raw_ostream &OS,
471                                  const TypeIndexOffset &TIOff) {
472   OS << "{" << TIOff.Type.getIndex() << ", " << TIOff.Offset << "}";
473 }
474
475 static void dumpTpiHash(ScopedPrinter &P, TpiStream &Tpi) {
476   if (!opts::raw::DumpTpiHash)
477     return;
478   DictScope DD(P, "Hash");
479   P.printNumber("Number of Hash Buckets", Tpi.NumHashBuckets());
480   P.printNumber("Hash Key Size", Tpi.getHashKeySize());
481   P.printList("Values", Tpi.getHashValues());
482   P.printList("Type Index Offsets", Tpi.getTypeIndexOffsets(),
483               printTypeIndexOffset);
484   P.printList("Hash Adjustments", Tpi.getHashAdjustments(),
485               printTypeIndexOffset);
486 }
487
488 Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
489   assert(StreamIdx == StreamTPI || StreamIdx == StreamIPI);
490
491   bool DumpRecordBytes = false;
492   bool DumpRecords = false;
493   StringRef Label;
494   StringRef VerLabel;
495   if (StreamIdx == StreamTPI) {
496     if (!File.hasPDBTpiStream()) {
497       P.printString("Type Info Stream (TPI) not present");
498       return Error::success();
499     }
500     DumpRecordBytes = opts::raw::DumpTpiRecordBytes;
501     DumpRecords = opts::raw::DumpTpiRecords;
502     Label = "Type Info Stream (TPI)";
503     VerLabel = "TPI Version";
504   } else if (StreamIdx == StreamIPI) {
505     if (!File.hasPDBIpiStream()) {
506       P.printString("Type Info Stream (IPI) not present");
507       return Error::success();
508     }
509     DumpRecordBytes = opts::raw::DumpIpiRecordBytes;
510     DumpRecords = opts::raw::DumpIpiRecords;
511     Label = "Type Info Stream (IPI)";
512     VerLabel = "IPI Version";
513   }
514   if (!DumpRecordBytes && !DumpRecords && !opts::raw::DumpModuleSyms)
515     return Error::success();
516
517   auto Tpi = (StreamIdx == StreamTPI) ? File.getPDBTpiStream()
518                                       : File.getPDBIpiStream();
519   if (!Tpi)
520     return Tpi.takeError();
521
522   if (DumpRecords || DumpRecordBytes) {
523     DictScope D(P, Label);
524
525     P.printNumber(VerLabel, Tpi->getTpiVersion());
526     P.printNumber("Record count", Tpi->NumTypeRecords());
527
528     ListScope L(P, "Records");
529
530     bool HadError = false;
531     for (auto &Type : Tpi->types(&HadError)) {
532       DictScope DD(P, "");
533
534       if (DumpRecords) {
535         if (auto EC = Dumper.dump(Type))
536           return EC;
537       }
538
539       if (DumpRecordBytes)
540         P.printBinaryBlock("Bytes", Type.content());
541     }
542     dumpTpiHash(P, *Tpi);
543     if (HadError)
544       return make_error<RawError>(raw_error_code::corrupt_file,
545                                   "TPI stream contained corrupt record");
546   } else if (opts::raw::DumpModuleSyms) {
547     // Even if the user doesn't want to dump type records, we still need to
548     // iterate them in order to build the list of types so that we can print
549     // them when dumping module symbols. So when they want to dump symbols
550     // but not types, use a null output stream.
551     ScopedPrinter *OldP = Dumper.getPrinter();
552     Dumper.setPrinter(nullptr);
553
554     bool HadError = false;
555     for (auto &Type : Tpi->types(&HadError)) {
556       if (auto EC = Dumper.dump(Type))
557         return EC;
558     }
559
560     Dumper.setPrinter(OldP);
561     dumpTpiHash(P, *Tpi);
562     if (HadError)
563       return make_error<RawError>(raw_error_code::corrupt_file,
564                                   "TPI stream contained corrupt record");
565   }
566   P.flush();
567   return Error::success();
568 }
569
570 Error LLVMOutputStyle::dumpDbiStream() {
571   bool DumpModules = opts::raw::DumpModules || opts::raw::DumpModuleSyms ||
572                      opts::raw::DumpModuleFiles || opts::raw::DumpLineInfo;
573   if (!opts::raw::DumpHeaders && !DumpModules)
574     return Error::success();
575   if (!File.hasPDBDbiStream()) {
576     P.printString("DBI Stream not present");
577     return Error::success();
578   }
579
580   auto DS = File.getPDBDbiStream();
581   if (!DS)
582     return DS.takeError();
583
584   DictScope D(P, "DBI Stream");
585   P.printNumber("Dbi Version", DS->getDbiVersion());
586   P.printNumber("Age", DS->getAge());
587   P.printBoolean("Incremental Linking", DS->isIncrementallyLinked());
588   P.printBoolean("Has CTypes", DS->hasCTypes());
589   P.printBoolean("Is Stripped", DS->isStripped());
590   P.printObject("Machine Type", DS->getMachineType());
591   P.printNumber("Symbol Record Stream Index", DS->getSymRecordStreamIndex());
592   P.printNumber("Public Symbol Stream Index", DS->getPublicSymbolStreamIndex());
593   P.printNumber("Global Symbol Stream Index", DS->getGlobalSymbolStreamIndex());
594
595   uint16_t Major = DS->getBuildMajorVersion();
596   uint16_t Minor = DS->getBuildMinorVersion();
597   P.printVersion("Toolchain Version", Major, Minor);
598
599   std::string DllName;
600   raw_string_ostream DllStream(DllName);
601   DllStream << "mspdb" << Major << Minor << ".dll version";
602   DllStream.flush();
603   P.printVersion(DllName, Major, Minor, DS->getPdbDllVersion());
604
605   if (DumpModules) {
606     ListScope L(P, "Modules");
607     for (auto &Modi : DS->modules()) {
608       DictScope DD(P);
609       P.printString("Name", Modi.Info.getModuleName().str());
610       P.printNumber("Debug Stream Index", Modi.Info.getModuleStreamIndex());
611       P.printString("Object File Name", Modi.Info.getObjFileName().str());
612       P.printNumber("Num Files", Modi.Info.getNumberOfFiles());
613       P.printNumber("Source File Name Idx", Modi.Info.getSourceFileNameIndex());
614       P.printNumber("Pdb File Name Idx", Modi.Info.getPdbFilePathNameIndex());
615       P.printNumber("Line Info Byte Size", Modi.Info.getLineInfoByteSize());
616       P.printNumber("C13 Line Info Byte Size",
617                     Modi.Info.getC13LineInfoByteSize());
618       P.printNumber("Symbol Byte Size", Modi.Info.getSymbolDebugInfoByteSize());
619       P.printNumber("Type Server Index", Modi.Info.getTypeServerIndex());
620       P.printBoolean("Has EC Info", Modi.Info.hasECInfo());
621       if (opts::raw::DumpModuleFiles) {
622         std::string FileListName =
623             to_string(Modi.SourceFiles.size()) + " Contributing Source Files";
624         ListScope LL(P, FileListName);
625         for (auto File : Modi.SourceFiles)
626           P.printString(File.str());
627       }
628       bool HasModuleDI =
629           (Modi.Info.getModuleStreamIndex() < File.getNumStreams());
630       bool ShouldDumpSymbols =
631           (opts::raw::DumpModuleSyms || opts::raw::DumpSymRecordBytes);
632       if (HasModuleDI && (ShouldDumpSymbols || opts::raw::DumpLineInfo)) {
633         auto ModStreamData = MappedBlockStream::createIndexedStream(
634             File.getMsfLayout(), File.getMsfBuffer(),
635             Modi.Info.getModuleStreamIndex());
636
637         ModStream ModS(Modi.Info, std::move(ModStreamData));
638         if (auto EC = ModS.reload())
639           return EC;
640
641         if (ShouldDumpSymbols) {
642           ListScope SS(P, "Symbols");
643           codeview::CVSymbolDumper SD(P, Dumper, nullptr, false);
644           bool HadError = false;
645           for (auto S : ModS.symbols(&HadError)) {
646             DictScope LL(P, "");
647             if (opts::raw::DumpModuleSyms) {
648               if (auto EC = SD.dump(S)) {
649                 llvm::consumeError(std::move(EC));
650                 HadError = true;
651                 break;
652               }
653             }
654             if (opts::raw::DumpSymRecordBytes)
655               P.printBinaryBlock("Bytes", S.content());
656           }
657           if (HadError)
658             return make_error<RawError>(
659                 raw_error_code::corrupt_file,
660                 "DBI stream contained corrupt symbol record");
661         }
662         if (opts::raw::DumpLineInfo) {
663           ListScope SS(P, "LineInfo");
664           bool HadError = false;
665           // Define a locally scoped visitor to print the different
666           // substream types types.
667           class RecordVisitor : public codeview::IModuleSubstreamVisitor {
668           public:
669             RecordVisitor(ScopedPrinter &P, PDBFile &F) : P(P), F(F) {}
670             Error visitUnknown(ModuleSubstreamKind Kind,
671                                ReadableStreamRef Stream) override {
672               DictScope DD(P, "Unknown");
673               ArrayRef<uint8_t> Data;
674               StreamReader R(Stream);
675               if (auto EC = R.readBytes(Data, R.bytesRemaining())) {
676                 return make_error<RawError>(
677                     raw_error_code::corrupt_file,
678                     "DBI stream contained corrupt line info record");
679               }
680               P.printBinaryBlock("Data", Data);
681               return Error::success();
682             }
683             Error
684             visitFileChecksums(ReadableStreamRef Data,
685                                const FileChecksumArray &Checksums) override {
686               DictScope DD(P, "FileChecksums");
687               for (const auto &C : Checksums) {
688                 DictScope DDD(P, "Checksum");
689                 if (auto Result = getFileNameForOffset(C.FileNameOffset))
690                   P.printString("FileName", Result.get());
691                 else
692                   return Result.takeError();
693                 P.flush();
694                 P.printEnum("Kind", uint8_t(C.Kind), getFileChecksumNames());
695                 P.printBinaryBlock("Checksum", C.Checksum);
696               }
697               return Error::success();
698             }
699
700             Error visitLines(ReadableStreamRef Data,
701                              const LineSubstreamHeader *Header,
702                              const LineInfoArray &Lines) override {
703               DictScope DD(P, "Lines");
704               for (const auto &L : Lines) {
705                 if (auto Result = getFileNameForOffset2(L.NameIndex))
706                   P.printString("FileName", Result.get());
707                 else
708                   return Result.takeError();
709                 P.flush();
710                 for (const auto &N : L.LineNumbers) {
711                   DictScope DDD(P, "Line");
712                   LineInfo LI(N.Flags);
713                   P.printNumber("Offset", N.Offset);
714                   if (LI.isAlwaysStepInto())
715                     P.printString("StepInto", StringRef("Always"));
716                   else if (LI.isNeverStepInto())
717                     P.printString("StepInto", StringRef("Never"));
718                   else
719                     P.printNumber("LineNumberStart", LI.getStartLine());
720                   P.printNumber("EndDelta", LI.getLineDelta());
721                   P.printBoolean("IsStatement", LI.isStatement());
722                 }
723                 for (const auto &C : L.Columns) {
724                   DictScope DDD(P, "Column");
725                   P.printNumber("Start", C.StartColumn);
726                   P.printNumber("End", C.EndColumn);
727                 }
728               }
729               return Error::success();
730             }
731
732           private:
733             Expected<StringRef> getFileNameForOffset(uint32_t Offset) {
734               auto ST = F.getStringTable();
735               if (!ST)
736                 return ST.takeError();
737
738               return ST->getStringForID(Offset);
739             }
740             Expected<StringRef> getFileNameForOffset2(uint32_t Offset) {
741               auto DS = F.getPDBDbiStream();
742               if (!DS)
743                 return DS.takeError();
744               return DS->getFileNameForIndex(Offset);
745             }
746             ScopedPrinter &P;
747             PDBFile &F;
748           };
749
750           RecordVisitor V(P, File);
751           for (const auto &L : ModS.lines(&HadError)) {
752             if (auto EC = codeview::visitModuleSubstream(L, V))
753               return EC;
754           }
755         }
756       }
757     }
758   }
759   return Error::success();
760 }
761
762 Error LLVMOutputStyle::dumpSectionContribs() {
763   if (!opts::raw::DumpSectionContribs)
764     return Error::success();
765   if (!File.hasPDBDbiStream()) {
766     P.printString("DBI Stream not present");
767     return Error::success();
768   }
769
770   auto Dbi = File.getPDBDbiStream();
771   if (!Dbi)
772     return Dbi.takeError();
773
774   ListScope L(P, "Section Contributions");
775   class Visitor : public ISectionContribVisitor {
776   public:
777     Visitor(ScopedPrinter &P, DbiStream &DS) : P(P), DS(DS) {}
778     void visit(const SectionContrib &SC) override {
779       DictScope D(P, "Contribution");
780       P.printNumber("ISect", SC.ISect);
781       P.printNumber("Off", SC.Off);
782       P.printNumber("Size", SC.Size);
783       P.printFlags("Characteristics", SC.Characteristics,
784                    codeview::getImageSectionCharacteristicNames(),
785                    COFF::SectionCharacteristics(0x00F00000));
786       {
787         DictScope DD(P, "Module");
788         P.printNumber("Index", SC.Imod);
789         auto M = DS.modules();
790         if (M.size() > SC.Imod) {
791           P.printString("Name", M[SC.Imod].Info.getModuleName());
792         }
793       }
794       P.printNumber("Data CRC", SC.DataCrc);
795       P.printNumber("Reloc CRC", SC.RelocCrc);
796       P.flush();
797     }
798     void visit(const SectionContrib2 &SC) override {
799       visit(SC.Base);
800       P.printNumber("ISect Coff", SC.ISectCoff);
801       P.flush();
802     }
803
804   private:
805     ScopedPrinter &P;
806     DbiStream &DS;
807   };
808   Visitor V(P, *Dbi);
809   Dbi->visitSectionContributions(V);
810   return Error::success();
811 }
812
813 Error LLVMOutputStyle::dumpSectionMap() {
814   if (!opts::raw::DumpSectionMap)
815     return Error::success();
816   if (!File.hasPDBDbiStream()) {
817     P.printString("DBI Stream not present");
818     return Error::success();
819   }
820
821   auto Dbi = File.getPDBDbiStream();
822   if (!Dbi)
823     return Dbi.takeError();
824
825   ListScope L(P, "Section Map");
826   for (auto &M : Dbi->getSectionMap()) {
827     DictScope D(P, "Entry");
828     P.printFlags("Flags", M.Flags, getOMFSegMapDescFlagNames());
829     P.printNumber("Ovl", M.Ovl);
830     P.printNumber("Group", M.Group);
831     P.printNumber("Frame", M.Frame);
832     P.printNumber("SecName", M.SecName);
833     P.printNumber("ClassName", M.ClassName);
834     P.printNumber("Offset", M.Offset);
835     P.printNumber("SecByteLength", M.SecByteLength);
836     P.flush();
837   }
838   return Error::success();
839 }
840
841 Error LLVMOutputStyle::dumpPublicsStream() {
842   if (!opts::raw::DumpPublics)
843     return Error::success();
844   if (!File.hasPDBPublicsStream()) {
845     P.printString("Publics Stream not present");
846     return Error::success();
847   }
848
849   auto Publics = File.getPDBPublicsStream();
850   if (!Publics)
851     return Publics.takeError();
852   DictScope D(P, "Publics Stream");
853
854   auto Dbi = File.getPDBDbiStream();
855   if (!Dbi)
856     return Dbi.takeError();
857
858   P.printNumber("Stream number", Dbi->getPublicSymbolStreamIndex());
859   P.printNumber("SymHash", Publics->getSymHash());
860   P.printNumber("AddrMap", Publics->getAddrMap());
861   P.printNumber("Number of buckets", Publics->getNumBuckets());
862   P.printList("Hash Buckets", Publics->getHashBuckets());
863   P.printList("Address Map", Publics->getAddressMap());
864   P.printList("Thunk Map", Publics->getThunkMap());
865   P.printList("Section Offsets", Publics->getSectionOffsets(),
866               printSectionOffset);
867   ListScope L(P, "Symbols");
868   codeview::CVSymbolDumper SD(P, Dumper, nullptr, false);
869   bool HadError = false;
870   for (auto S : Publics->getSymbols(&HadError)) {
871     DictScope DD(P, "");
872
873     if (auto EC = SD.dump(S)) {
874       HadError = true;
875       break;
876     }
877     if (opts::raw::DumpSymRecordBytes)
878       P.printBinaryBlock("Bytes", S.content());
879   }
880   if (HadError)
881     return make_error<RawError>(
882         raw_error_code::corrupt_file,
883         "Public symbol stream contained corrupt record");
884
885   return Error::success();
886 }
887
888 Error LLVMOutputStyle::dumpSectionHeaders() {
889   if (!opts::raw::DumpSectionHeaders)
890     return Error::success();
891   if (!File.hasPDBDbiStream()) {
892     P.printString("DBI Stream not present");
893     return Error::success();
894   }
895
896   auto Dbi = File.getPDBDbiStream();
897   if (!Dbi)
898     return Dbi.takeError();
899
900   ListScope D(P, "Section Headers");
901   for (const object::coff_section &Section : Dbi->getSectionHeaders()) {
902     DictScope DD(P, "");
903
904     // If a name is 8 characters long, there is no NUL character at end.
905     StringRef Name(Section.Name, strnlen(Section.Name, sizeof(Section.Name)));
906     P.printString("Name", Name);
907     P.printNumber("Virtual Size", Section.VirtualSize);
908     P.printNumber("Virtual Address", Section.VirtualAddress);
909     P.printNumber("Size of Raw Data", Section.SizeOfRawData);
910     P.printNumber("File Pointer to Raw Data", Section.PointerToRawData);
911     P.printNumber("File Pointer to Relocations", Section.PointerToRelocations);
912     P.printNumber("File Pointer to Linenumbers", Section.PointerToLinenumbers);
913     P.printNumber("Number of Relocations", Section.NumberOfRelocations);
914     P.printNumber("Number of Linenumbers", Section.NumberOfLinenumbers);
915     P.printFlags("Characteristics", Section.Characteristics,
916                  getImageSectionCharacteristicNames());
917   }
918   return Error::success();
919 }
920
921 Error LLVMOutputStyle::dumpFpoStream() {
922   if (!opts::raw::DumpFpo)
923     return Error::success();
924   if (!File.hasPDBDbiStream()) {
925     P.printString("DBI Stream not present");
926     return Error::success();
927   }
928
929   auto Dbi = File.getPDBDbiStream();
930   if (!Dbi)
931     return Dbi.takeError();
932
933   ListScope D(P, "New FPO");
934   for (const object::FpoData &Fpo : Dbi->getFpoRecords()) {
935     DictScope DD(P, "");
936     P.printNumber("Offset", Fpo.Offset);
937     P.printNumber("Size", Fpo.Size);
938     P.printNumber("Number of locals", Fpo.NumLocals);
939     P.printNumber("Number of params", Fpo.NumParams);
940     P.printNumber("Size of Prolog", Fpo.getPrologSize());
941     P.printNumber("Number of Saved Registers", Fpo.getNumSavedRegs());
942     P.printBoolean("Has SEH", Fpo.hasSEH());
943     P.printBoolean("Use BP", Fpo.useBP());
944     P.printNumber("Frame Pointer", Fpo.getFP());
945   }
946   return Error::success();
947 }
948
949 void LLVMOutputStyle::flush() { P.flush(); }