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