blob: a05e5cf03e99b0b1737ec0f36fd7ef93a92d68a4 [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));
202 }
203
204 return Error::success();
205}
206
Zachary Turner0e327d02017-06-15 23:12:41 +0000207static Expected<ModuleDebugStreamRef> getModuleDebugStream(PDBFile &File,
208 uint32_t Index) {
209 ExitOnError Err("Unexpected error");
210
211 auto &Dbi = Err(File.getPDBDbiStream());
212 const auto &Modules = Dbi.modules();
213 auto Modi = Modules.getModuleDescriptor(Index);
214
215 uint16_t ModiStream = Modi.getModuleStreamIndex();
216 if (ModiStream == kInvalidStreamIndex)
217 return make_error<RawError>(raw_error_code::no_stream,
218 "Module stream not present");
219
220 auto ModStreamData = MappedBlockStream::createIndexedStream(
221 File.getMsfLayout(), File.getMsfBuffer(), ModiStream,
222 File.getAllocator());
223
224 ModuleDebugStreamRef ModS(Modi, std::move(ModStreamData));
225 if (auto EC = ModS.reload())
226 return make_error<RawError>(raw_error_code::corrupt_file,
227 "Invalid module stream");
228
229 return std::move(ModS);
230}
231
Zachary Turner0e327d02017-06-15 23:12:41 +0000232static std::string formatChecksumKind(FileChecksumKind Kind) {
233 switch (Kind) {
234 RETURN_CASE(FileChecksumKind, None, "None");
235 RETURN_CASE(FileChecksumKind, MD5, "MD5");
236 RETURN_CASE(FileChecksumKind, SHA1, "SHA-1");
237 RETURN_CASE(FileChecksumKind, SHA256, "SHA-256");
238 }
239 return formatUnknownEnum(Kind);
240}
241
Zachary Turner4e950642017-06-15 23:56:19 +0000242namespace {
243class StringsAndChecksumsPrinter {
244 const DebugStringTableSubsectionRef &extractStringTable(PDBFile &File) {
245 ExitOnError Err("Unexpected error processing modules");
246 return Err(File.getStringTable()).getStringTable();
247 }
248
249 template <typename... Args>
250 void formatInternal(LinePrinter &Printer, bool Append,
251 Args &&... args) const {
252 if (Append)
253 Printer.format(std::forward<Args>(args)...);
254 else
255 Printer.formatLine(std::forward<Args>(args)...);
256 }
257
258public:
259 StringsAndChecksumsPrinter(PDBFile &File, uint32_t Modi)
260 : Records(extractStringTable(File)) {
261 auto MDS = getModuleDebugStream(File, Modi);
262 if (!MDS) {
263 consumeError(MDS.takeError());
264 return;
265 }
266
267 DebugStream = llvm::make_unique<ModuleDebugStreamRef>(std::move(*MDS));
268 Records.initialize(MDS->subsections());
269 if (Records.hasChecksums()) {
270 for (const auto &Entry : Records.checksums()) {
271 auto S = Records.strings().getString(Entry.FileNameOffset);
272 if (!S)
273 continue;
274 ChecksumsByFile[*S] = Entry;
275 }
276 }
277 }
278
279 Expected<StringRef> getNameFromStringTable(uint32_t Offset) const {
280 return Records.strings().getString(Offset);
281 }
282
283 void formatFromFileName(LinePrinter &Printer, StringRef File,
284 bool Append = false) const {
285 auto FC = ChecksumsByFile.find(File);
286 if (FC == ChecksumsByFile.end()) {
287 formatInternal(Printer, Append, "- (no checksum) {0}", File);
288 return;
289 }
290
291 formatInternal(Printer, Append, "- ({0}: {1}) {2}",
292 formatChecksumKind(FC->getValue().Kind),
293 toHex(FC->getValue().Checksum), File);
294 }
295
296 void formatFromChecksumsOffset(LinePrinter &Printer, uint32_t Offset,
297 bool Append = false) const {
298 if (!Records.hasChecksums()) {
299 formatInternal(Printer, Append, "(unknown file name offset {0})", Offset);
300 return;
301 }
302
303 auto Iter = Records.checksums().getArray().at(Offset);
304 if (Iter == Records.checksums().getArray().end()) {
305 formatInternal(Printer, Append, "(unknown file name offset {0})", Offset);
306 return;
307 }
308
309 uint32_t FO = Iter->FileNameOffset;
310 auto ExpectedFile = getNameFromStringTable(FO);
311 if (!ExpectedFile) {
312 formatInternal(Printer, Append, "(unknown file name offset {0})", Offset);
313 consumeError(ExpectedFile.takeError());
314 return;
315 }
316 if (Iter->Kind == FileChecksumKind::None) {
317 formatInternal(Printer, Append, "{0} (no checksum)", *ExpectedFile);
318 } else {
319 formatInternal(Printer, Append, "{0} ({1}: {2})", *ExpectedFile,
320 formatChecksumKind(Iter->Kind), toHex(Iter->Checksum));
321 }
322 }
323
324 std::unique_ptr<ModuleDebugStreamRef> DebugStream;
325 StringsAndChecksumsRef Records;
326 StringMap<FileChecksumEntry> ChecksumsByFile;
327};
328} // namespace
329
Zachary Turnerf2872b92017-06-15 23:59:56 +0000330template <typename CallbackT>
331static void iterateModules(PDBFile &File, LinePrinter &P, uint32_t IndentLevel,
332 CallbackT Callback) {
333 AutoIndent Indent(P);
334 if (!File.hasPDBDbiStream()) {
335 P.formatLine("DBI Stream not present");
336 return;
337 }
338
339 ExitOnError Err("Unexpected error processing modules");
340
341 auto &Stream = Err(File.getPDBDbiStream());
342
343 const DbiModuleList &Modules = Stream.modules();
344 uint32_t Count = Modules.getModuleCount();
345 uint32_t Digits = NumDigits(Count);
346 for (uint32_t I = 0; I < Count; ++I) {
347 auto Modi = Modules.getModuleDescriptor(I);
348 P.formatLine("Mod {0:4} | `{1}`: ", fmt_align(I, AlignStyle::Right, Digits),
349 Modi.getModuleName());
350
351 StringsAndChecksumsPrinter Strings(File, I);
352 AutoIndent Indent2(P, IndentLevel);
353 Callback(I, Strings);
354 }
355}
356
357template <typename SubsectionT>
358static void iterateModuleSubsections(
359 PDBFile &File, LinePrinter &P, uint32_t IndentLevel,
360 llvm::function_ref<void(uint32_t, StringsAndChecksumsPrinter &,
361 SubsectionT &)>
362 Callback) {
363
364 iterateModules(
365 File, P, IndentLevel,
366 [&File, &Callback](uint32_t Modi, StringsAndChecksumsPrinter &Strings) {
367 auto MDS = getModuleDebugStream(File, Modi);
368 if (!MDS) {
369 consumeError(MDS.takeError());
370 return;
371 }
372
373 for (const auto &SS : MDS->subsections()) {
374 SubsectionT Subsection;
375
376 if (SS.kind() != Subsection.kind())
377 continue;
378
379 BinaryStreamReader Reader(SS.getRecordData());
380 if (auto EC = Subsection.initialize(Reader))
381 continue;
382 Callback(Modi, Strings, Subsection);
383 }
384 });
385}
386
Zachary Turner7df69952017-06-22 20:57:39 +0000387Error DumpOutputStyle::dumpModules() {
Zachary Turner63055452017-06-15 22:24:24 +0000388 printHeader(P, "Modules");
389
390 AutoIndent Indent(P);
391 if (!File.hasPDBDbiStream()) {
392 P.formatLine("DBI Stream not present");
393 return Error::success();
394 }
395
Zachary Turner0e327d02017-06-15 23:12:41 +0000396 ExitOnError Err("Unexpected error processing modules");
Zachary Turner63055452017-06-15 22:24:24 +0000397
398 auto &Stream = Err(File.getPDBDbiStream());
399
400 const DbiModuleList &Modules = Stream.modules();
401 uint32_t Count = Modules.getModuleCount();
402 uint32_t Digits = NumDigits(Count);
403 for (uint32_t I = 0; I < Count; ++I) {
404 auto Modi = Modules.getModuleDescriptor(I);
405 P.formatLine("Mod {0:4} | Name: `{1}`: ",
406 fmt_align(I, AlignStyle::Right, Digits), Modi.getModuleName());
407 P.formatLine(" Obj: `{0}`: ", Modi.getObjFileName());
408 P.formatLine(" debug stream: {0}, # files: {1}, has ec info: {2}",
409 Modi.getModuleStreamIndex(), Modi.getNumberOfFiles(),
410 Modi.hasECInfo());
Zachary Turner0e327d02017-06-15 23:12:41 +0000411 }
412 return Error::success();
413}
414
Zachary Turner7df69952017-06-22 20:57:39 +0000415Error DumpOutputStyle::dumpModuleFiles() {
Zachary Turner0e327d02017-06-15 23:12:41 +0000416 printHeader(P, "Files");
417
Zachary Turner0e327d02017-06-15 23:12:41 +0000418 ExitOnError Err("Unexpected error processing modules");
419
Zachary Turnerf2872b92017-06-15 23:59:56 +0000420 iterateModules(
421 File, P, 11,
422 [this, &Err](uint32_t Modi, StringsAndChecksumsPrinter &Strings) {
423 auto &Stream = Err(File.getPDBDbiStream());
Zachary Turner0e327d02017-06-15 23:12:41 +0000424
Zachary Turnerf2872b92017-06-15 23:59:56 +0000425 const DbiModuleList &Modules = Stream.modules();
426 for (const auto &F : Modules.source_files(Modi)) {
427 Strings.formatFromFileName(P, F);
428 }
429 });
Zachary Turner4e950642017-06-15 23:56:19 +0000430 return Error::success();
431}
432
433static void typesetLinesAndColumns(PDBFile &File, LinePrinter &P,
434 uint32_t Start, const LineColumnEntry &E) {
435 const uint32_t kMaxCharsPerLineNumber = 4; // 4 digit line number
436 uint32_t MinColumnWidth = kMaxCharsPerLineNumber + 5;
437
438 // Let's try to keep it under 100 characters
439 constexpr uint32_t kMaxRowLength = 100;
440 // At least 3 spaces between columns.
441 uint32_t ColumnsPerRow = kMaxRowLength / (MinColumnWidth + 3);
442 uint32_t ItemsLeft = E.LineNumbers.size();
443 auto LineIter = E.LineNumbers.begin();
444 while (ItemsLeft != 0) {
445 uint32_t RowColumns = std::min(ItemsLeft, ColumnsPerRow);
446 for (uint32_t I = 0; I < RowColumns; ++I) {
447 LineInfo Line(LineIter->Flags);
448 std::string LineStr;
449 if (Line.isAlwaysStepInto())
450 LineStr = "ASI";
451 else if (Line.isNeverStepInto())
452 LineStr = "NSI";
Zachary Turner0e327d02017-06-15 23:12:41 +0000453 else
Zachary Turner4e950642017-06-15 23:56:19 +0000454 LineStr = utostr(Line.getStartLine());
455 char Statement = Line.isStatement() ? ' ' : '!';
456 P.format("{0} {1:X-} {2} ",
457 fmt_align(LineStr, AlignStyle::Right, kMaxCharsPerLineNumber),
458 fmt_align(Start + LineIter->Offset, AlignStyle::Right, 8, '0'),
459 Statement);
460 ++LineIter;
461 --ItemsLeft;
Zachary Turner63055452017-06-15 22:24:24 +0000462 }
Zachary Turner4e950642017-06-15 23:56:19 +0000463 P.NewLine();
Zachary Turner63055452017-06-15 22:24:24 +0000464 }
Zachary Turner4e950642017-06-15 23:56:19 +0000465}
466
Zachary Turner7df69952017-06-22 20:57:39 +0000467Error DumpOutputStyle::dumpLines() {
Zachary Turner4e950642017-06-15 23:56:19 +0000468 printHeader(P, "Lines");
Zachary Turner4e950642017-06-15 23:56:19 +0000469
Zachary Turnerf2872b92017-06-15 23:59:56 +0000470 uint32_t LastModi = UINT32_MAX;
471 uint32_t LastNameIndex = UINT32_MAX;
472 iterateModuleSubsections<DebugLinesSubsectionRef>(
473 File, P, 4,
474 [this, &LastModi, &LastNameIndex](uint32_t Modi,
475 StringsAndChecksumsPrinter &Strings,
476 DebugLinesSubsectionRef &Lines) {
477 uint16_t Segment = Lines.header()->RelocSegment;
478 uint32_t Begin = Lines.header()->RelocOffset;
479 uint32_t End = Begin + Lines.header()->CodeSize;
480 for (const auto &Block : Lines) {
481 if (LastModi != Modi || LastNameIndex != Block.NameIndex) {
482 LastModi = Modi;
483 LastNameIndex = Block.NameIndex;
484 Strings.formatFromChecksumsOffset(P, Block.NameIndex);
Zachary Turner4e950642017-06-15 23:56:19 +0000485 }
486
Zachary Turnerf2872b92017-06-15 23:59:56 +0000487 AutoIndent Indent(P, 2);
488 P.formatLine("{0:X-4}:{1:X-8}-{2:X-8}, ", Segment, Begin, End);
489 uint32_t Count = Block.LineNumbers.size();
490 if (Lines.hasColumnInfo())
491 P.format("line/column/addr entries = {0}", Count);
492 else
493 P.format("line/addr entries = {0}", Count);
Zachary Turner4e950642017-06-15 23:56:19 +0000494
Zachary Turnerf2872b92017-06-15 23:59:56 +0000495 P.NewLine();
496 typesetLinesAndColumns(File, P, Begin, Block);
Zachary Turner4e950642017-06-15 23:56:19 +0000497 }
498 });
499
500 return Error::success();
501}
502
Zachary Turner7df69952017-06-22 20:57:39 +0000503Error DumpOutputStyle::dumpInlineeLines() {
Zachary Turner4e950642017-06-15 23:56:19 +0000504 printHeader(P, "Inlinee Lines");
Zachary Turner4e950642017-06-15 23:56:19 +0000505
Zachary Turnerf2872b92017-06-15 23:59:56 +0000506 iterateModuleSubsections<DebugInlineeLinesSubsectionRef>(
507 File, P, 2,
508 [this](uint32_t Modi, StringsAndChecksumsPrinter &Strings,
509 DebugInlineeLinesSubsectionRef &Lines) {
510 P.formatLine("{0,+8} | {1,+5} | {2}", "Inlinee", "Line", "Source File");
511 for (const auto &Entry : Lines) {
512 P.formatLine("{0,+8} | {1,+5} | ", Entry.Header->Inlinee,
513 fmtle(Entry.Header->SourceLineNum));
514 Strings.formatFromChecksumsOffset(P, Entry.Header->FileID, true);
Zachary Turner4e950642017-06-15 23:56:19 +0000515 }
Zachary Turnerf2872b92017-06-15 23:59:56 +0000516 P.NewLine();
Zachary Turner4e950642017-06-15 23:56:19 +0000517 });
518
Zachary Turner63055452017-06-15 22:24:24 +0000519 return Error::success();
520}
Zachary Turner0e327d02017-06-15 23:12:41 +0000521
Zachary Turner7df69952017-06-22 20:57:39 +0000522Error DumpOutputStyle::dumpXmi() {
Zachary Turner47d9a562017-06-16 00:04:24 +0000523 printHeader(P, "Cross Module Imports");
524 iterateModuleSubsections<DebugCrossModuleImportsSubsectionRef>(
525 File, P, 2,
526 [this](uint32_t Modi, StringsAndChecksumsPrinter &Strings,
527 DebugCrossModuleImportsSubsectionRef &Imports) {
528 P.formatLine("{0,=32} | {1}", "Imported Module", "Type IDs");
529
530 for (const auto &Xmi : Imports) {
531 auto ExpectedModule =
532 Strings.getNameFromStringTable(Xmi.Header->ModuleNameOffset);
533 StringRef Module;
534 SmallString<32> ModuleStorage;
535 if (!ExpectedModule) {
536 Module = "(unknown module)";
537 consumeError(ExpectedModule.takeError());
538 } else
539 Module = *ExpectedModule;
540 if (Module.size() > 32) {
541 ModuleStorage = "...";
542 ModuleStorage += Module.take_back(32 - 3);
543 Module = ModuleStorage;
544 }
545 std::vector<std::string> TIs;
546 for (const auto I : Xmi.Imports)
547 TIs.push_back(formatv("{0,+10:X+}", fmtle(I)));
548 std::string Result =
549 typesetItemList(TIs, P.getIndentLevel() + 35, 12, " ");
550 P.formatLine("{0,+32} | {1}", Module, Result);
551 }
552 });
553
554 return Error::success();
555}
556
Zachary Turner7df69952017-06-22 20:57:39 +0000557Error DumpOutputStyle::dumpXme() {
Zachary Turner47d9a562017-06-16 00:04:24 +0000558 printHeader(P, "Cross Module Exports");
559
560 iterateModuleSubsections<DebugCrossModuleExportsSubsectionRef>(
561 File, P, 2,
562 [this](uint32_t Modi, StringsAndChecksumsPrinter &Strings,
563 DebugCrossModuleExportsSubsectionRef &Exports) {
564 P.formatLine("{0,-10} | {1}", "Local ID", "Global ID");
565 for (const auto &Export : Exports) {
566 P.formatLine("{0,+10:X+} | {1}", TypeIndex(Export.Local),
567 TypeIndex(Export.Global));
568 }
569 });
570
571 return Error::success();
572}
573
Zachary Turner7df69952017-06-22 20:57:39 +0000574Error DumpOutputStyle::dumpStringTable() {
Zachary Turner63055452017-06-15 22:24:24 +0000575 printHeader(P, "String Table");
576
577 AutoIndent Indent(P);
578 auto IS = File.getStringTable();
579 if (!IS) {
580 P.formatLine("Not present in file");
581 consumeError(IS.takeError());
582 return Error::success();
583 }
584
585 if (IS->name_ids().empty()) {
586 P.formatLine("Empty");
587 return Error::success();
588 }
589
590 auto MaxID = std::max_element(IS->name_ids().begin(), IS->name_ids().end());
591 uint32_t Digits = NumDigits(*MaxID);
592
593 P.formatLine("{0} | {1}", fmt_align("ID", AlignStyle::Right, Digits),
594 "String");
595
596 std::vector<uint32_t> SortedIDs(IS->name_ids().begin(), IS->name_ids().end());
597 std::sort(SortedIDs.begin(), SortedIDs.end());
598 for (uint32_t I : SortedIDs) {
599 auto ES = IS->getStringForID(I);
600 llvm::SmallString<32> Str;
601 if (!ES) {
602 consumeError(ES.takeError());
603 Str = "Error reading string";
604 } else if (!ES->empty()) {
605 Str.append("'");
606 Str.append(*ES);
607 Str.append("'");
608 }
609
610 if (!Str.empty())
611 P.formatLine("{0} | {1}", fmt_align(I, AlignStyle::Right, Digits), Str);
612 }
613 return Error::success();
614}
615
Zachary Turner7df69952017-06-22 20:57:39 +0000616Error DumpOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
Zachary Turner63055452017-06-15 22:24:24 +0000617 assert(StreamIdx == StreamTPI || StreamIdx == StreamIPI);
618
619 bool Present = false;
Zachary Turnerf8a2e042017-06-15 23:04:42 +0000620 bool DumpTypes = false;
Zachary Turner63055452017-06-15 22:24:24 +0000621 bool DumpBytes = false;
Zachary Turnerf8a2e042017-06-15 23:04:42 +0000622 bool DumpExtras = false;
Zachary Turner59224cb2017-06-16 23:42:15 +0000623 std::vector<uint32_t> Indices;
Zachary Turner63055452017-06-15 22:24:24 +0000624 if (StreamIdx == StreamTPI) {
625 printHeader(P, "Types (TPI Stream)");
626 Present = File.hasPDBTpiStream();
Zachary Turner7df69952017-06-22 20:57:39 +0000627 DumpTypes = opts::dump::DumpTypes;
628 DumpBytes = opts::dump::DumpTypeData;
629 DumpExtras = opts::dump::DumpTypeExtras;
630 Indices.assign(opts::dump::DumpTypeIndex.begin(),
631 opts::dump::DumpTypeIndex.end());
Zachary Turner63055452017-06-15 22:24:24 +0000632 } else if (StreamIdx == StreamIPI) {
633 printHeader(P, "Types (IPI Stream)");
634 Present = File.hasPDBIpiStream();
Zachary Turner7df69952017-06-22 20:57:39 +0000635 DumpTypes = opts::dump::DumpIds;
636 DumpBytes = opts::dump::DumpIdData;
637 DumpExtras = opts::dump::DumpIdExtras;
638 Indices.assign(opts::dump::DumpIdIndex.begin(),
639 opts::dump::DumpIdIndex.end());
Zachary Turner63055452017-06-15 22:24:24 +0000640 }
641
642 AutoIndent Indent(P);
643 if (!Present) {
644 P.formatLine("Stream not present");
645 return Error::success();
646 }
647
648 ExitOnError Err("Unexpected error processing types");
649
650 auto &Stream = Err((StreamIdx == StreamTPI) ? File.getPDBTpiStream()
651 : File.getPDBIpiStream());
652
Zachary Turner59224cb2017-06-16 23:42:15 +0000653 auto &Types = Err(initializeTypes(StreamIdx));
Zachary Turner63055452017-06-15 22:24:24 +0000654
Zachary Turnerf8a2e042017-06-15 23:04:42 +0000655 if (DumpTypes) {
656 P.formatLine("Showing {0:N} records", Stream.getNumTypeRecords());
657 uint32_t Width =
658 NumDigits(TypeIndex::FirstNonSimpleIndex + Stream.getNumTypeRecords());
Zachary Turner63055452017-06-15 22:24:24 +0000659
Zachary Turnerf8a2e042017-06-15 23:04:42 +0000660 MinimalTypeDumpVisitor V(P, Width + 2, DumpBytes, DumpExtras, Types,
661 Stream.getHashValues());
Zachary Turner63055452017-06-15 22:24:24 +0000662
Zachary Turner59224cb2017-06-16 23:42:15 +0000663 if (Indices.empty()) {
664 if (auto EC = codeview::visitTypeStream(Types, V)) {
665 P.formatLine("An error occurred dumping type records: {0}",
666 toString(std::move(EC)));
667 }
668 } else {
669 for (const auto &I : Indices) {
670 TypeIndex TI(I);
671 CVType Type = Types.getType(TI);
672 if (auto EC = codeview::visitTypeRecord(Type, TI, V))
673 P.formatLine("An error occurred dumping type record {0}: {1}", TI,
674 toString(std::move(EC)));
675 }
Zachary Turnerf8a2e042017-06-15 23:04:42 +0000676 }
677 }
678
679 if (DumpExtras) {
680 P.NewLine();
681 auto IndexOffsets = Stream.getTypeIndexOffsets();
682 P.formatLine("Type Index Offsets:");
683 for (const auto &IO : IndexOffsets) {
684 AutoIndent Indent2(P);
685 P.formatLine("TI: {0}, Offset: {1}", IO.Type, fmtle(IO.Offset));
686 }
687
688 P.NewLine();
689 P.formatLine("Hash Adjusters:");
690 auto &Adjusters = Stream.getHashAdjusters();
691 auto &Strings = Err(File.getStringTable());
692 for (const auto &A : Adjusters) {
693 AutoIndent Indent2(P);
694 auto ExpectedStr = Strings.getStringForID(A.first);
695 TypeIndex TI(A.second);
696 if (ExpectedStr)
697 P.formatLine("`{0}` -> {1}", *ExpectedStr, TI);
698 else {
699 P.formatLine("unknown str id ({0}) -> {1}", A.first, TI);
700 consumeError(ExpectedStr.takeError());
701 }
702 }
Zachary Turner63055452017-06-15 22:24:24 +0000703 }
704 return Error::success();
705}
706
707Expected<codeview::LazyRandomTypeCollection &>
Zachary Turner7df69952017-06-22 20:57:39 +0000708DumpOutputStyle::initializeTypes(uint32_t SN) {
Zachary Turner63055452017-06-15 22:24:24 +0000709 auto &TypeCollection = (SN == StreamTPI) ? TpiTypes : IpiTypes;
710 auto Tpi =
711 (SN == StreamTPI) ? File.getPDBTpiStream() : File.getPDBIpiStream();
712 if (!Tpi)
713 return Tpi.takeError();
714
715 if (!TypeCollection) {
716 auto &Types = Tpi->typeArray();
717 uint32_t Count = Tpi->getNumTypeRecords();
718 auto Offsets = Tpi->getTypeIndexOffsets();
719 TypeCollection =
720 llvm::make_unique<LazyRandomTypeCollection>(Types, Count, Offsets);
721 }
722
723 return *TypeCollection;
724}
725
Zachary Turner7df69952017-06-22 20:57:39 +0000726Error DumpOutputStyle::dumpModuleSyms() {
Zachary Turner63055452017-06-15 22:24:24 +0000727 printHeader(P, "Symbols");
728
729 AutoIndent Indent(P);
730 if (!File.hasPDBDbiStream()) {
731 P.formatLine("DBI Stream not present");
732 return Error::success();
733 }
734
735 ExitOnError Err("Unexpected error processing symbols");
736
737 auto &Stream = Err(File.getPDBDbiStream());
738
Zachary Turner59224cb2017-06-16 23:42:15 +0000739 auto &Types = Err(initializeTypes(StreamTPI));
Zachary Turner63055452017-06-15 22:24:24 +0000740
741 const DbiModuleList &Modules = Stream.modules();
742 uint32_t Count = Modules.getModuleCount();
743 uint32_t Digits = NumDigits(Count);
744 for (uint32_t I = 0; I < Count; ++I) {
745 auto Modi = Modules.getModuleDescriptor(I);
746 P.formatLine("Mod {0:4} | `{1}`: ", fmt_align(I, AlignStyle::Right, Digits),
747 Modi.getModuleName());
748 uint16_t ModiStream = Modi.getModuleStreamIndex();
749 if (ModiStream == kInvalidStreamIndex) {
750 P.formatLine(" <symbols not present>");
751 continue;
752 }
753 auto ModStreamData = MappedBlockStream::createIndexedStream(
754 File.getMsfLayout(), File.getMsfBuffer(), ModiStream,
755 File.getAllocator());
756
757 ModuleDebugStreamRef ModS(Modi, std::move(ModStreamData));
758 if (auto EC = ModS.reload()) {
759 P.formatLine("Error loading module stream {0}. {1}", I,
760 toString(std::move(EC)));
761 continue;
762 }
763
764 SymbolVisitorCallbackPipeline Pipeline;
765 SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
Zachary Turner7df69952017-06-22 20:57:39 +0000766 MinimalSymbolDumper Dumper(P, opts::dump::DumpSymRecordBytes, Types);
Zachary Turner63055452017-06-15 22:24:24 +0000767
768 Pipeline.addCallbackToPipeline(Deserializer);
769 Pipeline.addCallbackToPipeline(Dumper);
770 CVSymbolVisitor Visitor(Pipeline);
771 if (auto EC = Visitor.visitSymbolStream(ModS.getSymbolArray())) {
772 P.formatLine("Error while processing symbol records. {0}",
773 toString(std::move(EC)));
774 continue;
775 }
776 }
777 return Error::success();
778}
779
Zachary Turner7df69952017-06-22 20:57:39 +0000780Error DumpOutputStyle::dumpPublics() {
Zachary Turner63055452017-06-15 22:24:24 +0000781 printHeader(P, "Public Symbols");
782
783 AutoIndent Indent(P);
784 if (!File.hasPDBPublicsStream()) {
785 P.formatLine("Publics stream not present");
786 return Error::success();
787 }
788
789 ExitOnError Err("Error dumping publics stream");
790
Zachary Turner59224cb2017-06-16 23:42:15 +0000791 auto &Types = Err(initializeTypes(StreamTPI));
Zachary Turner63055452017-06-15 22:24:24 +0000792 auto &Publics = Err(File.getPDBPublicsStream());
793 SymbolVisitorCallbackPipeline Pipeline;
794 SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
Zachary Turner7df69952017-06-22 20:57:39 +0000795 MinimalSymbolDumper Dumper(P, opts::dump::DumpSymRecordBytes, Types);
Zachary Turner63055452017-06-15 22:24:24 +0000796
797 Pipeline.addCallbackToPipeline(Deserializer);
798 Pipeline.addCallbackToPipeline(Dumper);
799 CVSymbolVisitor Visitor(Pipeline);
800 auto ExpectedSymbols = Publics.getSymbolArray();
801 if (!ExpectedSymbols) {
802 P.formatLine("Could not read public symbol record stream");
803 return Error::success();
804 }
805
806 if (auto EC = Visitor.visitSymbolStream(*ExpectedSymbols))
807 P.formatLine("Error while processing public symbol records. {0}",
808 toString(std::move(EC)));
809
810 return Error::success();
811}
812
813static std::string formatSectionCharacteristics(uint32_t IndentLevel,
814 uint32_t C) {
815 using SC = COFF::SectionCharacteristics;
816 std::vector<std::string> Opts;
817 if (C == COFF::SC_Invalid)
818 return "invalid";
819 if (C == 0)
820 return "none";
821
822 PUSH_FLAG(SC, IMAGE_SCN_TYPE_NOLOAD, C, "IMAGE_SCN_TYPE_NOLOAD");
823 PUSH_FLAG(SC, IMAGE_SCN_TYPE_NO_PAD, C, "IMAGE_SCN_TYPE_NO_PAD");
824 PUSH_FLAG(SC, IMAGE_SCN_CNT_CODE, C, "IMAGE_SCN_CNT_CODE");
825 PUSH_FLAG(SC, IMAGE_SCN_CNT_INITIALIZED_DATA, C,
826 "IMAGE_SCN_CNT_INITIALIZED_DATA");
827 PUSH_FLAG(SC, IMAGE_SCN_CNT_UNINITIALIZED_DATA, C,
828 "IMAGE_SCN_CNT_UNINITIALIZED_DATA");
829 PUSH_FLAG(SC, IMAGE_SCN_LNK_OTHER, C, "IMAGE_SCN_LNK_OTHER");
830 PUSH_FLAG(SC, IMAGE_SCN_LNK_INFO, C, "IMAGE_SCN_LNK_INFO");
831 PUSH_FLAG(SC, IMAGE_SCN_LNK_REMOVE, C, "IMAGE_SCN_LNK_REMOVE");
832 PUSH_FLAG(SC, IMAGE_SCN_LNK_COMDAT, C, "IMAGE_SCN_LNK_COMDAT");
833 PUSH_FLAG(SC, IMAGE_SCN_GPREL, C, "IMAGE_SCN_GPREL");
834 PUSH_FLAG(SC, IMAGE_SCN_MEM_PURGEABLE, C, "IMAGE_SCN_MEM_PURGEABLE");
835 PUSH_FLAG(SC, IMAGE_SCN_MEM_16BIT, C, "IMAGE_SCN_MEM_16BIT");
836 PUSH_FLAG(SC, IMAGE_SCN_MEM_LOCKED, C, "IMAGE_SCN_MEM_LOCKED");
837 PUSH_FLAG(SC, IMAGE_SCN_MEM_PRELOAD, C, "IMAGE_SCN_MEM_PRELOAD");
838 PUSH_FLAG(SC, IMAGE_SCN_GPREL, C, "IMAGE_SCN_GPREL");
839 PUSH_FLAG(SC, IMAGE_SCN_GPREL, C, "IMAGE_SCN_GPREL");
840 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_1BYTES, C,
841 "IMAGE_SCN_ALIGN_1BYTES");
842 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_2BYTES, C,
843 "IMAGE_SCN_ALIGN_2BYTES");
844 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_4BYTES, C,
845 "IMAGE_SCN_ALIGN_4BYTES");
846 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_8BYTES, C,
847 "IMAGE_SCN_ALIGN_8BYTES");
848 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_16BYTES, C,
849 "IMAGE_SCN_ALIGN_16BYTES");
850 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_32BYTES, C,
851 "IMAGE_SCN_ALIGN_32BYTES");
852 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_64BYTES, C,
853 "IMAGE_SCN_ALIGN_64BYTES");
854 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_128BYTES, C,
855 "IMAGE_SCN_ALIGN_128BYTES");
856 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_256BYTES, C,
857 "IMAGE_SCN_ALIGN_256BYTES");
858 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_512BYTES, C,
859 "IMAGE_SCN_ALIGN_512BYTES");
860 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_1024BYTES, C,
861 "IMAGE_SCN_ALIGN_1024BYTES");
862 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_2048BYTES, C,
863 "IMAGE_SCN_ALIGN_2048BYTES");
864 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_4096BYTES, C,
865 "IMAGE_SCN_ALIGN_4096BYTES");
866 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_8192BYTES, C,
867 "IMAGE_SCN_ALIGN_8192BYTES");
868 PUSH_FLAG(SC, IMAGE_SCN_LNK_NRELOC_OVFL, C, "IMAGE_SCN_LNK_NRELOC_OVFL");
869 PUSH_FLAG(SC, IMAGE_SCN_MEM_DISCARDABLE, C, "IMAGE_SCN_MEM_DISCARDABLE");
870 PUSH_FLAG(SC, IMAGE_SCN_MEM_NOT_CACHED, C, "IMAGE_SCN_MEM_NOT_CACHED");
871 PUSH_FLAG(SC, IMAGE_SCN_MEM_NOT_PAGED, C, "IMAGE_SCN_MEM_NOT_PAGED");
872 PUSH_FLAG(SC, IMAGE_SCN_MEM_SHARED, C, "IMAGE_SCN_MEM_SHARED");
873 PUSH_FLAG(SC, IMAGE_SCN_MEM_EXECUTE, C, "IMAGE_SCN_MEM_EXECUTE");
874 PUSH_FLAG(SC, IMAGE_SCN_MEM_READ, C, "IMAGE_SCN_MEM_READ");
875 PUSH_FLAG(SC, IMAGE_SCN_MEM_WRITE, C, "IMAGE_SCN_MEM_WRITE");
Zachary Turner47d9a562017-06-16 00:04:24 +0000876 return typesetItemList(Opts, IndentLevel, 3, " | ");
Zachary Turner63055452017-06-15 22:24:24 +0000877}
878
879static std::string formatSegMapDescriptorFlag(uint32_t IndentLevel,
880 OMFSegDescFlags Flags) {
881 std::vector<std::string> Opts;
882 if (Flags == OMFSegDescFlags::None)
883 return "none";
884
885 PUSH_FLAG(OMFSegDescFlags, Read, Flags, "read");
886 PUSH_FLAG(OMFSegDescFlags, Write, Flags, "write");
887 PUSH_FLAG(OMFSegDescFlags, Execute, Flags, "execute");
888 PUSH_FLAG(OMFSegDescFlags, AddressIs32Bit, Flags, "32 bit addr");
889 PUSH_FLAG(OMFSegDescFlags, IsSelector, Flags, "selector");
890 PUSH_FLAG(OMFSegDescFlags, IsAbsoluteAddress, Flags, "absolute addr");
891 PUSH_FLAG(OMFSegDescFlags, IsGroup, Flags, "group");
Zachary Turner47d9a562017-06-16 00:04:24 +0000892 return typesetItemList(Opts, IndentLevel, 4, " | ");
Zachary Turner63055452017-06-15 22:24:24 +0000893}
894
Zachary Turner7df69952017-06-22 20:57:39 +0000895Error DumpOutputStyle::dumpSectionContribs() {
Zachary Turner63055452017-06-15 22:24:24 +0000896 printHeader(P, "Section Contributions");
897 ExitOnError Err("Error dumping publics stream");
898
899 AutoIndent Indent(P);
900 if (!File.hasPDBDbiStream()) {
901 P.formatLine(
902 "Section contribs require a DBI Stream, which could not be loaded");
903 return Error::success();
904 }
905
906 auto &Dbi = Err(File.getPDBDbiStream());
907
908 class Visitor : public ISectionContribVisitor {
909 public:
910 Visitor(LinePrinter &P) : P(P) {}
911 void visit(const SectionContrib &SC) override {
912 P.formatLine(
913 "SC | mod = {2}, {0}, size = {1}, data crc = {3}, reloc crc = {4}",
914 formatSegmentOffset(SC.ISect, SC.Off), fmtle(SC.Size), fmtle(SC.Imod),
915 fmtle(SC.DataCrc), fmtle(SC.RelocCrc));
916 P.formatLine(" {0}",
917 formatSectionCharacteristics(P.getIndentLevel() + 6,
918 SC.Characteristics));
919 }
920 void visit(const SectionContrib2 &SC) override {
921 P.formatLine("SC2 | mod = {2}, {0}, size = {1}, data crc = {3}, reloc "
922 "crc = {4}, coff section = {5}",
923 formatSegmentOffset(SC.Base.ISect, SC.Base.Off),
924 fmtle(SC.Base.Size), fmtle(SC.Base.Imod),
925 fmtle(SC.Base.DataCrc), fmtle(SC.Base.RelocCrc),
926 fmtle(SC.ISectCoff));
927 P.formatLine(" {0}",
928 formatSectionCharacteristics(P.getIndentLevel() + 6,
929 SC.Base.Characteristics));
930 }
931
932 private:
933 LinePrinter &P;
934 };
935
936 Visitor V(P);
937 Dbi.visitSectionContributions(V);
938 return Error::success();
939}
940
Zachary Turner7df69952017-06-22 20:57:39 +0000941Error DumpOutputStyle::dumpSectionMap() {
Zachary Turner63055452017-06-15 22:24:24 +0000942 printHeader(P, "Section Map");
943 ExitOnError Err("Error dumping section map");
944
945 AutoIndent Indent(P);
946 if (!File.hasPDBDbiStream()) {
947 P.formatLine("Dumping the section map requires a DBI Stream, which could "
948 "not be loaded");
949 return Error::success();
950 }
951
952 auto &Dbi = Err(File.getPDBDbiStream());
953
954 uint32_t I = 0;
955 for (auto &M : Dbi.getSectionMap()) {
956 P.formatLine(
957 "Section {0:4} | ovl = {0}, group = {1}, frame = {2}, name = {3}", I,
958 fmtle(M.Ovl), fmtle(M.Group), fmtle(M.Frame), fmtle(M.SecName));
959 P.formatLine(" class = {0}, offset = {1}, size = {2}",
960 fmtle(M.ClassName), fmtle(M.Offset), fmtle(M.SecByteLength));
961 P.formatLine(" flags = {0}",
962 formatSegMapDescriptorFlag(
963 P.getIndentLevel() + 13,
964 static_cast<OMFSegDescFlags>(uint16_t(M.Flags))));
965 ++I;
966 }
967 return Error::success();
968}