blob: 11c566facb30914c06832f9bd555b8d0583e0720 [file] [log] [blame]
Zachary Turnerd3117392016-06-03 19:28:33 +00001//===- 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
Zachary Turner44a643c2017-01-12 22:28:15 +000012#include "CompactTypeDumpVisitor.h"
Zachary Turnerd3117392016-06-03 19:28:33 +000013#include "llvm-pdbdump.h"
Zachary Turner44a643c2017-01-12 22:28:15 +000014
Zachary Turner629cb7d2017-01-11 23:24:22 +000015#include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
16#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
Zachary Turnerd3117392016-06-03 19:28:33 +000017#include "llvm/DebugInfo/CodeView/EnumTables.h"
18#include "llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h"
19#include "llvm/DebugInfo/CodeView/SymbolDumper.h"
Zachary Turner629cb7d2017-01-11 23:24:22 +000020#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
21#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
22#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
23#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
Zachary Turnerd2684b72017-02-25 00:33:34 +000024#include "llvm/DebugInfo/MSF/BinaryStreamReader.h"
Zachary Turneraf299ea2017-02-25 00:44:30 +000025#include "llvm/DebugInfo/MSF/BinaryStreamReader.h"
Zachary Turnera3225b02016-07-29 20:56:36 +000026#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
Adrian McCarthy6b6b8c42017-01-25 22:38:55 +000027#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
28#include "llvm/DebugInfo/PDB/Native/EnumTables.h"
29#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
30#include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h"
31#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
32#include "llvm/DebugInfo/PDB/Native/ModInfo.h"
33#include "llvm/DebugInfo/PDB/Native/ModStream.h"
34#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
35#include "llvm/DebugInfo/PDB/Native/PublicsStream.h"
36#include "llvm/DebugInfo/PDB/Native/RawError.h"
37#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
Zachary Turnerd3117392016-06-03 19:28:33 +000038#include "llvm/DebugInfo/PDB/PDBExtras.h"
Zachary Turnerd3117392016-06-03 19:28:33 +000039#include "llvm/Object/COFF.h"
Zachary Turner44a643c2017-01-12 22:28:15 +000040#include "llvm/Support/FormatVariadic.h"
Zachary Turnerd3117392016-06-03 19:28:33 +000041
42#include <unordered_map>
43
44using namespace llvm;
45using namespace llvm::codeview;
Zachary Turnerbac69d32016-07-22 19:56:05 +000046using namespace llvm::msf;
Zachary Turnerd3117392016-06-03 19:28:33 +000047using namespace llvm::pdb;
48
Zachary Turnerd3c7b8e2016-08-01 21:19:45 +000049namespace {
50struct 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
79static 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
Zachary Turnerd3117392016-06-03 19:28:33 +000091static void printSectionOffset(llvm::raw_ostream &OS,
92 const SectionOffset &Off) {
93 OS << Off.Off << ", " << Off.Isect;
94}
95
Zachary Turner629cb7d2017-01-11 23:24:22 +000096LLVMOutputStyle::LLVMOutputStyle(PDBFile &File) : File(File), P(outs()) {}
Zachary Turnerd3117392016-06-03 19:28:33 +000097
Zachary Turnera30bd1a2016-06-30 17:42:48 +000098Error LLVMOutputStyle::dump() {
99 if (auto EC = dumpFileHeaders())
100 return EC;
101
102 if (auto EC = dumpStreamSummary())
103 return EC;
104
Rui Ueyama7a5cdc62016-07-29 21:38:00 +0000105 if (auto EC = dumpFreePageMap())
106 return EC;
107
Zachary Turnera30bd1a2016-06-30 17:42:48 +0000108 if (auto EC = dumpStreamBlocks())
109 return EC;
110
Zachary Turner72c5b642016-09-09 18:17:52 +0000111 if (auto EC = dumpBlockRanges())
112 return EC;
113
114 if (auto EC = dumpStreamBytes())
Zachary Turnera30bd1a2016-06-30 17:42:48 +0000115 return EC;
116
Zachary Turner760ad4d2017-01-20 22:42:09 +0000117 if (auto EC = dumpStringTable())
118 return EC;
119
Zachary Turnera30bd1a2016-06-30 17:42:48 +0000120 if (auto EC = dumpInfoStream())
121 return EC;
122
Zachary Turnera30bd1a2016-06-30 17:42:48 +0000123 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
Bob Haarman653baa22016-10-21 19:43:19 +0000138 if (auto EC = dumpGlobalsStream())
139 return EC;
140
Zachary Turnera30bd1a2016-06-30 17:42:48 +0000141 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
Zachary Turnerd3117392016-06-03 19:28:33 +0000155Error LLVMOutputStyle::dumpFileHeaders() {
Zachary Turnera30bd1a2016-06-30 17:42:48 +0000156 if (!opts::raw::DumpHeaders)
Zachary Turnerd3117392016-06-03 19:28:33 +0000157 return Error::success();
158
159 DictScope D(P, "FileHeaders");
160 P.printNumber("BlockSize", File.getBlockSize());
Zachary Turnerb927e022016-07-15 22:17:19 +0000161 P.printNumber("FreeBlockMap", File.getFreeBlockMapBlock());
Zachary Turnerd3117392016-06-03 19:28:33 +0000162 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());
Zachary Turnerd3117392016-06-03 19:28:33 +0000167
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
Zachary Turner36efbfa2016-09-09 19:00:49 +0000176void LLVMOutputStyle::discoverStreamPurposes() {
177 if (!StreamPurposes.empty())
178 return;
Zachary Turnerd3117392016-06-03 19:28:33 +0000179
Reid Kleckner11582c52016-06-17 20:38:01 +0000180 // It's OK if we fail to load some of these streams, we still attempt to print
181 // what we can.
Zachary Turnera1657a92016-06-08 17:26:39 +0000182 auto Dbi = File.getPDBDbiStream();
Zachary Turnera1657a92016-06-08 17:26:39 +0000183 auto Tpi = File.getPDBTpiStream();
Zachary Turnera1657a92016-06-08 17:26:39 +0000184 auto Ipi = File.getPDBIpiStream();
Zachary Turnera1657a92016-06-08 17:26:39 +0000185 auto Info = File.getPDBInfoStream();
Zachary Turnerd3117392016-06-03 19:28:33 +0000186
Zachary Turnerd3117392016-06-03 19:28:33 +0000187 uint32_t StreamCount = File.getNumStreams();
188 std::unordered_map<uint16_t, const ModuleInfoEx *> ModStreams;
189 std::unordered_map<uint16_t, std::string> NamedStreams;
190
Reid Kleckner11582c52016-06-17 20:38:01 +0000191 if (Dbi) {
192 for (auto &ModI : Dbi->modules()) {
193 uint16_t SN = ModI.Info.getModuleStreamIndex();
194 ModStreams[SN] = &ModI;
195 }
Zachary Turnerd3117392016-06-03 19:28:33 +0000196 }
Reid Kleckner11582c52016-06-17 20:38:01 +0000197 if (Info) {
198 for (auto &NSE : Info->named_streams()) {
199 NamedStreams[NSE.second] = NSE.first();
200 }
Zachary Turnerd3117392016-06-03 19:28:33 +0000201 }
202
Zachary Turner36efbfa2016-09-09 19:00:49 +0000203 StreamPurposes.resize(StreamCount);
Zachary Turnerd3117392016-06-03 19:28:33 +0000204 for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
Zachary Turnerd3117392016-06-03 19:28:33 +0000205 std::string Value;
206 if (StreamIdx == OldMSFDirectory)
207 Value = "Old MSF Directory";
208 else if (StreamIdx == StreamPDB)
209 Value = "PDB Stream";
210 else if (StreamIdx == StreamDBI)
211 Value = "DBI Stream";
212 else if (StreamIdx == StreamTPI)
213 Value = "TPI Stream";
214 else if (StreamIdx == StreamIPI)
215 Value = "IPI Stream";
Reid Kleckner11582c52016-06-17 20:38:01 +0000216 else if (Dbi && StreamIdx == Dbi->getGlobalSymbolStreamIndex())
Zachary Turnerd3117392016-06-03 19:28:33 +0000217 Value = "Global Symbol Hash";
Reid Kleckner11582c52016-06-17 20:38:01 +0000218 else if (Dbi && StreamIdx == Dbi->getPublicSymbolStreamIndex())
Zachary Turnerd3117392016-06-03 19:28:33 +0000219 Value = "Public Symbol Hash";
Reid Kleckner11582c52016-06-17 20:38:01 +0000220 else if (Dbi && StreamIdx == Dbi->getSymRecordStreamIndex())
Zachary Turnerd3117392016-06-03 19:28:33 +0000221 Value = "Public Symbol Records";
Reid Kleckner11582c52016-06-17 20:38:01 +0000222 else if (Tpi && StreamIdx == Tpi->getTypeHashStreamIndex())
Zachary Turnerd3117392016-06-03 19:28:33 +0000223 Value = "TPI Hash";
Reid Kleckner11582c52016-06-17 20:38:01 +0000224 else if (Tpi && StreamIdx == Tpi->getTypeHashStreamAuxIndex())
Zachary Turnerd3117392016-06-03 19:28:33 +0000225 Value = "TPI Aux Hash";
Reid Kleckner11582c52016-06-17 20:38:01 +0000226 else if (Ipi && StreamIdx == Ipi->getTypeHashStreamIndex())
Zachary Turnerd3117392016-06-03 19:28:33 +0000227 Value = "IPI Hash";
Reid Kleckner11582c52016-06-17 20:38:01 +0000228 else if (Ipi && StreamIdx == Ipi->getTypeHashStreamAuxIndex())
Zachary Turnerd3117392016-06-03 19:28:33 +0000229 Value = "IPI Aux Hash";
Reid Kleckner11582c52016-06-17 20:38:01 +0000230 else if (Dbi &&
231 StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Exception))
Zachary Turnerd3117392016-06-03 19:28:33 +0000232 Value = "Exception Data";
Reid Kleckner11582c52016-06-17 20:38:01 +0000233 else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Fixup))
Zachary Turnerd3117392016-06-03 19:28:33 +0000234 Value = "Fixup Data";
Reid Kleckner11582c52016-06-17 20:38:01 +0000235 else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::FPO))
Zachary Turnerd3117392016-06-03 19:28:33 +0000236 Value = "FPO Data";
Reid Kleckner11582c52016-06-17 20:38:01 +0000237 else if (Dbi &&
238 StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::NewFPO))
Zachary Turnerd3117392016-06-03 19:28:33 +0000239 Value = "New FPO Data";
Reid Kleckner11582c52016-06-17 20:38:01 +0000240 else if (Dbi &&
241 StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::OmapFromSrc))
Zachary Turnerd3117392016-06-03 19:28:33 +0000242 Value = "Omap From Source Data";
Reid Kleckner11582c52016-06-17 20:38:01 +0000243 else if (Dbi &&
244 StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::OmapToSrc))
Zachary Turnerd3117392016-06-03 19:28:33 +0000245 Value = "Omap To Source Data";
Reid Kleckner11582c52016-06-17 20:38:01 +0000246 else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Pdata))
Zachary Turnerd3117392016-06-03 19:28:33 +0000247 Value = "Pdata";
Reid Kleckner11582c52016-06-17 20:38:01 +0000248 else if (Dbi &&
249 StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::SectionHdr))
Zachary Turnerd3117392016-06-03 19:28:33 +0000250 Value = "Section Header Data";
Reid Kleckner11582c52016-06-17 20:38:01 +0000251 else if (Dbi &&
252 StreamIdx ==
253 Dbi->getDebugStreamIndex(DbgHeaderType::SectionHdrOrig))
Zachary Turnerd3117392016-06-03 19:28:33 +0000254 Value = "Section Header Original Data";
Reid Kleckner11582c52016-06-17 20:38:01 +0000255 else if (Dbi &&
256 StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::TokenRidMap))
Zachary Turnerd3117392016-06-03 19:28:33 +0000257 Value = "Token Rid Data";
Reid Kleckner11582c52016-06-17 20:38:01 +0000258 else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Xdata))
Zachary Turnerd3117392016-06-03 19:28:33 +0000259 Value = "Xdata";
260 else {
261 auto ModIter = ModStreams.find(StreamIdx);
262 auto NSIter = NamedStreams.find(StreamIdx);
263 if (ModIter != ModStreams.end()) {
264 Value = "Module \"";
265 Value += ModIter->second->Info.getModuleName().str();
266 Value += "\"";
267 } else if (NSIter != NamedStreams.end()) {
268 Value = "Named Stream \"";
269 Value += NSIter->second;
270 Value += "\"";
271 } else {
272 Value = "???";
273 }
274 }
Zachary Turner36efbfa2016-09-09 19:00:49 +0000275 StreamPurposes[StreamIdx] = Value;
Zachary Turnerd3117392016-06-03 19:28:33 +0000276 }
Reid Kleckner11582c52016-06-17 20:38:01 +0000277
278 // Consume errors from missing streams.
279 if (!Dbi)
280 consumeError(Dbi.takeError());
281 if (!Tpi)
282 consumeError(Tpi.takeError());
283 if (!Ipi)
284 consumeError(Ipi.takeError());
285 if (!Info)
286 consumeError(Info.takeError());
Zachary Turner36efbfa2016-09-09 19:00:49 +0000287}
288
289Error LLVMOutputStyle::dumpStreamSummary() {
290 if (!opts::raw::DumpStreamSummary)
291 return Error::success();
292
293 discoverStreamPurposes();
294
295 uint32_t StreamCount = File.getNumStreams();
296
297 ListScope L(P, "Streams");
298 for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
299 std::string Label("Stream ");
300 Label += to_string(StreamIdx);
301
302 std::string Value = "[" + StreamPurposes[StreamIdx] + "] (";
303 Value += to_string(File.getStreamByteSize(StreamIdx));
304 Value += " bytes)";
305
306 P.printString(Label, Value);
307 }
Reid Kleckner11582c52016-06-17 20:38:01 +0000308
Zachary Turnerd3117392016-06-03 19:28:33 +0000309 P.flush();
310 return Error::success();
311}
312
Rui Ueyama7a5cdc62016-07-29 21:38:00 +0000313Error LLVMOutputStyle::dumpFreePageMap() {
Zachary Turnerd3c7b8e2016-08-01 21:19:45 +0000314 if (!opts::raw::DumpPageStats)
Rui Ueyama7a5cdc62016-07-29 21:38:00 +0000315 return Error::success();
Rui Ueyama7a5cdc62016-07-29 21:38:00 +0000316
Zachary Turnerd3c7b8e2016-08-01 21:19:45 +0000317 // Start with used pages instead of free pages because
Rui Ueyama7a5cdc62016-07-29 21:38:00 +0000318 // the number of free pages is far larger than used pages.
Zachary Turnerd3c7b8e2016-08-01 21:19:45 +0000319 BitVector FPM = File.getMsfLayout().FreePageMap;
320
321 PageStats PS(FPM);
322
323 recordKnownUsedPage(PS, 0); // MSF Super Block
324
Zachary Turner8cf51c32016-08-03 16:53:21 +0000325 uint32_t BlocksPerSection = msf::getFpmIntervalLength(File.getMsfLayout());
326 uint32_t NumSections = msf::getNumFpmIntervals(File.getMsfLayout());
Zachary Turnerd3c7b8e2016-08-01 21:19:45 +0000327 for (uint32_t I = 0; I < NumSections; ++I) {
328 uint32_t Fpm0 = 1 + BlocksPerSection * I;
329 // 2 Fpm blocks spaced at `getBlockSize()` block intervals
330 recordKnownUsedPage(PS, Fpm0);
331 recordKnownUsedPage(PS, Fpm0 + 1);
332 }
333
334 recordKnownUsedPage(PS, File.getBlockMapIndex()); // Stream Table
335
Rui Ueyama22e67382016-08-02 23:22:46 +0000336 for (auto DB : File.getDirectoryBlockArray())
Zachary Turnerd3c7b8e2016-08-01 21:19:45 +0000337 recordKnownUsedPage(PS, DB);
Rui Ueyama22e67382016-08-02 23:22:46 +0000338
339 // Record pages used by streams. Note that pages for stream 0
340 // are considered being unused because that's what MSVC tools do.
341 // Stream 0 doesn't contain actual data, so it makes some sense,
342 // though it's a bit confusing to us.
343 for (auto &SE : File.getStreamMap().drop_front(1))
344 for (auto &S : SE)
Zachary Turnerd3c7b8e2016-08-01 21:19:45 +0000345 recordKnownUsedPage(PS, S);
Zachary Turnerd3c7b8e2016-08-01 21:19:45 +0000346
347 dumpBitVector("Msf Free Pages", FPM);
348 dumpBitVector("Orphaned Pages", PS.OrphanedPages);
349 dumpBitVector("Multiply Used Pages", PS.MultiUsePages);
350 dumpBitVector("Use After Free Pages", PS.UseAfterFreePages);
Rui Ueyama7a5cdc62016-07-29 21:38:00 +0000351 return Error::success();
352}
353
Zachary Turnerd3c7b8e2016-08-01 21:19:45 +0000354void LLVMOutputStyle::dumpBitVector(StringRef Name, const BitVector &V) {
355 std::vector<uint32_t> Vec;
356 for (uint32_t I = 0, E = V.size(); I != E; ++I)
357 if (V[I])
358 Vec.push_back(I);
359 P.printList(Name, Vec);
360}
361
Bob Haarman653baa22016-10-21 19:43:19 +0000362Error LLVMOutputStyle::dumpGlobalsStream() {
363 if (!opts::raw::DumpGlobals)
364 return Error::success();
Bob Haarmana5b43582016-12-05 22:44:00 +0000365 if (!File.hasPDBGlobalsStream()) {
366 P.printString("Globals Stream not present");
367 return Error::success();
368 }
Bob Haarman653baa22016-10-21 19:43:19 +0000369
Bob Haarman653baa22016-10-21 19:43:19 +0000370 auto Globals = File.getPDBGlobalsStream();
371 if (!Globals)
Bob Haarman312fd0e2016-12-06 00:55:55 +0000372 return Globals.takeError();
Bob Haarmana5b43582016-12-05 22:44:00 +0000373 DictScope D(P, "Globals Stream");
Bob Haarman653baa22016-10-21 19:43:19 +0000374
375 auto Dbi = File.getPDBDbiStream();
376 if (!Dbi)
377 return Dbi.takeError();
378
379 P.printNumber("Stream number", Dbi->getGlobalSymbolStreamIndex());
380 P.printNumber("Number of buckets", Globals->getNumBuckets());
381 P.printList("Hash Buckets", Globals->getHashBuckets());
382
383 return Error::success();
384}
385
Zachary Turnerd3117392016-06-03 19:28:33 +0000386Error LLVMOutputStyle::dumpStreamBlocks() {
Zachary Turnera30bd1a2016-06-30 17:42:48 +0000387 if (!opts::raw::DumpStreamBlocks)
Zachary Turnerd3117392016-06-03 19:28:33 +0000388 return Error::success();
389
390 ListScope L(P, "StreamBlocks");
391 uint32_t StreamCount = File.getNumStreams();
392 for (uint32_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
393 std::string Name("Stream ");
394 Name += to_string(StreamIdx);
395 auto StreamBlocks = File.getStreamBlockList(StreamIdx);
396 P.printList(Name, StreamBlocks);
397 }
398 return Error::success();
399}
400
Zachary Turner72c5b642016-09-09 18:17:52 +0000401Error LLVMOutputStyle::dumpBlockRanges() {
402 if (!opts::raw::DumpBlockRange.hasValue())
403 return Error::success();
404 auto &R = *opts::raw::DumpBlockRange;
405 uint32_t Max = R.Max.getValueOr(R.Min);
406
407 if (Max < R.Min)
408 return make_error<StringError>(
409 "Invalid block range specified. Max < Min",
410 std::make_error_code(std::errc::bad_address));
411 if (Max >= File.getBlockCount())
412 return make_error<StringError>(
413 "Invalid block range specified. Requested block out of bounds",
414 std::make_error_code(std::errc::bad_address));
415
416 DictScope D(P, "Block Data");
417 for (uint32_t I = R.Min; I <= Max; ++I) {
418 auto ExpectedData = File.getBlockData(I, File.getBlockSize());
419 if (!ExpectedData)
420 return ExpectedData.takeError();
421 std::string Label;
422 llvm::raw_string_ostream S(Label);
423 S << "Block " << I;
424 S.flush();
425 P.printBinaryBlock(Label, *ExpectedData);
426 }
427
428 return Error::success();
429}
430
431Error LLVMOutputStyle::dumpStreamBytes() {
432 if (opts::raw::DumpStreamData.empty())
Zachary Turnerd3117392016-06-03 19:28:33 +0000433 return Error::success();
434
Zachary Turner36efbfa2016-09-09 19:00:49 +0000435 discoverStreamPurposes();
436
Zachary Turner72c5b642016-09-09 18:17:52 +0000437 DictScope D(P, "Stream Data");
438 for (uint32_t SI : opts::raw::DumpStreamData) {
439 if (SI >= File.getNumStreams())
440 return make_error<RawError>(raw_error_code::no_stream);
Zachary Turnerd2b2bfe2016-06-08 00:25:08 +0000441
Zachary Turner72c5b642016-09-09 18:17:52 +0000442 auto S = MappedBlockStream::createIndexedStream(File.getMsfLayout(),
443 File.getMsfBuffer(), SI);
444 if (!S)
445 continue;
Zachary Turner36efbfa2016-09-09 19:00:49 +0000446 DictScope DD(P, "Stream");
447
448 P.printNumber("Index", SI);
449 P.printString("Type", StreamPurposes[SI]);
450 P.printNumber("Size", S->getLength());
451 auto Blocks = File.getMsfLayout().StreamMap[SI];
452 P.printList("Blocks", Blocks);
453
Zachary Turneraf299ea2017-02-25 00:44:30 +0000454 BinaryStreamReader R(*S);
Zachary Turner72c5b642016-09-09 18:17:52 +0000455 ArrayRef<uint8_t> StreamData;
456 if (auto EC = R.readBytes(StreamData, S->getLength()))
Zachary Turnerd3117392016-06-03 19:28:33 +0000457 return EC;
Zachary Turner36efbfa2016-09-09 19:00:49 +0000458 P.printBinaryBlock("Data", StreamData);
Zachary Turnerd3117392016-06-03 19:28:33 +0000459 }
460 return Error::success();
461}
462
Zachary Turner760ad4d2017-01-20 22:42:09 +0000463Error LLVMOutputStyle::dumpStringTable() {
464 if (!opts::raw::DumpStringTable)
465 return Error::success();
466
467 auto IS = File.getStringTable();
468 if (!IS)
469 return IS.takeError();
470
471 DictScope D(P, "String Table");
472 for (uint32_t I : IS->name_ids()) {
473 StringRef S = IS->getStringForID(I);
474 if (!S.empty()) {
475 llvm::SmallString<32> Str;
476 Str.append("'");
477 Str.append(S);
478 Str.append("'");
479 P.printString(Str);
480 }
481 }
482 return Error::success();
483}
484
Zachary Turnerd3117392016-06-03 19:28:33 +0000485Error LLVMOutputStyle::dumpInfoStream() {
Zachary Turnera30bd1a2016-06-30 17:42:48 +0000486 if (!opts::raw::DumpHeaders)
Zachary Turnerd3117392016-06-03 19:28:33 +0000487 return Error::success();
Bob Haarmana5b43582016-12-05 22:44:00 +0000488 if (!File.hasPDBInfoStream()) {
489 P.printString("PDB Stream not present");
490 return Error::success();
491 }
Zachary Turnera1657a92016-06-08 17:26:39 +0000492 auto IS = File.getPDBInfoStream();
493 if (!IS)
494 return IS.takeError();
Zachary Turnerd3117392016-06-03 19:28:33 +0000495
496 DictScope D(P, "PDB Stream");
Zachary Turnera1657a92016-06-08 17:26:39 +0000497 P.printNumber("Version", IS->getVersion());
498 P.printHex("Signature", IS->getSignature());
499 P.printNumber("Age", IS->getAge());
500 P.printObject("Guid", IS->getGuid());
Zachary Turner760ad4d2017-01-20 22:42:09 +0000501 {
502 DictScope DD(P, "Named Streams");
503 for (const auto &S : IS->getNamedStreams().entries())
504 P.printObject(S.getKey(), S.getValue());
505 }
Zachary Turnerd3117392016-06-03 19:28:33 +0000506 return Error::success();
507}
508
Zachary Turner29da5db2017-01-25 21:17:40 +0000509namespace {
510class RecordBytesVisitor : public TypeVisitorCallbacks {
511public:
512 explicit RecordBytesVisitor(ScopedPrinter &P) : P(P) {}
513
514 Error visitTypeEnd(CVType &Record) override {
515 P.printBinaryBlock("Bytes", Record.content());
516 return Error::success();
517 }
518
519private:
520 ScopedPrinter &P;
521};
Rui Ueyamafd97bf12016-06-03 20:48:51 +0000522}
523
Zachary Turnerd3117392016-06-03 19:28:33 +0000524Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
525 assert(StreamIdx == StreamTPI || StreamIdx == StreamIPI);
526
527 bool DumpRecordBytes = false;
528 bool DumpRecords = false;
Zachary Turner29da5db2017-01-25 21:17:40 +0000529 bool DumpTpiHash = false;
Zachary Turnerd3117392016-06-03 19:28:33 +0000530 StringRef Label;
531 StringRef VerLabel;
532 if (StreamIdx == StreamTPI) {
Bob Haarmana5b43582016-12-05 22:44:00 +0000533 if (!File.hasPDBTpiStream()) {
534 P.printString("Type Info Stream (TPI) not present");
535 return Error::success();
536 }
Zachary Turnera30bd1a2016-06-30 17:42:48 +0000537 DumpRecordBytes = opts::raw::DumpTpiRecordBytes;
538 DumpRecords = opts::raw::DumpTpiRecords;
Zachary Turner29da5db2017-01-25 21:17:40 +0000539 DumpTpiHash = opts::raw::DumpTpiHash;
Zachary Turnerd3117392016-06-03 19:28:33 +0000540 Label = "Type Info Stream (TPI)";
541 VerLabel = "TPI Version";
542 } else if (StreamIdx == StreamIPI) {
Bob Haarmana5b43582016-12-05 22:44:00 +0000543 if (!File.hasPDBIpiStream()) {
544 P.printString("Type Info Stream (IPI) not present");
545 return Error::success();
546 }
Zachary Turnera30bd1a2016-06-30 17:42:48 +0000547 DumpRecordBytes = opts::raw::DumpIpiRecordBytes;
548 DumpRecords = opts::raw::DumpIpiRecords;
Zachary Turnerd3117392016-06-03 19:28:33 +0000549 Label = "Type Info Stream (IPI)";
550 VerLabel = "IPI Version";
551 }
Zachary Turner29da5db2017-01-25 21:17:40 +0000552 if (!DumpRecordBytes && !DumpRecords && !DumpTpiHash &&
553 !opts::raw::DumpModuleSyms)
Zachary Turnerd3117392016-06-03 19:28:33 +0000554 return Error::success();
555
Zachary Turner29da5db2017-01-25 21:17:40 +0000556 bool IsSilentDatabaseBuild = !DumpRecordBytes && !DumpRecords && !DumpTpiHash;
557
Zachary Turnera1657a92016-06-08 17:26:39 +0000558 auto Tpi = (StreamIdx == StreamTPI) ? File.getPDBTpiStream()
559 : File.getPDBIpiStream();
560 if (!Tpi)
561 return Tpi.takeError();
Zachary Turnerd3117392016-06-03 19:28:33 +0000562
Zachary Turner29da5db2017-01-25 21:17:40 +0000563 std::unique_ptr<DictScope> StreamScope;
564 std::unique_ptr<ListScope> RecordScope;
565
566 if (!IsSilentDatabaseBuild) {
567 StreamScope = llvm::make_unique<DictScope>(P, Label);
568 P.printNumber(VerLabel, Tpi->getTpiVersion());
569 P.printNumber("Record count", Tpi->NumTypeRecords());
570 }
571
Zachary Turner44a643c2017-01-12 22:28:15 +0000572 TypeDatabaseVisitor DBV(TypeDB);
573 CompactTypeDumpVisitor CTDV(TypeDB, &P);
574 TypeDumpVisitor TDV(TypeDB, &P, false);
Zachary Turner29da5db2017-01-25 21:17:40 +0000575 RecordBytesVisitor RBV(P);
Zachary Turner44a643c2017-01-12 22:28:15 +0000576 TypeDeserializer Deserializer;
Zachary Turner29da5db2017-01-25 21:17:40 +0000577
578 // We always need to deserialize and add it to the type database. This is
579 // true if even if we're not dumping anything, because we could need the
580 // type database for the purposes of dumping symbols.
Zachary Turner44a643c2017-01-12 22:28:15 +0000581 TypeVisitorCallbackPipeline Pipeline;
582 Pipeline.addCallbackToPipeline(Deserializer);
583 Pipeline.addCallbackToPipeline(DBV);
584
Zachary Turner29da5db2017-01-25 21:17:40 +0000585 // If we're in dump mode, add a dumper with the appropriate detail level.
586 if (DumpRecords) {
Zachary Turner44a643c2017-01-12 22:28:15 +0000587 if (opts::raw::CompactRecords)
588 Pipeline.addCallbackToPipeline(CTDV);
589 else
590 Pipeline.addCallbackToPipeline(TDV);
Zachary Turnerd3117392016-06-03 19:28:33 +0000591 }
Zachary Turner29da5db2017-01-25 21:17:40 +0000592 if (DumpRecordBytes)
593 Pipeline.addCallbackToPipeline(RBV);
594
595 CVTypeVisitor Visitor(Pipeline);
596
597 if (DumpRecords || DumpRecordBytes)
598 RecordScope = llvm::make_unique<ListScope>(P, "Records");
599
600 bool HadError = false;
601
602 TypeIndex T(TypeIndex::FirstNonSimpleIndex);
603 for (auto Type : Tpi->types(&HadError)) {
604 std::unique_ptr<DictScope> OneRecordScope;
605
606 if ((DumpRecords || DumpRecordBytes) && !opts::raw::CompactRecords)
607 OneRecordScope = llvm::make_unique<DictScope>(P, "");
608
609 if (auto EC = Visitor.visitTypeRecord(Type))
610 return EC;
611 }
612 if (HadError)
613 return make_error<RawError>(raw_error_code::corrupt_file,
614 "TPI stream contained corrupt record");
615
616 if (DumpTpiHash) {
617 DictScope DD(P, "Hash");
618 P.printNumber("Number of Hash Buckets", Tpi->NumHashBuckets());
619 P.printNumber("Hash Key Size", Tpi->getHashKeySize());
620 P.printList("Values", Tpi->getHashValues());
621
622 ListScope LHA(P, "Adjusters");
623 auto ExpectedST = File.getStringTable();
624 if (!ExpectedST)
625 return ExpectedST.takeError();
626 const auto &ST = *ExpectedST;
627 for (const auto &E : Tpi->getHashAdjusters()) {
628 DictScope DHA(P);
629 StringRef Name = ST.getStringForID(E.first);
630 P.printString("Type", Name);
631 P.printHex("TI", E.second);
632 }
633 }
634
635 if (!IsSilentDatabaseBuild) {
636 ListScope L(P, "TypeIndexOffsets");
637 for (const auto &IO : Tpi->getTypeIndexOffsets()) {
638 P.printString(formatv("Index: {0:x}, Offset: {1:N}", IO.Type.getIndex(),
639 (uint32_t)IO.Offset)
640 .str());
641 }
642 }
643
Zachary Turnerd3117392016-06-03 19:28:33 +0000644 P.flush();
645 return Error::success();
646}
647
648Error LLVMOutputStyle::dumpDbiStream() {
Zachary Turnera30bd1a2016-06-30 17:42:48 +0000649 bool DumpModules = opts::raw::DumpModules || opts::raw::DumpModuleSyms ||
650 opts::raw::DumpModuleFiles || opts::raw::DumpLineInfo;
651 if (!opts::raw::DumpHeaders && !DumpModules)
Zachary Turnerd3117392016-06-03 19:28:33 +0000652 return Error::success();
Bob Haarmana5b43582016-12-05 22:44:00 +0000653 if (!File.hasPDBDbiStream()) {
654 P.printString("DBI Stream not present");
655 return Error::success();
656 }
Zachary Turnerd3117392016-06-03 19:28:33 +0000657
Zachary Turnera1657a92016-06-08 17:26:39 +0000658 auto DS = File.getPDBDbiStream();
659 if (!DS)
660 return DS.takeError();
Zachary Turnerd3117392016-06-03 19:28:33 +0000661
662 DictScope D(P, "DBI Stream");
Zachary Turnera1657a92016-06-08 17:26:39 +0000663 P.printNumber("Dbi Version", DS->getDbiVersion());
664 P.printNumber("Age", DS->getAge());
665 P.printBoolean("Incremental Linking", DS->isIncrementallyLinked());
666 P.printBoolean("Has CTypes", DS->hasCTypes());
667 P.printBoolean("Is Stripped", DS->isStripped());
668 P.printObject("Machine Type", DS->getMachineType());
669 P.printNumber("Symbol Record Stream Index", DS->getSymRecordStreamIndex());
670 P.printNumber("Public Symbol Stream Index", DS->getPublicSymbolStreamIndex());
671 P.printNumber("Global Symbol Stream Index", DS->getGlobalSymbolStreamIndex());
Zachary Turnerd3117392016-06-03 19:28:33 +0000672
Zachary Turnera1657a92016-06-08 17:26:39 +0000673 uint16_t Major = DS->getBuildMajorVersion();
674 uint16_t Minor = DS->getBuildMinorVersion();
Zachary Turnerd3117392016-06-03 19:28:33 +0000675 P.printVersion("Toolchain Version", Major, Minor);
676
677 std::string DllName;
678 raw_string_ostream DllStream(DllName);
679 DllStream << "mspdb" << Major << Minor << ".dll version";
680 DllStream.flush();
Zachary Turnera1657a92016-06-08 17:26:39 +0000681 P.printVersion(DllName, Major, Minor, DS->getPdbDllVersion());
Zachary Turnerd3117392016-06-03 19:28:33 +0000682
683 if (DumpModules) {
684 ListScope L(P, "Modules");
Zachary Turnera1657a92016-06-08 17:26:39 +0000685 for (auto &Modi : DS->modules()) {
Zachary Turnerd3117392016-06-03 19:28:33 +0000686 DictScope DD(P);
687 P.printString("Name", Modi.Info.getModuleName().str());
688 P.printNumber("Debug Stream Index", Modi.Info.getModuleStreamIndex());
689 P.printString("Object File Name", Modi.Info.getObjFileName().str());
690 P.printNumber("Num Files", Modi.Info.getNumberOfFiles());
691 P.printNumber("Source File Name Idx", Modi.Info.getSourceFileNameIndex());
692 P.printNumber("Pdb File Name Idx", Modi.Info.getPdbFilePathNameIndex());
693 P.printNumber("Line Info Byte Size", Modi.Info.getLineInfoByteSize());
694 P.printNumber("C13 Line Info Byte Size",
695 Modi.Info.getC13LineInfoByteSize());
696 P.printNumber("Symbol Byte Size", Modi.Info.getSymbolDebugInfoByteSize());
697 P.printNumber("Type Server Index", Modi.Info.getTypeServerIndex());
698 P.printBoolean("Has EC Info", Modi.Info.hasECInfo());
Zachary Turnera30bd1a2016-06-30 17:42:48 +0000699 if (opts::raw::DumpModuleFiles) {
Zachary Turnerd3117392016-06-03 19:28:33 +0000700 std::string FileListName =
701 to_string(Modi.SourceFiles.size()) + " Contributing Source Files";
702 ListScope LL(P, FileListName);
703 for (auto File : Modi.SourceFiles)
704 P.printString(File.str());
705 }
706 bool HasModuleDI =
707 (Modi.Info.getModuleStreamIndex() < File.getNumStreams());
708 bool ShouldDumpSymbols =
Zachary Turnera30bd1a2016-06-30 17:42:48 +0000709 (opts::raw::DumpModuleSyms || opts::raw::DumpSymRecordBytes);
710 if (HasModuleDI && (ShouldDumpSymbols || opts::raw::DumpLineInfo)) {
Zachary Turnera1657a92016-06-08 17:26:39 +0000711 auto ModStreamData = MappedBlockStream::createIndexedStream(
Zachary Turnerd66889c2016-07-28 19:12:28 +0000712 File.getMsfLayout(), File.getMsfBuffer(),
713 Modi.Info.getModuleStreamIndex());
714
715 ModStream ModS(Modi.Info, std::move(ModStreamData));
Zachary Turnerd3117392016-06-03 19:28:33 +0000716 if (auto EC = ModS.reload())
717 return EC;
718
719 if (ShouldDumpSymbols) {
720 ListScope SS(P, "Symbols");
Zachary Turner629cb7d2017-01-11 23:24:22 +0000721 codeview::CVSymbolDumper SD(P, TypeDB, nullptr, false);
Zachary Turnerd3117392016-06-03 19:28:33 +0000722 bool HadError = false;
Zachary Turner0d840742016-10-07 21:34:46 +0000723 for (auto S : ModS.symbols(&HadError)) {
724 DictScope LL(P, "");
725 if (opts::raw::DumpModuleSyms) {
726 if (auto EC = SD.dump(S)) {
727 llvm::consumeError(std::move(EC));
728 HadError = true;
729 break;
730 }
731 }
Zachary Turnera30bd1a2016-06-30 17:42:48 +0000732 if (opts::raw::DumpSymRecordBytes)
Zachary Turnerc67b00c2016-09-14 23:00:16 +0000733 P.printBinaryBlock("Bytes", S.content());
Zachary Turnerd3117392016-06-03 19:28:33 +0000734 }
735 if (HadError)
736 return make_error<RawError>(
737 raw_error_code::corrupt_file,
738 "DBI stream contained corrupt symbol record");
739 }
Zachary Turnera30bd1a2016-06-30 17:42:48 +0000740 if (opts::raw::DumpLineInfo) {
Zachary Turnerd3117392016-06-03 19:28:33 +0000741 ListScope SS(P, "LineInfo");
742 bool HadError = false;
743 // Define a locally scoped visitor to print the different
744 // substream types types.
745 class RecordVisitor : public codeview::IModuleSubstreamVisitor {
746 public:
747 RecordVisitor(ScopedPrinter &P, PDBFile &F) : P(P), F(F) {}
748 Error visitUnknown(ModuleSubstreamKind Kind,
Zachary Turneraf299ea2017-02-25 00:44:30 +0000749 BinaryStreamRef Stream) override {
Zachary Turnerd3117392016-06-03 19:28:33 +0000750 DictScope DD(P, "Unknown");
751 ArrayRef<uint8_t> Data;
Zachary Turneraf299ea2017-02-25 00:44:30 +0000752 BinaryStreamReader R(Stream);
Zachary Turnerd3117392016-06-03 19:28:33 +0000753 if (auto EC = R.readBytes(Data, R.bytesRemaining())) {
754 return make_error<RawError>(
755 raw_error_code::corrupt_file,
756 "DBI stream contained corrupt line info record");
757 }
758 P.printBinaryBlock("Data", Data);
759 return Error::success();
760 }
761 Error
Zachary Turneraf299ea2017-02-25 00:44:30 +0000762 visitFileChecksums(BinaryStreamRef Data,
Zachary Turnerd3117392016-06-03 19:28:33 +0000763 const FileChecksumArray &Checksums) override {
764 DictScope DD(P, "FileChecksums");
765 for (const auto &C : Checksums) {
766 DictScope DDD(P, "Checksum");
767 if (auto Result = getFileNameForOffset(C.FileNameOffset))
768 P.printString("FileName", Result.get());
769 else
770 return Result.takeError();
771 P.flush();
772 P.printEnum("Kind", uint8_t(C.Kind), getFileChecksumNames());
773 P.printBinaryBlock("Checksum", C.Checksum);
774 }
775 return Error::success();
776 }
777
Zachary Turneraf299ea2017-02-25 00:44:30 +0000778 Error visitLines(BinaryStreamRef Data,
Zachary Turnerd66889c2016-07-28 19:12:28 +0000779 const LineSubstreamHeader *Header,
Zachary Turnerd3117392016-06-03 19:28:33 +0000780 const LineInfoArray &Lines) override {
781 DictScope DD(P, "Lines");
782 for (const auto &L : Lines) {
783 if (auto Result = getFileNameForOffset2(L.NameIndex))
784 P.printString("FileName", Result.get());
785 else
786 return Result.takeError();
787 P.flush();
788 for (const auto &N : L.LineNumbers) {
789 DictScope DDD(P, "Line");
790 LineInfo LI(N.Flags);
791 P.printNumber("Offset", N.Offset);
792 if (LI.isAlwaysStepInto())
793 P.printString("StepInto", StringRef("Always"));
794 else if (LI.isNeverStepInto())
795 P.printString("StepInto", StringRef("Never"));
796 else
797 P.printNumber("LineNumberStart", LI.getStartLine());
798 P.printNumber("EndDelta", LI.getLineDelta());
799 P.printBoolean("IsStatement", LI.isStatement());
800 }
801 for (const auto &C : L.Columns) {
802 DictScope DDD(P, "Column");
803 P.printNumber("Start", C.StartColumn);
804 P.printNumber("End", C.EndColumn);
805 }
806 }
807 return Error::success();
808 }
809
810 private:
811 Expected<StringRef> getFileNameForOffset(uint32_t Offset) {
Zachary Turnera1657a92016-06-08 17:26:39 +0000812 auto ST = F.getStringTable();
813 if (!ST)
814 return ST.takeError();
815
816 return ST->getStringForID(Offset);
Zachary Turnerd3117392016-06-03 19:28:33 +0000817 }
818 Expected<StringRef> getFileNameForOffset2(uint32_t Offset) {
Zachary Turnera1657a92016-06-08 17:26:39 +0000819 auto DS = F.getPDBDbiStream();
820 if (!DS)
821 return DS.takeError();
822 return DS->getFileNameForIndex(Offset);
Zachary Turnerd3117392016-06-03 19:28:33 +0000823 }
824 ScopedPrinter &P;
825 PDBFile &F;
826 };
827
828 RecordVisitor V(P, File);
829 for (const auto &L : ModS.lines(&HadError)) {
830 if (auto EC = codeview::visitModuleSubstream(L, V))
831 return EC;
832 }
833 }
834 }
835 }
836 }
837 return Error::success();
838}
839
840Error LLVMOutputStyle::dumpSectionContribs() {
Zachary Turnera30bd1a2016-06-30 17:42:48 +0000841 if (!opts::raw::DumpSectionContribs)
Zachary Turnerd3117392016-06-03 19:28:33 +0000842 return Error::success();
Bob Haarmana5b43582016-12-05 22:44:00 +0000843 if (!File.hasPDBDbiStream()) {
844 P.printString("DBI Stream not present");
845 return Error::success();
846 }
Zachary Turnerd3117392016-06-03 19:28:33 +0000847
Zachary Turnera1657a92016-06-08 17:26:39 +0000848 auto Dbi = File.getPDBDbiStream();
849 if (!Dbi)
850 return Dbi.takeError();
851
Zachary Turnerd3117392016-06-03 19:28:33 +0000852 ListScope L(P, "Section Contributions");
853 class Visitor : public ISectionContribVisitor {
854 public:
855 Visitor(ScopedPrinter &P, DbiStream &DS) : P(P), DS(DS) {}
856 void visit(const SectionContrib &SC) override {
857 DictScope D(P, "Contribution");
858 P.printNumber("ISect", SC.ISect);
859 P.printNumber("Off", SC.Off);
860 P.printNumber("Size", SC.Size);
861 P.printFlags("Characteristics", SC.Characteristics,
862 codeview::getImageSectionCharacteristicNames(),
863 COFF::SectionCharacteristics(0x00F00000));
864 {
865 DictScope DD(P, "Module");
866 P.printNumber("Index", SC.Imod);
867 auto M = DS.modules();
868 if (M.size() > SC.Imod) {
869 P.printString("Name", M[SC.Imod].Info.getModuleName());
870 }
871 }
872 P.printNumber("Data CRC", SC.DataCrc);
873 P.printNumber("Reloc CRC", SC.RelocCrc);
874 P.flush();
875 }
876 void visit(const SectionContrib2 &SC) override {
877 visit(SC.Base);
878 P.printNumber("ISect Coff", SC.ISectCoff);
879 P.flush();
880 }
881
882 private:
883 ScopedPrinter &P;
884 DbiStream &DS;
885 };
Zachary Turnera1657a92016-06-08 17:26:39 +0000886 Visitor V(P, *Dbi);
887 Dbi->visitSectionContributions(V);
Zachary Turnerd3117392016-06-03 19:28:33 +0000888 return Error::success();
889}
890
891Error LLVMOutputStyle::dumpSectionMap() {
Zachary Turnera30bd1a2016-06-30 17:42:48 +0000892 if (!opts::raw::DumpSectionMap)
Zachary Turnerd3117392016-06-03 19:28:33 +0000893 return Error::success();
Bob Haarmana5b43582016-12-05 22:44:00 +0000894 if (!File.hasPDBDbiStream()) {
895 P.printString("DBI Stream not present");
896 return Error::success();
897 }
Zachary Turnerd3117392016-06-03 19:28:33 +0000898
Zachary Turnera1657a92016-06-08 17:26:39 +0000899 auto Dbi = File.getPDBDbiStream();
900 if (!Dbi)
901 return Dbi.takeError();
902
Zachary Turnerd3117392016-06-03 19:28:33 +0000903 ListScope L(P, "Section Map");
Zachary Turnera1657a92016-06-08 17:26:39 +0000904 for (auto &M : Dbi->getSectionMap()) {
Zachary Turnerd3117392016-06-03 19:28:33 +0000905 DictScope D(P, "Entry");
906 P.printFlags("Flags", M.Flags, getOMFSegMapDescFlagNames());
Zachary Turnerd3117392016-06-03 19:28:33 +0000907 P.printNumber("Ovl", M.Ovl);
908 P.printNumber("Group", M.Group);
909 P.printNumber("Frame", M.Frame);
910 P.printNumber("SecName", M.SecName);
911 P.printNumber("ClassName", M.ClassName);
912 P.printNumber("Offset", M.Offset);
913 P.printNumber("SecByteLength", M.SecByteLength);
914 P.flush();
915 }
916 return Error::success();
917}
918
919Error LLVMOutputStyle::dumpPublicsStream() {
Zachary Turnera30bd1a2016-06-30 17:42:48 +0000920 if (!opts::raw::DumpPublics)
Zachary Turnerd3117392016-06-03 19:28:33 +0000921 return Error::success();
Bob Haarmana5b43582016-12-05 22:44:00 +0000922 if (!File.hasPDBPublicsStream()) {
923 P.printString("Publics Stream not present");
924 return Error::success();
925 }
Zachary Turnerd3117392016-06-03 19:28:33 +0000926
Zachary Turnera1657a92016-06-08 17:26:39 +0000927 auto Publics = File.getPDBPublicsStream();
928 if (!Publics)
929 return Publics.takeError();
Bob Haarmana5b43582016-12-05 22:44:00 +0000930 DictScope D(P, "Publics Stream");
Zachary Turnera1657a92016-06-08 17:26:39 +0000931
932 auto Dbi = File.getPDBDbiStream();
933 if (!Dbi)
934 return Dbi.takeError();
935
936 P.printNumber("Stream number", Dbi->getPublicSymbolStreamIndex());
937 P.printNumber("SymHash", Publics->getSymHash());
938 P.printNumber("AddrMap", Publics->getAddrMap());
939 P.printNumber("Number of buckets", Publics->getNumBuckets());
940 P.printList("Hash Buckets", Publics->getHashBuckets());
941 P.printList("Address Map", Publics->getAddressMap());
942 P.printList("Thunk Map", Publics->getThunkMap());
943 P.printList("Section Offsets", Publics->getSectionOffsets(),
Zachary Turnerd3117392016-06-03 19:28:33 +0000944 printSectionOffset);
945 ListScope L(P, "Symbols");
Zachary Turner629cb7d2017-01-11 23:24:22 +0000946 codeview::CVSymbolDumper SD(P, TypeDB, nullptr, false);
Zachary Turnerd3117392016-06-03 19:28:33 +0000947 bool HadError = false;
Zachary Turnera1657a92016-06-08 17:26:39 +0000948 for (auto S : Publics->getSymbols(&HadError)) {
Zachary Turnerd3117392016-06-03 19:28:33 +0000949 DictScope DD(P, "");
950
Zachary Turner0d840742016-10-07 21:34:46 +0000951 if (auto EC = SD.dump(S)) {
952 HadError = true;
953 break;
954 }
Zachary Turnera30bd1a2016-06-30 17:42:48 +0000955 if (opts::raw::DumpSymRecordBytes)
Zachary Turnerc67b00c2016-09-14 23:00:16 +0000956 P.printBinaryBlock("Bytes", S.content());
Zachary Turnerd3117392016-06-03 19:28:33 +0000957 }
958 if (HadError)
959 return make_error<RawError>(
960 raw_error_code::corrupt_file,
961 "Public symbol stream contained corrupt record");
962
963 return Error::success();
964}
965
966Error LLVMOutputStyle::dumpSectionHeaders() {
Zachary Turnera30bd1a2016-06-30 17:42:48 +0000967 if (!opts::raw::DumpSectionHeaders)
Zachary Turnerd3117392016-06-03 19:28:33 +0000968 return Error::success();
Bob Haarmana5b43582016-12-05 22:44:00 +0000969 if (!File.hasPDBDbiStream()) {
970 P.printString("DBI Stream not present");
971 return Error::success();
972 }
Zachary Turnerd3117392016-06-03 19:28:33 +0000973
Zachary Turnera1657a92016-06-08 17:26:39 +0000974 auto Dbi = File.getPDBDbiStream();
975 if (!Dbi)
976 return Dbi.takeError();
Zachary Turnerd3117392016-06-03 19:28:33 +0000977
978 ListScope D(P, "Section Headers");
Zachary Turnera1657a92016-06-08 17:26:39 +0000979 for (const object::coff_section &Section : Dbi->getSectionHeaders()) {
Zachary Turnerd3117392016-06-03 19:28:33 +0000980 DictScope DD(P, "");
981
982 // If a name is 8 characters long, there is no NUL character at end.
983 StringRef Name(Section.Name, strnlen(Section.Name, sizeof(Section.Name)));
984 P.printString("Name", Name);
985 P.printNumber("Virtual Size", Section.VirtualSize);
986 P.printNumber("Virtual Address", Section.VirtualAddress);
987 P.printNumber("Size of Raw Data", Section.SizeOfRawData);
988 P.printNumber("File Pointer to Raw Data", Section.PointerToRawData);
989 P.printNumber("File Pointer to Relocations", Section.PointerToRelocations);
990 P.printNumber("File Pointer to Linenumbers", Section.PointerToLinenumbers);
991 P.printNumber("Number of Relocations", Section.NumberOfRelocations);
992 P.printNumber("Number of Linenumbers", Section.NumberOfLinenumbers);
Rui Ueyama2c5384a2016-06-06 21:34:55 +0000993 P.printFlags("Characteristics", Section.Characteristics,
994 getImageSectionCharacteristicNames());
Zachary Turnerd3117392016-06-03 19:28:33 +0000995 }
996 return Error::success();
997}
Rui Ueyamaef2b4882016-06-06 18:39:21 +0000998
999Error LLVMOutputStyle::dumpFpoStream() {
Zachary Turnera30bd1a2016-06-30 17:42:48 +00001000 if (!opts::raw::DumpFpo)
Rui Ueyamaef2b4882016-06-06 18:39:21 +00001001 return Error::success();
Bob Haarmana5b43582016-12-05 22:44:00 +00001002 if (!File.hasPDBDbiStream()) {
1003 P.printString("DBI Stream not present");
1004 return Error::success();
1005 }
Rui Ueyamaef2b4882016-06-06 18:39:21 +00001006
Zachary Turnera1657a92016-06-08 17:26:39 +00001007 auto Dbi = File.getPDBDbiStream();
1008 if (!Dbi)
1009 return Dbi.takeError();
Rui Ueyamaef2b4882016-06-06 18:39:21 +00001010
1011 ListScope D(P, "New FPO");
Zachary Turnera1657a92016-06-08 17:26:39 +00001012 for (const object::FpoData &Fpo : Dbi->getFpoRecords()) {
Rui Ueyamaef2b4882016-06-06 18:39:21 +00001013 DictScope DD(P, "");
1014 P.printNumber("Offset", Fpo.Offset);
1015 P.printNumber("Size", Fpo.Size);
1016 P.printNumber("Number of locals", Fpo.NumLocals);
1017 P.printNumber("Number of params", Fpo.NumParams);
1018 P.printNumber("Size of Prolog", Fpo.getPrologSize());
1019 P.printNumber("Number of Saved Registers", Fpo.getNumSavedRegs());
1020 P.printBoolean("Has SEH", Fpo.hasSEH());
1021 P.printBoolean("Use BP", Fpo.useBP());
1022 P.printNumber("Frame Pointer", Fpo.getFP());
1023 }
1024 return Error::success();
1025}
Zachary Turnera30bd1a2016-06-30 17:42:48 +00001026
Zachary Turner7120a472016-06-06 20:37:05 +00001027void LLVMOutputStyle::flush() { P.flush(); }