blob: 01c7481c30865825d54770da3a701c57a6e32b2e [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"
Zachary Turner02a26772017-06-30 18:15:47 +000040#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
Zachary Turner63055452017-06-15 22:24:24 +000041#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
42#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
43#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
44#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
45#include "llvm/DebugInfo/PDB/Native/EnumTables.h"
46#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
47#include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h"
48#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
49#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
50#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
51#include "llvm/DebugInfo/PDB/Native/PublicsStream.h"
52#include "llvm/DebugInfo/PDB/Native/RawError.h"
53#include "llvm/DebugInfo/PDB/Native/TpiHashing.h"
54#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
55#include "llvm/DebugInfo/PDB/PDBExtras.h"
56#include "llvm/Object/COFF.h"
57#include "llvm/Support/BinaryStreamReader.h"
58#include "llvm/Support/FormatAdapters.h"
59#include "llvm/Support/FormatVariadic.h"
60
61#include <unordered_map>
62
63using namespace llvm;
64using namespace llvm::codeview;
65using namespace llvm::msf;
66using namespace llvm::pdb;
67
Zachary Turner7df69952017-06-22 20:57:39 +000068DumpOutputStyle::DumpOutputStyle(PDBFile &File)
Zachary Turner63055452017-06-15 22:24:24 +000069 : File(File), P(2, false, outs()) {}
70
Zachary Turner7df69952017-06-22 20:57:39 +000071Error DumpOutputStyle::dump() {
72 if (opts::dump::DumpSummary) {
Zachary Turner63055452017-06-15 22:24:24 +000073 if (auto EC = dumpFileSummary())
74 return EC;
75 P.NewLine();
76 }
77
Zachary Turner7df69952017-06-22 20:57:39 +000078 if (opts::dump::DumpStreams) {
Zachary Turner63055452017-06-15 22:24:24 +000079 if (auto EC = dumpStreamSummary())
80 return EC;
81 P.NewLine();
82 }
83
Zachary Turner7df69952017-06-22 20:57:39 +000084 if (opts::dump::DumpStringTable) {
Zachary Turner63055452017-06-15 22:24:24 +000085 if (auto EC = dumpStringTable())
86 return EC;
87 P.NewLine();
88 }
89
Zachary Turner7df69952017-06-22 20:57:39 +000090 if (opts::dump::DumpModules) {
Zachary Turner63055452017-06-15 22:24:24 +000091 if (auto EC = dumpModules())
92 return EC;
93 }
94
Zachary Turner7df69952017-06-22 20:57:39 +000095 if (opts::dump::DumpModuleFiles) {
Zachary Turner0e327d02017-06-15 23:12:41 +000096 if (auto EC = dumpModuleFiles())
97 return EC;
98 }
99
Zachary Turner7df69952017-06-22 20:57:39 +0000100 if (opts::dump::DumpLines) {
Zachary Turner4e950642017-06-15 23:56:19 +0000101 if (auto EC = dumpLines())
102 return EC;
103 }
104
Zachary Turner7df69952017-06-22 20:57:39 +0000105 if (opts::dump::DumpInlineeLines) {
Zachary Turner4e950642017-06-15 23:56:19 +0000106 if (auto EC = dumpInlineeLines())
107 return EC;
108 }
109
Zachary Turner7df69952017-06-22 20:57:39 +0000110 if (opts::dump::DumpXmi) {
Zachary Turner47d9a562017-06-16 00:04:24 +0000111 if (auto EC = dumpXmi())
112 return EC;
113 }
114
Zachary Turner7df69952017-06-22 20:57:39 +0000115 if (opts::dump::DumpXme) {
Zachary Turner47d9a562017-06-16 00:04:24 +0000116 if (auto EC = dumpXme())
117 return EC;
118 }
119
Zachary Turner02a26772017-06-30 18:15:47 +0000120 if (opts::dump::DumpTypes || !opts::dump::DumpTypeIndex.empty() ||
121 opts::dump::DumpTypeExtras) {
Zachary Turner63055452017-06-15 22:24:24 +0000122 if (auto EC = dumpTpiStream(StreamTPI))
123 return EC;
124 }
125
Zachary Turner02a26772017-06-30 18:15:47 +0000126 if (opts::dump::DumpIds || !opts::dump::DumpIdIndex.empty() ||
127 opts::dump::DumpIdExtras) {
Zachary Turner63055452017-06-15 22:24:24 +0000128 if (auto EC = dumpTpiStream(StreamIPI))
129 return EC;
130 }
131
Zachary Turner7df69952017-06-22 20:57:39 +0000132 if (opts::dump::DumpPublics) {
Zachary Turner63055452017-06-15 22:24:24 +0000133 if (auto EC = dumpPublics())
134 return EC;
135 }
136
Zachary Turner7df69952017-06-22 20:57:39 +0000137 if (opts::dump::DumpSymbols) {
Zachary Turner63055452017-06-15 22:24:24 +0000138 if (auto EC = dumpModuleSyms())
139 return EC;
140 }
141
Zachary Turner7df69952017-06-22 20:57:39 +0000142 if (opts::dump::DumpSectionContribs) {
Zachary Turner63055452017-06-15 22:24:24 +0000143 if (auto EC = dumpSectionContribs())
144 return EC;
145 }
146
Zachary Turner7df69952017-06-22 20:57:39 +0000147 if (opts::dump::DumpSectionMap) {
Zachary Turner63055452017-06-15 22:24:24 +0000148 if (auto EC = dumpSectionMap())
149 return EC;
150 }
151
152 return Error::success();
153}
154
155static void printHeader(LinePrinter &P, const Twine &S) {
156 P.NewLine();
157 P.formatLine("{0,=60}", S);
158 P.formatLine("{0}", fmt_repeat('=', 60));
159}
160
Zachary Turner7df69952017-06-22 20:57:39 +0000161Error DumpOutputStyle::dumpFileSummary() {
Zachary Turner63055452017-06-15 22:24:24 +0000162 printHeader(P, "Summary");
163
164 ExitOnError Err("Invalid PDB Format");
165
166 AutoIndent Indent(P);
167 P.formatLine("Block Size: {0}", File.getBlockSize());
168 P.formatLine("Number of blocks: {0}", File.getBlockCount());
169 P.formatLine("Number of streams: {0}", File.getNumStreams());
170
171 auto &PS = Err(File.getPDBInfoStream());
172 P.formatLine("Signature: {0}", PS.getSignature());
173 P.formatLine("Age: {0}", PS.getAge());
174 P.formatLine("GUID: {0}", fmt_guid(PS.getGuid().Guid));
175 P.formatLine("Features: {0:x+}", static_cast<uint32_t>(PS.getFeatures()));
176 P.formatLine("Has Debug Info: {0}", File.hasPDBDbiStream());
177 P.formatLine("Has Types: {0}", File.hasPDBTpiStream());
178 P.formatLine("Has IDs: {0}", File.hasPDBIpiStream());
179 P.formatLine("Has Globals: {0}", File.hasPDBGlobalsStream());
180 P.formatLine("Has Publics: {0}", File.hasPDBPublicsStream());
181 if (File.hasPDBDbiStream()) {
182 auto &DBI = Err(File.getPDBDbiStream());
183 P.formatLine("Is incrementally linked: {0}", DBI.isIncrementallyLinked());
184 P.formatLine("Has conflicting types: {0}", DBI.hasCTypes());
185 P.formatLine("Is stripped: {0}", DBI.isStripped());
186 }
187
188 return Error::success();
189}
190
Zachary Turner7df69952017-06-22 20:57:39 +0000191Error DumpOutputStyle::dumpStreamSummary() {
Zachary Turner63055452017-06-15 22:24:24 +0000192 printHeader(P, "Streams");
193
194 if (StreamPurposes.empty())
195 discoverStreamPurposes(File, StreamPurposes);
196
197 AutoIndent Indent(P);
198 uint32_t StreamCount = File.getNumStreams();
199
200 for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
201 P.formatLine(
202 "Stream {0}: [{1}] ({2} bytes)",
203 fmt_align(StreamIdx, AlignStyle::Right, NumDigits(StreamCount)),
204 StreamPurposes[StreamIdx], File.getStreamByteSize(StreamIdx));
Zachary Turner5f098522017-06-23 20:28:14 +0000205 if (opts::dump::DumpStreamBlocks) {
206 auto Blocks = File.getStreamBlockList(StreamIdx);
207 std::vector<uint32_t> BV(Blocks.begin(), Blocks.end());
208 P.formatLine(" {0} Blocks: [{1}]",
209 fmt_repeat(' ', NumDigits(StreamCount)),
210 make_range(BV.begin(), BV.end()));
211 }
Zachary Turner63055452017-06-15 22:24:24 +0000212 }
213
214 return Error::success();
215}
216
Zachary Turner0e327d02017-06-15 23:12:41 +0000217static Expected<ModuleDebugStreamRef> getModuleDebugStream(PDBFile &File,
218 uint32_t Index) {
219 ExitOnError Err("Unexpected error");
220
221 auto &Dbi = Err(File.getPDBDbiStream());
222 const auto &Modules = Dbi.modules();
223 auto Modi = Modules.getModuleDescriptor(Index);
224
225 uint16_t ModiStream = Modi.getModuleStreamIndex();
226 if (ModiStream == kInvalidStreamIndex)
227 return make_error<RawError>(raw_error_code::no_stream,
228 "Module stream not present");
229
230 auto ModStreamData = MappedBlockStream::createIndexedStream(
231 File.getMsfLayout(), File.getMsfBuffer(), ModiStream,
232 File.getAllocator());
233
234 ModuleDebugStreamRef ModS(Modi, std::move(ModStreamData));
235 if (auto EC = ModS.reload())
236 return make_error<RawError>(raw_error_code::corrupt_file,
237 "Invalid module stream");
238
239 return std::move(ModS);
240}
241
Zachary Turner0e327d02017-06-15 23:12:41 +0000242static std::string formatChecksumKind(FileChecksumKind Kind) {
243 switch (Kind) {
244 RETURN_CASE(FileChecksumKind, None, "None");
245 RETURN_CASE(FileChecksumKind, MD5, "MD5");
246 RETURN_CASE(FileChecksumKind, SHA1, "SHA-1");
247 RETURN_CASE(FileChecksumKind, SHA256, "SHA-256");
248 }
249 return formatUnknownEnum(Kind);
250}
251
Zachary Turner4e950642017-06-15 23:56:19 +0000252namespace {
253class StringsAndChecksumsPrinter {
254 const DebugStringTableSubsectionRef &extractStringTable(PDBFile &File) {
255 ExitOnError Err("Unexpected error processing modules");
256 return Err(File.getStringTable()).getStringTable();
257 }
258
259 template <typename... Args>
260 void formatInternal(LinePrinter &Printer, bool Append,
261 Args &&... args) const {
262 if (Append)
263 Printer.format(std::forward<Args>(args)...);
264 else
265 Printer.formatLine(std::forward<Args>(args)...);
266 }
267
268public:
269 StringsAndChecksumsPrinter(PDBFile &File, uint32_t Modi)
270 : Records(extractStringTable(File)) {
271 auto MDS = getModuleDebugStream(File, Modi);
272 if (!MDS) {
273 consumeError(MDS.takeError());
274 return;
275 }
276
277 DebugStream = llvm::make_unique<ModuleDebugStreamRef>(std::move(*MDS));
278 Records.initialize(MDS->subsections());
279 if (Records.hasChecksums()) {
280 for (const auto &Entry : Records.checksums()) {
281 auto S = Records.strings().getString(Entry.FileNameOffset);
282 if (!S)
283 continue;
284 ChecksumsByFile[*S] = Entry;
285 }
286 }
287 }
288
289 Expected<StringRef> getNameFromStringTable(uint32_t Offset) const {
290 return Records.strings().getString(Offset);
291 }
292
293 void formatFromFileName(LinePrinter &Printer, StringRef File,
294 bool Append = false) const {
295 auto FC = ChecksumsByFile.find(File);
296 if (FC == ChecksumsByFile.end()) {
297 formatInternal(Printer, Append, "- (no checksum) {0}", File);
298 return;
299 }
300
301 formatInternal(Printer, Append, "- ({0}: {1}) {2}",
302 formatChecksumKind(FC->getValue().Kind),
303 toHex(FC->getValue().Checksum), File);
304 }
305
306 void formatFromChecksumsOffset(LinePrinter &Printer, uint32_t Offset,
307 bool Append = false) const {
308 if (!Records.hasChecksums()) {
309 formatInternal(Printer, Append, "(unknown file name offset {0})", Offset);
310 return;
311 }
312
313 auto Iter = Records.checksums().getArray().at(Offset);
314 if (Iter == Records.checksums().getArray().end()) {
315 formatInternal(Printer, Append, "(unknown file name offset {0})", Offset);
316 return;
317 }
318
319 uint32_t FO = Iter->FileNameOffset;
320 auto ExpectedFile = getNameFromStringTable(FO);
321 if (!ExpectedFile) {
322 formatInternal(Printer, Append, "(unknown file name offset {0})", Offset);
323 consumeError(ExpectedFile.takeError());
324 return;
325 }
326 if (Iter->Kind == FileChecksumKind::None) {
327 formatInternal(Printer, Append, "{0} (no checksum)", *ExpectedFile);
328 } else {
329 formatInternal(Printer, Append, "{0} ({1}: {2})", *ExpectedFile,
330 formatChecksumKind(Iter->Kind), toHex(Iter->Checksum));
331 }
332 }
333
334 std::unique_ptr<ModuleDebugStreamRef> DebugStream;
335 StringsAndChecksumsRef Records;
336 StringMap<FileChecksumEntry> ChecksumsByFile;
337};
338} // namespace
339
Zachary Turnerf2872b92017-06-15 23:59:56 +0000340template <typename CallbackT>
341static void iterateModules(PDBFile &File, LinePrinter &P, uint32_t IndentLevel,
342 CallbackT Callback) {
343 AutoIndent Indent(P);
344 if (!File.hasPDBDbiStream()) {
345 P.formatLine("DBI Stream not present");
346 return;
347 }
348
349 ExitOnError Err("Unexpected error processing modules");
350
351 auto &Stream = Err(File.getPDBDbiStream());
352
353 const DbiModuleList &Modules = Stream.modules();
354 uint32_t Count = Modules.getModuleCount();
355 uint32_t Digits = NumDigits(Count);
356 for (uint32_t I = 0; I < Count; ++I) {
357 auto Modi = Modules.getModuleDescriptor(I);
358 P.formatLine("Mod {0:4} | `{1}`: ", fmt_align(I, AlignStyle::Right, Digits),
359 Modi.getModuleName());
360
361 StringsAndChecksumsPrinter Strings(File, I);
362 AutoIndent Indent2(P, IndentLevel);
363 Callback(I, Strings);
364 }
365}
366
367template <typename SubsectionT>
368static void iterateModuleSubsections(
369 PDBFile &File, LinePrinter &P, uint32_t IndentLevel,
370 llvm::function_ref<void(uint32_t, StringsAndChecksumsPrinter &,
371 SubsectionT &)>
372 Callback) {
373
374 iterateModules(
375 File, P, IndentLevel,
376 [&File, &Callback](uint32_t Modi, StringsAndChecksumsPrinter &Strings) {
377 auto MDS = getModuleDebugStream(File, Modi);
378 if (!MDS) {
379 consumeError(MDS.takeError());
380 return;
381 }
382
383 for (const auto &SS : MDS->subsections()) {
384 SubsectionT Subsection;
385
386 if (SS.kind() != Subsection.kind())
387 continue;
388
389 BinaryStreamReader Reader(SS.getRecordData());
390 if (auto EC = Subsection.initialize(Reader))
391 continue;
392 Callback(Modi, Strings, Subsection);
393 }
394 });
395}
396
Zachary Turner7df69952017-06-22 20:57:39 +0000397Error DumpOutputStyle::dumpModules() {
Zachary Turner63055452017-06-15 22:24:24 +0000398 printHeader(P, "Modules");
399
400 AutoIndent Indent(P);
401 if (!File.hasPDBDbiStream()) {
402 P.formatLine("DBI Stream not present");
403 return Error::success();
404 }
405
Zachary Turner0e327d02017-06-15 23:12:41 +0000406 ExitOnError Err("Unexpected error processing modules");
Zachary Turner63055452017-06-15 22:24:24 +0000407
408 auto &Stream = Err(File.getPDBDbiStream());
409
410 const DbiModuleList &Modules = Stream.modules();
411 uint32_t Count = Modules.getModuleCount();
412 uint32_t Digits = NumDigits(Count);
413 for (uint32_t I = 0; I < Count; ++I) {
414 auto Modi = Modules.getModuleDescriptor(I);
415 P.formatLine("Mod {0:4} | Name: `{1}`: ",
416 fmt_align(I, AlignStyle::Right, Digits), Modi.getModuleName());
417 P.formatLine(" Obj: `{0}`: ", Modi.getObjFileName());
418 P.formatLine(" debug stream: {0}, # files: {1}, has ec info: {2}",
419 Modi.getModuleStreamIndex(), Modi.getNumberOfFiles(),
420 Modi.hasECInfo());
Zachary Turner6c4bfba2017-07-07 05:04:36 +0000421 StringRef PdbFilePath =
422 Err(Stream.getECName(Modi.getPdbFilePathNameIndex()));
423 StringRef SrcFilePath =
424 Err(Stream.getECName(Modi.getSourceFileNameIndex()));
425 P.formatLine(" pdb file ni: {0} `{1}`, src file ni: {2} `{3}`",
426 Modi.getPdbFilePathNameIndex(), PdbFilePath,
427 Modi.getSourceFileNameIndex(), SrcFilePath);
Zachary Turner0e327d02017-06-15 23:12:41 +0000428 }
429 return Error::success();
430}
431
Zachary Turner7df69952017-06-22 20:57:39 +0000432Error DumpOutputStyle::dumpModuleFiles() {
Zachary Turner0e327d02017-06-15 23:12:41 +0000433 printHeader(P, "Files");
434
Zachary Turner0e327d02017-06-15 23:12:41 +0000435 ExitOnError Err("Unexpected error processing modules");
436
Zachary Turnerf2872b92017-06-15 23:59:56 +0000437 iterateModules(
438 File, P, 11,
439 [this, &Err](uint32_t Modi, StringsAndChecksumsPrinter &Strings) {
440 auto &Stream = Err(File.getPDBDbiStream());
Zachary Turner0e327d02017-06-15 23:12:41 +0000441
Zachary Turnerf2872b92017-06-15 23:59:56 +0000442 const DbiModuleList &Modules = Stream.modules();
443 for (const auto &F : Modules.source_files(Modi)) {
444 Strings.formatFromFileName(P, F);
445 }
446 });
Zachary Turner4e950642017-06-15 23:56:19 +0000447 return Error::success();
448}
449
450static void typesetLinesAndColumns(PDBFile &File, LinePrinter &P,
451 uint32_t Start, const LineColumnEntry &E) {
452 const uint32_t kMaxCharsPerLineNumber = 4; // 4 digit line number
453 uint32_t MinColumnWidth = kMaxCharsPerLineNumber + 5;
454
455 // Let's try to keep it under 100 characters
456 constexpr uint32_t kMaxRowLength = 100;
457 // At least 3 spaces between columns.
458 uint32_t ColumnsPerRow = kMaxRowLength / (MinColumnWidth + 3);
459 uint32_t ItemsLeft = E.LineNumbers.size();
460 auto LineIter = E.LineNumbers.begin();
461 while (ItemsLeft != 0) {
462 uint32_t RowColumns = std::min(ItemsLeft, ColumnsPerRow);
463 for (uint32_t I = 0; I < RowColumns; ++I) {
464 LineInfo Line(LineIter->Flags);
465 std::string LineStr;
466 if (Line.isAlwaysStepInto())
467 LineStr = "ASI";
468 else if (Line.isNeverStepInto())
469 LineStr = "NSI";
Zachary Turner0e327d02017-06-15 23:12:41 +0000470 else
Zachary Turner4e950642017-06-15 23:56:19 +0000471 LineStr = utostr(Line.getStartLine());
472 char Statement = Line.isStatement() ? ' ' : '!';
473 P.format("{0} {1:X-} {2} ",
474 fmt_align(LineStr, AlignStyle::Right, kMaxCharsPerLineNumber),
475 fmt_align(Start + LineIter->Offset, AlignStyle::Right, 8, '0'),
476 Statement);
477 ++LineIter;
478 --ItemsLeft;
Zachary Turner63055452017-06-15 22:24:24 +0000479 }
Zachary Turner4e950642017-06-15 23:56:19 +0000480 P.NewLine();
Zachary Turner63055452017-06-15 22:24:24 +0000481 }
Zachary Turner4e950642017-06-15 23:56:19 +0000482}
483
Zachary Turner7df69952017-06-22 20:57:39 +0000484Error DumpOutputStyle::dumpLines() {
Zachary Turner4e950642017-06-15 23:56:19 +0000485 printHeader(P, "Lines");
Zachary Turner4e950642017-06-15 23:56:19 +0000486
Zachary Turnerf2872b92017-06-15 23:59:56 +0000487 uint32_t LastModi = UINT32_MAX;
488 uint32_t LastNameIndex = UINT32_MAX;
489 iterateModuleSubsections<DebugLinesSubsectionRef>(
490 File, P, 4,
491 [this, &LastModi, &LastNameIndex](uint32_t Modi,
492 StringsAndChecksumsPrinter &Strings,
493 DebugLinesSubsectionRef &Lines) {
494 uint16_t Segment = Lines.header()->RelocSegment;
495 uint32_t Begin = Lines.header()->RelocOffset;
496 uint32_t End = Begin + Lines.header()->CodeSize;
497 for (const auto &Block : Lines) {
498 if (LastModi != Modi || LastNameIndex != Block.NameIndex) {
499 LastModi = Modi;
500 LastNameIndex = Block.NameIndex;
501 Strings.formatFromChecksumsOffset(P, Block.NameIndex);
Zachary Turner4e950642017-06-15 23:56:19 +0000502 }
503
Zachary Turnerf2872b92017-06-15 23:59:56 +0000504 AutoIndent Indent(P, 2);
505 P.formatLine("{0:X-4}:{1:X-8}-{2:X-8}, ", Segment, Begin, End);
506 uint32_t Count = Block.LineNumbers.size();
507 if (Lines.hasColumnInfo())
508 P.format("line/column/addr entries = {0}", Count);
509 else
510 P.format("line/addr entries = {0}", Count);
Zachary Turner4e950642017-06-15 23:56:19 +0000511
Zachary Turnerf2872b92017-06-15 23:59:56 +0000512 P.NewLine();
513 typesetLinesAndColumns(File, P, Begin, Block);
Zachary Turner4e950642017-06-15 23:56:19 +0000514 }
515 });
516
517 return Error::success();
518}
519
Zachary Turner7df69952017-06-22 20:57:39 +0000520Error DumpOutputStyle::dumpInlineeLines() {
Zachary Turner4e950642017-06-15 23:56:19 +0000521 printHeader(P, "Inlinee Lines");
Zachary Turner4e950642017-06-15 23:56:19 +0000522
Zachary Turnerf2872b92017-06-15 23:59:56 +0000523 iterateModuleSubsections<DebugInlineeLinesSubsectionRef>(
524 File, P, 2,
525 [this](uint32_t Modi, StringsAndChecksumsPrinter &Strings,
526 DebugInlineeLinesSubsectionRef &Lines) {
527 P.formatLine("{0,+8} | {1,+5} | {2}", "Inlinee", "Line", "Source File");
528 for (const auto &Entry : Lines) {
529 P.formatLine("{0,+8} | {1,+5} | ", Entry.Header->Inlinee,
530 fmtle(Entry.Header->SourceLineNum));
531 Strings.formatFromChecksumsOffset(P, Entry.Header->FileID, true);
Zachary Turner4e950642017-06-15 23:56:19 +0000532 }
Zachary Turnerf2872b92017-06-15 23:59:56 +0000533 P.NewLine();
Zachary Turner4e950642017-06-15 23:56:19 +0000534 });
535
Zachary Turner63055452017-06-15 22:24:24 +0000536 return Error::success();
537}
Zachary Turner0e327d02017-06-15 23:12:41 +0000538
Zachary Turner7df69952017-06-22 20:57:39 +0000539Error DumpOutputStyle::dumpXmi() {
Zachary Turner47d9a562017-06-16 00:04:24 +0000540 printHeader(P, "Cross Module Imports");
541 iterateModuleSubsections<DebugCrossModuleImportsSubsectionRef>(
542 File, P, 2,
543 [this](uint32_t Modi, StringsAndChecksumsPrinter &Strings,
544 DebugCrossModuleImportsSubsectionRef &Imports) {
545 P.formatLine("{0,=32} | {1}", "Imported Module", "Type IDs");
546
547 for (const auto &Xmi : Imports) {
548 auto ExpectedModule =
549 Strings.getNameFromStringTable(Xmi.Header->ModuleNameOffset);
550 StringRef Module;
551 SmallString<32> ModuleStorage;
552 if (!ExpectedModule) {
553 Module = "(unknown module)";
554 consumeError(ExpectedModule.takeError());
555 } else
556 Module = *ExpectedModule;
557 if (Module.size() > 32) {
558 ModuleStorage = "...";
559 ModuleStorage += Module.take_back(32 - 3);
560 Module = ModuleStorage;
561 }
562 std::vector<std::string> TIs;
563 for (const auto I : Xmi.Imports)
564 TIs.push_back(formatv("{0,+10:X+}", fmtle(I)));
565 std::string Result =
566 typesetItemList(TIs, P.getIndentLevel() + 35, 12, " ");
567 P.formatLine("{0,+32} | {1}", Module, Result);
568 }
569 });
570
571 return Error::success();
572}
573
Zachary Turner7df69952017-06-22 20:57:39 +0000574Error DumpOutputStyle::dumpXme() {
Zachary Turner47d9a562017-06-16 00:04:24 +0000575 printHeader(P, "Cross Module Exports");
576
577 iterateModuleSubsections<DebugCrossModuleExportsSubsectionRef>(
578 File, P, 2,
579 [this](uint32_t Modi, StringsAndChecksumsPrinter &Strings,
580 DebugCrossModuleExportsSubsectionRef &Exports) {
581 P.formatLine("{0,-10} | {1}", "Local ID", "Global ID");
582 for (const auto &Export : Exports) {
583 P.formatLine("{0,+10:X+} | {1}", TypeIndex(Export.Local),
584 TypeIndex(Export.Global));
585 }
586 });
587
588 return Error::success();
589}
590
Zachary Turner7df69952017-06-22 20:57:39 +0000591Error DumpOutputStyle::dumpStringTable() {
Zachary Turner63055452017-06-15 22:24:24 +0000592 printHeader(P, "String Table");
593
594 AutoIndent Indent(P);
595 auto IS = File.getStringTable();
596 if (!IS) {
597 P.formatLine("Not present in file");
598 consumeError(IS.takeError());
599 return Error::success();
600 }
601
602 if (IS->name_ids().empty()) {
603 P.formatLine("Empty");
604 return Error::success();
605 }
606
607 auto MaxID = std::max_element(IS->name_ids().begin(), IS->name_ids().end());
608 uint32_t Digits = NumDigits(*MaxID);
609
610 P.formatLine("{0} | {1}", fmt_align("ID", AlignStyle::Right, Digits),
611 "String");
612
613 std::vector<uint32_t> SortedIDs(IS->name_ids().begin(), IS->name_ids().end());
614 std::sort(SortedIDs.begin(), SortedIDs.end());
615 for (uint32_t I : SortedIDs) {
616 auto ES = IS->getStringForID(I);
617 llvm::SmallString<32> Str;
618 if (!ES) {
619 consumeError(ES.takeError());
620 Str = "Error reading string";
621 } else if (!ES->empty()) {
622 Str.append("'");
623 Str.append(*ES);
624 Str.append("'");
625 }
626
627 if (!Str.empty())
628 P.formatLine("{0} | {1}", fmt_align(I, AlignStyle::Right, Digits), Str);
629 }
630 return Error::success();
631}
632
Zachary Turner02a26772017-06-30 18:15:47 +0000633static void buildDepSet(LazyRandomTypeCollection &Types,
634 ArrayRef<TypeIndex> Indices,
635 std::map<TypeIndex, CVType> &DepSet) {
636 SmallVector<TypeIndex, 4> DepList;
637 for (const auto &I : Indices) {
638 TypeIndex TI(I);
639 if (DepSet.find(TI) != DepSet.end() || TI.isSimple() || TI.isNoneType())
640 continue;
641
642 CVType Type = Types.getType(TI);
643 DepSet[TI] = Type;
644 codeview::discoverTypeIndices(Type, DepList);
645 buildDepSet(Types, DepList, DepSet);
646 }
647}
648
649static void dumpFullTypeStream(LinePrinter &Printer,
650 LazyRandomTypeCollection &Types,
651 TpiStream &Stream, bool Bytes, bool Extras) {
652 Printer.formatLine("Showing {0:N} records", Stream.getNumTypeRecords());
653 uint32_t Width =
654 NumDigits(TypeIndex::FirstNonSimpleIndex + Stream.getNumTypeRecords());
655
656 MinimalTypeDumpVisitor V(Printer, Width + 2, Bytes, Extras, Types,
Reid Klecknerc50349d2017-07-18 00:33:45 +0000657 Stream.getNumHashBuckets(), Stream.getHashValues());
Zachary Turner02a26772017-06-30 18:15:47 +0000658
659 if (auto EC = codeview::visitTypeStream(Types, V)) {
660 Printer.formatLine("An error occurred dumping type records: {0}",
661 toString(std::move(EC)));
662 }
663}
664
665static void dumpPartialTypeStream(LinePrinter &Printer,
666 LazyRandomTypeCollection &Types,
667 TpiStream &Stream, ArrayRef<TypeIndex> TiList,
668 bool Bytes, bool Extras, bool Deps) {
669 uint32_t Width =
670 NumDigits(TypeIndex::FirstNonSimpleIndex + Stream.getNumTypeRecords());
671
672 MinimalTypeDumpVisitor V(Printer, Width + 2, Bytes, Extras, Types,
Reid Klecknerc50349d2017-07-18 00:33:45 +0000673 Stream.getNumHashBuckets(), Stream.getHashValues());
Zachary Turner02a26772017-06-30 18:15:47 +0000674
675 if (opts::dump::DumpTypeDependents) {
676 // If we need to dump all dependents, then iterate each index and find
677 // all dependents, adding them to a map ordered by TypeIndex.
678 std::map<TypeIndex, CVType> DepSet;
679 buildDepSet(Types, TiList, DepSet);
680
681 Printer.formatLine(
682 "Showing {0:N} records and their dependents ({1:N} records total)",
683 TiList.size(), DepSet.size());
684
685 for (auto &Dep : DepSet) {
686 if (auto EC = codeview::visitTypeRecord(Dep.second, Dep.first, V))
687 Printer.formatLine("An error occurred dumping type record {0}: {1}",
688 Dep.first, toString(std::move(EC)));
689 }
690 } else {
691 Printer.formatLine("Showing {0:N} records.", TiList.size());
692
693 for (const auto &I : TiList) {
694 TypeIndex TI(I);
695 CVType Type = Types.getType(TI);
696 if (auto EC = codeview::visitTypeRecord(Type, TI, V))
697 Printer.formatLine("An error occurred dumping type record {0}: {1}", TI,
698 toString(std::move(EC)));
699 }
700 }
701}
702
Zachary Turner7df69952017-06-22 20:57:39 +0000703Error DumpOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
Zachary Turner63055452017-06-15 22:24:24 +0000704 assert(StreamIdx == StreamTPI || StreamIdx == StreamIPI);
705
706 bool Present = false;
Zachary Turnerf8a2e042017-06-15 23:04:42 +0000707 bool DumpTypes = false;
Zachary Turner63055452017-06-15 22:24:24 +0000708 bool DumpBytes = false;
Zachary Turnerf8a2e042017-06-15 23:04:42 +0000709 bool DumpExtras = false;
Zachary Turner59224cb2017-06-16 23:42:15 +0000710 std::vector<uint32_t> Indices;
Zachary Turner63055452017-06-15 22:24:24 +0000711 if (StreamIdx == StreamTPI) {
712 printHeader(P, "Types (TPI Stream)");
713 Present = File.hasPDBTpiStream();
Zachary Turner7df69952017-06-22 20:57:39 +0000714 DumpTypes = opts::dump::DumpTypes;
715 DumpBytes = opts::dump::DumpTypeData;
716 DumpExtras = opts::dump::DumpTypeExtras;
717 Indices.assign(opts::dump::DumpTypeIndex.begin(),
718 opts::dump::DumpTypeIndex.end());
Zachary Turner63055452017-06-15 22:24:24 +0000719 } else if (StreamIdx == StreamIPI) {
720 printHeader(P, "Types (IPI Stream)");
721 Present = File.hasPDBIpiStream();
Zachary Turner7df69952017-06-22 20:57:39 +0000722 DumpTypes = opts::dump::DumpIds;
723 DumpBytes = opts::dump::DumpIdData;
724 DumpExtras = opts::dump::DumpIdExtras;
725 Indices.assign(opts::dump::DumpIdIndex.begin(),
726 opts::dump::DumpIdIndex.end());
Zachary Turner63055452017-06-15 22:24:24 +0000727 }
728
729 AutoIndent Indent(P);
730 if (!Present) {
731 P.formatLine("Stream not present");
732 return Error::success();
733 }
734
735 ExitOnError Err("Unexpected error processing types");
736
737 auto &Stream = Err((StreamIdx == StreamTPI) ? File.getPDBTpiStream()
738 : File.getPDBIpiStream());
739
Zachary Turner59224cb2017-06-16 23:42:15 +0000740 auto &Types = Err(initializeTypes(StreamIdx));
Zachary Turner63055452017-06-15 22:24:24 +0000741
Zachary Turner02a26772017-06-30 18:15:47 +0000742 if (DumpTypes || !Indices.empty()) {
743 if (Indices.empty())
744 dumpFullTypeStream(P, Types, Stream, DumpBytes, DumpExtras);
745 else {
746 std::vector<TypeIndex> TiList(Indices.begin(), Indices.end());
747 dumpPartialTypeStream(P, Types, Stream, TiList, DumpBytes, DumpExtras,
748 opts::dump::DumpTypeDependents);
Zachary Turnerf8a2e042017-06-15 23:04:42 +0000749 }
750 }
751
752 if (DumpExtras) {
753 P.NewLine();
754 auto IndexOffsets = Stream.getTypeIndexOffsets();
755 P.formatLine("Type Index Offsets:");
756 for (const auto &IO : IndexOffsets) {
757 AutoIndent Indent2(P);
758 P.formatLine("TI: {0}, Offset: {1}", IO.Type, fmtle(IO.Offset));
759 }
760
761 P.NewLine();
762 P.formatLine("Hash Adjusters:");
763 auto &Adjusters = Stream.getHashAdjusters();
764 auto &Strings = Err(File.getStringTable());
765 for (const auto &A : Adjusters) {
766 AutoIndent Indent2(P);
767 auto ExpectedStr = Strings.getStringForID(A.first);
768 TypeIndex TI(A.second);
769 if (ExpectedStr)
770 P.formatLine("`{0}` -> {1}", *ExpectedStr, TI);
771 else {
772 P.formatLine("unknown str id ({0}) -> {1}", A.first, TI);
773 consumeError(ExpectedStr.takeError());
774 }
775 }
Zachary Turner63055452017-06-15 22:24:24 +0000776 }
777 return Error::success();
778}
779
780Expected<codeview::LazyRandomTypeCollection &>
Zachary Turner7df69952017-06-22 20:57:39 +0000781DumpOutputStyle::initializeTypes(uint32_t SN) {
Zachary Turner63055452017-06-15 22:24:24 +0000782 auto &TypeCollection = (SN == StreamTPI) ? TpiTypes : IpiTypes;
783 auto Tpi =
784 (SN == StreamTPI) ? File.getPDBTpiStream() : File.getPDBIpiStream();
785 if (!Tpi)
786 return Tpi.takeError();
787
788 if (!TypeCollection) {
789 auto &Types = Tpi->typeArray();
790 uint32_t Count = Tpi->getNumTypeRecords();
791 auto Offsets = Tpi->getTypeIndexOffsets();
792 TypeCollection =
793 llvm::make_unique<LazyRandomTypeCollection>(Types, Count, Offsets);
794 }
795
796 return *TypeCollection;
797}
798
Zachary Turner7df69952017-06-22 20:57:39 +0000799Error DumpOutputStyle::dumpModuleSyms() {
Zachary Turner63055452017-06-15 22:24:24 +0000800 printHeader(P, "Symbols");
801
802 AutoIndent Indent(P);
803 if (!File.hasPDBDbiStream()) {
804 P.formatLine("DBI Stream not present");
805 return Error::success();
806 }
807
808 ExitOnError Err("Unexpected error processing symbols");
809
810 auto &Stream = Err(File.getPDBDbiStream());
811
Zachary Turner59224cb2017-06-16 23:42:15 +0000812 auto &Types = Err(initializeTypes(StreamTPI));
Zachary Turner63055452017-06-15 22:24:24 +0000813
814 const DbiModuleList &Modules = Stream.modules();
815 uint32_t Count = Modules.getModuleCount();
816 uint32_t Digits = NumDigits(Count);
817 for (uint32_t I = 0; I < Count; ++I) {
818 auto Modi = Modules.getModuleDescriptor(I);
819 P.formatLine("Mod {0:4} | `{1}`: ", fmt_align(I, AlignStyle::Right, Digits),
820 Modi.getModuleName());
821 uint16_t ModiStream = Modi.getModuleStreamIndex();
822 if (ModiStream == kInvalidStreamIndex) {
823 P.formatLine(" <symbols not present>");
824 continue;
825 }
826 auto ModStreamData = MappedBlockStream::createIndexedStream(
827 File.getMsfLayout(), File.getMsfBuffer(), ModiStream,
828 File.getAllocator());
829
830 ModuleDebugStreamRef ModS(Modi, std::move(ModStreamData));
831 if (auto EC = ModS.reload()) {
832 P.formatLine("Error loading module stream {0}. {1}", I,
833 toString(std::move(EC)));
834 continue;
835 }
836
837 SymbolVisitorCallbackPipeline Pipeline;
838 SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
Zachary Turner7df69952017-06-22 20:57:39 +0000839 MinimalSymbolDumper Dumper(P, opts::dump::DumpSymRecordBytes, Types);
Zachary Turner63055452017-06-15 22:24:24 +0000840
841 Pipeline.addCallbackToPipeline(Deserializer);
842 Pipeline.addCallbackToPipeline(Dumper);
843 CVSymbolVisitor Visitor(Pipeline);
Zachary Turneraf8c75a2017-06-30 21:35:00 +0000844 auto SS = ModS.getSymbolsSubstream();
845 if (auto EC = Visitor.visitSymbolStream(ModS.getSymbolArray(), SS.Offset)) {
Zachary Turner63055452017-06-15 22:24:24 +0000846 P.formatLine("Error while processing symbol records. {0}",
847 toString(std::move(EC)));
848 continue;
849 }
850 }
851 return Error::success();
852}
853
Zachary Turner7df69952017-06-22 20:57:39 +0000854Error DumpOutputStyle::dumpPublics() {
Zachary Turner63055452017-06-15 22:24:24 +0000855 printHeader(P, "Public Symbols");
856
857 AutoIndent Indent(P);
858 if (!File.hasPDBPublicsStream()) {
859 P.formatLine("Publics stream not present");
860 return Error::success();
861 }
862
863 ExitOnError Err("Error dumping publics stream");
864
Zachary Turner59224cb2017-06-16 23:42:15 +0000865 auto &Types = Err(initializeTypes(StreamTPI));
Zachary Turner63055452017-06-15 22:24:24 +0000866 auto &Publics = Err(File.getPDBPublicsStream());
867 SymbolVisitorCallbackPipeline Pipeline;
868 SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
Zachary Turner7df69952017-06-22 20:57:39 +0000869 MinimalSymbolDumper Dumper(P, opts::dump::DumpSymRecordBytes, Types);
Zachary Turner63055452017-06-15 22:24:24 +0000870
871 Pipeline.addCallbackToPipeline(Deserializer);
872 Pipeline.addCallbackToPipeline(Dumper);
873 CVSymbolVisitor Visitor(Pipeline);
Zachary Turneraf8c75a2017-06-30 21:35:00 +0000874
Zachary Turner63055452017-06-15 22:24:24 +0000875 auto ExpectedSymbols = Publics.getSymbolArray();
876 if (!ExpectedSymbols) {
877 P.formatLine("Could not read public symbol record stream");
878 return Error::success();
879 }
880
Zachary Turneraf8c75a2017-06-30 21:35:00 +0000881 if (auto EC = Visitor.visitSymbolStream(*ExpectedSymbols, 0))
Zachary Turner63055452017-06-15 22:24:24 +0000882 P.formatLine("Error while processing public symbol records. {0}",
883 toString(std::move(EC)));
884
885 return Error::success();
886}
887
888static std::string formatSectionCharacteristics(uint32_t IndentLevel,
889 uint32_t C) {
890 using SC = COFF::SectionCharacteristics;
891 std::vector<std::string> Opts;
892 if (C == COFF::SC_Invalid)
893 return "invalid";
894 if (C == 0)
895 return "none";
896
897 PUSH_FLAG(SC, IMAGE_SCN_TYPE_NOLOAD, C, "IMAGE_SCN_TYPE_NOLOAD");
898 PUSH_FLAG(SC, IMAGE_SCN_TYPE_NO_PAD, C, "IMAGE_SCN_TYPE_NO_PAD");
899 PUSH_FLAG(SC, IMAGE_SCN_CNT_CODE, C, "IMAGE_SCN_CNT_CODE");
900 PUSH_FLAG(SC, IMAGE_SCN_CNT_INITIALIZED_DATA, C,
901 "IMAGE_SCN_CNT_INITIALIZED_DATA");
902 PUSH_FLAG(SC, IMAGE_SCN_CNT_UNINITIALIZED_DATA, C,
903 "IMAGE_SCN_CNT_UNINITIALIZED_DATA");
904 PUSH_FLAG(SC, IMAGE_SCN_LNK_OTHER, C, "IMAGE_SCN_LNK_OTHER");
905 PUSH_FLAG(SC, IMAGE_SCN_LNK_INFO, C, "IMAGE_SCN_LNK_INFO");
906 PUSH_FLAG(SC, IMAGE_SCN_LNK_REMOVE, C, "IMAGE_SCN_LNK_REMOVE");
907 PUSH_FLAG(SC, IMAGE_SCN_LNK_COMDAT, C, "IMAGE_SCN_LNK_COMDAT");
908 PUSH_FLAG(SC, IMAGE_SCN_GPREL, C, "IMAGE_SCN_GPREL");
909 PUSH_FLAG(SC, IMAGE_SCN_MEM_PURGEABLE, C, "IMAGE_SCN_MEM_PURGEABLE");
910 PUSH_FLAG(SC, IMAGE_SCN_MEM_16BIT, C, "IMAGE_SCN_MEM_16BIT");
911 PUSH_FLAG(SC, IMAGE_SCN_MEM_LOCKED, C, "IMAGE_SCN_MEM_LOCKED");
912 PUSH_FLAG(SC, IMAGE_SCN_MEM_PRELOAD, C, "IMAGE_SCN_MEM_PRELOAD");
913 PUSH_FLAG(SC, IMAGE_SCN_GPREL, C, "IMAGE_SCN_GPREL");
914 PUSH_FLAG(SC, IMAGE_SCN_GPREL, C, "IMAGE_SCN_GPREL");
915 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_1BYTES, C,
916 "IMAGE_SCN_ALIGN_1BYTES");
917 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_2BYTES, C,
918 "IMAGE_SCN_ALIGN_2BYTES");
919 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_4BYTES, C,
920 "IMAGE_SCN_ALIGN_4BYTES");
921 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_8BYTES, C,
922 "IMAGE_SCN_ALIGN_8BYTES");
923 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_16BYTES, C,
924 "IMAGE_SCN_ALIGN_16BYTES");
925 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_32BYTES, C,
926 "IMAGE_SCN_ALIGN_32BYTES");
927 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_64BYTES, C,
928 "IMAGE_SCN_ALIGN_64BYTES");
929 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_128BYTES, C,
930 "IMAGE_SCN_ALIGN_128BYTES");
931 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_256BYTES, C,
932 "IMAGE_SCN_ALIGN_256BYTES");
933 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_512BYTES, C,
934 "IMAGE_SCN_ALIGN_512BYTES");
935 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_1024BYTES, C,
936 "IMAGE_SCN_ALIGN_1024BYTES");
937 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_2048BYTES, C,
938 "IMAGE_SCN_ALIGN_2048BYTES");
939 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_4096BYTES, C,
940 "IMAGE_SCN_ALIGN_4096BYTES");
941 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_8192BYTES, C,
942 "IMAGE_SCN_ALIGN_8192BYTES");
943 PUSH_FLAG(SC, IMAGE_SCN_LNK_NRELOC_OVFL, C, "IMAGE_SCN_LNK_NRELOC_OVFL");
944 PUSH_FLAG(SC, IMAGE_SCN_MEM_DISCARDABLE, C, "IMAGE_SCN_MEM_DISCARDABLE");
945 PUSH_FLAG(SC, IMAGE_SCN_MEM_NOT_CACHED, C, "IMAGE_SCN_MEM_NOT_CACHED");
946 PUSH_FLAG(SC, IMAGE_SCN_MEM_NOT_PAGED, C, "IMAGE_SCN_MEM_NOT_PAGED");
947 PUSH_FLAG(SC, IMAGE_SCN_MEM_SHARED, C, "IMAGE_SCN_MEM_SHARED");
948 PUSH_FLAG(SC, IMAGE_SCN_MEM_EXECUTE, C, "IMAGE_SCN_MEM_EXECUTE");
949 PUSH_FLAG(SC, IMAGE_SCN_MEM_READ, C, "IMAGE_SCN_MEM_READ");
950 PUSH_FLAG(SC, IMAGE_SCN_MEM_WRITE, C, "IMAGE_SCN_MEM_WRITE");
Zachary Turner47d9a562017-06-16 00:04:24 +0000951 return typesetItemList(Opts, IndentLevel, 3, " | ");
Zachary Turner63055452017-06-15 22:24:24 +0000952}
953
954static std::string formatSegMapDescriptorFlag(uint32_t IndentLevel,
955 OMFSegDescFlags Flags) {
956 std::vector<std::string> Opts;
957 if (Flags == OMFSegDescFlags::None)
958 return "none";
959
960 PUSH_FLAG(OMFSegDescFlags, Read, Flags, "read");
961 PUSH_FLAG(OMFSegDescFlags, Write, Flags, "write");
962 PUSH_FLAG(OMFSegDescFlags, Execute, Flags, "execute");
963 PUSH_FLAG(OMFSegDescFlags, AddressIs32Bit, Flags, "32 bit addr");
964 PUSH_FLAG(OMFSegDescFlags, IsSelector, Flags, "selector");
965 PUSH_FLAG(OMFSegDescFlags, IsAbsoluteAddress, Flags, "absolute addr");
966 PUSH_FLAG(OMFSegDescFlags, IsGroup, Flags, "group");
Zachary Turner47d9a562017-06-16 00:04:24 +0000967 return typesetItemList(Opts, IndentLevel, 4, " | ");
Zachary Turner63055452017-06-15 22:24:24 +0000968}
969
Zachary Turner7df69952017-06-22 20:57:39 +0000970Error DumpOutputStyle::dumpSectionContribs() {
Zachary Turner63055452017-06-15 22:24:24 +0000971 printHeader(P, "Section Contributions");
972 ExitOnError Err("Error dumping publics stream");
973
974 AutoIndent Indent(P);
975 if (!File.hasPDBDbiStream()) {
976 P.formatLine(
977 "Section contribs require a DBI Stream, which could not be loaded");
978 return Error::success();
979 }
980
981 auto &Dbi = Err(File.getPDBDbiStream());
982
983 class Visitor : public ISectionContribVisitor {
984 public:
985 Visitor(LinePrinter &P) : P(P) {}
986 void visit(const SectionContrib &SC) override {
987 P.formatLine(
988 "SC | mod = {2}, {0}, size = {1}, data crc = {3}, reloc crc = {4}",
989 formatSegmentOffset(SC.ISect, SC.Off), fmtle(SC.Size), fmtle(SC.Imod),
990 fmtle(SC.DataCrc), fmtle(SC.RelocCrc));
991 P.formatLine(" {0}",
992 formatSectionCharacteristics(P.getIndentLevel() + 6,
993 SC.Characteristics));
994 }
995 void visit(const SectionContrib2 &SC) override {
996 P.formatLine("SC2 | mod = {2}, {0}, size = {1}, data crc = {3}, reloc "
997 "crc = {4}, coff section = {5}",
998 formatSegmentOffset(SC.Base.ISect, SC.Base.Off),
999 fmtle(SC.Base.Size), fmtle(SC.Base.Imod),
1000 fmtle(SC.Base.DataCrc), fmtle(SC.Base.RelocCrc),
1001 fmtle(SC.ISectCoff));
1002 P.formatLine(" {0}",
1003 formatSectionCharacteristics(P.getIndentLevel() + 6,
1004 SC.Base.Characteristics));
1005 }
1006
1007 private:
1008 LinePrinter &P;
1009 };
1010
1011 Visitor V(P);
1012 Dbi.visitSectionContributions(V);
1013 return Error::success();
1014}
1015
Zachary Turner7df69952017-06-22 20:57:39 +00001016Error DumpOutputStyle::dumpSectionMap() {
Zachary Turner63055452017-06-15 22:24:24 +00001017 printHeader(P, "Section Map");
1018 ExitOnError Err("Error dumping section map");
1019
1020 AutoIndent Indent(P);
1021 if (!File.hasPDBDbiStream()) {
1022 P.formatLine("Dumping the section map requires a DBI Stream, which could "
1023 "not be loaded");
1024 return Error::success();
1025 }
1026
1027 auto &Dbi = Err(File.getPDBDbiStream());
1028
1029 uint32_t I = 0;
1030 for (auto &M : Dbi.getSectionMap()) {
1031 P.formatLine(
1032 "Section {0:4} | ovl = {0}, group = {1}, frame = {2}, name = {3}", I,
1033 fmtle(M.Ovl), fmtle(M.Group), fmtle(M.Frame), fmtle(M.SecName));
1034 P.formatLine(" class = {0}, offset = {1}, size = {2}",
1035 fmtle(M.ClassName), fmtle(M.Offset), fmtle(M.SecByteLength));
1036 P.formatLine(" flags = {0}",
1037 formatSegMapDescriptorFlag(
1038 P.getIndentLevel() + 13,
1039 static_cast<OMFSegDescFlags>(uint16_t(M.Flags))));
1040 ++I;
1041 }
1042 return Error::success();
1043}