blob: 248e0de675e3bae92e505e5343a70b80193a8785 [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"
Reid Kleckner14d90fd2017-07-26 00:40:36 +000052#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
Zachary Turner63055452017-06-15 22:24:24 +000053#include "llvm/DebugInfo/PDB/Native/RawError.h"
54#include "llvm/DebugInfo/PDB/Native/TpiHashing.h"
55#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
56#include "llvm/DebugInfo/PDB/PDBExtras.h"
57#include "llvm/Object/COFF.h"
58#include "llvm/Support/BinaryStreamReader.h"
59#include "llvm/Support/FormatAdapters.h"
60#include "llvm/Support/FormatVariadic.h"
61
62#include <unordered_map>
63
64using namespace llvm;
65using namespace llvm::codeview;
66using namespace llvm::msf;
67using namespace llvm::pdb;
68
Zachary Turner7df69952017-06-22 20:57:39 +000069DumpOutputStyle::DumpOutputStyle(PDBFile &File)
Zachary Turner63055452017-06-15 22:24:24 +000070 : File(File), P(2, false, outs()) {}
71
Zachary Turner7df69952017-06-22 20:57:39 +000072Error DumpOutputStyle::dump() {
73 if (opts::dump::DumpSummary) {
Zachary Turner63055452017-06-15 22:24:24 +000074 if (auto EC = dumpFileSummary())
75 return EC;
76 P.NewLine();
77 }
78
Zachary Turner7df69952017-06-22 20:57:39 +000079 if (opts::dump::DumpStreams) {
Zachary Turner63055452017-06-15 22:24:24 +000080 if (auto EC = dumpStreamSummary())
81 return EC;
82 P.NewLine();
83 }
84
Zachary Turner7df69952017-06-22 20:57:39 +000085 if (opts::dump::DumpStringTable) {
Zachary Turner63055452017-06-15 22:24:24 +000086 if (auto EC = dumpStringTable())
87 return EC;
88 P.NewLine();
89 }
90
Zachary Turner7df69952017-06-22 20:57:39 +000091 if (opts::dump::DumpModules) {
Zachary Turner63055452017-06-15 22:24:24 +000092 if (auto EC = dumpModules())
93 return EC;
94 }
95
Zachary Turner7df69952017-06-22 20:57:39 +000096 if (opts::dump::DumpModuleFiles) {
Zachary Turner0e327d02017-06-15 23:12:41 +000097 if (auto EC = dumpModuleFiles())
98 return EC;
99 }
100
Zachary Turner7df69952017-06-22 20:57:39 +0000101 if (opts::dump::DumpLines) {
Zachary Turner4e950642017-06-15 23:56:19 +0000102 if (auto EC = dumpLines())
103 return EC;
104 }
105
Zachary Turner7df69952017-06-22 20:57:39 +0000106 if (opts::dump::DumpInlineeLines) {
Zachary Turner4e950642017-06-15 23:56:19 +0000107 if (auto EC = dumpInlineeLines())
108 return EC;
109 }
110
Zachary Turner7df69952017-06-22 20:57:39 +0000111 if (opts::dump::DumpXmi) {
Zachary Turner47d9a562017-06-16 00:04:24 +0000112 if (auto EC = dumpXmi())
113 return EC;
114 }
115
Zachary Turner7df69952017-06-22 20:57:39 +0000116 if (opts::dump::DumpXme) {
Zachary Turner47d9a562017-06-16 00:04:24 +0000117 if (auto EC = dumpXme())
118 return EC;
119 }
120
Zachary Turner02a26772017-06-30 18:15:47 +0000121 if (opts::dump::DumpTypes || !opts::dump::DumpTypeIndex.empty() ||
122 opts::dump::DumpTypeExtras) {
Zachary Turner63055452017-06-15 22:24:24 +0000123 if (auto EC = dumpTpiStream(StreamTPI))
124 return EC;
125 }
126
Zachary Turner02a26772017-06-30 18:15:47 +0000127 if (opts::dump::DumpIds || !opts::dump::DumpIdIndex.empty() ||
128 opts::dump::DumpIdExtras) {
Zachary Turner63055452017-06-15 22:24:24 +0000129 if (auto EC = dumpTpiStream(StreamIPI))
130 return EC;
131 }
132
Reid Kleckner14d90fd2017-07-26 00:40:36 +0000133 if (opts::dump::DumpGlobals) {
134 if (auto EC = dumpGlobals())
135 return EC;
136 }
137
Zachary Turner7df69952017-06-22 20:57:39 +0000138 if (opts::dump::DumpPublics) {
Zachary Turner63055452017-06-15 22:24:24 +0000139 if (auto EC = dumpPublics())
140 return EC;
141 }
142
Zachary Turner7df69952017-06-22 20:57:39 +0000143 if (opts::dump::DumpSymbols) {
Zachary Turner63055452017-06-15 22:24:24 +0000144 if (auto EC = dumpModuleSyms())
145 return EC;
146 }
147
Zachary Turner7df69952017-06-22 20:57:39 +0000148 if (opts::dump::DumpSectionContribs) {
Zachary Turner63055452017-06-15 22:24:24 +0000149 if (auto EC = dumpSectionContribs())
150 return EC;
151 }
152
Zachary Turner7df69952017-06-22 20:57:39 +0000153 if (opts::dump::DumpSectionMap) {
Zachary Turner63055452017-06-15 22:24:24 +0000154 if (auto EC = dumpSectionMap())
155 return EC;
156 }
157
158 return Error::success();
159}
160
161static void printHeader(LinePrinter &P, const Twine &S) {
162 P.NewLine();
163 P.formatLine("{0,=60}", S);
164 P.formatLine("{0}", fmt_repeat('=', 60));
165}
166
Zachary Turner7df69952017-06-22 20:57:39 +0000167Error DumpOutputStyle::dumpFileSummary() {
Zachary Turner63055452017-06-15 22:24:24 +0000168 printHeader(P, "Summary");
169
Reid Klecknerdd853e52017-07-27 23:13:18 +0000170 ExitOnError Err("Invalid PDB Format: ");
Zachary Turner63055452017-06-15 22:24:24 +0000171
172 AutoIndent Indent(P);
173 P.formatLine("Block Size: {0}", File.getBlockSize());
174 P.formatLine("Number of blocks: {0}", File.getBlockCount());
175 P.formatLine("Number of streams: {0}", File.getNumStreams());
176
177 auto &PS = Err(File.getPDBInfoStream());
178 P.formatLine("Signature: {0}", PS.getSignature());
179 P.formatLine("Age: {0}", PS.getAge());
180 P.formatLine("GUID: {0}", fmt_guid(PS.getGuid().Guid));
181 P.formatLine("Features: {0:x+}", static_cast<uint32_t>(PS.getFeatures()));
182 P.formatLine("Has Debug Info: {0}", File.hasPDBDbiStream());
183 P.formatLine("Has Types: {0}", File.hasPDBTpiStream());
184 P.formatLine("Has IDs: {0}", File.hasPDBIpiStream());
185 P.formatLine("Has Globals: {0}", File.hasPDBGlobalsStream());
186 P.formatLine("Has Publics: {0}", File.hasPDBPublicsStream());
187 if (File.hasPDBDbiStream()) {
188 auto &DBI = Err(File.getPDBDbiStream());
189 P.formatLine("Is incrementally linked: {0}", DBI.isIncrementallyLinked());
190 P.formatLine("Has conflicting types: {0}", DBI.hasCTypes());
191 P.formatLine("Is stripped: {0}", DBI.isStripped());
192 }
193
194 return Error::success();
195}
196
Zachary Turner7df69952017-06-22 20:57:39 +0000197Error DumpOutputStyle::dumpStreamSummary() {
Zachary Turner63055452017-06-15 22:24:24 +0000198 printHeader(P, "Streams");
199
200 if (StreamPurposes.empty())
201 discoverStreamPurposes(File, StreamPurposes);
202
203 AutoIndent Indent(P);
204 uint32_t StreamCount = File.getNumStreams();
205
206 for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
207 P.formatLine(
208 "Stream {0}: [{1}] ({2} bytes)",
209 fmt_align(StreamIdx, AlignStyle::Right, NumDigits(StreamCount)),
210 StreamPurposes[StreamIdx], File.getStreamByteSize(StreamIdx));
Zachary Turner5f098522017-06-23 20:28:14 +0000211 if (opts::dump::DumpStreamBlocks) {
212 auto Blocks = File.getStreamBlockList(StreamIdx);
213 std::vector<uint32_t> BV(Blocks.begin(), Blocks.end());
214 P.formatLine(" {0} Blocks: [{1}]",
215 fmt_repeat(' ', NumDigits(StreamCount)),
216 make_range(BV.begin(), BV.end()));
217 }
Zachary Turner63055452017-06-15 22:24:24 +0000218 }
219
220 return Error::success();
221}
222
Zachary Turner0e327d02017-06-15 23:12:41 +0000223static Expected<ModuleDebugStreamRef> getModuleDebugStream(PDBFile &File,
224 uint32_t Index) {
Reid Klecknerdd853e52017-07-27 23:13:18 +0000225 ExitOnError Err("Unexpected error: ");
Zachary Turner0e327d02017-06-15 23:12:41 +0000226
227 auto &Dbi = Err(File.getPDBDbiStream());
228 const auto &Modules = Dbi.modules();
229 auto Modi = Modules.getModuleDescriptor(Index);
230
231 uint16_t ModiStream = Modi.getModuleStreamIndex();
232 if (ModiStream == kInvalidStreamIndex)
233 return make_error<RawError>(raw_error_code::no_stream,
234 "Module stream not present");
235
236 auto ModStreamData = MappedBlockStream::createIndexedStream(
237 File.getMsfLayout(), File.getMsfBuffer(), ModiStream,
238 File.getAllocator());
239
240 ModuleDebugStreamRef ModS(Modi, std::move(ModStreamData));
241 if (auto EC = ModS.reload())
242 return make_error<RawError>(raw_error_code::corrupt_file,
243 "Invalid module stream");
244
245 return std::move(ModS);
246}
247
Zachary Turner0e327d02017-06-15 23:12:41 +0000248static std::string formatChecksumKind(FileChecksumKind Kind) {
249 switch (Kind) {
250 RETURN_CASE(FileChecksumKind, None, "None");
251 RETURN_CASE(FileChecksumKind, MD5, "MD5");
252 RETURN_CASE(FileChecksumKind, SHA1, "SHA-1");
253 RETURN_CASE(FileChecksumKind, SHA256, "SHA-256");
254 }
255 return formatUnknownEnum(Kind);
256}
257
Zachary Turner4e950642017-06-15 23:56:19 +0000258namespace {
259class StringsAndChecksumsPrinter {
260 const DebugStringTableSubsectionRef &extractStringTable(PDBFile &File) {
Reid Klecknerdd853e52017-07-27 23:13:18 +0000261 ExitOnError Err("Unexpected error processing modules: ");
Zachary Turner4e950642017-06-15 23:56:19 +0000262 return Err(File.getStringTable()).getStringTable();
263 }
264
265 template <typename... Args>
266 void formatInternal(LinePrinter &Printer, bool Append,
267 Args &&... args) const {
268 if (Append)
269 Printer.format(std::forward<Args>(args)...);
270 else
271 Printer.formatLine(std::forward<Args>(args)...);
272 }
273
274public:
275 StringsAndChecksumsPrinter(PDBFile &File, uint32_t Modi)
276 : Records(extractStringTable(File)) {
277 auto MDS = getModuleDebugStream(File, Modi);
278 if (!MDS) {
279 consumeError(MDS.takeError());
280 return;
281 }
282
283 DebugStream = llvm::make_unique<ModuleDebugStreamRef>(std::move(*MDS));
284 Records.initialize(MDS->subsections());
285 if (Records.hasChecksums()) {
286 for (const auto &Entry : Records.checksums()) {
287 auto S = Records.strings().getString(Entry.FileNameOffset);
288 if (!S)
289 continue;
290 ChecksumsByFile[*S] = Entry;
291 }
292 }
293 }
294
295 Expected<StringRef> getNameFromStringTable(uint32_t Offset) const {
296 return Records.strings().getString(Offset);
297 }
298
299 void formatFromFileName(LinePrinter &Printer, StringRef File,
300 bool Append = false) const {
301 auto FC = ChecksumsByFile.find(File);
302 if (FC == ChecksumsByFile.end()) {
303 formatInternal(Printer, Append, "- (no checksum) {0}", File);
304 return;
305 }
306
307 formatInternal(Printer, Append, "- ({0}: {1}) {2}",
308 formatChecksumKind(FC->getValue().Kind),
309 toHex(FC->getValue().Checksum), File);
310 }
311
312 void formatFromChecksumsOffset(LinePrinter &Printer, uint32_t Offset,
313 bool Append = false) const {
314 if (!Records.hasChecksums()) {
315 formatInternal(Printer, Append, "(unknown file name offset {0})", Offset);
316 return;
317 }
318
319 auto Iter = Records.checksums().getArray().at(Offset);
320 if (Iter == Records.checksums().getArray().end()) {
321 formatInternal(Printer, Append, "(unknown file name offset {0})", Offset);
322 return;
323 }
324
325 uint32_t FO = Iter->FileNameOffset;
326 auto ExpectedFile = getNameFromStringTable(FO);
327 if (!ExpectedFile) {
328 formatInternal(Printer, Append, "(unknown file name offset {0})", Offset);
329 consumeError(ExpectedFile.takeError());
330 return;
331 }
332 if (Iter->Kind == FileChecksumKind::None) {
333 formatInternal(Printer, Append, "{0} (no checksum)", *ExpectedFile);
334 } else {
335 formatInternal(Printer, Append, "{0} ({1}: {2})", *ExpectedFile,
336 formatChecksumKind(Iter->Kind), toHex(Iter->Checksum));
337 }
338 }
339
340 std::unique_ptr<ModuleDebugStreamRef> DebugStream;
341 StringsAndChecksumsRef Records;
342 StringMap<FileChecksumEntry> ChecksumsByFile;
343};
344} // namespace
345
Zachary Turnerf2872b92017-06-15 23:59:56 +0000346template <typename CallbackT>
Zachary Turner58699362017-08-03 23:11:52 +0000347static void iterateOneModule(PDBFile &File, LinePrinter &P,
348 const DbiModuleDescriptor &Descriptor,
349 uint32_t Modi, uint32_t IndentLevel,
350 uint32_t Digits, CallbackT Callback) {
351 P.formatLine(
352 "Mod {0:4} | `{1}`: ", fmt_align(Modi, AlignStyle::Right, Digits),
353 Descriptor.getModuleName());
354
355 StringsAndChecksumsPrinter Strings(File, Modi);
356 AutoIndent Indent2(P, IndentLevel);
357 Callback(Modi, Strings);
358}
359
360template <typename CallbackT>
Zachary Turnerf2872b92017-06-15 23:59:56 +0000361static void iterateModules(PDBFile &File, LinePrinter &P, uint32_t IndentLevel,
362 CallbackT Callback) {
363 AutoIndent Indent(P);
364 if (!File.hasPDBDbiStream()) {
365 P.formatLine("DBI Stream not present");
366 return;
367 }
368
Reid Klecknerdd853e52017-07-27 23:13:18 +0000369 ExitOnError Err("Unexpected error processing modules: ");
Zachary Turnerf2872b92017-06-15 23:59:56 +0000370
371 auto &Stream = Err(File.getPDBDbiStream());
372
373 const DbiModuleList &Modules = Stream.modules();
Zachary Turner58699362017-08-03 23:11:52 +0000374
375 if (opts::dump::DumpModi.getNumOccurrences() > 0) {
376 assert(opts::dump::DumpModi.getNumOccurrences() == 1);
377 uint32_t Modi = opts::dump::DumpModi;
378 auto Descriptor = Modules.getModuleDescriptor(Modi);
379 iterateOneModule(File, P, Descriptor, Modi, IndentLevel, NumDigits(Modi),
380 Callback);
381 return;
382 }
383
Zachary Turnerf2872b92017-06-15 23:59:56 +0000384 uint32_t Count = Modules.getModuleCount();
385 uint32_t Digits = NumDigits(Count);
386 for (uint32_t I = 0; I < Count; ++I) {
Zachary Turner58699362017-08-03 23:11:52 +0000387 auto Descriptor = Modules.getModuleDescriptor(I);
388 iterateOneModule(File, P, Descriptor, I, IndentLevel, Digits, Callback);
Zachary Turnerf2872b92017-06-15 23:59:56 +0000389 }
390}
391
392template <typename SubsectionT>
393static void iterateModuleSubsections(
394 PDBFile &File, LinePrinter &P, uint32_t IndentLevel,
395 llvm::function_ref<void(uint32_t, StringsAndChecksumsPrinter &,
396 SubsectionT &)>
397 Callback) {
398
399 iterateModules(
400 File, P, IndentLevel,
401 [&File, &Callback](uint32_t Modi, StringsAndChecksumsPrinter &Strings) {
402 auto MDS = getModuleDebugStream(File, Modi);
403 if (!MDS) {
404 consumeError(MDS.takeError());
405 return;
406 }
407
408 for (const auto &SS : MDS->subsections()) {
409 SubsectionT Subsection;
410
411 if (SS.kind() != Subsection.kind())
412 continue;
413
414 BinaryStreamReader Reader(SS.getRecordData());
415 if (auto EC = Subsection.initialize(Reader))
416 continue;
417 Callback(Modi, Strings, Subsection);
418 }
419 });
420}
421
Zachary Turner7df69952017-06-22 20:57:39 +0000422Error DumpOutputStyle::dumpModules() {
Zachary Turner63055452017-06-15 22:24:24 +0000423 printHeader(P, "Modules");
424
425 AutoIndent Indent(P);
426 if (!File.hasPDBDbiStream()) {
427 P.formatLine("DBI Stream not present");
428 return Error::success();
429 }
430
Reid Klecknerdd853e52017-07-27 23:13:18 +0000431 ExitOnError Err("Unexpected error processing modules: ");
Zachary Turner63055452017-06-15 22:24:24 +0000432
433 auto &Stream = Err(File.getPDBDbiStream());
434
435 const DbiModuleList &Modules = Stream.modules();
436 uint32_t Count = Modules.getModuleCount();
437 uint32_t Digits = NumDigits(Count);
438 for (uint32_t I = 0; I < Count; ++I) {
439 auto Modi = Modules.getModuleDescriptor(I);
440 P.formatLine("Mod {0:4} | Name: `{1}`: ",
441 fmt_align(I, AlignStyle::Right, Digits), Modi.getModuleName());
442 P.formatLine(" Obj: `{0}`: ", Modi.getObjFileName());
443 P.formatLine(" debug stream: {0}, # files: {1}, has ec info: {2}",
444 Modi.getModuleStreamIndex(), Modi.getNumberOfFiles(),
445 Modi.hasECInfo());
Zachary Turner6c4bfba2017-07-07 05:04:36 +0000446 StringRef PdbFilePath =
447 Err(Stream.getECName(Modi.getPdbFilePathNameIndex()));
448 StringRef SrcFilePath =
449 Err(Stream.getECName(Modi.getSourceFileNameIndex()));
450 P.formatLine(" pdb file ni: {0} `{1}`, src file ni: {2} `{3}`",
451 Modi.getPdbFilePathNameIndex(), PdbFilePath,
452 Modi.getSourceFileNameIndex(), SrcFilePath);
Zachary Turner0e327d02017-06-15 23:12:41 +0000453 }
454 return Error::success();
455}
456
Zachary Turner7df69952017-06-22 20:57:39 +0000457Error DumpOutputStyle::dumpModuleFiles() {
Zachary Turner0e327d02017-06-15 23:12:41 +0000458 printHeader(P, "Files");
459
Reid Klecknerdd853e52017-07-27 23:13:18 +0000460 ExitOnError Err("Unexpected error processing modules: ");
Zachary Turner0e327d02017-06-15 23:12:41 +0000461
Zachary Turnerf2872b92017-06-15 23:59:56 +0000462 iterateModules(
463 File, P, 11,
464 [this, &Err](uint32_t Modi, StringsAndChecksumsPrinter &Strings) {
465 auto &Stream = Err(File.getPDBDbiStream());
Zachary Turner0e327d02017-06-15 23:12:41 +0000466
Zachary Turnerf2872b92017-06-15 23:59:56 +0000467 const DbiModuleList &Modules = Stream.modules();
468 for (const auto &F : Modules.source_files(Modi)) {
469 Strings.formatFromFileName(P, F);
470 }
471 });
Zachary Turner4e950642017-06-15 23:56:19 +0000472 return Error::success();
473}
474
475static void typesetLinesAndColumns(PDBFile &File, LinePrinter &P,
476 uint32_t Start, const LineColumnEntry &E) {
477 const uint32_t kMaxCharsPerLineNumber = 4; // 4 digit line number
478 uint32_t MinColumnWidth = kMaxCharsPerLineNumber + 5;
479
480 // Let's try to keep it under 100 characters
481 constexpr uint32_t kMaxRowLength = 100;
482 // At least 3 spaces between columns.
483 uint32_t ColumnsPerRow = kMaxRowLength / (MinColumnWidth + 3);
484 uint32_t ItemsLeft = E.LineNumbers.size();
485 auto LineIter = E.LineNumbers.begin();
486 while (ItemsLeft != 0) {
487 uint32_t RowColumns = std::min(ItemsLeft, ColumnsPerRow);
488 for (uint32_t I = 0; I < RowColumns; ++I) {
489 LineInfo Line(LineIter->Flags);
490 std::string LineStr;
491 if (Line.isAlwaysStepInto())
492 LineStr = "ASI";
493 else if (Line.isNeverStepInto())
494 LineStr = "NSI";
Zachary Turner0e327d02017-06-15 23:12:41 +0000495 else
Zachary Turner4e950642017-06-15 23:56:19 +0000496 LineStr = utostr(Line.getStartLine());
497 char Statement = Line.isStatement() ? ' ' : '!';
498 P.format("{0} {1:X-} {2} ",
499 fmt_align(LineStr, AlignStyle::Right, kMaxCharsPerLineNumber),
500 fmt_align(Start + LineIter->Offset, AlignStyle::Right, 8, '0'),
501 Statement);
502 ++LineIter;
503 --ItemsLeft;
Zachary Turner63055452017-06-15 22:24:24 +0000504 }
Zachary Turner4e950642017-06-15 23:56:19 +0000505 P.NewLine();
Zachary Turner63055452017-06-15 22:24:24 +0000506 }
Zachary Turner4e950642017-06-15 23:56:19 +0000507}
508
Zachary Turner7df69952017-06-22 20:57:39 +0000509Error DumpOutputStyle::dumpLines() {
Zachary Turner4e950642017-06-15 23:56:19 +0000510 printHeader(P, "Lines");
Zachary Turner4e950642017-06-15 23:56:19 +0000511
Zachary Turnerf2872b92017-06-15 23:59:56 +0000512 uint32_t LastModi = UINT32_MAX;
513 uint32_t LastNameIndex = UINT32_MAX;
514 iterateModuleSubsections<DebugLinesSubsectionRef>(
515 File, P, 4,
516 [this, &LastModi, &LastNameIndex](uint32_t Modi,
517 StringsAndChecksumsPrinter &Strings,
518 DebugLinesSubsectionRef &Lines) {
519 uint16_t Segment = Lines.header()->RelocSegment;
520 uint32_t Begin = Lines.header()->RelocOffset;
521 uint32_t End = Begin + Lines.header()->CodeSize;
522 for (const auto &Block : Lines) {
523 if (LastModi != Modi || LastNameIndex != Block.NameIndex) {
524 LastModi = Modi;
525 LastNameIndex = Block.NameIndex;
526 Strings.formatFromChecksumsOffset(P, Block.NameIndex);
Zachary Turner4e950642017-06-15 23:56:19 +0000527 }
528
Zachary Turnerf2872b92017-06-15 23:59:56 +0000529 AutoIndent Indent(P, 2);
530 P.formatLine("{0:X-4}:{1:X-8}-{2:X-8}, ", Segment, Begin, End);
531 uint32_t Count = Block.LineNumbers.size();
532 if (Lines.hasColumnInfo())
533 P.format("line/column/addr entries = {0}", Count);
534 else
535 P.format("line/addr entries = {0}", Count);
Zachary Turner4e950642017-06-15 23:56:19 +0000536
Zachary Turnerf2872b92017-06-15 23:59:56 +0000537 P.NewLine();
538 typesetLinesAndColumns(File, P, Begin, Block);
Zachary Turner4e950642017-06-15 23:56:19 +0000539 }
540 });
541
542 return Error::success();
543}
544
Zachary Turner7df69952017-06-22 20:57:39 +0000545Error DumpOutputStyle::dumpInlineeLines() {
Zachary Turner4e950642017-06-15 23:56:19 +0000546 printHeader(P, "Inlinee Lines");
Zachary Turner4e950642017-06-15 23:56:19 +0000547
Zachary Turnerf2872b92017-06-15 23:59:56 +0000548 iterateModuleSubsections<DebugInlineeLinesSubsectionRef>(
549 File, P, 2,
550 [this](uint32_t Modi, StringsAndChecksumsPrinter &Strings,
551 DebugInlineeLinesSubsectionRef &Lines) {
552 P.formatLine("{0,+8} | {1,+5} | {2}", "Inlinee", "Line", "Source File");
553 for (const auto &Entry : Lines) {
554 P.formatLine("{0,+8} | {1,+5} | ", Entry.Header->Inlinee,
555 fmtle(Entry.Header->SourceLineNum));
556 Strings.formatFromChecksumsOffset(P, Entry.Header->FileID, true);
Zachary Turner4e950642017-06-15 23:56:19 +0000557 }
Zachary Turnerf2872b92017-06-15 23:59:56 +0000558 P.NewLine();
Zachary Turner4e950642017-06-15 23:56:19 +0000559 });
560
Zachary Turner63055452017-06-15 22:24:24 +0000561 return Error::success();
562}
Zachary Turner0e327d02017-06-15 23:12:41 +0000563
Zachary Turner7df69952017-06-22 20:57:39 +0000564Error DumpOutputStyle::dumpXmi() {
Zachary Turner47d9a562017-06-16 00:04:24 +0000565 printHeader(P, "Cross Module Imports");
566 iterateModuleSubsections<DebugCrossModuleImportsSubsectionRef>(
567 File, P, 2,
568 [this](uint32_t Modi, StringsAndChecksumsPrinter &Strings,
569 DebugCrossModuleImportsSubsectionRef &Imports) {
570 P.formatLine("{0,=32} | {1}", "Imported Module", "Type IDs");
571
572 for (const auto &Xmi : Imports) {
573 auto ExpectedModule =
574 Strings.getNameFromStringTable(Xmi.Header->ModuleNameOffset);
575 StringRef Module;
576 SmallString<32> ModuleStorage;
577 if (!ExpectedModule) {
578 Module = "(unknown module)";
579 consumeError(ExpectedModule.takeError());
580 } else
581 Module = *ExpectedModule;
582 if (Module.size() > 32) {
583 ModuleStorage = "...";
584 ModuleStorage += Module.take_back(32 - 3);
585 Module = ModuleStorage;
586 }
587 std::vector<std::string> TIs;
588 for (const auto I : Xmi.Imports)
589 TIs.push_back(formatv("{0,+10:X+}", fmtle(I)));
590 std::string Result =
591 typesetItemList(TIs, P.getIndentLevel() + 35, 12, " ");
592 P.formatLine("{0,+32} | {1}", Module, Result);
593 }
594 });
595
596 return Error::success();
597}
598
Zachary Turner7df69952017-06-22 20:57:39 +0000599Error DumpOutputStyle::dumpXme() {
Zachary Turner47d9a562017-06-16 00:04:24 +0000600 printHeader(P, "Cross Module Exports");
601
602 iterateModuleSubsections<DebugCrossModuleExportsSubsectionRef>(
603 File, P, 2,
604 [this](uint32_t Modi, StringsAndChecksumsPrinter &Strings,
605 DebugCrossModuleExportsSubsectionRef &Exports) {
606 P.formatLine("{0,-10} | {1}", "Local ID", "Global ID");
607 for (const auto &Export : Exports) {
608 P.formatLine("{0,+10:X+} | {1}", TypeIndex(Export.Local),
609 TypeIndex(Export.Global));
610 }
611 });
612
613 return Error::success();
614}
615
Zachary Turner7df69952017-06-22 20:57:39 +0000616Error DumpOutputStyle::dumpStringTable() {
Zachary Turner63055452017-06-15 22:24:24 +0000617 printHeader(P, "String Table");
618
619 AutoIndent Indent(P);
620 auto IS = File.getStringTable();
621 if (!IS) {
622 P.formatLine("Not present in file");
623 consumeError(IS.takeError());
624 return Error::success();
625 }
626
627 if (IS->name_ids().empty()) {
628 P.formatLine("Empty");
629 return Error::success();
630 }
631
632 auto MaxID = std::max_element(IS->name_ids().begin(), IS->name_ids().end());
633 uint32_t Digits = NumDigits(*MaxID);
634
635 P.formatLine("{0} | {1}", fmt_align("ID", AlignStyle::Right, Digits),
636 "String");
637
638 std::vector<uint32_t> SortedIDs(IS->name_ids().begin(), IS->name_ids().end());
639 std::sort(SortedIDs.begin(), SortedIDs.end());
640 for (uint32_t I : SortedIDs) {
641 auto ES = IS->getStringForID(I);
642 llvm::SmallString<32> Str;
643 if (!ES) {
644 consumeError(ES.takeError());
645 Str = "Error reading string";
646 } else if (!ES->empty()) {
647 Str.append("'");
648 Str.append(*ES);
649 Str.append("'");
650 }
651
652 if (!Str.empty())
653 P.formatLine("{0} | {1}", fmt_align(I, AlignStyle::Right, Digits), Str);
654 }
655 return Error::success();
656}
657
Zachary Turner02a26772017-06-30 18:15:47 +0000658static void buildDepSet(LazyRandomTypeCollection &Types,
659 ArrayRef<TypeIndex> Indices,
660 std::map<TypeIndex, CVType> &DepSet) {
661 SmallVector<TypeIndex, 4> DepList;
662 for (const auto &I : Indices) {
663 TypeIndex TI(I);
664 if (DepSet.find(TI) != DepSet.end() || TI.isSimple() || TI.isNoneType())
665 continue;
666
667 CVType Type = Types.getType(TI);
668 DepSet[TI] = Type;
669 codeview::discoverTypeIndices(Type, DepList);
670 buildDepSet(Types, DepList, DepSet);
671 }
672}
673
674static void dumpFullTypeStream(LinePrinter &Printer,
675 LazyRandomTypeCollection &Types,
676 TpiStream &Stream, bool Bytes, bool Extras) {
677 Printer.formatLine("Showing {0:N} records", Stream.getNumTypeRecords());
678 uint32_t Width =
679 NumDigits(TypeIndex::FirstNonSimpleIndex + Stream.getNumTypeRecords());
680
681 MinimalTypeDumpVisitor V(Printer, Width + 2, Bytes, Extras, Types,
Reid Klecknerc50349d2017-07-18 00:33:45 +0000682 Stream.getNumHashBuckets(), Stream.getHashValues());
Zachary Turner02a26772017-06-30 18:15:47 +0000683
684 if (auto EC = codeview::visitTypeStream(Types, V)) {
685 Printer.formatLine("An error occurred dumping type records: {0}",
686 toString(std::move(EC)));
687 }
688}
689
690static void dumpPartialTypeStream(LinePrinter &Printer,
691 LazyRandomTypeCollection &Types,
692 TpiStream &Stream, ArrayRef<TypeIndex> TiList,
693 bool Bytes, bool Extras, bool Deps) {
694 uint32_t Width =
695 NumDigits(TypeIndex::FirstNonSimpleIndex + Stream.getNumTypeRecords());
696
697 MinimalTypeDumpVisitor V(Printer, Width + 2, Bytes, Extras, Types,
Reid Klecknerc50349d2017-07-18 00:33:45 +0000698 Stream.getNumHashBuckets(), Stream.getHashValues());
Zachary Turner02a26772017-06-30 18:15:47 +0000699
700 if (opts::dump::DumpTypeDependents) {
701 // If we need to dump all dependents, then iterate each index and find
702 // all dependents, adding them to a map ordered by TypeIndex.
703 std::map<TypeIndex, CVType> DepSet;
704 buildDepSet(Types, TiList, DepSet);
705
706 Printer.formatLine(
707 "Showing {0:N} records and their dependents ({1:N} records total)",
708 TiList.size(), DepSet.size());
709
710 for (auto &Dep : DepSet) {
711 if (auto EC = codeview::visitTypeRecord(Dep.second, Dep.first, V))
712 Printer.formatLine("An error occurred dumping type record {0}: {1}",
713 Dep.first, toString(std::move(EC)));
714 }
715 } else {
716 Printer.formatLine("Showing {0:N} records.", TiList.size());
717
718 for (const auto &I : TiList) {
719 TypeIndex TI(I);
720 CVType Type = Types.getType(TI);
721 if (auto EC = codeview::visitTypeRecord(Type, TI, V))
722 Printer.formatLine("An error occurred dumping type record {0}: {1}", TI,
723 toString(std::move(EC)));
724 }
725 }
726}
727
Zachary Turner7df69952017-06-22 20:57:39 +0000728Error DumpOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
Zachary Turner63055452017-06-15 22:24:24 +0000729 assert(StreamIdx == StreamTPI || StreamIdx == StreamIPI);
730
731 bool Present = false;
Zachary Turnerf8a2e042017-06-15 23:04:42 +0000732 bool DumpTypes = false;
Zachary Turner63055452017-06-15 22:24:24 +0000733 bool DumpBytes = false;
Zachary Turnerf8a2e042017-06-15 23:04:42 +0000734 bool DumpExtras = false;
Zachary Turner59224cb2017-06-16 23:42:15 +0000735 std::vector<uint32_t> Indices;
Zachary Turner63055452017-06-15 22:24:24 +0000736 if (StreamIdx == StreamTPI) {
737 printHeader(P, "Types (TPI Stream)");
738 Present = File.hasPDBTpiStream();
Zachary Turner7df69952017-06-22 20:57:39 +0000739 DumpTypes = opts::dump::DumpTypes;
740 DumpBytes = opts::dump::DumpTypeData;
741 DumpExtras = opts::dump::DumpTypeExtras;
742 Indices.assign(opts::dump::DumpTypeIndex.begin(),
743 opts::dump::DumpTypeIndex.end());
Zachary Turner63055452017-06-15 22:24:24 +0000744 } else if (StreamIdx == StreamIPI) {
745 printHeader(P, "Types (IPI Stream)");
746 Present = File.hasPDBIpiStream();
Zachary Turner7df69952017-06-22 20:57:39 +0000747 DumpTypes = opts::dump::DumpIds;
748 DumpBytes = opts::dump::DumpIdData;
749 DumpExtras = opts::dump::DumpIdExtras;
750 Indices.assign(opts::dump::DumpIdIndex.begin(),
751 opts::dump::DumpIdIndex.end());
Zachary Turner63055452017-06-15 22:24:24 +0000752 }
753
754 AutoIndent Indent(P);
755 if (!Present) {
756 P.formatLine("Stream not present");
757 return Error::success();
758 }
759
Reid Klecknerdd853e52017-07-27 23:13:18 +0000760 ExitOnError Err("Unexpected error processing types: ");
Zachary Turner63055452017-06-15 22:24:24 +0000761
762 auto &Stream = Err((StreamIdx == StreamTPI) ? File.getPDBTpiStream()
763 : File.getPDBIpiStream());
764
Zachary Turner59224cb2017-06-16 23:42:15 +0000765 auto &Types = Err(initializeTypes(StreamIdx));
Zachary Turner63055452017-06-15 22:24:24 +0000766
Zachary Turner02a26772017-06-30 18:15:47 +0000767 if (DumpTypes || !Indices.empty()) {
768 if (Indices.empty())
769 dumpFullTypeStream(P, Types, Stream, DumpBytes, DumpExtras);
770 else {
771 std::vector<TypeIndex> TiList(Indices.begin(), Indices.end());
772 dumpPartialTypeStream(P, Types, Stream, TiList, DumpBytes, DumpExtras,
773 opts::dump::DumpTypeDependents);
Zachary Turnerf8a2e042017-06-15 23:04:42 +0000774 }
775 }
776
777 if (DumpExtras) {
778 P.NewLine();
779 auto IndexOffsets = Stream.getTypeIndexOffsets();
780 P.formatLine("Type Index Offsets:");
781 for (const auto &IO : IndexOffsets) {
782 AutoIndent Indent2(P);
783 P.formatLine("TI: {0}, Offset: {1}", IO.Type, fmtle(IO.Offset));
784 }
785
786 P.NewLine();
787 P.formatLine("Hash Adjusters:");
788 auto &Adjusters = Stream.getHashAdjusters();
789 auto &Strings = Err(File.getStringTable());
790 for (const auto &A : Adjusters) {
791 AutoIndent Indent2(P);
792 auto ExpectedStr = Strings.getStringForID(A.first);
793 TypeIndex TI(A.second);
794 if (ExpectedStr)
795 P.formatLine("`{0}` -> {1}", *ExpectedStr, TI);
796 else {
797 P.formatLine("unknown str id ({0}) -> {1}", A.first, TI);
798 consumeError(ExpectedStr.takeError());
799 }
800 }
Zachary Turner63055452017-06-15 22:24:24 +0000801 }
802 return Error::success();
803}
804
805Expected<codeview::LazyRandomTypeCollection &>
Zachary Turner7df69952017-06-22 20:57:39 +0000806DumpOutputStyle::initializeTypes(uint32_t SN) {
Zachary Turner63055452017-06-15 22:24:24 +0000807 auto &TypeCollection = (SN == StreamTPI) ? TpiTypes : IpiTypes;
808 auto Tpi =
809 (SN == StreamTPI) ? File.getPDBTpiStream() : File.getPDBIpiStream();
810 if (!Tpi)
811 return Tpi.takeError();
812
813 if (!TypeCollection) {
814 auto &Types = Tpi->typeArray();
815 uint32_t Count = Tpi->getNumTypeRecords();
816 auto Offsets = Tpi->getTypeIndexOffsets();
817 TypeCollection =
818 llvm::make_unique<LazyRandomTypeCollection>(Types, Count, Offsets);
819 }
820
821 return *TypeCollection;
822}
823
Zachary Turner7df69952017-06-22 20:57:39 +0000824Error DumpOutputStyle::dumpModuleSyms() {
Zachary Turner63055452017-06-15 22:24:24 +0000825 printHeader(P, "Symbols");
826
827 AutoIndent Indent(P);
828 if (!File.hasPDBDbiStream()) {
829 P.formatLine("DBI Stream not present");
830 return Error::success();
831 }
832
Reid Klecknerdd853e52017-07-27 23:13:18 +0000833 ExitOnError Err("Unexpected error processing symbols: ");
Zachary Turner63055452017-06-15 22:24:24 +0000834
Zachary Turner59224cb2017-06-16 23:42:15 +0000835 auto &Types = Err(initializeTypes(StreamTPI));
Zachary Turner63055452017-06-15 22:24:24 +0000836
Zachary Turner58699362017-08-03 23:11:52 +0000837 iterateModules(
838 File, P, 2, [&](uint32_t I, StringsAndChecksumsPrinter &Strings) {
839 auto ExpectedModS = getModuleDebugStream(File, I);
840 if (!ExpectedModS) {
841 P.formatLine("Error loading module stream {0}. {1}", I,
842 toString(ExpectedModS.takeError()));
843 return;
844 }
Zachary Turner63055452017-06-15 22:24:24 +0000845
Zachary Turner58699362017-08-03 23:11:52 +0000846 ModuleDebugStreamRef &ModS = *ExpectedModS;
Zachary Turner63055452017-06-15 22:24:24 +0000847
Zachary Turner58699362017-08-03 23:11:52 +0000848 SymbolVisitorCallbackPipeline Pipeline;
849 SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
850 MinimalSymbolDumper Dumper(P, opts::dump::DumpSymRecordBytes, Types);
Zachary Turner63055452017-06-15 22:24:24 +0000851
Zachary Turner58699362017-08-03 23:11:52 +0000852 Pipeline.addCallbackToPipeline(Deserializer);
853 Pipeline.addCallbackToPipeline(Dumper);
854 CVSymbolVisitor Visitor(Pipeline);
855 auto SS = ModS.getSymbolsSubstream();
856 if (auto EC =
857 Visitor.visitSymbolStream(ModS.getSymbolArray(), SS.Offset)) {
858 P.formatLine("Error while processing symbol records. {0}",
859 toString(std::move(EC)));
860 return;
861 }
862 });
Zachary Turner63055452017-06-15 22:24:24 +0000863 return Error::success();
864}
865
Reid Kleckner14d90fd2017-07-26 00:40:36 +0000866Error DumpOutputStyle::dumpGlobals() {
867 printHeader(P, "Global Symbols");
868 AutoIndent Indent(P);
869 if (!File.hasPDBGlobalsStream()) {
870 P.formatLine("Globals stream not present");
871 return Error::success();
872 }
Reid Klecknerdd853e52017-07-27 23:13:18 +0000873 ExitOnError Err("Error dumping globals stream: ");
Reid Kleckner14d90fd2017-07-26 00:40:36 +0000874 auto &Globals = Err(File.getPDBGlobalsStream());
875
876 const GSIHashTable &Table = Globals.getGlobalsTable();
877 Err(dumpSymbolsFromGSI(Table, opts::dump::DumpGlobalExtras));
878 return Error::success();
879}
880
Zachary Turner7df69952017-06-22 20:57:39 +0000881Error DumpOutputStyle::dumpPublics() {
Zachary Turner63055452017-06-15 22:24:24 +0000882 printHeader(P, "Public Symbols");
Zachary Turner63055452017-06-15 22:24:24 +0000883 AutoIndent Indent(P);
884 if (!File.hasPDBPublicsStream()) {
885 P.formatLine("Publics stream not present");
886 return Error::success();
887 }
Reid Klecknerdd853e52017-07-27 23:13:18 +0000888 ExitOnError Err("Error dumping publics stream: ");
Zachary Turner63055452017-06-15 22:24:24 +0000889 auto &Publics = Err(File.getPDBPublicsStream());
Zachary Turner63055452017-06-15 22:24:24 +0000890
Reid Kleckner14d90fd2017-07-26 00:40:36 +0000891 const GSIHashTable &PublicsTable = Publics.getPublicsTable();
892 Err(dumpSymbolsFromGSI(PublicsTable, opts::dump::DumpPublicExtras));
Zachary Turneraf8c75a2017-06-30 21:35:00 +0000893
Reid Kleckner14d90fd2017-07-26 00:40:36 +0000894 // Skip the rest if we aren't dumping extras.
Reid Kleckner686f1212017-07-21 18:28:55 +0000895 if (!opts::dump::DumpPublicExtras)
896 return Error::success();
897
Reid Kleckner686f1212017-07-21 18:28:55 +0000898 P.formatLine("Address Map");
899 {
900 // These are offsets into the publics stream sorted by secidx:secrel.
901 AutoIndent Indent2(P);
902 for (uint32_t Addr : Publics.getAddressMap())
903 P.formatLine("off = {0}", Addr);
904 }
905
906 // The thunk map is optional debug info used for ILT thunks.
907 if (!Publics.getThunkMap().empty()) {
908 P.formatLine("Thunk Map");
909 AutoIndent Indent2(P);
910 for (uint32_t Addr : Publics.getThunkMap())
911 P.formatLine("{0:x8}", Addr);
912 }
913
914 // The section offsets table appears to be empty when incremental linking
915 // isn't in use.
916 if (!Publics.getSectionOffsets().empty()) {
917 P.formatLine("Section Offsets");
918 AutoIndent Indent2(P);
919 for (const SectionOffset &SO : Publics.getSectionOffsets())
920 P.formatLine("{0:x4}:{1:x8}", uint16_t(SO.Isect), uint32_t(SO.Off));
921 }
922
Zachary Turner63055452017-06-15 22:24:24 +0000923 return Error::success();
924}
925
Reid Kleckner14d90fd2017-07-26 00:40:36 +0000926Error DumpOutputStyle::dumpSymbolsFromGSI(const GSIHashTable &Table,
927 bool HashExtras) {
928 auto ExpectedSyms = File.getPDBSymbolStream();
929 if (!ExpectedSyms)
930 return ExpectedSyms.takeError();
931 auto ExpectedTypes = initializeTypes(StreamTPI);
932 if (!ExpectedTypes)
933 return ExpectedTypes.takeError();
934 SymbolVisitorCallbackPipeline Pipeline;
935 SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
936 MinimalSymbolDumper Dumper(P, opts::dump::DumpSymRecordBytes, *ExpectedTypes);
937
938 Pipeline.addCallbackToPipeline(Deserializer);
939 Pipeline.addCallbackToPipeline(Dumper);
940 CVSymbolVisitor Visitor(Pipeline);
941
942 BinaryStreamRef SymStream =
943 ExpectedSyms->getSymbolArray().getUnderlyingStream();
944 for (uint32_t PubSymOff : Table) {
945 Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, PubSymOff);
946 if (!Sym)
947 return Sym.takeError();
948 if (auto E = Visitor.visitSymbolRecord(*Sym, PubSymOff))
949 return E;
950 }
951
952 // Return early if we aren't dumping public hash table and address map info.
953 if (!HashExtras)
954 return Error::success();
955
956 P.formatLine("Hash Records");
957 {
958 AutoIndent Indent2(P);
959 for (const PSHashRecord &HR : Table.HashRecords)
960 P.formatLine("off = {0}, refcnt = {1}", uint32_t(HR.Off),
961 uint32_t(HR.CRef));
962 }
963
964 // FIXME: Dump the bitmap.
965
966 P.formatLine("Hash Buckets");
967 {
968 AutoIndent Indent2(P);
969 for (uint32_t Hash : Table.HashBuckets)
970 P.formatLine("{0:x8}", Hash);
971 }
972
973 return Error::success();
974}
975
Zachary Turner63055452017-06-15 22:24:24 +0000976static std::string formatSectionCharacteristics(uint32_t IndentLevel,
977 uint32_t C) {
978 using SC = COFF::SectionCharacteristics;
979 std::vector<std::string> Opts;
980 if (C == COFF::SC_Invalid)
981 return "invalid";
982 if (C == 0)
983 return "none";
984
985 PUSH_FLAG(SC, IMAGE_SCN_TYPE_NOLOAD, C, "IMAGE_SCN_TYPE_NOLOAD");
986 PUSH_FLAG(SC, IMAGE_SCN_TYPE_NO_PAD, C, "IMAGE_SCN_TYPE_NO_PAD");
987 PUSH_FLAG(SC, IMAGE_SCN_CNT_CODE, C, "IMAGE_SCN_CNT_CODE");
988 PUSH_FLAG(SC, IMAGE_SCN_CNT_INITIALIZED_DATA, C,
989 "IMAGE_SCN_CNT_INITIALIZED_DATA");
990 PUSH_FLAG(SC, IMAGE_SCN_CNT_UNINITIALIZED_DATA, C,
991 "IMAGE_SCN_CNT_UNINITIALIZED_DATA");
992 PUSH_FLAG(SC, IMAGE_SCN_LNK_OTHER, C, "IMAGE_SCN_LNK_OTHER");
993 PUSH_FLAG(SC, IMAGE_SCN_LNK_INFO, C, "IMAGE_SCN_LNK_INFO");
994 PUSH_FLAG(SC, IMAGE_SCN_LNK_REMOVE, C, "IMAGE_SCN_LNK_REMOVE");
995 PUSH_FLAG(SC, IMAGE_SCN_LNK_COMDAT, C, "IMAGE_SCN_LNK_COMDAT");
996 PUSH_FLAG(SC, IMAGE_SCN_GPREL, C, "IMAGE_SCN_GPREL");
997 PUSH_FLAG(SC, IMAGE_SCN_MEM_PURGEABLE, C, "IMAGE_SCN_MEM_PURGEABLE");
998 PUSH_FLAG(SC, IMAGE_SCN_MEM_16BIT, C, "IMAGE_SCN_MEM_16BIT");
999 PUSH_FLAG(SC, IMAGE_SCN_MEM_LOCKED, C, "IMAGE_SCN_MEM_LOCKED");
1000 PUSH_FLAG(SC, IMAGE_SCN_MEM_PRELOAD, C, "IMAGE_SCN_MEM_PRELOAD");
1001 PUSH_FLAG(SC, IMAGE_SCN_GPREL, C, "IMAGE_SCN_GPREL");
1002 PUSH_FLAG(SC, IMAGE_SCN_GPREL, C, "IMAGE_SCN_GPREL");
1003 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_1BYTES, C,
1004 "IMAGE_SCN_ALIGN_1BYTES");
1005 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_2BYTES, C,
1006 "IMAGE_SCN_ALIGN_2BYTES");
1007 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_4BYTES, C,
1008 "IMAGE_SCN_ALIGN_4BYTES");
1009 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_8BYTES, C,
1010 "IMAGE_SCN_ALIGN_8BYTES");
1011 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_16BYTES, C,
1012 "IMAGE_SCN_ALIGN_16BYTES");
1013 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_32BYTES, C,
1014 "IMAGE_SCN_ALIGN_32BYTES");
1015 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_64BYTES, C,
1016 "IMAGE_SCN_ALIGN_64BYTES");
1017 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_128BYTES, C,
1018 "IMAGE_SCN_ALIGN_128BYTES");
1019 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_256BYTES, C,
1020 "IMAGE_SCN_ALIGN_256BYTES");
1021 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_512BYTES, C,
1022 "IMAGE_SCN_ALIGN_512BYTES");
1023 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_1024BYTES, C,
1024 "IMAGE_SCN_ALIGN_1024BYTES");
1025 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_2048BYTES, C,
1026 "IMAGE_SCN_ALIGN_2048BYTES");
1027 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_4096BYTES, C,
1028 "IMAGE_SCN_ALIGN_4096BYTES");
1029 PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_8192BYTES, C,
1030 "IMAGE_SCN_ALIGN_8192BYTES");
1031 PUSH_FLAG(SC, IMAGE_SCN_LNK_NRELOC_OVFL, C, "IMAGE_SCN_LNK_NRELOC_OVFL");
1032 PUSH_FLAG(SC, IMAGE_SCN_MEM_DISCARDABLE, C, "IMAGE_SCN_MEM_DISCARDABLE");
1033 PUSH_FLAG(SC, IMAGE_SCN_MEM_NOT_CACHED, C, "IMAGE_SCN_MEM_NOT_CACHED");
1034 PUSH_FLAG(SC, IMAGE_SCN_MEM_NOT_PAGED, C, "IMAGE_SCN_MEM_NOT_PAGED");
1035 PUSH_FLAG(SC, IMAGE_SCN_MEM_SHARED, C, "IMAGE_SCN_MEM_SHARED");
1036 PUSH_FLAG(SC, IMAGE_SCN_MEM_EXECUTE, C, "IMAGE_SCN_MEM_EXECUTE");
1037 PUSH_FLAG(SC, IMAGE_SCN_MEM_READ, C, "IMAGE_SCN_MEM_READ");
1038 PUSH_FLAG(SC, IMAGE_SCN_MEM_WRITE, C, "IMAGE_SCN_MEM_WRITE");
Zachary Turner47d9a562017-06-16 00:04:24 +00001039 return typesetItemList(Opts, IndentLevel, 3, " | ");
Zachary Turner63055452017-06-15 22:24:24 +00001040}
1041
1042static std::string formatSegMapDescriptorFlag(uint32_t IndentLevel,
1043 OMFSegDescFlags Flags) {
1044 std::vector<std::string> Opts;
1045 if (Flags == OMFSegDescFlags::None)
1046 return "none";
1047
1048 PUSH_FLAG(OMFSegDescFlags, Read, Flags, "read");
1049 PUSH_FLAG(OMFSegDescFlags, Write, Flags, "write");
1050 PUSH_FLAG(OMFSegDescFlags, Execute, Flags, "execute");
1051 PUSH_FLAG(OMFSegDescFlags, AddressIs32Bit, Flags, "32 bit addr");
1052 PUSH_FLAG(OMFSegDescFlags, IsSelector, Flags, "selector");
1053 PUSH_FLAG(OMFSegDescFlags, IsAbsoluteAddress, Flags, "absolute addr");
1054 PUSH_FLAG(OMFSegDescFlags, IsGroup, Flags, "group");
Zachary Turner47d9a562017-06-16 00:04:24 +00001055 return typesetItemList(Opts, IndentLevel, 4, " | ");
Zachary Turner63055452017-06-15 22:24:24 +00001056}
1057
Zachary Turner7df69952017-06-22 20:57:39 +00001058Error DumpOutputStyle::dumpSectionContribs() {
Zachary Turner63055452017-06-15 22:24:24 +00001059 printHeader(P, "Section Contributions");
Reid Klecknerdd853e52017-07-27 23:13:18 +00001060 ExitOnError Err("Error dumping publics stream: ");
Zachary Turner63055452017-06-15 22:24:24 +00001061
1062 AutoIndent Indent(P);
1063 if (!File.hasPDBDbiStream()) {
1064 P.formatLine(
1065 "Section contribs require a DBI Stream, which could not be loaded");
1066 return Error::success();
1067 }
1068
1069 auto &Dbi = Err(File.getPDBDbiStream());
1070
1071 class Visitor : public ISectionContribVisitor {
1072 public:
1073 Visitor(LinePrinter &P) : P(P) {}
1074 void visit(const SectionContrib &SC) override {
1075 P.formatLine(
1076 "SC | mod = {2}, {0}, size = {1}, data crc = {3}, reloc crc = {4}",
1077 formatSegmentOffset(SC.ISect, SC.Off), fmtle(SC.Size), fmtle(SC.Imod),
1078 fmtle(SC.DataCrc), fmtle(SC.RelocCrc));
1079 P.formatLine(" {0}",
1080 formatSectionCharacteristics(P.getIndentLevel() + 6,
1081 SC.Characteristics));
1082 }
1083 void visit(const SectionContrib2 &SC) override {
1084 P.formatLine("SC2 | mod = {2}, {0}, size = {1}, data crc = {3}, reloc "
1085 "crc = {4}, coff section = {5}",
1086 formatSegmentOffset(SC.Base.ISect, SC.Base.Off),
1087 fmtle(SC.Base.Size), fmtle(SC.Base.Imod),
1088 fmtle(SC.Base.DataCrc), fmtle(SC.Base.RelocCrc),
1089 fmtle(SC.ISectCoff));
1090 P.formatLine(" {0}",
1091 formatSectionCharacteristics(P.getIndentLevel() + 6,
1092 SC.Base.Characteristics));
1093 }
1094
1095 private:
1096 LinePrinter &P;
1097 };
1098
1099 Visitor V(P);
1100 Dbi.visitSectionContributions(V);
1101 return Error::success();
1102}
1103
Zachary Turner7df69952017-06-22 20:57:39 +00001104Error DumpOutputStyle::dumpSectionMap() {
Zachary Turner63055452017-06-15 22:24:24 +00001105 printHeader(P, "Section Map");
Reid Klecknerdd853e52017-07-27 23:13:18 +00001106 ExitOnError Err("Error dumping section map: ");
Zachary Turner63055452017-06-15 22:24:24 +00001107
1108 AutoIndent Indent(P);
1109 if (!File.hasPDBDbiStream()) {
1110 P.formatLine("Dumping the section map requires a DBI Stream, which could "
1111 "not be loaded");
1112 return Error::success();
1113 }
1114
1115 auto &Dbi = Err(File.getPDBDbiStream());
1116
1117 uint32_t I = 0;
1118 for (auto &M : Dbi.getSectionMap()) {
1119 P.formatLine(
1120 "Section {0:4} | ovl = {0}, group = {1}, frame = {2}, name = {3}", I,
1121 fmtle(M.Ovl), fmtle(M.Group), fmtle(M.Frame), fmtle(M.SecName));
1122 P.formatLine(" class = {0}, offset = {1}, size = {2}",
1123 fmtle(M.ClassName), fmtle(M.Offset), fmtle(M.SecByteLength));
1124 P.formatLine(" flags = {0}",
1125 formatSegMapDescriptorFlag(
1126 P.getIndentLevel() + 13,
1127 static_cast<OMFSegDescFlags>(uint16_t(M.Flags))));
1128 ++I;
1129 }
1130 return Error::success();
1131}