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