blob: f76635f9e51187379fde1279d2c1ac71f6f2193f [file] [log] [blame]
Zachary Turner7df69952017-06-22 20:57:39 +00001//===- DumpOutputStyle.cpp ------------------------------------ *- C++ --*-===//
Zachary Turner63055452017-06-15 22:24:24 +00002//
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
Zachary Turner7df69952017-06-22 20:57:39 +000010#include "DumpOutputStyle.h"
Zachary Turner63055452017-06-15 22:24:24 +000011
Zachary Turner63055452017-06-15 22:24:24 +000012#include "FormatUtil.h"
13#include "MinimalSymbolDumper.h"
14#include "MinimalTypeDumper.h"
15#include "StreamUtil.h"
16#include "llvm-pdbutil.h"
17
Zachary Turnerf2872b92017-06-15 23:59:56 +000018#include "llvm/ADT/STLExtras.h"
Zachary Turner63055452017-06-15 22:24:24 +000019#include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
20#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
21#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
22#include "llvm/DebugInfo/CodeView/DebugCrossExSubsection.h"
23#include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h"
24#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h"
25#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
26#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
27#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
28#include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h"
29#include "llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h"
30#include "llvm/DebugInfo/CodeView/DebugUnknownSubsection.h"
31#include "llvm/DebugInfo/CodeView/EnumTables.h"
32#include "llvm/DebugInfo/CodeView/Formatters.h"
33#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
34#include "llvm/DebugInfo/CodeView/Line.h"
35#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
36#include "llvm/DebugInfo/CodeView/SymbolDumper.h"
37#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h"
38#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
39#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
40#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
41#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
42#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
43#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
44#include "llvm/DebugInfo/PDB/Native/EnumTables.h"
45#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
46#include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h"
47#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
48#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
49#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
50#include "llvm/DebugInfo/PDB/Native/PublicsStream.h"
51#include "llvm/DebugInfo/PDB/Native/RawError.h"
52#include "llvm/DebugInfo/PDB/Native/TpiHashing.h"
53#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
54#include "llvm/DebugInfo/PDB/PDBExtras.h"
55#include "llvm/Object/COFF.h"
56#include "llvm/Support/BinaryStreamReader.h"
57#include "llvm/Support/FormatAdapters.h"
58#include "llvm/Support/FormatVariadic.h"
59
60#include <unordered_map>
61
62using namespace llvm;
63using namespace llvm::codeview;
64using namespace llvm::msf;
65using namespace llvm::pdb;
66
Zachary Turner7df69952017-06-22 20:57:39 +000067DumpOutputStyle::DumpOutputStyle(PDBFile &File)
Zachary Turner63055452017-06-15 22:24:24 +000068 : File(File), P(2, false, outs()) {}
69
Zachary Turner7df69952017-06-22 20:57:39 +000070Error DumpOutputStyle::dump() {
71 if (opts::dump::DumpSummary) {
Zachary Turner63055452017-06-15 22:24:24 +000072 if (auto EC = dumpFileSummary())
73 return EC;
74 P.NewLine();
75 }
76
Zachary Turner7df69952017-06-22 20:57:39 +000077 if (opts::dump::DumpStreams) {
Zachary Turner63055452017-06-15 22:24:24 +000078 if (auto EC = dumpStreamSummary())
79 return EC;
80 P.NewLine();
81 }
82
Zachary Turner7df69952017-06-22 20:57:39 +000083 if (opts::dump::DumpStringTable) {
Zachary Turner63055452017-06-15 22:24:24 +000084 if (auto EC = dumpStringTable())
85 return EC;
86 P.NewLine();
87 }
88
Zachary Turner7df69952017-06-22 20:57:39 +000089 if (opts::dump::DumpModules) {
Zachary Turner63055452017-06-15 22:24:24 +000090 if (auto EC = dumpModules())
91 return EC;
92 }
93
Zachary Turner7df69952017-06-22 20:57:39 +000094 if (opts::dump::DumpModuleFiles) {
Zachary Turner0e327d02017-06-15 23:12:41 +000095 if (auto EC = dumpModuleFiles())
96 return EC;
97 }
98
Zachary Turner7df69952017-06-22 20:57:39 +000099 if (opts::dump::DumpLines) {
Zachary Turner4e950642017-06-15 23:56:19 +0000100 if (auto EC = dumpLines())
101 return EC;
102 }
103
Zachary Turner7df69952017-06-22 20:57:39 +0000104 if (opts::dump::DumpInlineeLines) {
Zachary Turner4e950642017-06-15 23:56:19 +0000105 if (auto EC = dumpInlineeLines())
106 return EC;
107 }
108
Zachary Turner7df69952017-06-22 20:57:39 +0000109 if (opts::dump::DumpXmi) {
Zachary Turner47d9a562017-06-16 00:04:24 +0000110 if (auto EC = dumpXmi())
111 return EC;
112 }
113
Zachary Turner7df69952017-06-22 20:57:39 +0000114 if (opts::dump::DumpXme) {
Zachary Turner47d9a562017-06-16 00:04:24 +0000115 if (auto EC = dumpXme())
116 return EC;
117 }
118
Zachary Turner7df69952017-06-22 20:57:39 +0000119 if (opts::dump::DumpTypes || opts::dump::DumpTypeExtras) {
Zachary Turner63055452017-06-15 22:24:24 +0000120 if (auto EC = dumpTpiStream(StreamTPI))
121 return EC;
122 }
123
Zachary Turner7df69952017-06-22 20:57:39 +0000124 if (opts::dump::DumpIds || opts::dump::DumpIdExtras) {
Zachary Turner63055452017-06-15 22:24:24 +0000125 if (auto EC = dumpTpiStream(StreamIPI))
126 return EC;
127 }
128
Zachary Turner7df69952017-06-22 20:57:39 +0000129 if (opts::dump::DumpPublics) {
Zachary Turner63055452017-06-15 22:24:24 +0000130 if (auto EC = dumpPublics())
131 return EC;
132 }
133
Zachary Turner7df69952017-06-22 20:57:39 +0000134 if (opts::dump::DumpSymbols) {
Zachary Turner63055452017-06-15 22:24:24 +0000135 if (auto EC = dumpModuleSyms())
136 return EC;
137 }
138
Zachary Turner7df69952017-06-22 20:57:39 +0000139 if (opts::dump::DumpSectionContribs) {
Zachary Turner63055452017-06-15 22:24:24 +0000140 if (auto EC = dumpSectionContribs())
141 return EC;
142 }
143
Zachary Turner7df69952017-06-22 20:57:39 +0000144 if (opts::dump::DumpSectionMap) {
Zachary Turner63055452017-06-15 22:24:24 +0000145 if (auto EC = dumpSectionMap())
146 return EC;
147 }
148
149 return Error::success();
150}
151
152static void printHeader(LinePrinter &P, const Twine &S) {
153 P.NewLine();
154 P.formatLine("{0,=60}", S);
155 P.formatLine("{0}", fmt_repeat('=', 60));
156}
157
Zachary Turner7df69952017-06-22 20:57:39 +0000158Error DumpOutputStyle::dumpFileSummary() {
Zachary Turner63055452017-06-15 22:24:24 +0000159 printHeader(P, "Summary");
160
161 ExitOnError Err("Invalid PDB Format");
162
163 AutoIndent Indent(P);
164 P.formatLine("Block Size: {0}", File.getBlockSize());
165 P.formatLine("Number of blocks: {0}", File.getBlockCount());
166 P.formatLine("Number of streams: {0}", File.getNumStreams());
167
168 auto &PS = Err(File.getPDBInfoStream());
169 P.formatLine("Signature: {0}", PS.getSignature());
170 P.formatLine("Age: {0}", PS.getAge());
171 P.formatLine("GUID: {0}", fmt_guid(PS.getGuid().Guid));
172 P.formatLine("Features: {0:x+}", static_cast<uint32_t>(PS.getFeatures()));
173 P.formatLine("Has Debug Info: {0}", File.hasPDBDbiStream());
174 P.formatLine("Has Types: {0}", File.hasPDBTpiStream());
175 P.formatLine("Has IDs: {0}", File.hasPDBIpiStream());
176 P.formatLine("Has Globals: {0}", File.hasPDBGlobalsStream());
177 P.formatLine("Has Publics: {0}", File.hasPDBPublicsStream());
178 if (File.hasPDBDbiStream()) {
179 auto &DBI = Err(File.getPDBDbiStream());
180 P.formatLine("Is incrementally linked: {0}", DBI.isIncrementallyLinked());
181 P.formatLine("Has conflicting types: {0}", DBI.hasCTypes());
182 P.formatLine("Is stripped: {0}", DBI.isStripped());
183 }
184
185 return Error::success();
186}
187
Zachary Turner7df69952017-06-22 20:57:39 +0000188Error DumpOutputStyle::dumpStreamSummary() {
Zachary Turner63055452017-06-15 22:24:24 +0000189 printHeader(P, "Streams");
190
191 if (StreamPurposes.empty())
192 discoverStreamPurposes(File, StreamPurposes);
193
194 AutoIndent Indent(P);
195 uint32_t StreamCount = File.getNumStreams();
196
197 for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
198 P.formatLine(
199 "Stream {0}: [{1}] ({2} bytes)",
200 fmt_align(StreamIdx, AlignStyle::Right, NumDigits(StreamCount)),
201 StreamPurposes[StreamIdx], File.getStreamByteSize(StreamIdx));
Zachary Turner5f098522017-06-23 20:28:14 +0000202 if (opts::dump::DumpStreamBlocks) {
203 auto Blocks = File.getStreamBlockList(StreamIdx);
204 std::vector<uint32_t> BV(Blocks.begin(), Blocks.end());
205 P.formatLine(" {0} Blocks: [{1}]",
206 fmt_repeat(' ', NumDigits(StreamCount)),
207 make_range(BV.begin(), BV.end()));
208 }
Zachary Turner63055452017-06-15 22:24:24 +0000209 }
210
211 return Error::success();
212}
213
Zachary Turner0e327d02017-06-15 23:12:41 +0000214static Expected<ModuleDebugStreamRef> getModuleDebugStream(PDBFile &File,
215 uint32_t Index) {
216 ExitOnError Err("Unexpected error");
217
218 auto &Dbi = Err(File.getPDBDbiStream());
219 const auto &Modules = Dbi.modules();
220 auto Modi = Modules.getModuleDescriptor(Index);
221
222 uint16_t ModiStream = Modi.getModuleStreamIndex();
223 if (ModiStream == kInvalidStreamIndex)
224 return make_error<RawError>(raw_error_code::no_stream,
225 "Module stream not present");
226
227 auto ModStreamData = MappedBlockStream::createIndexedStream(
228 File.getMsfLayout(), File.getMsfBuffer(), ModiStream,
229 File.getAllocator());
230
231 ModuleDebugStreamRef ModS(Modi, std::move(ModStreamData));
232 if (auto EC = ModS.reload())
233 return make_error<RawError>(raw_error_code::corrupt_file,
234 "Invalid module stream");
235
236 return std::move(ModS);
237}
238
Zachary Turner0e327d02017-06-15 23:12:41 +0000239static std::string formatChecksumKind(FileChecksumKind Kind) {
240 switch (Kind) {
241 RETURN_CASE(FileChecksumKind, None, "None");
242 RETURN_CASE(FileChecksumKind, MD5, "MD5");
243 RETURN_CASE(FileChecksumKind, SHA1, "SHA-1");
244 RETURN_CASE(FileChecksumKind, SHA256, "SHA-256");
245 }
246 return formatUnknownEnum(Kind);
247}
248
Zachary Turner4e950642017-06-15 23:56:19 +0000249namespace {
250class StringsAndChecksumsPrinter {
251 const DebugStringTableSubsectionRef &extractStringTable(PDBFile &File) {
252 ExitOnError Err("Unexpected error processing modules");
253 return Err(File.getStringTable()).getStringTable();
254 }
255
256 template <typename... Args>
257 void formatInternal(LinePrinter &Printer, bool Append,
258 Args &&... args) const {
259 if (Append)
260 Printer.format(std::forward<Args>(args)...);
261 else
262 Printer.formatLine(std::forward<Args>(args)...);
263 }
264
265public:
266 StringsAndChecksumsPrinter(PDBFile &File, uint32_t Modi)
267 : Records(extractStringTable(File)) {
268 auto MDS = getModuleDebugStream(File, Modi);
269 if (!MDS) {
270 consumeError(MDS.takeError());
271 return;
272 }
273
274 DebugStream = llvm::make_unique<ModuleDebugStreamRef>(std::move(*MDS));
275 Records.initialize(MDS->subsections());
276 if (Records.hasChecksums()) {
277 for (const auto &Entry : Records.checksums()) {
278 auto S = Records.strings().getString(Entry.FileNameOffset);
279 if (!S)
280 continue;
281 ChecksumsByFile[*S] = Entry;
282 }
283 }
284 }
285
286 Expected<StringRef> getNameFromStringTable(uint32_t Offset) const {
287 return Records.strings().getString(Offset);
288 }
289
290 void formatFromFileName(LinePrinter &Printer, StringRef File,
291 bool Append = false) const {
292 auto FC = ChecksumsByFile.find(File);
293 if (FC == ChecksumsByFile.end()) {
294 formatInternal(Printer, Append, "- (no checksum) {0}", File);
295 return;
296 }
297
298 formatInternal(Printer, Append, "- ({0}: {1}) {2}",
299 formatChecksumKind(FC->getValue().Kind),
300 toHex(FC->getValue().Checksum), File);
301 }
302
303 void formatFromChecksumsOffset(LinePrinter &Printer, uint32_t Offset,
304 bool Append = false) const {
305 if (!Records.hasChecksums()) {
306 formatInternal(Printer, Append, "(unknown file name offset {0})", Offset);
307 return;
308 }
309
310 auto Iter = Records.checksums().getArray().at(Offset);
311 if (Iter == Records.checksums().getArray().end()) {
312 formatInternal(Printer, Append, "(unknown file name offset {0})", Offset);
313 return;
314 }
315
316 uint32_t FO = Iter->FileNameOffset;
317 auto ExpectedFile = getNameFromStringTable(FO);
318 if (!ExpectedFile) {
319 formatInternal(Printer, Append, "(unknown file name offset {0})", Offset);
320 consumeError(ExpectedFile.takeError());
321 return;
322 }
323 if (Iter->Kind == FileChecksumKind::None) {
324 formatInternal(Printer, Append, "{0} (no checksum)", *ExpectedFile);
325 } else {
326 formatInternal(Printer, Append, "{0} ({1}: {2})", *ExpectedFile,
327 formatChecksumKind(Iter->Kind), toHex(Iter->Checksum));
328 }
329 }
330
331 std::unique_ptr<ModuleDebugStreamRef> DebugStream;
332 StringsAndChecksumsRef Records;
333 StringMap<FileChecksumEntry> ChecksumsByFile;
334};
335} // namespace
336
Zachary Turnerf2872b92017-06-15 23:59:56 +0000337template <typename CallbackT>
338static void iterateModules(PDBFile &File, LinePrinter &P, uint32_t IndentLevel,
339 CallbackT Callback) {
340 AutoIndent Indent(P);
341 if (!File.hasPDBDbiStream()) {
342 P.formatLine("DBI Stream not present");
343 return;
344 }
345
346 ExitOnError Err("Unexpected error processing modules");
347
348 auto &Stream = Err(File.getPDBDbiStream());
349
350 const DbiModuleList &Modules = Stream.modules();
351 uint32_t Count = Modules.getModuleCount();
352 uint32_t Digits = NumDigits(Count);
353 for (uint32_t I = 0; I < Count; ++I) {
354 auto Modi = Modules.getModuleDescriptor(I);
355 P.formatLine("Mod {0:4} | `{1}`: ", fmt_align(I, AlignStyle::Right, Digits),
356 Modi.getModuleName());
357
358 StringsAndChecksumsPrinter Strings(File, I);
359 AutoIndent Indent2(P, IndentLevel);
360 Callback(I, Strings);
361 }
362}
363
364template <typename SubsectionT>
365static void iterateModuleSubsections(
366 PDBFile &File, LinePrinter &P, uint32_t IndentLevel,
367 llvm::function_ref<void(uint32_t, StringsAndChecksumsPrinter &,
368 SubsectionT &)>
369 Callback) {
370
371 iterateModules(
372 File, P, IndentLevel,
373 [&File, &Callback](uint32_t Modi, StringsAndChecksumsPrinter &Strings) {
374 auto MDS = getModuleDebugStream(File, Modi);
375 if (!MDS) {
376 consumeError(MDS.takeError());
377 return;
378 }
379
380 for (const auto &SS : MDS->subsections()) {
381 SubsectionT Subsection;
382
383 if (SS.kind() != Subsection.kind())
384 continue;
385
386 BinaryStreamReader Reader(SS.getRecordData());
387 if (auto EC = Subsection.initialize(Reader))
388 continue;
389 Callback(Modi, Strings, Subsection);
390 }
391 });
392}
393
Zachary Turner7df69952017-06-22 20:57:39 +0000394Error DumpOutputStyle::dumpModules() {
Zachary Turner63055452017-06-15 22:24:24 +0000395 printHeader(P, "Modules");
396
397 AutoIndent Indent(P);
398 if (!File.hasPDBDbiStream()) {
399 P.formatLine("DBI Stream not present");
400 return Error::success();
401 }
402
Zachary Turner0e327d02017-06-15 23:12:41 +0000403 ExitOnError Err("Unexpected error processing modules");
Zachary Turner63055452017-06-15 22:24:24 +0000404
405 auto &Stream = Err(File.getPDBDbiStream());
406
407 const DbiModuleList &Modules = Stream.modules();
408 uint32_t Count = Modules.getModuleCount();
409 uint32_t Digits = NumDigits(Count);
410 for (uint32_t I = 0; I < Count; ++I) {
411 auto Modi = Modules.getModuleDescriptor(I);
412 P.formatLine("Mod {0:4} | Name: `{1}`: ",
413 fmt_align(I, AlignStyle::Right, Digits), Modi.getModuleName());
414 P.formatLine(" Obj: `{0}`: ", Modi.getObjFileName());
415 P.formatLine(" debug stream: {0}, # files: {1}, has ec info: {2}",
416 Modi.getModuleStreamIndex(), Modi.getNumberOfFiles(),
417 Modi.hasECInfo());
Zachary Turner0e327d02017-06-15 23:12:41 +0000418 }
419 return Error::success();
420}
421
Zachary Turner7df69952017-06-22 20:57:39 +0000422Error DumpOutputStyle::dumpModuleFiles() {
Zachary Turner0e327d02017-06-15 23:12:41 +0000423 printHeader(P, "Files");
424
Zachary Turner0e327d02017-06-15 23:12:41 +0000425 ExitOnError Err("Unexpected error processing modules");
426
Zachary Turnerf2872b92017-06-15 23:59:56 +0000427 iterateModules(
428 File, P, 11,
429 [this, &Err](uint32_t Modi, StringsAndChecksumsPrinter &Strings) {
430 auto &Stream = Err(File.getPDBDbiStream());
Zachary Turner0e327d02017-06-15 23:12:41 +0000431
Zachary Turnerf2872b92017-06-15 23:59:56 +0000432 const DbiModuleList &Modules = Stream.modules();
433 for (const auto &F : Modules.source_files(Modi)) {
434 Strings.formatFromFileName(P, F);
435 }
436 });
Zachary Turner4e950642017-06-15 23:56:19 +0000437 return Error::success();
438}
439
440static void typesetLinesAndColumns(PDBFile &File, LinePrinter &P,
441 uint32_t Start, const LineColumnEntry &E) {
442 const uint32_t kMaxCharsPerLineNumber = 4; // 4 digit line number
443 uint32_t MinColumnWidth = kMaxCharsPerLineNumber + 5;
444
445 // Let's try to keep it under 100 characters
446 constexpr uint32_t kMaxRowLength = 100;
447 // At least 3 spaces between columns.
448 uint32_t ColumnsPerRow = kMaxRowLength / (MinColumnWidth + 3);
449 uint32_t ItemsLeft = E.LineNumbers.size();
450 auto LineIter = E.LineNumbers.begin();
451 while (ItemsLeft != 0) {
452 uint32_t RowColumns = std::min(ItemsLeft, ColumnsPerRow);
453 for (uint32_t I = 0; I < RowColumns; ++I) {
454 LineInfo Line(LineIter->Flags);
455 std::string LineStr;
456 if (Line.isAlwaysStepInto())
457 LineStr = "ASI";
458 else if (Line.isNeverStepInto())
459 LineStr = "NSI";
Zachary Turner0e327d02017-06-15 23:12:41 +0000460 else
Zachary Turner4e950642017-06-15 23:56:19 +0000461 LineStr = utostr(Line.getStartLine());
462 char Statement = Line.isStatement() ? ' ' : '!';
463 P.format("{0} {1:X-} {2} ",
464 fmt_align(LineStr, AlignStyle::Right, kMaxCharsPerLineNumber),
465 fmt_align(Start + LineIter->Offset, AlignStyle::Right, 8, '0'),
466 Statement);
467 ++LineIter;
468 --ItemsLeft;
Zachary Turner63055452017-06-15 22:24:24 +0000469 }
Zachary Turner4e950642017-06-15 23:56:19 +0000470 P.NewLine();
Zachary Turner63055452017-06-15 22:24:24 +0000471 }
Zachary Turner4e950642017-06-15 23:56:19 +0000472}
473
Zachary Turner7df69952017-06-22 20:57:39 +0000474Error DumpOutputStyle::dumpLines() {
Zachary Turner4e950642017-06-15 23:56:19 +0000475 printHeader(P, "Lines");
Zachary Turner4e950642017-06-15 23:56:19 +0000476
Zachary Turnerf2872b92017-06-15 23:59:56 +0000477 uint32_t LastModi = UINT32_MAX;
478 uint32_t LastNameIndex = UINT32_MAX;
479 iterateModuleSubsections<DebugLinesSubsectionRef>(
480 File, P, 4,
481 [this, &LastModi, &LastNameIndex](uint32_t Modi,
482 StringsAndChecksumsPrinter &Strings,
483 DebugLinesSubsectionRef &Lines) {
484 uint16_t Segment = Lines.header()->RelocSegment;
485 uint32_t Begin = Lines.header()->RelocOffset;
486 uint32_t End = Begin + Lines.header()->CodeSize;
487 for (const auto &Block : Lines) {
488 if (LastModi != Modi || LastNameIndex != Block.NameIndex) {
489 LastModi = Modi;
490 LastNameIndex = Block.NameIndex;
491 Strings.formatFromChecksumsOffset(P, Block.NameIndex);
Zachary Turner4e950642017-06-15 23:56:19 +0000492 }
493
Zachary Turnerf2872b92017-06-15 23:59:56 +0000494 AutoIndent Indent(P, 2);
495 P.formatLine("{0:X-4}:{1:X-8}-{2:X-8}, ", Segment, Begin, End);
496 uint32_t Count = Block.LineNumbers.size();
497 if (Lines.hasColumnInfo())
498 P.format("line/column/addr entries = {0}", Count);
499 else
500 P.format("line/addr entries = {0}", Count);
Zachary Turner4e950642017-06-15 23:56:19 +0000501
Zachary Turnerf2872b92017-06-15 23:59:56 +0000502 P.NewLine();
503 typesetLinesAndColumns(File, P, Begin, Block);
Zachary Turner4e950642017-06-15 23:56:19 +0000504 }
505 });
506
507 return Error::success();
508}
509
Zachary Turner7df69952017-06-22 20:57:39 +0000510Error DumpOutputStyle::dumpInlineeLines() {
Zachary Turner4e950642017-06-15 23:56:19 +0000511 printHeader(P, "Inlinee Lines");
Zachary Turner4e950642017-06-15 23:56:19 +0000512
Zachary Turnerf2872b92017-06-15 23:59:56 +0000513 iterateModuleSubsections<DebugInlineeLinesSubsectionRef>(
514 File, P, 2,
515 [this](uint32_t Modi, StringsAndChecksumsPrinter &Strings,
516 DebugInlineeLinesSubsectionRef &Lines) {
517 P.formatLine("{0,+8} | {1,+5} | {2}", "Inlinee", "Line", "Source File");
518 for (const auto &Entry : Lines) {
519 P.formatLine("{0,+8} | {1,+5} | ", Entry.Header->Inlinee,
520 fmtle(Entry.Header->SourceLineNum));
521 Strings.formatFromChecksumsOffset(P, Entry.Header->FileID, true);
Zachary Turner4e950642017-06-15 23:56:19 +0000522 }
Zachary Turnerf2872b92017-06-15 23:59:56 +0000523 P.NewLine();
Zachary Turner4e950642017-06-15 23:56:19 +0000524 });
525
Zachary Turner63055452017-06-15 22:24:24 +0000526 return Error::success();
527}
Zachary Turner0e327d02017-06-15 23:12:41 +0000528
Zachary Turner7df69952017-06-22 20:57:39 +0000529Error DumpOutputStyle::dumpXmi() {
Zachary Turner47d9a562017-06-16 00:04:24 +0000530 printHeader(P, "Cross Module Imports");
531 iterateModuleSubsections<DebugCrossModuleImportsSubsectionRef>(
532 File, P, 2,
533 [this](uint32_t Modi, StringsAndChecksumsPrinter &Strings,
534 DebugCrossModuleImportsSubsectionRef &Imports) {
535 P.formatLine("{0,=32} | {1}", "Imported Module", "Type IDs");
536
537 for (const auto &Xmi : Imports) {
538 auto ExpectedModule =
539 Strings.getNameFromStringTable(Xmi.Header->ModuleNameOffset);
540 StringRef Module;
541 SmallString<32> ModuleStorage;
542 if (!ExpectedModule) {
543 Module = "(unknown module)";
544 consumeError(ExpectedModule.takeError());
545 } else
546 Module = *ExpectedModule;
547 if (Module.size() > 32) {
548 ModuleStorage = "...";
549 ModuleStorage += Module.take_back(32 - 3);
550 Module = ModuleStorage;
551 }
552 std::vector<std::string> TIs;
553 for (const auto I : Xmi.Imports)
554 TIs.push_back(formatv("{0,+10:X+}", fmtle(I)));
555 std::string Result =
556 typesetItemList(TIs, P.getIndentLevel() + 35, 12, " ");
557 P.formatLine("{0,+32} | {1}", Module, Result);
558 }
559 });
560
561 return Error::success();
562}
563
Zachary Turner7df69952017-06-22 20:57:39 +0000564Error DumpOutputStyle::dumpXme() {
Zachary Turner47d9a562017-06-16 00:04:24 +0000565 printHeader(P, "Cross Module Exports");
566
567 iterateModuleSubsections<DebugCrossModuleExportsSubsectionRef>(
568 File, P, 2,
569 [this](uint32_t Modi, StringsAndChecksumsPrinter &Strings,
570 DebugCrossModuleExportsSubsectionRef &Exports) {
571 P.formatLine("{0,-10} | {1}", "Local ID", "Global ID");
572 for (const auto &Export : Exports) {
573 P.formatLine("{0,+10:X+} | {1}", TypeIndex(Export.Local),
574 TypeIndex(Export.Global));
575 }
576 });
577
578 return Error::success();
579}
580
Zachary Turner7df69952017-06-22 20:57:39 +0000581Error DumpOutputStyle::dumpStringTable() {
Zachary Turner63055452017-06-15 22:24:24 +0000582 printHeader(P, "String Table");
583
584 AutoIndent Indent(P);
585 auto IS = File.getStringTable();
586 if (!IS) {
587 P.formatLine("Not present in file");
588 consumeError(IS.takeError());
589 return Error::success();
590 }
591
592 if (IS->name_ids().empty()) {
593 P.formatLine("Empty");
594 return Error::success();
595 }
596
597 auto MaxID = std::max_element(IS->name_ids().begin(), IS->name_ids().end());
598 uint32_t Digits = NumDigits(*MaxID);
599
600 P.formatLine("{0} | {1}", fmt_align("ID", AlignStyle::Right, Digits),
601 "String");
602
603 std::vector<uint32_t> SortedIDs(IS->name_ids().begin(), IS->name_ids().end());
604 std::sort(SortedIDs.begin(), SortedIDs.end());
605 for (uint32_t I : SortedIDs) {
606 auto ES = IS->getStringForID(I);
607 llvm::SmallString<32> Str;
608 if (!ES) {
609 consumeError(ES.takeError());
610 Str = "Error reading string";
611 } else if (!ES->empty()) {
612 Str.append("'");
613 Str.append(*ES);
614 Str.append("'");
615 }
616
617 if (!Str.empty())
618 P.formatLine("{0} | {1}", fmt_align(I, AlignStyle::Right, Digits), Str);
619 }
620 return Error::success();
621}
622
Zachary Turner7df69952017-06-22 20:57:39 +0000623Error DumpOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
Zachary Turner63055452017-06-15 22:24:24 +0000624 assert(StreamIdx == StreamTPI || StreamIdx == StreamIPI);
625
626 bool Present = false;
Zachary Turnerf8a2e042017-06-15 23:04:42 +0000627 bool DumpTypes = false;
Zachary Turner63055452017-06-15 22:24:24 +0000628 bool DumpBytes = false;
Zachary Turnerf8a2e042017-06-15 23:04:42 +0000629 bool DumpExtras = false;
Zachary Turner59224cb2017-06-16 23:42:15 +0000630 std::vector<uint32_t> Indices;
Zachary Turner63055452017-06-15 22:24:24 +0000631 if (StreamIdx == StreamTPI) {
632 printHeader(P, "Types (TPI Stream)");
633 Present = File.hasPDBTpiStream();
Zachary Turner7df69952017-06-22 20:57:39 +0000634 DumpTypes = opts::dump::DumpTypes;
635 DumpBytes = opts::dump::DumpTypeData;
636 DumpExtras = opts::dump::DumpTypeExtras;
637 Indices.assign(opts::dump::DumpTypeIndex.begin(),
638 opts::dump::DumpTypeIndex.end());
Zachary Turner63055452017-06-15 22:24:24 +0000639 } else if (StreamIdx == StreamIPI) {
640 printHeader(P, "Types (IPI Stream)");
641 Present = File.hasPDBIpiStream();
Zachary Turner7df69952017-06-22 20:57:39 +0000642 DumpTypes = opts::dump::DumpIds;
643 DumpBytes = opts::dump::DumpIdData;
644 DumpExtras = opts::dump::DumpIdExtras;
645 Indices.assign(opts::dump::DumpIdIndex.begin(),
646 opts::dump::DumpIdIndex.end());
Zachary Turner63055452017-06-15 22:24:24 +0000647 }
648
649 AutoIndent Indent(P);
650 if (!Present) {
651 P.formatLine("Stream not present");
652 return Error::success();
653 }
654
655 ExitOnError Err("Unexpected error processing types");
656
657 auto &Stream = Err((StreamIdx == StreamTPI) ? File.getPDBTpiStream()
658 : File.getPDBIpiStream());
659
Zachary Turner59224cb2017-06-16 23:42:15 +0000660 auto &Types = Err(initializeTypes(StreamIdx));
Zachary Turner63055452017-06-15 22:24:24 +0000661
Zachary Turnerf8a2e042017-06-15 23:04:42 +0000662 if (DumpTypes) {
663 P.formatLine("Showing {0:N} records", Stream.getNumTypeRecords());
664 uint32_t Width =
665 NumDigits(TypeIndex::FirstNonSimpleIndex + Stream.getNumTypeRecords());
Zachary Turner63055452017-06-15 22:24:24 +0000666
Zachary Turnerf8a2e042017-06-15 23:04:42 +0000667 MinimalTypeDumpVisitor V(P, Width + 2, DumpBytes, DumpExtras, Types,
668 Stream.getHashValues());
Zachary Turner63055452017-06-15 22:24:24 +0000669
Zachary Turner59224cb2017-06-16 23:42:15 +0000670 if (Indices.empty()) {
671 if (auto EC = codeview::visitTypeStream(Types, V)) {
672 P.formatLine("An error occurred dumping type records: {0}",
673 toString(std::move(EC)));
674 }
675 } else {
676 for (const auto &I : Indices) {
677 TypeIndex TI(I);
678 CVType Type = Types.getType(TI);
679 if (auto EC = codeview::visitTypeRecord(Type, TI, V))
680 P.formatLine("An error occurred dumping type record {0}: {1}", TI,
681 toString(std::move(EC)));
682 }
Zachary Turnerf8a2e042017-06-15 23:04:42 +0000683 }
684 }
685
686 if (DumpExtras) {
687 P.NewLine();
688 auto IndexOffsets = Stream.getTypeIndexOffsets();
689 P.formatLine("Type Index Offsets:");
690 for (const auto &IO : IndexOffsets) {
691 AutoIndent Indent2(P);
692 P.formatLine("TI: {0}, Offset: {1}", IO.Type, fmtle(IO.Offset));
693 }
694
695 P.NewLine();
696 P.formatLine("Hash Adjusters:");
697 auto &Adjusters = Stream.getHashAdjusters();
698 auto &Strings = Err(File.getStringTable());
699 for (const auto &A : Adjusters) {
700 AutoIndent Indent2(P);
701 auto ExpectedStr = Strings.getStringForID(A.first);
702 TypeIndex TI(A.second);
703 if (ExpectedStr)
704 P.formatLine("`{0}` -> {1}", *ExpectedStr, TI);
705 else {
706 P.formatLine("unknown str id ({0}) -> {1}", A.first, TI);
707 consumeError(ExpectedStr.takeError());
708 }
709 }
Zachary Turner63055452017-06-15 22:24:24 +0000710 }
711 return Error::success();
712}
713
714Expected<codeview::LazyRandomTypeCollection &>
Zachary Turner7df69952017-06-22 20:57:39 +0000715DumpOutputStyle::initializeTypes(uint32_t SN) {
Zachary Turner63055452017-06-15 22:24:24 +0000716 auto &TypeCollection = (SN == StreamTPI) ? TpiTypes : IpiTypes;
717 auto Tpi =
718 (SN == StreamTPI) ? File.getPDBTpiStream() : File.getPDBIpiStream();
719 if (!Tpi)
720 return Tpi.takeError();
721
722 if (!TypeCollection) {
723 auto &Types = Tpi->typeArray();
724 uint32_t Count = Tpi->getNumTypeRecords();
725 auto Offsets = Tpi->getTypeIndexOffsets();
726 TypeCollection =
727 llvm::make_unique<LazyRandomTypeCollection>(Types, Count, Offsets);
728 }
729
730 return *TypeCollection;
731}
732
Zachary Turner7df69952017-06-22 20:57:39 +0000733Error DumpOutputStyle::dumpModuleSyms() {
Zachary Turner63055452017-06-15 22:24:24 +0000734 printHeader(P, "Symbols");
735
736 AutoIndent Indent(P);
737 if (!File.hasPDBDbiStream()) {
738 P.formatLine("DBI Stream not present");
739 return Error::success();
740 }
741
742 ExitOnError Err("Unexpected error processing symbols");
743
744 auto &Stream = Err(File.getPDBDbiStream());
745
Zachary Turner59224cb2017-06-16 23:42:15 +0000746 auto &Types = Err(initializeTypes(StreamTPI));
Zachary Turner63055452017-06-15 22:24:24 +0000747
748 const DbiModuleList &Modules = Stream.modules();
749 uint32_t Count = Modules.getModuleCount();
750 uint32_t Digits = NumDigits(Count);
751 for (uint32_t I = 0; I < Count; ++I) {
752 auto Modi = Modules.getModuleDescriptor(I);
753 P.formatLine("Mod {0:4} | `{1}`: ", fmt_align(I, AlignStyle::Right, Digits),
754 Modi.getModuleName());
755 uint16_t ModiStream = Modi.getModuleStreamIndex();
756 if (ModiStream == kInvalidStreamIndex) {
757 P.formatLine(" <symbols not present>");
758 continue;
759 }
760 auto ModStreamData = MappedBlockStream::createIndexedStream(
761 File.getMsfLayout(), File.getMsfBuffer(), ModiStream,
762 File.getAllocator());
763
764 ModuleDebugStreamRef ModS(Modi, std::move(ModStreamData));
765 if (auto EC = ModS.reload()) {
766 P.formatLine("Error loading module stream {0}. {1}", I,
767 toString(std::move(EC)));
768 continue;
769 }
770
771 SymbolVisitorCallbackPipeline Pipeline;
772 SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
Zachary Turner7df69952017-06-22 20:57:39 +0000773 MinimalSymbolDumper Dumper(P, opts::dump::DumpSymRecordBytes, Types);
Zachary Turner63055452017-06-15 22:24:24 +0000774
775 Pipeline.addCallbackToPipeline(Deserializer);
776 Pipeline.addCallbackToPipeline(Dumper);
777 CVSymbolVisitor Visitor(Pipeline);
778 if (auto EC = Visitor.visitSymbolStream(ModS.getSymbolArray())) {
779 P.formatLine("Error while processing symbol records. {0}",
780 toString(std::move(EC)));
781 continue;
782 }
783 }
784 return Error::success();
785}
786
Zachary Turner7df69952017-06-22 20:57:39 +0000787Error DumpOutputStyle::dumpPublics() {
Zachary Turner63055452017-06-15 22:24:24 +0000788 printHeader(P, "Public Symbols");
789
790 AutoIndent Indent(P);
791 if (!File.hasPDBPublicsStream()) {
792 P.formatLine("Publics stream not present");
793 return Error::success();
794 }
795
796 ExitOnError Err("Error dumping publics stream");
797
Zachary Turner59224cb2017-06-16 23:42:15 +0000798 auto &Types = Err(initializeTypes(StreamTPI));
Zachary Turner63055452017-06-15 22:24:24 +0000799 auto &Publics = Err(File.getPDBPublicsStream());
800 SymbolVisitorCallbackPipeline Pipeline;
801 SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
Zachary Turner7df69952017-06-22 20:57:39 +0000802 MinimalSymbolDumper Dumper(P, opts::dump::DumpSymRecordBytes, Types);
Zachary Turner63055452017-06-15 22:24:24 +0000803
804 Pipeline.addCallbackToPipeline(Deserializer);
805 Pipeline.addCallbackToPipeline(Dumper);
806 CVSymbolVisitor Visitor(Pipeline);
807 auto ExpectedSymbols = Publics.getSymbolArray();
808 if (!ExpectedSymbols) {
809 P.formatLine("Could not read public symbol record stream");
810 return Error::success();
811 }
812
813 if (auto EC = Visitor.visitSymbolStream(*ExpectedSymbols))
814 P.formatLine("Error while processing public symbol records. {0}",
815 toString(std::move(EC)));
816
817 return Error::success();
818}
819
820static std::string formatSectionCharacteristics(uint32_t IndentLevel,
821 uint32_t C) {
822 using SC = COFF::SectionCharacteristics;
823 std::vector<std::string> Opts;
824 if (C == COFF::SC_Invalid)
825 return "invalid";
826 if (C == 0)
827 return "none";
828
829 PUSH_FLAG(SC, IMAGE_SCN_TYPE_NOLOAD, C, "IMAGE_SCN_TYPE_NOLOAD");
830 PUSH_FLAG(SC, IMAGE_SCN_TYPE_NO_PAD, C, "IMAGE_SCN_TYPE_NO_PAD");
831 PUSH_FLAG(SC, IMAGE_SCN_CNT_CODE, C, "IMAGE_SCN_CNT_CODE");
832 PUSH_FLAG(SC, IMAGE_SCN_CNT_INITIALIZED_DATA, C,
833 "IMAGE_SCN_CNT_INITIALIZED_DATA");
834 PUSH_FLAG(SC, IMAGE_SCN_CNT_UNINITIALIZED_DATA, C,
835 "IMAGE_SCN_CNT_UNINITIALIZED_DATA");
836 PUSH_FLAG(SC, IMAGE_SCN_LNK_OTHER, C, "IMAGE_SCN_LNK_OTHER");
837 PUSH_FLAG(SC, IMAGE_SCN_LNK_INFO, C, "IMAGE_SCN_LNK_INFO");
838 PUSH_FLAG(SC, IMAGE_SCN_LNK_REMOVE, C, "IMAGE_SCN_LNK_REMOVE");
839 PUSH_FLAG(SC, IMAGE_SCN_LNK_COMDAT, C, "IMAGE_SCN_LNK_COMDAT");
840 PUSH_FLAG(SC, IMAGE_SCN_GPREL, C, "IMAGE_SCN_GPREL");
841 PUSH_FLAG(SC, IMAGE_SCN_MEM_PURGEABLE, C, "IMAGE_SCN_MEM_PURGEABLE");
842 PUSH_FLAG(SC, IMAGE_SCN_MEM_16BIT, C, "IMAGE_SCN_MEM_16BIT");
843 PUSH_FLAG(SC, IMAGE_SCN_MEM_LOCKED, C, "IMAGE_SCN_MEM_LOCKED");
844 PUSH_FLAG(SC, IMAGE_SCN_MEM_PRELOAD, C, "IMAGE_SCN_MEM_PRELOAD");
845 PUSH_FLAG(SC, IMAGE_SCN_GPREL, C, "IMAGE_SCN_GPREL");
846 PUSH_FLAG(SC, IMAGE_SCN_GPREL, C, "IMAGE_SCN_GPREL");
847 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_1BYTES, C,
848 "IMAGE_SCN_ALIGN_1BYTES");
849 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_2BYTES, C,
850 "IMAGE_SCN_ALIGN_2BYTES");
851 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_4BYTES, C,
852 "IMAGE_SCN_ALIGN_4BYTES");
853 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_8BYTES, C,
854 "IMAGE_SCN_ALIGN_8BYTES");
855 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_16BYTES, C,
856 "IMAGE_SCN_ALIGN_16BYTES");
857 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_32BYTES, C,
858 "IMAGE_SCN_ALIGN_32BYTES");
859 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_64BYTES, C,
860 "IMAGE_SCN_ALIGN_64BYTES");
861 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_128BYTES, C,
862 "IMAGE_SCN_ALIGN_128BYTES");
863 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_256BYTES, C,
864 "IMAGE_SCN_ALIGN_256BYTES");
865 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_512BYTES, C,
866 "IMAGE_SCN_ALIGN_512BYTES");
867 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_1024BYTES, C,
868 "IMAGE_SCN_ALIGN_1024BYTES");
869 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_2048BYTES, C,
870 "IMAGE_SCN_ALIGN_2048BYTES");
871 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_4096BYTES, C,
872 "IMAGE_SCN_ALIGN_4096BYTES");
873 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_8192BYTES, C,
874 "IMAGE_SCN_ALIGN_8192BYTES");
875 PUSH_FLAG(SC, IMAGE_SCN_LNK_NRELOC_OVFL, C, "IMAGE_SCN_LNK_NRELOC_OVFL");
876 PUSH_FLAG(SC, IMAGE_SCN_MEM_DISCARDABLE, C, "IMAGE_SCN_MEM_DISCARDABLE");
877 PUSH_FLAG(SC, IMAGE_SCN_MEM_NOT_CACHED, C, "IMAGE_SCN_MEM_NOT_CACHED");
878 PUSH_FLAG(SC, IMAGE_SCN_MEM_NOT_PAGED, C, "IMAGE_SCN_MEM_NOT_PAGED");
879 PUSH_FLAG(SC, IMAGE_SCN_MEM_SHARED, C, "IMAGE_SCN_MEM_SHARED");
880 PUSH_FLAG(SC, IMAGE_SCN_MEM_EXECUTE, C, "IMAGE_SCN_MEM_EXECUTE");
881 PUSH_FLAG(SC, IMAGE_SCN_MEM_READ, C, "IMAGE_SCN_MEM_READ");
882 PUSH_FLAG(SC, IMAGE_SCN_MEM_WRITE, C, "IMAGE_SCN_MEM_WRITE");
Zachary Turner47d9a562017-06-16 00:04:24 +0000883 return typesetItemList(Opts, IndentLevel, 3, " | ");
Zachary Turner63055452017-06-15 22:24:24 +0000884}
885
886static std::string formatSegMapDescriptorFlag(uint32_t IndentLevel,
887 OMFSegDescFlags Flags) {
888 std::vector<std::string> Opts;
889 if (Flags == OMFSegDescFlags::None)
890 return "none";
891
892 PUSH_FLAG(OMFSegDescFlags, Read, Flags, "read");
893 PUSH_FLAG(OMFSegDescFlags, Write, Flags, "write");
894 PUSH_FLAG(OMFSegDescFlags, Execute, Flags, "execute");
895 PUSH_FLAG(OMFSegDescFlags, AddressIs32Bit, Flags, "32 bit addr");
896 PUSH_FLAG(OMFSegDescFlags, IsSelector, Flags, "selector");
897 PUSH_FLAG(OMFSegDescFlags, IsAbsoluteAddress, Flags, "absolute addr");
898 PUSH_FLAG(OMFSegDescFlags, IsGroup, Flags, "group");
Zachary Turner47d9a562017-06-16 00:04:24 +0000899 return typesetItemList(Opts, IndentLevel, 4, " | ");
Zachary Turner63055452017-06-15 22:24:24 +0000900}
901
Zachary Turner7df69952017-06-22 20:57:39 +0000902Error DumpOutputStyle::dumpSectionContribs() {
Zachary Turner63055452017-06-15 22:24:24 +0000903 printHeader(P, "Section Contributions");
904 ExitOnError Err("Error dumping publics stream");
905
906 AutoIndent Indent(P);
907 if (!File.hasPDBDbiStream()) {
908 P.formatLine(
909 "Section contribs require a DBI Stream, which could not be loaded");
910 return Error::success();
911 }
912
913 auto &Dbi = Err(File.getPDBDbiStream());
914
915 class Visitor : public ISectionContribVisitor {
916 public:
917 Visitor(LinePrinter &P) : P(P) {}
918 void visit(const SectionContrib &SC) override {
919 P.formatLine(
920 "SC | mod = {2}, {0}, size = {1}, data crc = {3}, reloc crc = {4}",
921 formatSegmentOffset(SC.ISect, SC.Off), fmtle(SC.Size), fmtle(SC.Imod),
922 fmtle(SC.DataCrc), fmtle(SC.RelocCrc));
923 P.formatLine(" {0}",
924 formatSectionCharacteristics(P.getIndentLevel() + 6,
925 SC.Characteristics));
926 }
927 void visit(const SectionContrib2 &SC) override {
928 P.formatLine("SC2 | mod = {2}, {0}, size = {1}, data crc = {3}, reloc "
929 "crc = {4}, coff section = {5}",
930 formatSegmentOffset(SC.Base.ISect, SC.Base.Off),
931 fmtle(SC.Base.Size), fmtle(SC.Base.Imod),
932 fmtle(SC.Base.DataCrc), fmtle(SC.Base.RelocCrc),
933 fmtle(SC.ISectCoff));
934 P.formatLine(" {0}",
935 formatSectionCharacteristics(P.getIndentLevel() + 6,
936 SC.Base.Characteristics));
937 }
938
939 private:
940 LinePrinter &P;
941 };
942
943 Visitor V(P);
944 Dbi.visitSectionContributions(V);
945 return Error::success();
946}
947
Zachary Turner7df69952017-06-22 20:57:39 +0000948Error DumpOutputStyle::dumpSectionMap() {
Zachary Turner63055452017-06-15 22:24:24 +0000949 printHeader(P, "Section Map");
950 ExitOnError Err("Error dumping section map");
951
952 AutoIndent Indent(P);
953 if (!File.hasPDBDbiStream()) {
954 P.formatLine("Dumping the section map requires a DBI Stream, which could "
955 "not be loaded");
956 return Error::success();
957 }
958
959 auto &Dbi = Err(File.getPDBDbiStream());
960
961 uint32_t I = 0;
962 for (auto &M : Dbi.getSectionMap()) {
963 P.formatLine(
964 "Section {0:4} | ovl = {0}, group = {1}, frame = {2}, name = {3}", I,
965 fmtle(M.Ovl), fmtle(M.Group), fmtle(M.Frame), fmtle(M.SecName));
966 P.formatLine(" class = {0}, offset = {1}, size = {2}",
967 fmtle(M.ClassName), fmtle(M.Offset), fmtle(M.SecByteLength));
968 P.formatLine(" flags = {0}",
969 formatSegMapDescriptorFlag(
970 P.getIndentLevel() + 13,
971 static_cast<OMFSegDescFlags>(uint16_t(M.Flags))));
972 ++I;
973 }
974 return Error::success();
975}