blob: 515125739b32ded0c8cdab1da6ddbb5df1e8a40f [file] [log] [blame]
Zachary Turner63055452017-06-15 22:24:24 +00001//===- RawOutputStyle.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 "RawOutputStyle.h"
11
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
67RawOutputStyle::RawOutputStyle(PDBFile &File)
68 : File(File), P(2, false, outs()) {}
69
70Error RawOutputStyle::dump() {
71 if (opts::raw::DumpSummary) {
72 if (auto EC = dumpFileSummary())
73 return EC;
74 P.NewLine();
75 }
76
77 if (opts::raw::DumpStreams) {
78 if (auto EC = dumpStreamSummary())
79 return EC;
80 P.NewLine();
81 }
82
83 if (opts::raw::DumpBlockRange.hasValue()) {
84 if (auto EC = dumpBlockRanges())
85 return EC;
86 P.NewLine();
87 }
88
89 if (!opts::raw::DumpStreamData.empty()) {
90 if (auto EC = dumpStreamBytes())
91 return EC;
92 P.NewLine();
93 }
94
95 if (opts::raw::DumpStringTable) {
96 if (auto EC = dumpStringTable())
97 return EC;
98 P.NewLine();
99 }
100
101 if (opts::raw::DumpModules) {
102 if (auto EC = dumpModules())
103 return EC;
104 }
105
Zachary Turner0e327d02017-06-15 23:12:41 +0000106 if (opts::raw::DumpModuleFiles) {
107 if (auto EC = dumpModuleFiles())
108 return EC;
109 }
110
Zachary Turner4e950642017-06-15 23:56:19 +0000111 if (opts::raw::DumpLines) {
112 if (auto EC = dumpLines())
113 return EC;
114 }
115
116 if (opts::raw::DumpInlineeLines) {
117 if (auto EC = dumpInlineeLines())
118 return EC;
119 }
120
Zachary Turner47d9a562017-06-16 00:04:24 +0000121 if (opts::raw::DumpXmi) {
122 if (auto EC = dumpXmi())
123 return EC;
124 }
125
126 if (opts::raw::DumpXme) {
127 if (auto EC = dumpXme())
128 return EC;
129 }
130
Zachary Turnerf8a2e042017-06-15 23:04:42 +0000131 if (opts::raw::DumpTypes || opts::raw::DumpTypeExtras) {
Zachary Turner63055452017-06-15 22:24:24 +0000132 if (auto EC = dumpTpiStream(StreamTPI))
133 return EC;
134 }
135
Zachary Turnerf8a2e042017-06-15 23:04:42 +0000136 if (opts::raw::DumpIds || opts::raw::DumpIdExtras) {
Zachary Turner63055452017-06-15 22:24:24 +0000137 if (auto EC = dumpTpiStream(StreamIPI))
138 return EC;
139 }
140
141 if (opts::raw::DumpPublics) {
142 if (auto EC = dumpPublics())
143 return EC;
144 }
145
146 if (opts::raw::DumpSymbols) {
147 if (auto EC = dumpModuleSyms())
148 return EC;
149 }
150
151 if (opts::raw::DumpSectionContribs) {
152 if (auto EC = dumpSectionContribs())
153 return EC;
154 }
155
156 if (opts::raw::DumpSectionMap) {
157 if (auto EC = dumpSectionMap())
158 return EC;
159 }
160
161 return Error::success();
162}
163
164static void printHeader(LinePrinter &P, const Twine &S) {
165 P.NewLine();
166 P.formatLine("{0,=60}", S);
167 P.formatLine("{0}", fmt_repeat('=', 60));
168}
169
170Error RawOutputStyle::dumpFileSummary() {
171 printHeader(P, "Summary");
172
173 ExitOnError Err("Invalid PDB Format");
174
175 AutoIndent Indent(P);
176 P.formatLine("Block Size: {0}", File.getBlockSize());
177 P.formatLine("Number of blocks: {0}", File.getBlockCount());
178 P.formatLine("Number of streams: {0}", File.getNumStreams());
179
180 auto &PS = Err(File.getPDBInfoStream());
181 P.formatLine("Signature: {0}", PS.getSignature());
182 P.formatLine("Age: {0}", PS.getAge());
183 P.formatLine("GUID: {0}", fmt_guid(PS.getGuid().Guid));
184 P.formatLine("Features: {0:x+}", static_cast<uint32_t>(PS.getFeatures()));
185 P.formatLine("Has Debug Info: {0}", File.hasPDBDbiStream());
186 P.formatLine("Has Types: {0}", File.hasPDBTpiStream());
187 P.formatLine("Has IDs: {0}", File.hasPDBIpiStream());
188 P.formatLine("Has Globals: {0}", File.hasPDBGlobalsStream());
189 P.formatLine("Has Publics: {0}", File.hasPDBPublicsStream());
190 if (File.hasPDBDbiStream()) {
191 auto &DBI = Err(File.getPDBDbiStream());
192 P.formatLine("Is incrementally linked: {0}", DBI.isIncrementallyLinked());
193 P.formatLine("Has conflicting types: {0}", DBI.hasCTypes());
194 P.formatLine("Is stripped: {0}", DBI.isStripped());
195 }
196
197 return Error::success();
198}
199
200Error RawOutputStyle::dumpStreamSummary() {
201 printHeader(P, "Streams");
202
203 if (StreamPurposes.empty())
204 discoverStreamPurposes(File, StreamPurposes);
205
206 AutoIndent Indent(P);
207 uint32_t StreamCount = File.getNumStreams();
208
209 for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
210 P.formatLine(
211 "Stream {0}: [{1}] ({2} bytes)",
212 fmt_align(StreamIdx, AlignStyle::Right, NumDigits(StreamCount)),
213 StreamPurposes[StreamIdx], File.getStreamByteSize(StreamIdx));
214 }
215
216 return Error::success();
217}
218
219Error RawOutputStyle::dumpBlockRanges() {
220 printHeader(P, "MSF Blocks");
221
222 auto &R = *opts::raw::DumpBlockRange;
223 uint32_t Max = R.Max.getValueOr(R.Min);
224
225 AutoIndent Indent(P);
226 if (Max < R.Min)
227 return make_error<StringError>(
228 "Invalid block range specified. Max < Min",
229 std::make_error_code(std::errc::bad_address));
230 if (Max >= File.getBlockCount())
231 return make_error<StringError>(
232 "Invalid block range specified. Requested block out of bounds",
233 std::make_error_code(std::errc::bad_address));
234
235 for (uint32_t I = R.Min; I <= Max; ++I) {
236 auto ExpectedData = File.getBlockData(I, File.getBlockSize());
237 if (!ExpectedData)
238 return ExpectedData.takeError();
239 std::string Label = formatv("Block {0}", I).str();
240 P.formatBinary(Label, *ExpectedData, 0);
241 }
242
243 return Error::success();
244}
245
246static Error parseStreamSpec(StringRef Str, uint32_t &SI, uint32_t &Offset,
247 uint32_t &Size) {
248 if (Str.consumeInteger(0, SI))
249 return make_error<RawError>(raw_error_code::invalid_format,
250 "Invalid Stream Specification");
251 if (Str.consume_front(":")) {
252 if (Str.consumeInteger(0, Offset))
253 return make_error<RawError>(raw_error_code::invalid_format,
254 "Invalid Stream Specification");
255 }
256 if (Str.consume_front("@")) {
257 if (Str.consumeInteger(0, Size))
258 return make_error<RawError>(raw_error_code::invalid_format,
259 "Invalid Stream Specification");
260 }
261 if (!Str.empty())
262 return make_error<RawError>(raw_error_code::invalid_format,
263 "Invalid Stream Specification");
264 return Error::success();
265}
266
267Error RawOutputStyle::dumpStreamBytes() {
268 if (StreamPurposes.empty())
269 discoverStreamPurposes(File, StreamPurposes);
270
271 printHeader(P, "Stream Data");
272 ExitOnError Err("Unexpected error reading stream data");
273
274 for (auto &Str : opts::raw::DumpStreamData) {
275 uint32_t SI = 0;
276 uint32_t Begin = 0;
277 uint32_t Size = 0;
278 uint32_t End = 0;
279
280 if (auto EC = parseStreamSpec(Str, SI, Begin, Size))
281 return EC;
282
283 AutoIndent Indent(P);
284 if (SI >= File.getNumStreams()) {
285 P.formatLine("Stream {0}: Not present", SI);
286 continue;
287 }
288
289 auto S = MappedBlockStream::createIndexedStream(
290 File.getMsfLayout(), File.getMsfBuffer(), SI, File.getAllocator());
291 if (!S) {
292 P.NewLine();
293 P.formatLine("Stream {0}: Not present", SI);
294 continue;
295 }
296
297 if (Size == 0)
298 End = S->getLength();
299 else
300 End = std::min(Begin + Size, S->getLength());
301
302 P.formatLine("Stream {0} ({1:N} bytes): {2}", SI, S->getLength(),
303 StreamPurposes[SI]);
304 AutoIndent Indent2(P);
305
306 BinaryStreamReader R(*S);
307 ArrayRef<uint8_t> StreamData;
308 Err(R.readBytes(StreamData, S->getLength()));
309 Size = End - Begin;
310 StreamData = StreamData.slice(Begin, Size);
311 P.formatBinary("Data", StreamData, Begin);
312 }
313 return Error::success();
314}
315
Zachary Turner0e327d02017-06-15 23:12:41 +0000316static Expected<ModuleDebugStreamRef> getModuleDebugStream(PDBFile &File,
317 uint32_t Index) {
318 ExitOnError Err("Unexpected error");
319
320 auto &Dbi = Err(File.getPDBDbiStream());
321 const auto &Modules = Dbi.modules();
322 auto Modi = Modules.getModuleDescriptor(Index);
323
324 uint16_t ModiStream = Modi.getModuleStreamIndex();
325 if (ModiStream == kInvalidStreamIndex)
326 return make_error<RawError>(raw_error_code::no_stream,
327 "Module stream not present");
328
329 auto ModStreamData = MappedBlockStream::createIndexedStream(
330 File.getMsfLayout(), File.getMsfBuffer(), ModiStream,
331 File.getAllocator());
332
333 ModuleDebugStreamRef ModS(Modi, std::move(ModStreamData));
334 if (auto EC = ModS.reload())
335 return make_error<RawError>(raw_error_code::corrupt_file,
336 "Invalid module stream");
337
338 return std::move(ModS);
339}
340
Zachary Turner0e327d02017-06-15 23:12:41 +0000341static std::string formatChecksumKind(FileChecksumKind Kind) {
342 switch (Kind) {
343 RETURN_CASE(FileChecksumKind, None, "None");
344 RETURN_CASE(FileChecksumKind, MD5, "MD5");
345 RETURN_CASE(FileChecksumKind, SHA1, "SHA-1");
346 RETURN_CASE(FileChecksumKind, SHA256, "SHA-256");
347 }
348 return formatUnknownEnum(Kind);
349}
350
Zachary Turner4e950642017-06-15 23:56:19 +0000351namespace {
352class StringsAndChecksumsPrinter {
353 const DebugStringTableSubsectionRef &extractStringTable(PDBFile &File) {
354 ExitOnError Err("Unexpected error processing modules");
355 return Err(File.getStringTable()).getStringTable();
356 }
357
358 template <typename... Args>
359 void formatInternal(LinePrinter &Printer, bool Append,
360 Args &&... args) const {
361 if (Append)
362 Printer.format(std::forward<Args>(args)...);
363 else
364 Printer.formatLine(std::forward<Args>(args)...);
365 }
366
367public:
368 StringsAndChecksumsPrinter(PDBFile &File, uint32_t Modi)
369 : Records(extractStringTable(File)) {
370 auto MDS = getModuleDebugStream(File, Modi);
371 if (!MDS) {
372 consumeError(MDS.takeError());
373 return;
374 }
375
376 DebugStream = llvm::make_unique<ModuleDebugStreamRef>(std::move(*MDS));
377 Records.initialize(MDS->subsections());
378 if (Records.hasChecksums()) {
379 for (const auto &Entry : Records.checksums()) {
380 auto S = Records.strings().getString(Entry.FileNameOffset);
381 if (!S)
382 continue;
383 ChecksumsByFile[*S] = Entry;
384 }
385 }
386 }
387
388 Expected<StringRef> getNameFromStringTable(uint32_t Offset) const {
389 return Records.strings().getString(Offset);
390 }
391
392 void formatFromFileName(LinePrinter &Printer, StringRef File,
393 bool Append = false) const {
394 auto FC = ChecksumsByFile.find(File);
395 if (FC == ChecksumsByFile.end()) {
396 formatInternal(Printer, Append, "- (no checksum) {0}", File);
397 return;
398 }
399
400 formatInternal(Printer, Append, "- ({0}: {1}) {2}",
401 formatChecksumKind(FC->getValue().Kind),
402 toHex(FC->getValue().Checksum), File);
403 }
404
405 void formatFromChecksumsOffset(LinePrinter &Printer, uint32_t Offset,
406 bool Append = false) const {
407 if (!Records.hasChecksums()) {
408 formatInternal(Printer, Append, "(unknown file name offset {0})", Offset);
409 return;
410 }
411
412 auto Iter = Records.checksums().getArray().at(Offset);
413 if (Iter == Records.checksums().getArray().end()) {
414 formatInternal(Printer, Append, "(unknown file name offset {0})", Offset);
415 return;
416 }
417
418 uint32_t FO = Iter->FileNameOffset;
419 auto ExpectedFile = getNameFromStringTable(FO);
420 if (!ExpectedFile) {
421 formatInternal(Printer, Append, "(unknown file name offset {0})", Offset);
422 consumeError(ExpectedFile.takeError());
423 return;
424 }
425 if (Iter->Kind == FileChecksumKind::None) {
426 formatInternal(Printer, Append, "{0} (no checksum)", *ExpectedFile);
427 } else {
428 formatInternal(Printer, Append, "{0} ({1}: {2})", *ExpectedFile,
429 formatChecksumKind(Iter->Kind), toHex(Iter->Checksum));
430 }
431 }
432
433 std::unique_ptr<ModuleDebugStreamRef> DebugStream;
434 StringsAndChecksumsRef Records;
435 StringMap<FileChecksumEntry> ChecksumsByFile;
436};
437} // namespace
438
Zachary Turnerf2872b92017-06-15 23:59:56 +0000439template <typename CallbackT>
440static void iterateModules(PDBFile &File, LinePrinter &P, uint32_t IndentLevel,
441 CallbackT Callback) {
442 AutoIndent Indent(P);
443 if (!File.hasPDBDbiStream()) {
444 P.formatLine("DBI Stream not present");
445 return;
446 }
447
448 ExitOnError Err("Unexpected error processing modules");
449
450 auto &Stream = Err(File.getPDBDbiStream());
451
452 const DbiModuleList &Modules = Stream.modules();
453 uint32_t Count = Modules.getModuleCount();
454 uint32_t Digits = NumDigits(Count);
455 for (uint32_t I = 0; I < Count; ++I) {
456 auto Modi = Modules.getModuleDescriptor(I);
457 P.formatLine("Mod {0:4} | `{1}`: ", fmt_align(I, AlignStyle::Right, Digits),
458 Modi.getModuleName());
459
460 StringsAndChecksumsPrinter Strings(File, I);
461 AutoIndent Indent2(P, IndentLevel);
462 Callback(I, Strings);
463 }
464}
465
466template <typename SubsectionT>
467static void iterateModuleSubsections(
468 PDBFile &File, LinePrinter &P, uint32_t IndentLevel,
469 llvm::function_ref<void(uint32_t, StringsAndChecksumsPrinter &,
470 SubsectionT &)>
471 Callback) {
472
473 iterateModules(
474 File, P, IndentLevel,
475 [&File, &Callback](uint32_t Modi, StringsAndChecksumsPrinter &Strings) {
476 auto MDS = getModuleDebugStream(File, Modi);
477 if (!MDS) {
478 consumeError(MDS.takeError());
479 return;
480 }
481
482 for (const auto &SS : MDS->subsections()) {
483 SubsectionT Subsection;
484
485 if (SS.kind() != Subsection.kind())
486 continue;
487
488 BinaryStreamReader Reader(SS.getRecordData());
489 if (auto EC = Subsection.initialize(Reader))
490 continue;
491 Callback(Modi, Strings, Subsection);
492 }
493 });
494}
495
Zachary Turner63055452017-06-15 22:24:24 +0000496Error RawOutputStyle::dumpModules() {
497 printHeader(P, "Modules");
498
499 AutoIndent Indent(P);
500 if (!File.hasPDBDbiStream()) {
501 P.formatLine("DBI Stream not present");
502 return Error::success();
503 }
504
Zachary Turner0e327d02017-06-15 23:12:41 +0000505 ExitOnError Err("Unexpected error processing modules");
Zachary Turner63055452017-06-15 22:24:24 +0000506
507 auto &Stream = Err(File.getPDBDbiStream());
508
509 const DbiModuleList &Modules = Stream.modules();
510 uint32_t Count = Modules.getModuleCount();
511 uint32_t Digits = NumDigits(Count);
512 for (uint32_t I = 0; I < Count; ++I) {
513 auto Modi = Modules.getModuleDescriptor(I);
514 P.formatLine("Mod {0:4} | Name: `{1}`: ",
515 fmt_align(I, AlignStyle::Right, Digits), Modi.getModuleName());
516 P.formatLine(" Obj: `{0}`: ", Modi.getObjFileName());
517 P.formatLine(" debug stream: {0}, # files: {1}, has ec info: {2}",
518 Modi.getModuleStreamIndex(), Modi.getNumberOfFiles(),
519 Modi.hasECInfo());
Zachary Turner0e327d02017-06-15 23:12:41 +0000520 }
521 return Error::success();
522}
523
524Error RawOutputStyle::dumpModuleFiles() {
525 printHeader(P, "Files");
526
Zachary Turner0e327d02017-06-15 23:12:41 +0000527 ExitOnError Err("Unexpected error processing modules");
528
Zachary Turnerf2872b92017-06-15 23:59:56 +0000529 iterateModules(
530 File, P, 11,
531 [this, &Err](uint32_t Modi, StringsAndChecksumsPrinter &Strings) {
532 auto &Stream = Err(File.getPDBDbiStream());
Zachary Turner0e327d02017-06-15 23:12:41 +0000533
Zachary Turnerf2872b92017-06-15 23:59:56 +0000534 const DbiModuleList &Modules = Stream.modules();
535 for (const auto &F : Modules.source_files(Modi)) {
536 Strings.formatFromFileName(P, F);
537 }
538 });
Zachary Turner4e950642017-06-15 23:56:19 +0000539 return Error::success();
540}
541
542static void typesetLinesAndColumns(PDBFile &File, LinePrinter &P,
543 uint32_t Start, const LineColumnEntry &E) {
544 const uint32_t kMaxCharsPerLineNumber = 4; // 4 digit line number
545 uint32_t MinColumnWidth = kMaxCharsPerLineNumber + 5;
546
547 // Let's try to keep it under 100 characters
548 constexpr uint32_t kMaxRowLength = 100;
549 // At least 3 spaces between columns.
550 uint32_t ColumnsPerRow = kMaxRowLength / (MinColumnWidth + 3);
551 uint32_t ItemsLeft = E.LineNumbers.size();
552 auto LineIter = E.LineNumbers.begin();
553 while (ItemsLeft != 0) {
554 uint32_t RowColumns = std::min(ItemsLeft, ColumnsPerRow);
555 for (uint32_t I = 0; I < RowColumns; ++I) {
556 LineInfo Line(LineIter->Flags);
557 std::string LineStr;
558 if (Line.isAlwaysStepInto())
559 LineStr = "ASI";
560 else if (Line.isNeverStepInto())
561 LineStr = "NSI";
Zachary Turner0e327d02017-06-15 23:12:41 +0000562 else
Zachary Turner4e950642017-06-15 23:56:19 +0000563 LineStr = utostr(Line.getStartLine());
564 char Statement = Line.isStatement() ? ' ' : '!';
565 P.format("{0} {1:X-} {2} ",
566 fmt_align(LineStr, AlignStyle::Right, kMaxCharsPerLineNumber),
567 fmt_align(Start + LineIter->Offset, AlignStyle::Right, 8, '0'),
568 Statement);
569 ++LineIter;
570 --ItemsLeft;
Zachary Turner63055452017-06-15 22:24:24 +0000571 }
Zachary Turner4e950642017-06-15 23:56:19 +0000572 P.NewLine();
Zachary Turner63055452017-06-15 22:24:24 +0000573 }
Zachary Turner4e950642017-06-15 23:56:19 +0000574}
575
576Error RawOutputStyle::dumpLines() {
577 printHeader(P, "Lines");
Zachary Turner4e950642017-06-15 23:56:19 +0000578
Zachary Turnerf2872b92017-06-15 23:59:56 +0000579 uint32_t LastModi = UINT32_MAX;
580 uint32_t LastNameIndex = UINT32_MAX;
581 iterateModuleSubsections<DebugLinesSubsectionRef>(
582 File, P, 4,
583 [this, &LastModi, &LastNameIndex](uint32_t Modi,
584 StringsAndChecksumsPrinter &Strings,
585 DebugLinesSubsectionRef &Lines) {
586 uint16_t Segment = Lines.header()->RelocSegment;
587 uint32_t Begin = Lines.header()->RelocOffset;
588 uint32_t End = Begin + Lines.header()->CodeSize;
589 for (const auto &Block : Lines) {
590 if (LastModi != Modi || LastNameIndex != Block.NameIndex) {
591 LastModi = Modi;
592 LastNameIndex = Block.NameIndex;
593 Strings.formatFromChecksumsOffset(P, Block.NameIndex);
Zachary Turner4e950642017-06-15 23:56:19 +0000594 }
595
Zachary Turnerf2872b92017-06-15 23:59:56 +0000596 AutoIndent Indent(P, 2);
597 P.formatLine("{0:X-4}:{1:X-8}-{2:X-8}, ", Segment, Begin, End);
598 uint32_t Count = Block.LineNumbers.size();
599 if (Lines.hasColumnInfo())
600 P.format("line/column/addr entries = {0}", Count);
601 else
602 P.format("line/addr entries = {0}", Count);
Zachary Turner4e950642017-06-15 23:56:19 +0000603
Zachary Turnerf2872b92017-06-15 23:59:56 +0000604 P.NewLine();
605 typesetLinesAndColumns(File, P, Begin, Block);
Zachary Turner4e950642017-06-15 23:56:19 +0000606 }
607 });
608
609 return Error::success();
610}
611
612Error RawOutputStyle::dumpInlineeLines() {
613 printHeader(P, "Inlinee Lines");
Zachary Turner4e950642017-06-15 23:56:19 +0000614
Zachary Turnerf2872b92017-06-15 23:59:56 +0000615 iterateModuleSubsections<DebugInlineeLinesSubsectionRef>(
616 File, P, 2,
617 [this](uint32_t Modi, StringsAndChecksumsPrinter &Strings,
618 DebugInlineeLinesSubsectionRef &Lines) {
619 P.formatLine("{0,+8} | {1,+5} | {2}", "Inlinee", "Line", "Source File");
620 for (const auto &Entry : Lines) {
621 P.formatLine("{0,+8} | {1,+5} | ", Entry.Header->Inlinee,
622 fmtle(Entry.Header->SourceLineNum));
623 Strings.formatFromChecksumsOffset(P, Entry.Header->FileID, true);
Zachary Turner4e950642017-06-15 23:56:19 +0000624 }
Zachary Turnerf2872b92017-06-15 23:59:56 +0000625 P.NewLine();
Zachary Turner4e950642017-06-15 23:56:19 +0000626 });
627
Zachary Turner63055452017-06-15 22:24:24 +0000628 return Error::success();
629}
Zachary Turner0e327d02017-06-15 23:12:41 +0000630
Zachary Turner47d9a562017-06-16 00:04:24 +0000631Error RawOutputStyle::dumpXmi() {
632 printHeader(P, "Cross Module Imports");
633 iterateModuleSubsections<DebugCrossModuleImportsSubsectionRef>(
634 File, P, 2,
635 [this](uint32_t Modi, StringsAndChecksumsPrinter &Strings,
636 DebugCrossModuleImportsSubsectionRef &Imports) {
637 P.formatLine("{0,=32} | {1}", "Imported Module", "Type IDs");
638
639 for (const auto &Xmi : Imports) {
640 auto ExpectedModule =
641 Strings.getNameFromStringTable(Xmi.Header->ModuleNameOffset);
642 StringRef Module;
643 SmallString<32> ModuleStorage;
644 if (!ExpectedModule) {
645 Module = "(unknown module)";
646 consumeError(ExpectedModule.takeError());
647 } else
648 Module = *ExpectedModule;
649 if (Module.size() > 32) {
650 ModuleStorage = "...";
651 ModuleStorage += Module.take_back(32 - 3);
652 Module = ModuleStorage;
653 }
654 std::vector<std::string> TIs;
655 for (const auto I : Xmi.Imports)
656 TIs.push_back(formatv("{0,+10:X+}", fmtle(I)));
657 std::string Result =
658 typesetItemList(TIs, P.getIndentLevel() + 35, 12, " ");
659 P.formatLine("{0,+32} | {1}", Module, Result);
660 }
661 });
662
663 return Error::success();
664}
665
666Error RawOutputStyle::dumpXme() {
667 printHeader(P, "Cross Module Exports");
668
669 iterateModuleSubsections<DebugCrossModuleExportsSubsectionRef>(
670 File, P, 2,
671 [this](uint32_t Modi, StringsAndChecksumsPrinter &Strings,
672 DebugCrossModuleExportsSubsectionRef &Exports) {
673 P.formatLine("{0,-10} | {1}", "Local ID", "Global ID");
674 for (const auto &Export : Exports) {
675 P.formatLine("{0,+10:X+} | {1}", TypeIndex(Export.Local),
676 TypeIndex(Export.Global));
677 }
678 });
679
680 return Error::success();
681}
682
Zachary Turner63055452017-06-15 22:24:24 +0000683Error RawOutputStyle::dumpStringTable() {
684 printHeader(P, "String Table");
685
686 AutoIndent Indent(P);
687 auto IS = File.getStringTable();
688 if (!IS) {
689 P.formatLine("Not present in file");
690 consumeError(IS.takeError());
691 return Error::success();
692 }
693
694 if (IS->name_ids().empty()) {
695 P.formatLine("Empty");
696 return Error::success();
697 }
698
699 auto MaxID = std::max_element(IS->name_ids().begin(), IS->name_ids().end());
700 uint32_t Digits = NumDigits(*MaxID);
701
702 P.formatLine("{0} | {1}", fmt_align("ID", AlignStyle::Right, Digits),
703 "String");
704
705 std::vector<uint32_t> SortedIDs(IS->name_ids().begin(), IS->name_ids().end());
706 std::sort(SortedIDs.begin(), SortedIDs.end());
707 for (uint32_t I : SortedIDs) {
708 auto ES = IS->getStringForID(I);
709 llvm::SmallString<32> Str;
710 if (!ES) {
711 consumeError(ES.takeError());
712 Str = "Error reading string";
713 } else if (!ES->empty()) {
714 Str.append("'");
715 Str.append(*ES);
716 Str.append("'");
717 }
718
719 if (!Str.empty())
720 P.formatLine("{0} | {1}", fmt_align(I, AlignStyle::Right, Digits), Str);
721 }
722 return Error::success();
723}
724
725Error RawOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
726 assert(StreamIdx == StreamTPI || StreamIdx == StreamIPI);
727
728 bool Present = false;
Zachary Turnerf8a2e042017-06-15 23:04:42 +0000729 bool DumpTypes = false;
Zachary Turner63055452017-06-15 22:24:24 +0000730 bool DumpBytes = false;
Zachary Turnerf8a2e042017-06-15 23:04:42 +0000731 bool DumpExtras = false;
Zachary Turner59224cb2017-06-16 23:42:15 +0000732 std::vector<uint32_t> Indices;
Zachary Turner63055452017-06-15 22:24:24 +0000733 if (StreamIdx == StreamTPI) {
734 printHeader(P, "Types (TPI Stream)");
735 Present = File.hasPDBTpiStream();
Zachary Turnerf8a2e042017-06-15 23:04:42 +0000736 DumpTypes = opts::raw::DumpTypes;
Zachary Turner63055452017-06-15 22:24:24 +0000737 DumpBytes = opts::raw::DumpTypeData;
Zachary Turnerf8a2e042017-06-15 23:04:42 +0000738 DumpExtras = opts::raw::DumpTypeExtras;
Zachary Turner59224cb2017-06-16 23:42:15 +0000739 Indices.assign(opts::raw::DumpTypeIndex.begin(),
740 opts::raw::DumpTypeIndex.end());
Zachary Turner63055452017-06-15 22:24:24 +0000741 } else if (StreamIdx == StreamIPI) {
742 printHeader(P, "Types (IPI Stream)");
743 Present = File.hasPDBIpiStream();
Zachary Turnerf8a2e042017-06-15 23:04:42 +0000744 DumpTypes = opts::raw::DumpIds;
Zachary Turner63055452017-06-15 22:24:24 +0000745 DumpBytes = opts::raw::DumpIdData;
Zachary Turnerf8a2e042017-06-15 23:04:42 +0000746 DumpExtras = opts::raw::DumpIdExtras;
Zachary Turner59224cb2017-06-16 23:42:15 +0000747 Indices.assign(opts::raw::DumpIdIndex.begin(),
748 opts::raw::DumpIdIndex.end());
Zachary Turner63055452017-06-15 22:24:24 +0000749 }
750
751 AutoIndent Indent(P);
752 if (!Present) {
753 P.formatLine("Stream not present");
754 return Error::success();
755 }
756
757 ExitOnError Err("Unexpected error processing types");
758
759 auto &Stream = Err((StreamIdx == StreamTPI) ? File.getPDBTpiStream()
760 : File.getPDBIpiStream());
761
Zachary Turner59224cb2017-06-16 23:42:15 +0000762 auto &Types = Err(initializeTypes(StreamIdx));
Zachary Turner63055452017-06-15 22:24:24 +0000763
Zachary Turnerf8a2e042017-06-15 23:04:42 +0000764 if (DumpTypes) {
765 P.formatLine("Showing {0:N} records", Stream.getNumTypeRecords());
766 uint32_t Width =
767 NumDigits(TypeIndex::FirstNonSimpleIndex + Stream.getNumTypeRecords());
Zachary Turner63055452017-06-15 22:24:24 +0000768
Zachary Turnerf8a2e042017-06-15 23:04:42 +0000769 MinimalTypeDumpVisitor V(P, Width + 2, DumpBytes, DumpExtras, Types,
770 Stream.getHashValues());
Zachary Turner63055452017-06-15 22:24:24 +0000771
Zachary Turner59224cb2017-06-16 23:42:15 +0000772 if (Indices.empty()) {
773 if (auto EC = codeview::visitTypeStream(Types, V)) {
774 P.formatLine("An error occurred dumping type records: {0}",
775 toString(std::move(EC)));
776 }
777 } else {
778 for (const auto &I : Indices) {
779 TypeIndex TI(I);
780 CVType Type = Types.getType(TI);
781 if (auto EC = codeview::visitTypeRecord(Type, TI, V))
782 P.formatLine("An error occurred dumping type record {0}: {1}", TI,
783 toString(std::move(EC)));
784 }
Zachary Turnerf8a2e042017-06-15 23:04:42 +0000785 }
786 }
787
788 if (DumpExtras) {
789 P.NewLine();
790 auto IndexOffsets = Stream.getTypeIndexOffsets();
791 P.formatLine("Type Index Offsets:");
792 for (const auto &IO : IndexOffsets) {
793 AutoIndent Indent2(P);
794 P.formatLine("TI: {0}, Offset: {1}", IO.Type, fmtle(IO.Offset));
795 }
796
797 P.NewLine();
798 P.formatLine("Hash Adjusters:");
799 auto &Adjusters = Stream.getHashAdjusters();
800 auto &Strings = Err(File.getStringTable());
801 for (const auto &A : Adjusters) {
802 AutoIndent Indent2(P);
803 auto ExpectedStr = Strings.getStringForID(A.first);
804 TypeIndex TI(A.second);
805 if (ExpectedStr)
806 P.formatLine("`{0}` -> {1}", *ExpectedStr, TI);
807 else {
808 P.formatLine("unknown str id ({0}) -> {1}", A.first, TI);
809 consumeError(ExpectedStr.takeError());
810 }
811 }
Zachary Turner63055452017-06-15 22:24:24 +0000812 }
813 return Error::success();
814}
815
816Expected<codeview::LazyRandomTypeCollection &>
Zachary Turner59224cb2017-06-16 23:42:15 +0000817RawOutputStyle::initializeTypes(uint32_t SN) {
Zachary Turner63055452017-06-15 22:24:24 +0000818 auto &TypeCollection = (SN == StreamTPI) ? TpiTypes : IpiTypes;
819 auto Tpi =
820 (SN == StreamTPI) ? File.getPDBTpiStream() : File.getPDBIpiStream();
821 if (!Tpi)
822 return Tpi.takeError();
823
824 if (!TypeCollection) {
825 auto &Types = Tpi->typeArray();
826 uint32_t Count = Tpi->getNumTypeRecords();
827 auto Offsets = Tpi->getTypeIndexOffsets();
828 TypeCollection =
829 llvm::make_unique<LazyRandomTypeCollection>(Types, Count, Offsets);
830 }
831
832 return *TypeCollection;
833}
834
835Error RawOutputStyle::dumpModuleSyms() {
836 printHeader(P, "Symbols");
837
838 AutoIndent Indent(P);
839 if (!File.hasPDBDbiStream()) {
840 P.formatLine("DBI Stream not present");
841 return Error::success();
842 }
843
844 ExitOnError Err("Unexpected error processing symbols");
845
846 auto &Stream = Err(File.getPDBDbiStream());
847
Zachary Turner59224cb2017-06-16 23:42:15 +0000848 auto &Types = Err(initializeTypes(StreamTPI));
Zachary Turner63055452017-06-15 22:24:24 +0000849
850 const DbiModuleList &Modules = Stream.modules();
851 uint32_t Count = Modules.getModuleCount();
852 uint32_t Digits = NumDigits(Count);
853 for (uint32_t I = 0; I < Count; ++I) {
854 auto Modi = Modules.getModuleDescriptor(I);
855 P.formatLine("Mod {0:4} | `{1}`: ", fmt_align(I, AlignStyle::Right, Digits),
856 Modi.getModuleName());
857 uint16_t ModiStream = Modi.getModuleStreamIndex();
858 if (ModiStream == kInvalidStreamIndex) {
859 P.formatLine(" <symbols not present>");
860 continue;
861 }
862 auto ModStreamData = MappedBlockStream::createIndexedStream(
863 File.getMsfLayout(), File.getMsfBuffer(), ModiStream,
864 File.getAllocator());
865
866 ModuleDebugStreamRef ModS(Modi, std::move(ModStreamData));
867 if (auto EC = ModS.reload()) {
868 P.formatLine("Error loading module stream {0}. {1}", I,
869 toString(std::move(EC)));
870 continue;
871 }
872
873 SymbolVisitorCallbackPipeline Pipeline;
874 SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
875 MinimalSymbolDumper Dumper(P, opts::raw::DumpSymRecordBytes, Types);
876
877 Pipeline.addCallbackToPipeline(Deserializer);
878 Pipeline.addCallbackToPipeline(Dumper);
879 CVSymbolVisitor Visitor(Pipeline);
880 if (auto EC = Visitor.visitSymbolStream(ModS.getSymbolArray())) {
881 P.formatLine("Error while processing symbol records. {0}",
882 toString(std::move(EC)));
883 continue;
884 }
885 }
886 return Error::success();
887}
888
889Error RawOutputStyle::dumpPublics() {
890 printHeader(P, "Public Symbols");
891
892 AutoIndent Indent(P);
893 if (!File.hasPDBPublicsStream()) {
894 P.formatLine("Publics stream not present");
895 return Error::success();
896 }
897
898 ExitOnError Err("Error dumping publics stream");
899
Zachary Turner59224cb2017-06-16 23:42:15 +0000900 auto &Types = Err(initializeTypes(StreamTPI));
Zachary Turner63055452017-06-15 22:24:24 +0000901 auto &Publics = Err(File.getPDBPublicsStream());
902 SymbolVisitorCallbackPipeline Pipeline;
903 SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
904 MinimalSymbolDumper Dumper(P, opts::raw::DumpSymRecordBytes, Types);
905
906 Pipeline.addCallbackToPipeline(Deserializer);
907 Pipeline.addCallbackToPipeline(Dumper);
908 CVSymbolVisitor Visitor(Pipeline);
909 auto ExpectedSymbols = Publics.getSymbolArray();
910 if (!ExpectedSymbols) {
911 P.formatLine("Could not read public symbol record stream");
912 return Error::success();
913 }
914
915 if (auto EC = Visitor.visitSymbolStream(*ExpectedSymbols))
916 P.formatLine("Error while processing public symbol records. {0}",
917 toString(std::move(EC)));
918
919 return Error::success();
920}
921
922static std::string formatSectionCharacteristics(uint32_t IndentLevel,
923 uint32_t C) {
924 using SC = COFF::SectionCharacteristics;
925 std::vector<std::string> Opts;
926 if (C == COFF::SC_Invalid)
927 return "invalid";
928 if (C == 0)
929 return "none";
930
931 PUSH_FLAG(SC, IMAGE_SCN_TYPE_NOLOAD, C, "IMAGE_SCN_TYPE_NOLOAD");
932 PUSH_FLAG(SC, IMAGE_SCN_TYPE_NO_PAD, C, "IMAGE_SCN_TYPE_NO_PAD");
933 PUSH_FLAG(SC, IMAGE_SCN_CNT_CODE, C, "IMAGE_SCN_CNT_CODE");
934 PUSH_FLAG(SC, IMAGE_SCN_CNT_INITIALIZED_DATA, C,
935 "IMAGE_SCN_CNT_INITIALIZED_DATA");
936 PUSH_FLAG(SC, IMAGE_SCN_CNT_UNINITIALIZED_DATA, C,
937 "IMAGE_SCN_CNT_UNINITIALIZED_DATA");
938 PUSH_FLAG(SC, IMAGE_SCN_LNK_OTHER, C, "IMAGE_SCN_LNK_OTHER");
939 PUSH_FLAG(SC, IMAGE_SCN_LNK_INFO, C, "IMAGE_SCN_LNK_INFO");
940 PUSH_FLAG(SC, IMAGE_SCN_LNK_REMOVE, C, "IMAGE_SCN_LNK_REMOVE");
941 PUSH_FLAG(SC, IMAGE_SCN_LNK_COMDAT, C, "IMAGE_SCN_LNK_COMDAT");
942 PUSH_FLAG(SC, IMAGE_SCN_GPREL, C, "IMAGE_SCN_GPREL");
943 PUSH_FLAG(SC, IMAGE_SCN_MEM_PURGEABLE, C, "IMAGE_SCN_MEM_PURGEABLE");
944 PUSH_FLAG(SC, IMAGE_SCN_MEM_16BIT, C, "IMAGE_SCN_MEM_16BIT");
945 PUSH_FLAG(SC, IMAGE_SCN_MEM_LOCKED, C, "IMAGE_SCN_MEM_LOCKED");
946 PUSH_FLAG(SC, IMAGE_SCN_MEM_PRELOAD, C, "IMAGE_SCN_MEM_PRELOAD");
947 PUSH_FLAG(SC, IMAGE_SCN_GPREL, C, "IMAGE_SCN_GPREL");
948 PUSH_FLAG(SC, IMAGE_SCN_GPREL, C, "IMAGE_SCN_GPREL");
949 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_1BYTES, C,
950 "IMAGE_SCN_ALIGN_1BYTES");
951 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_2BYTES, C,
952 "IMAGE_SCN_ALIGN_2BYTES");
953 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_4BYTES, C,
954 "IMAGE_SCN_ALIGN_4BYTES");
955 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_8BYTES, C,
956 "IMAGE_SCN_ALIGN_8BYTES");
957 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_16BYTES, C,
958 "IMAGE_SCN_ALIGN_16BYTES");
959 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_32BYTES, C,
960 "IMAGE_SCN_ALIGN_32BYTES");
961 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_64BYTES, C,
962 "IMAGE_SCN_ALIGN_64BYTES");
963 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_128BYTES, C,
964 "IMAGE_SCN_ALIGN_128BYTES");
965 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_256BYTES, C,
966 "IMAGE_SCN_ALIGN_256BYTES");
967 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_512BYTES, C,
968 "IMAGE_SCN_ALIGN_512BYTES");
969 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_1024BYTES, C,
970 "IMAGE_SCN_ALIGN_1024BYTES");
971 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_2048BYTES, C,
972 "IMAGE_SCN_ALIGN_2048BYTES");
973 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_4096BYTES, C,
974 "IMAGE_SCN_ALIGN_4096BYTES");
975 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_8192BYTES, C,
976 "IMAGE_SCN_ALIGN_8192BYTES");
977 PUSH_FLAG(SC, IMAGE_SCN_LNK_NRELOC_OVFL, C, "IMAGE_SCN_LNK_NRELOC_OVFL");
978 PUSH_FLAG(SC, IMAGE_SCN_MEM_DISCARDABLE, C, "IMAGE_SCN_MEM_DISCARDABLE");
979 PUSH_FLAG(SC, IMAGE_SCN_MEM_NOT_CACHED, C, "IMAGE_SCN_MEM_NOT_CACHED");
980 PUSH_FLAG(SC, IMAGE_SCN_MEM_NOT_PAGED, C, "IMAGE_SCN_MEM_NOT_PAGED");
981 PUSH_FLAG(SC, IMAGE_SCN_MEM_SHARED, C, "IMAGE_SCN_MEM_SHARED");
982 PUSH_FLAG(SC, IMAGE_SCN_MEM_EXECUTE, C, "IMAGE_SCN_MEM_EXECUTE");
983 PUSH_FLAG(SC, IMAGE_SCN_MEM_READ, C, "IMAGE_SCN_MEM_READ");
984 PUSH_FLAG(SC, IMAGE_SCN_MEM_WRITE, C, "IMAGE_SCN_MEM_WRITE");
Zachary Turner47d9a562017-06-16 00:04:24 +0000985 return typesetItemList(Opts, IndentLevel, 3, " | ");
Zachary Turner63055452017-06-15 22:24:24 +0000986}
987
988static std::string formatSegMapDescriptorFlag(uint32_t IndentLevel,
989 OMFSegDescFlags Flags) {
990 std::vector<std::string> Opts;
991 if (Flags == OMFSegDescFlags::None)
992 return "none";
993
994 PUSH_FLAG(OMFSegDescFlags, Read, Flags, "read");
995 PUSH_FLAG(OMFSegDescFlags, Write, Flags, "write");
996 PUSH_FLAG(OMFSegDescFlags, Execute, Flags, "execute");
997 PUSH_FLAG(OMFSegDescFlags, AddressIs32Bit, Flags, "32 bit addr");
998 PUSH_FLAG(OMFSegDescFlags, IsSelector, Flags, "selector");
999 PUSH_FLAG(OMFSegDescFlags, IsAbsoluteAddress, Flags, "absolute addr");
1000 PUSH_FLAG(OMFSegDescFlags, IsGroup, Flags, "group");
Zachary Turner47d9a562017-06-16 00:04:24 +00001001 return typesetItemList(Opts, IndentLevel, 4, " | ");
Zachary Turner63055452017-06-15 22:24:24 +00001002}
1003
1004Error RawOutputStyle::dumpSectionContribs() {
1005 printHeader(P, "Section Contributions");
1006 ExitOnError Err("Error dumping publics stream");
1007
1008 AutoIndent Indent(P);
1009 if (!File.hasPDBDbiStream()) {
1010 P.formatLine(
1011 "Section contribs require a DBI Stream, which could not be loaded");
1012 return Error::success();
1013 }
1014
1015 auto &Dbi = Err(File.getPDBDbiStream());
1016
1017 class Visitor : public ISectionContribVisitor {
1018 public:
1019 Visitor(LinePrinter &P) : P(P) {}
1020 void visit(const SectionContrib &SC) override {
1021 P.formatLine(
1022 "SC | mod = {2}, {0}, size = {1}, data crc = {3}, reloc crc = {4}",
1023 formatSegmentOffset(SC.ISect, SC.Off), fmtle(SC.Size), fmtle(SC.Imod),
1024 fmtle(SC.DataCrc), fmtle(SC.RelocCrc));
1025 P.formatLine(" {0}",
1026 formatSectionCharacteristics(P.getIndentLevel() + 6,
1027 SC.Characteristics));
1028 }
1029 void visit(const SectionContrib2 &SC) override {
1030 P.formatLine("SC2 | mod = {2}, {0}, size = {1}, data crc = {3}, reloc "
1031 "crc = {4}, coff section = {5}",
1032 formatSegmentOffset(SC.Base.ISect, SC.Base.Off),
1033 fmtle(SC.Base.Size), fmtle(SC.Base.Imod),
1034 fmtle(SC.Base.DataCrc), fmtle(SC.Base.RelocCrc),
1035 fmtle(SC.ISectCoff));
1036 P.formatLine(" {0}",
1037 formatSectionCharacteristics(P.getIndentLevel() + 6,
1038 SC.Base.Characteristics));
1039 }
1040
1041 private:
1042 LinePrinter &P;
1043 };
1044
1045 Visitor V(P);
1046 Dbi.visitSectionContributions(V);
1047 return Error::success();
1048}
1049
1050Error RawOutputStyle::dumpSectionMap() {
1051 printHeader(P, "Section Map");
1052 ExitOnError Err("Error dumping section map");
1053
1054 AutoIndent Indent(P);
1055 if (!File.hasPDBDbiStream()) {
1056 P.formatLine("Dumping the section map requires a DBI Stream, which could "
1057 "not be loaded");
1058 return Error::success();
1059 }
1060
1061 auto &Dbi = Err(File.getPDBDbiStream());
1062
1063 uint32_t I = 0;
1064 for (auto &M : Dbi.getSectionMap()) {
1065 P.formatLine(
1066 "Section {0:4} | ovl = {0}, group = {1}, frame = {2}, name = {3}", I,
1067 fmtle(M.Ovl), fmtle(M.Group), fmtle(M.Frame), fmtle(M.SecName));
1068 P.formatLine(" class = {0}, offset = {1}, size = {2}",
1069 fmtle(M.ClassName), fmtle(M.Offset), fmtle(M.SecByteLength));
1070 P.formatLine(" flags = {0}",
1071 formatSegMapDescriptorFlag(
1072 P.getIndentLevel() + 13,
1073 static_cast<OMFSegDescFlags>(uint16_t(M.Flags))));
1074 ++I;
1075 }
1076 return Error::success();
1077}