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