llvm.org GIT mirror llvm / 041e9f2
[llvm-pdbdump] Introduce an abstraction for the output style. This opens the door to introducing a YAML outputter which can be used for machine consumption. Currently the yaml output style is unimplemented and returns an error if you try to use it. Reviewed By: rnk, ruiu Differential Revision: http://reviews.llvm.org/D20967 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@271712 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 4 years ago
6 changed file(s) with 812 addition(s) and 677 deletion(s). Raw diff Collapse all Expand all
1313 ExternalSymbolDumper.cpp
1414 FunctionDumper.cpp
1515 LinePrinter.cpp
16 LLVMOutputStyle.cpp
1617 TypeDumper.cpp
1718 TypedefDumper.cpp
1819 VariableDumper.cpp
0 //===- LLVMOutputStyle.cpp ------------------------------------ *- C++ --*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "LLVMOutputStyle.h"
10
11 #include "llvm-pdbdump.h"
12 #include "llvm/DebugInfo/CodeView/EnumTables.h"
13 #include "llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h"
14 #include "llvm/DebugInfo/CodeView/SymbolDumper.h"
15 #include "llvm/DebugInfo/PDB/PDBExtras.h"
16 #include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
17 #include "llvm/DebugInfo/PDB/Raw/EnumTables.h"
18 #include "llvm/DebugInfo/PDB/Raw/ISectionContribVisitor.h"
19 #include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
20 #include "llvm/DebugInfo/PDB/Raw/ModInfo.h"
21 #include "llvm/DebugInfo/PDB/Raw/ModStream.h"
22 #include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
23 #include "llvm/DebugInfo/PDB/Raw/PublicsStream.h"
24 #include "llvm/DebugInfo/PDB/Raw/RawError.h"
25 #include "llvm/DebugInfo/PDB/Raw/TpiStream.h"
26 #include "llvm/Object/COFF.h"
27
28 #include
29
30 using namespace llvm;
31 using namespace llvm::codeview;
32 using namespace llvm::pdb;
33
34 static void printSectionOffset(llvm::raw_ostream &OS,
35 const SectionOffset &Off) {
36 OS << Off.Off << ", " << Off.Isect;
37 }
38
39 LLVMOutputStyle::LLVMOutputStyle(PDBFile &File)
40 : File(File), P(outs()), TD(&P, false) {}
41
42 Error LLVMOutputStyle::dumpFileHeaders() {
43 if (!opts::DumpHeaders)
44 return Error::success();
45
46 DictScope D(P, "FileHeaders");
47 P.printNumber("BlockSize", File.getBlockSize());
48 P.printNumber("Unknown0", File.getUnknown0());
49 P.printNumber("NumBlocks", File.getBlockCount());
50 P.printNumber("NumDirectoryBytes", File.getNumDirectoryBytes());
51 P.printNumber("Unknown1", File.getUnknown1());
52 P.printNumber("BlockMapAddr", File.getBlockMapIndex());
53 P.printNumber("NumDirectoryBlocks", File.getNumDirectoryBlocks());
54 P.printNumber("BlockMapOffset", File.getBlockMapOffset());
55
56 // The directory is not contiguous. Instead, the block map contains a
57 // contiguous list of block numbers whose contents, when concatenated in
58 // order, make up the directory.
59 P.printList("DirectoryBlocks", File.getDirectoryBlockArray());
60 P.printNumber("NumStreams", File.getNumStreams());
61 return Error::success();
62 }
63
64 Error LLVMOutputStyle::dumpStreamSummary() {
65 if (!opts::DumpStreamSummary)
66 return Error::success();
67
68 auto DbiS = File.getPDBDbiStream();
69 if (auto EC = DbiS.takeError())
70 return EC;
71 auto TpiS = File.getPDBTpiStream();
72 if (auto EC = TpiS.takeError())
73 return EC;
74 auto IpiS = File.getPDBIpiStream();
75 if (auto EC = IpiS.takeError())
76 return EC;
77 auto InfoS = File.getPDBInfoStream();
78 if (auto EC = InfoS.takeError())
79 return EC;
80 DbiStream &DS = DbiS.get();
81 TpiStream &TS = TpiS.get();
82 TpiStream &TIS = IpiS.get();
83 InfoStream &IS = InfoS.get();
84
85 ListScope L(P, "Streams");
86 uint32_t StreamCount = File.getNumStreams();
87 std::unordered_map ModStreams;
88 std::unordered_map NamedStreams;
89
90 for (auto &ModI : DS.modules()) {
91 uint16_t SN = ModI.Info.getModuleStreamIndex();
92 ModStreams[SN] = &ModI;
93 }
94 for (auto &NSE : IS.named_streams()) {
95 NamedStreams[NSE.second] = NSE.first();
96 }
97
98 for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
99 std::string Label("Stream ");
100 Label += to_string(StreamIdx);
101 std::string Value;
102 if (StreamIdx == OldMSFDirectory)
103 Value = "Old MSF Directory";
104 else if (StreamIdx == StreamPDB)
105 Value = "PDB Stream";
106 else if (StreamIdx == StreamDBI)
107 Value = "DBI Stream";
108 else if (StreamIdx == StreamTPI)
109 Value = "TPI Stream";
110 else if (StreamIdx == StreamIPI)
111 Value = "IPI Stream";
112 else if (StreamIdx == DS.getGlobalSymbolStreamIndex())
113 Value = "Global Symbol Hash";
114 else if (StreamIdx == DS.getPublicSymbolStreamIndex())
115 Value = "Public Symbol Hash";
116 else if (StreamIdx == DS.getSymRecordStreamIndex())
117 Value = "Public Symbol Records";
118 else if (StreamIdx == TS.getTypeHashStreamIndex())
119 Value = "TPI Hash";
120 else if (StreamIdx == TS.getTypeHashStreamAuxIndex())
121 Value = "TPI Aux Hash";
122 else if (StreamIdx == TIS.getTypeHashStreamIndex())
123 Value = "IPI Hash";
124 else if (StreamIdx == TIS.getTypeHashStreamAuxIndex())
125 Value = "IPI Aux Hash";
126 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::Exception))
127 Value = "Exception Data";
128 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::Fixup))
129 Value = "Fixup Data";
130 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::FPO))
131 Value = "FPO Data";
132 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::NewFPO))
133 Value = "New FPO Data";
134 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::OmapFromSrc))
135 Value = "Omap From Source Data";
136 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::OmapToSrc))
137 Value = "Omap To Source Data";
138 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::Pdata))
139 Value = "Pdata";
140 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::SectionHdr))
141 Value = "Section Header Data";
142 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::SectionHdrOrig))
143 Value = "Section Header Original Data";
144 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::TokenRidMap))
145 Value = "Token Rid Data";
146 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::Xdata))
147 Value = "Xdata";
148 else {
149 auto ModIter = ModStreams.find(StreamIdx);
150 auto NSIter = NamedStreams.find(StreamIdx);
151 if (ModIter != ModStreams.end()) {
152 Value = "Module \"";
153 Value += ModIter->second->Info.getModuleName().str();
154 Value += "\"";
155 } else if (NSIter != NamedStreams.end()) {
156 Value = "Named Stream \"";
157 Value += NSIter->second;
158 Value += "\"";
159 } else {
160 Value = "???";
161 }
162 }
163 Value = "[" + Value + "]";
164 Value =
165 Value + " (" + to_string(File.getStreamByteSize(StreamIdx)) + " bytes)";
166
167 P.printString(Label, Value);
168 }
169 P.flush();
170 return Error::success();
171 }
172
173 Error LLVMOutputStyle::dumpStreamBlocks() {
174 if (!opts::DumpStreamBlocks)
175 return Error::success();
176
177 ListScope L(P, "StreamBlocks");
178 uint32_t StreamCount = File.getNumStreams();
179 for (uint32_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
180 std::string Name("Stream ");
181 Name += to_string(StreamIdx);
182 auto StreamBlocks = File.getStreamBlockList(StreamIdx);
183 P.printList(Name, StreamBlocks);
184 }
185 return Error::success();
186 }
187
188 Error LLVMOutputStyle::dumpStreamData() {
189 uint32_t StreamCount = File.getNumStreams();
190 StringRef DumpStreamStr = opts::DumpStreamDataIdx;
191 uint32_t DumpStreamNum;
192 if (DumpStreamStr.getAsInteger(/*Radix=*/0U, DumpStreamNum) ||
193 DumpStreamNum >= StreamCount)
194 return Error::success();
195
196 MappedBlockStream S(DumpStreamNum, File);
197 codeview::StreamReader R(S);
198 while (R.bytesRemaining() > 0) {
199 ArrayRef Data;
200 uint32_t BytesToReadInBlock = std::min(
201 R.bytesRemaining(), static_cast(File.getBlockSize()));
202 if (auto EC = R.readBytes(Data, BytesToReadInBlock))
203 return EC;
204 P.printBinaryBlock(
205 "Data",
206 StringRef(reinterpret_cast(Data.begin()), Data.size()));
207 }
208 return Error::success();
209 }
210
211 Error LLVMOutputStyle::dumpInfoStream() {
212 if (!opts::DumpHeaders)
213 return Error::success();
214 auto InfoS = File.getPDBInfoStream();
215 if (auto EC = InfoS.takeError())
216 return EC;
217
218 InfoStream &IS = InfoS.get();
219
220 DictScope D(P, "PDB Stream");
221 P.printNumber("Version", IS.getVersion());
222 P.printHex("Signature", IS.getSignature());
223 P.printNumber("Age", IS.getAge());
224 P.printObject("Guid", IS.getGuid());
225 return Error::success();
226 }
227
228 Error LLVMOutputStyle::dumpNamedStream() {
229 if (opts::DumpStreamDataName.empty())
230 return Error::success();
231
232 auto InfoS = File.getPDBInfoStream();
233 if (auto EC = InfoS.takeError())
234 return EC;
235 InfoStream &IS = InfoS.get();
236
237 uint32_t NameStreamIndex = IS.getNamedStreamIndex(opts::DumpStreamDataName);
238
239 if (NameStreamIndex != 0) {
240 std::string Name("Stream '");
241 Name += opts::DumpStreamDataName;
242 Name += "'";
243 DictScope D(P, Name);
244 P.printNumber("Index", NameStreamIndex);
245
246 MappedBlockStream NameStream(NameStreamIndex, File);
247 codeview::StreamReader Reader(NameStream);
248
249 NameHashTable NameTable;
250 if (auto EC = NameTable.load(Reader))
251 return EC;
252
253 P.printHex("Signature", NameTable.getSignature());
254 P.printNumber("Version", NameTable.getHashVersion());
255 P.printNumber("Name Count", NameTable.getNameCount());
256 ListScope L(P, "Names");
257 for (uint32_t ID : NameTable.name_ids()) {
258 StringRef Str = NameTable.getStringForID(ID);
259 if (!Str.empty())
260 P.printString(to_string(ID), Str);
261 }
262 }
263 return Error::success();
264 }
265
266 Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
267 assert(StreamIdx == StreamTPI || StreamIdx == StreamIPI);
268
269 bool DumpRecordBytes = false;
270 bool DumpRecords = false;
271 StringRef Label;
272 StringRef VerLabel;
273 if (StreamIdx == StreamTPI) {
274 DumpRecordBytes = opts::DumpTpiRecordBytes;
275 DumpRecords = opts::DumpTpiRecords;
276 Label = "Type Info Stream (TPI)";
277 VerLabel = "TPI Version";
278 } else if (StreamIdx == StreamIPI) {
279 DumpRecordBytes = opts::DumpIpiRecordBytes;
280 DumpRecords = opts::DumpIpiRecords;
281 Label = "Type Info Stream (IPI)";
282 VerLabel = "IPI Version";
283 }
284 if (!DumpRecordBytes && !DumpRecords && !opts::DumpModuleSyms)
285 return Error::success();
286
287 auto TpiS = (StreamIdx == StreamTPI) ? File.getPDBTpiStream()
288 : File.getPDBIpiStream();
289 if (auto EC = TpiS.takeError())
290 return EC;
291 TpiStream &Tpi = TpiS.get();
292
293 if (DumpRecords || DumpRecordBytes) {
294 DictScope D(P, Label);
295
296 P.printNumber(VerLabel, Tpi.getTpiVersion());
297 P.printNumber("Record count", Tpi.NumTypeRecords());
298
299 ListScope L(P, "Records");
300
301 bool HadError = false;
302 for (auto &Type : Tpi.types(&HadError)) {
303 DictScope DD(P, "");
304
305 if (DumpRecords)
306 TD.dump(Type);
307
308 if (DumpRecordBytes)
309 P.printBinaryBlock("Bytes", Type.Data);
310 }
311 if (HadError)
312 return make_error(raw_error_code::corrupt_file,
313 "TPI stream contained corrupt record");
314 } else if (opts::DumpModuleSyms) {
315 // Even if the user doesn't want to dump type records, we still need to
316 // iterate them in order to build the list of types so that we can print
317 // them when dumping module symbols. So when they want to dump symbols
318 // but not types, use a null output stream.
319 ScopedPrinter *OldP = TD.getPrinter();
320 TD.setPrinter(nullptr);
321
322 bool HadError = false;
323 for (auto &Type : Tpi.types(&HadError))
324 TD.dump(Type);
325
326 TD.setPrinter(OldP);
327 if (HadError)
328 return make_error(raw_error_code::corrupt_file,
329 "TPI stream contained corrupt record");
330 }
331 P.flush();
332 return Error::success();
333 }
334
335 Error LLVMOutputStyle::dumpDbiStream() {
336 bool DumpModules = opts::DumpModules || opts::DumpModuleSyms ||
337 opts::DumpModuleFiles || opts::DumpLineInfo;
338 if (!opts::DumpHeaders && !DumpModules)
339 return Error::success();
340
341 auto DbiS = File.getPDBDbiStream();
342 if (auto EC = DbiS.takeError())
343 return EC;
344 DbiStream &DS = DbiS.get();
345
346 DictScope D(P, "DBI Stream");
347 P.printNumber("Dbi Version", DS.getDbiVersion());
348 P.printNumber("Age", DS.getAge());
349 P.printBoolean("Incremental Linking", DS.isIncrementallyLinked());
350 P.printBoolean("Has CTypes", DS.hasCTypes());
351 P.printBoolean("Is Stripped", DS.isStripped());
352 P.printObject("Machine Type", DS.getMachineType());
353 P.printNumber("Symbol Record Stream Index", DS.getSymRecordStreamIndex());
354 P.printNumber("Public Symbol Stream Index", DS.getPublicSymbolStreamIndex());
355 P.printNumber("Global Symbol Stream Index", DS.getGlobalSymbolStreamIndex());
356
357 uint16_t Major = DS.getBuildMajorVersion();
358 uint16_t Minor = DS.getBuildMinorVersion();
359 P.printVersion("Toolchain Version", Major, Minor);
360
361 std::string DllName;
362 raw_string_ostream DllStream(DllName);
363 DllStream << "mspdb" << Major << Minor << ".dll version";
364 DllStream.flush();
365 P.printVersion(DllName, Major, Minor, DS.getPdbDllVersion());
366
367 if (DumpModules) {
368 ListScope L(P, "Modules");
369 for (auto &Modi : DS.modules()) {
370 DictScope DD(P);
371 P.printString("Name", Modi.Info.getModuleName().str());
372 P.printNumber("Debug Stream Index", Modi.Info.getModuleStreamIndex());
373 P.printString("Object File Name", Modi.Info.getObjFileName().str());
374 P.printNumber("Num Files", Modi.Info.getNumberOfFiles());
375 P.printNumber("Source File Name Idx", Modi.Info.getSourceFileNameIndex());
376 P.printNumber("Pdb File Name Idx", Modi.Info.getPdbFilePathNameIndex());
377 P.printNumber("Line Info Byte Size", Modi.Info.getLineInfoByteSize());
378 P.printNumber("C13 Line Info Byte Size",
379 Modi.Info.getC13LineInfoByteSize());
380 P.printNumber("Symbol Byte Size", Modi.Info.getSymbolDebugInfoByteSize());
381 P.printNumber("Type Server Index", Modi.Info.getTypeServerIndex());
382 P.printBoolean("Has EC Info", Modi.Info.hasECInfo());
383 if (opts::DumpModuleFiles) {
384 std::string FileListName =
385 to_string(Modi.SourceFiles.size()) + " Contributing Source Files";
386 ListScope LL(P, FileListName);
387 for (auto File : Modi.SourceFiles)
388 P.printString(File.str());
389 }
390 bool HasModuleDI =
391 (Modi.Info.getModuleStreamIndex() < File.getNumStreams());
392 bool ShouldDumpSymbols =
393 (opts::DumpModuleSyms || opts::DumpSymRecordBytes);
394 if (HasModuleDI && (ShouldDumpSymbols || opts::DumpLineInfo)) {
395 ModStream ModS(File, Modi.Info);
396 if (auto EC = ModS.reload())
397 return EC;
398
399 if (ShouldDumpSymbols) {
400 ListScope SS(P, "Symbols");
401 codeview::CVSymbolDumper SD(P, TD, nullptr, false);
402 bool HadError = false;
403 for (const auto &S : ModS.symbols(&HadError)) {
404 DictScope DD(P, "");
405
406 if (opts::DumpModuleSyms)
407 SD.dump(S);
408 if (opts::DumpSymRecordBytes)
409 P.printBinaryBlock("Bytes", S.Data);
410 }
411 if (HadError)
412 return make_error(
413 raw_error_code::corrupt_file,
414 "DBI stream contained corrupt symbol record");
415 }
416 if (opts::DumpLineInfo) {
417 ListScope SS(P, "LineInfo");
418 bool HadError = false;
419 // Define a locally scoped visitor to print the different
420 // substream types types.
421 class RecordVisitor : public codeview::IModuleSubstreamVisitor {
422 public:
423 RecordVisitor(ScopedPrinter &P, PDBFile &F) : P(P), F(F) {}
424 Error visitUnknown(ModuleSubstreamKind Kind,
425 StreamRef Stream) override {
426 DictScope DD(P, "Unknown");
427 ArrayRef Data;
428 StreamReader R(Stream);
429 if (auto EC = R.readBytes(Data, R.bytesRemaining())) {
430 return make_error(
431 raw_error_code::corrupt_file,
432 "DBI stream contained corrupt line info record");
433 }
434 P.printBinaryBlock("Data", Data);
435 return Error::success();
436 }
437 Error
438 visitFileChecksums(StreamRef Data,
439 const FileChecksumArray &Checksums) override {
440 DictScope DD(P, "FileChecksums");
441 for (const auto &C : Checksums) {
442 DictScope DDD(P, "Checksum");
443 if (auto Result = getFileNameForOffset(C.FileNameOffset))
444 P.printString("FileName", Result.get());
445 else
446 return Result.takeError();
447 P.flush();
448 P.printEnum("Kind", uint8_t(C.Kind), getFileChecksumNames());
449 P.printBinaryBlock("Checksum", C.Checksum);
450 }
451 return Error::success();
452 }
453
454 Error visitLines(StreamRef Data, const LineSubstreamHeader *Header,
455 const LineInfoArray &Lines) override {
456 DictScope DD(P, "Lines");
457 for (const auto &L : Lines) {
458 if (auto Result = getFileNameForOffset2(L.NameIndex))
459 P.printString("FileName", Result.get());
460 else
461 return Result.takeError();
462 P.flush();
463 for (const auto &N : L.LineNumbers) {
464 DictScope DDD(P, "Line");
465 LineInfo LI(N.Flags);
466 P.printNumber("Offset", N.Offset);
467 if (LI.isAlwaysStepInto())
468 P.printString("StepInto", StringRef("Always"));
469 else if (LI.isNeverStepInto())
470 P.printString("StepInto", StringRef("Never"));
471 else
472 P.printNumber("LineNumberStart", LI.getStartLine());
473 P.printNumber("EndDelta", LI.getLineDelta());
474 P.printBoolean("IsStatement", LI.isStatement());
475 }
476 for (const auto &C : L.Columns) {
477 DictScope DDD(P, "Column");
478 P.printNumber("Start", C.StartColumn);
479 P.printNumber("End", C.EndColumn);
480 }
481 }
482 return Error::success();
483 }
484
485 private:
486 Expected getFileNameForOffset(uint32_t Offset) {
487 auto StringT = F.getStringTable();
488 if (auto EC = StringT.takeError())
489 return std::move(EC);
490 NameHashTable &ST = StringT.get();
491 return ST.getStringForID(Offset);
492 }
493 Expected getFileNameForOffset2(uint32_t Offset) {
494 auto DbiS = F.getPDBDbiStream();
495 if (auto EC = DbiS.takeError())
496 return std::move(EC);
497 auto &DS = DbiS.get();
498 return DS.getFileNameForIndex(Offset);
499 }
500 ScopedPrinter &P;
501 PDBFile &F;
502 };
503
504 RecordVisitor V(P, File);
505 for (const auto &L : ModS.lines(&HadError)) {
506 if (auto EC = codeview::visitModuleSubstream(L, V))
507 return EC;
508 }
509 }
510 }
511 }
512 }
513 return Error::success();
514 }
515
516 Error LLVMOutputStyle::dumpSectionContribs() {
517 if (!opts::DumpSectionContribs)
518 return Error::success();
519
520 auto DbiS = File.getPDBDbiStream();
521 if (auto EC = DbiS.takeError())
522 return EC;
523 DbiStream &DS = DbiS.get();
524 ListScope L(P, "Section Contributions");
525 class Visitor : public ISectionContribVisitor {
526 public:
527 Visitor(ScopedPrinter &P, DbiStream &DS) : P(P), DS(DS) {}
528 void visit(const SectionContrib &SC) override {
529 DictScope D(P, "Contribution");
530 P.printNumber("ISect", SC.ISect);
531 P.printNumber("Off", SC.Off);
532 P.printNumber("Size", SC.Size);
533 P.printFlags("Characteristics", SC.Characteristics,
534 codeview::getImageSectionCharacteristicNames(),
535 COFF::SectionCharacteristics(0x00F00000));
536 {
537 DictScope DD(P, "Module");
538 P.printNumber("Index", SC.Imod);
539 auto M = DS.modules();
540 if (M.size() > SC.Imod) {
541 P.printString("Name", M[SC.Imod].Info.getModuleName());
542 }
543 }
544 P.printNumber("Data CRC", SC.DataCrc);
545 P.printNumber("Reloc CRC", SC.RelocCrc);
546 P.flush();
547 }
548 void visit(const SectionContrib2 &SC) override {
549 visit(SC.Base);
550 P.printNumber("ISect Coff", SC.ISectCoff);
551 P.flush();
552 }
553
554 private:
555 ScopedPrinter &P;
556 DbiStream &DS;
557 };
558 Visitor V(P, DS);
559 DS.visitSectionContributions(V);
560 return Error::success();
561 }
562
563 Error LLVMOutputStyle::dumpSectionMap() {
564 if (!opts::DumpSectionMap)
565 return Error::success();
566
567 auto DbiS = File.getPDBDbiStream();
568 if (auto EC = DbiS.takeError())
569 return EC;
570 DbiStream &DS = DbiS.get();
571 ListScope L(P, "Section Map");
572 for (auto &M : DS.getSectionMap()) {
573 DictScope D(P, "Entry");
574 P.printFlags("Flags", M.Flags, getOMFSegMapDescFlagNames());
575 P.printNumber("Flags", M.Flags);
576 P.printNumber("Ovl", M.Ovl);
577 P.printNumber("Group", M.Group);
578 P.printNumber("Frame", M.Frame);
579 P.printNumber("SecName", M.SecName);
580 P.printNumber("ClassName", M.ClassName);
581 P.printNumber("Offset", M.Offset);
582 P.printNumber("SecByteLength", M.SecByteLength);
583 P.flush();
584 }
585 return Error::success();
586 }
587
588 Error LLVMOutputStyle::dumpPublicsStream() {
589 if (!opts::DumpPublics)
590 return Error::success();
591
592 DictScope D(P, "Publics Stream");
593 auto PublicsS = File.getPDBPublicsStream();
594 if (auto EC = PublicsS.takeError())
595 return EC;
596 PublicsStream &Publics = PublicsS.get();
597 P.printNumber("Stream number", Publics.getStreamNum());
598 P.printNumber("SymHash", Publics.getSymHash());
599 P.printNumber("AddrMap", Publics.getAddrMap());
600 P.printNumber("Number of buckets", Publics.getNumBuckets());
601 P.printList("Hash Buckets", Publics.getHashBuckets());
602 P.printList("Address Map", Publics.getAddressMap());
603 P.printList("Thunk Map", Publics.getThunkMap());
604 P.printList("Section Offsets", Publics.getSectionOffsets(),
605 printSectionOffset);
606 ListScope L(P, "Symbols");
607 codeview::CVSymbolDumper SD(P, TD, nullptr, false);
608 bool HadError = false;
609 for (auto S : Publics.getSymbols(&HadError)) {
610 DictScope DD(P, "");
611
612 SD.dump(S);
613 if (opts::DumpSymRecordBytes)
614 P.printBinaryBlock("Bytes", S.Data);
615 }
616 if (HadError)
617 return make_error(
618 raw_error_code::corrupt_file,
619 "Public symbol stream contained corrupt record");
620
621 return Error::success();
622 }
623
624 Error LLVMOutputStyle::dumpSectionHeaders() {
625 if (!opts::DumpSectionHeaders)
626 return Error::success();
627
628 auto DbiS = File.getPDBDbiStream();
629 if (auto EC = DbiS.takeError())
630 return EC;
631 DbiStream &DS = DbiS.get();
632
633 ListScope D(P, "Section Headers");
634 for (const object::coff_section &Section : DS.getSectionHeaders()) {
635 DictScope DD(P, "");
636
637 // If a name is 8 characters long, there is no NUL character at end.
638 StringRef Name(Section.Name, strnlen(Section.Name, sizeof(Section.Name)));
639 P.printString("Name", Name);
640 P.printNumber("Virtual Size", Section.VirtualSize);
641 P.printNumber("Virtual Address", Section.VirtualAddress);
642 P.printNumber("Size of Raw Data", Section.SizeOfRawData);
643 P.printNumber("File Pointer to Raw Data", Section.PointerToRawData);
644 P.printNumber("File Pointer to Relocations", Section.PointerToRelocations);
645 P.printNumber("File Pointer to Linenumbers", Section.PointerToLinenumbers);
646 P.printNumber("Number of Relocations", Section.NumberOfRelocations);
647 P.printNumber("Number of Linenumbers", Section.NumberOfLinenumbers);
648 P.printNumber("Characteristics", Section.Characteristics);
649 }
650 return Error::success();
651 }
0 //===- LLVMOutputStyle.h -------------------------------------- *- C++ --*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef LLVM_TOOLS_LLVMPDBDUMP_LLVMOUTPUTSTYLE_H
10 #define LLVM_TOOLS_LLVMPDBDUMP_LLVMOUTPUTSTYLE_H
11
12 #include "OutputStyle.h"
13
14 #include "llvm/DebugInfo/CodeView/TypeDumper.h"
15 #include "llvm/Support/ScopedPrinter.h"
16
17 namespace llvm {
18 namespace pdb {
19 class LLVMOutputStyle : public OutputStyle {
20 public:
21 LLVMOutputStyle(PDBFile &File);
22
23 Error dumpFileHeaders() override;
24 Error dumpStreamSummary() override;
25 Error dumpStreamBlocks() override;
26 Error dumpStreamData() override;
27 Error dumpInfoStream() override;
28 Error dumpNamedStream() override;
29 Error dumpTpiStream(uint32_t StreamIdx) override;
30 Error dumpDbiStream() override;
31 Error dumpSectionContribs() override;
32 Error dumpSectionMap() override;
33 Error dumpPublicsStream() override;
34 Error dumpSectionHeaders() override;
35
36 private:
37 PDBFile &File;
38 ScopedPrinter P;
39 codeview::CVTypeDumper TD;
40 };
41 }
42 }
43
44 #endif
0 //===- OutputStyle.h ------------------------------------------ *- C++ --*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef LLVM_TOOLS_LLVMPDBDUMP_OUTPUTSTYLE_H
10 #define LLVM_TOOLS_LLVMPDBDUMP_OUTPUTSTYLE_H
11
12 #include "llvm/Support/Error.h"
13
14 namespace llvm {
15 namespace pdb {
16 class PDBFile;
17
18 class OutputStyle {
19 public:
20 virtual ~OutputStyle() {}
21 virtual Error dumpFileHeaders() = 0;
22 virtual Error dumpStreamSummary() = 0;
23 virtual Error dumpStreamBlocks() = 0;
24 virtual Error dumpStreamData() = 0;
25 virtual Error dumpInfoStream() = 0;
26 virtual Error dumpNamedStream() = 0;
27 virtual Error dumpTpiStream(uint32_t StreamIdx) = 0;
28 virtual Error dumpDbiStream() = 0;
29 virtual Error dumpSectionContribs() = 0;
30 virtual Error dumpSectionMap() = 0;
31 virtual Error dumpPublicsStream() = 0;
32 virtual Error dumpSectionHeaders() = 0;
33 };
34 }
35 }
36
37 #endif
1616 #include "CompilandDumper.h"
1717 #include "ExternalSymbolDumper.h"
1818 #include "FunctionDumper.h"
19 #include "LLVMOutputStyle.h"
1920 #include "LinePrinter.h"
21 #include "OutputStyle.h"
2022 #include "TypeDumper.h"
2123 #include "VariableDumper.h"
2224
2527 #include "llvm/ADT/DenseMap.h"
2628 #include "llvm/ADT/StringExtras.h"
2729 #include "llvm/Config/config.h"
28 #include "llvm/DebugInfo/CodeView/EnumTables.h"
29 #include "llvm/DebugInfo/CodeView/Line.h"
30 #include "llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h"
31 #include "llvm/DebugInfo/CodeView/StreamReader.h"
32 #include "llvm/DebugInfo/CodeView/SymbolDumper.h"
33 #include "llvm/DebugInfo/CodeView/TypeDumper.h"
3430 #include "llvm/DebugInfo/PDB/GenericError.h"
3531 #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
3632 #include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"
4137 #include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
4238 #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
4339 #include "llvm/DebugInfo/PDB/PDBSymbolThunk.h"
44 #include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
45 #include "llvm/DebugInfo/PDB/Raw/EnumTables.h"
46 #include "llvm/DebugInfo/PDB/Raw/ISectionContribVisitor.h"
47 #include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
48 #include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
49 #include "llvm/DebugInfo/PDB/Raw/ModInfo.h"
50 #include "llvm/DebugInfo/PDB/Raw/ModStream.h"
51 #include "llvm/DebugInfo/PDB/Raw/NameHashTable.h"
5240 #include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
53 #include "llvm/DebugInfo/PDB/Raw/PublicsStream.h"
41 #include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
5442 #include "llvm/DebugInfo/PDB/Raw/RawError.h"
5543 #include "llvm/DebugInfo/PDB/Raw/RawSession.h"
56 #include "llvm/DebugInfo/PDB/Raw/TpiStream.h"
57 #include "llvm/Object/COFF.h"
5844 #include "llvm/Support/COM.h"
5945 #include "llvm/Support/CommandLine.h"
6046 #include "llvm/Support/ConvertUTF.h"
10389 "load-address",
10490 cl::desc("Assume the module is loaded at the specified address"),
10591 cl::cat(OtherOptions));
92
93 cl::opt
94 RawOutputStyle("raw-output-style", cl::desc("Specify dump outpout style"),
95 cl::values(clEnumVal(LLVM, "LLVM default style"),
96 clEnumVal(YAML, "YAML style"), clEnumValEnd),
97 cl::init(LLVM), cl::cat(NativeOptions));
10698
10799 cl::opt DumpHeaders("raw-headers", cl::desc("dump PDB headers"),
108100 cl::cat(NativeOptions));
208200
209201 static ExitOnError ExitOnErr;
210202
211 static Error dumpFileHeaders(ScopedPrinter &P, PDBFile &File) {
212 if (!opts::DumpHeaders)
213 return Error::success();
214
215 DictScope D(P, "FileHeaders");
216 P.printNumber("BlockSize", File.getBlockSize());
217 P.printNumber("Unknown0", File.getUnknown0());
218 P.printNumber("NumBlocks", File.getBlockCount());
219 P.printNumber("NumDirectoryBytes", File.getNumDirectoryBytes());
220 P.printNumber("Unknown1", File.getUnknown1());
221 P.printNumber("BlockMapAddr", File.getBlockMapIndex());
222 P.printNumber("NumDirectoryBlocks", File.getNumDirectoryBlocks());
223 P.printNumber("BlockMapOffset", File.getBlockMapOffset());
224
225 // The directory is not contiguous. Instead, the block map contains a
226 // contiguous list of block numbers whose contents, when concatenated in
227 // order, make up the directory.
228 P.printList("DirectoryBlocks", File.getDirectoryBlockArray());
229 P.printNumber("NumStreams", File.getNumStreams());
230 return Error::success();
231 }
232
233 static Error dumpStreamSummary(ScopedPrinter &P, PDBFile &File) {
234 if (!opts::DumpStreamSummary)
235 return Error::success();
236
237 auto DbiS = File.getPDBDbiStream();
238 if (auto EC = DbiS.takeError())
239 return EC;
240 auto TpiS = File.getPDBTpiStream();
241 if (auto EC = TpiS.takeError())
242 return EC;
243 auto IpiS = File.getPDBIpiStream();
244 if (auto EC = IpiS.takeError())
245 return EC;
246 auto InfoS = File.getPDBInfoStream();
247 if (auto EC = InfoS.takeError())
248 return EC;
249 DbiStream &DS = DbiS.get();
250 TpiStream &TS = TpiS.get();
251 TpiStream &TIS = IpiS.get();
252 InfoStream &IS = InfoS.get();
253
254 ListScope L(P, "Streams");
255 uint32_t StreamCount = File.getNumStreams();
256 std::unordered_map ModStreams;
257 std::unordered_map NamedStreams;
258
259 for (auto &ModI : DS.modules()) {
260 uint16_t SN = ModI.Info.getModuleStreamIndex();
261 ModStreams[SN] = &ModI;
262 }
263 for (auto &NSE : IS.named_streams()) {
264 NamedStreams[NSE.second] = NSE.first();
265 }
266
267 for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
268 std::string Label("Stream ");
269 Label += to_string(StreamIdx);
270 std::string Value;
271 if (StreamIdx == OldMSFDirectory)
272 Value = "Old MSF Directory";
273 else if (StreamIdx == StreamPDB)
274 Value = "PDB Stream";
275 else if (StreamIdx == StreamDBI)
276 Value = "DBI Stream";
277 else if (StreamIdx == StreamTPI)
278 Value = "TPI Stream";
279 else if (StreamIdx == StreamIPI)
280 Value = "IPI Stream";
281 else if (StreamIdx == DS.getGlobalSymbolStreamIndex())
282 Value = "Global Symbol Hash";
283 else if (StreamIdx == DS.getPublicSymbolStreamIndex())
284 Value = "Public Symbol Hash";
285 else if (StreamIdx == DS.getSymRecordStreamIndex())
286 Value = "Public Symbol Records";
287 else if (StreamIdx == TS.getTypeHashStreamIndex())
288 Value = "TPI Hash";
289 else if (StreamIdx == TS.getTypeHashStreamAuxIndex())
290 Value = "TPI Aux Hash";
291 else if (StreamIdx == TIS.getTypeHashStreamIndex())
292 Value = "IPI Hash";
293 else if (StreamIdx == TIS.getTypeHashStreamAuxIndex())
294 Value = "IPI Aux Hash";
295 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::Exception))
296 Value = "Exception Data";
297 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::Fixup))
298 Value = "Fixup Data";
299 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::FPO))
300 Value = "FPO Data";
301 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::NewFPO))
302 Value = "New FPO Data";
303 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::OmapFromSrc))
304 Value = "Omap From Source Data";
305 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::OmapToSrc))
306 Value = "Omap To Source Data";
307 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::Pdata))
308 Value = "Pdata";
309 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::SectionHdr))
310 Value = "Section Header Data";
311 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::SectionHdrOrig))
312 Value = "Section Header Original Data";
313 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::TokenRidMap))
314 Value = "Token Rid Data";
315 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::Xdata))
316 Value = "Xdata";
317 else {
318 auto ModIter = ModStreams.find(StreamIdx);
319 auto NSIter = NamedStreams.find(StreamIdx);
320 if (ModIter != ModStreams.end()) {
321 Value = "Module \"";
322 Value += ModIter->second->Info.getModuleName().str();
323 Value += "\"";
324 } else if (NSIter != NamedStreams.end()) {
325 Value = "Named Stream \"";
326 Value += NSIter->second;
327 Value += "\"";
328 } else {
329 Value = "???";
330 }
331 }
332 Value = "[" + Value + "]";
333 Value =
334 Value + " (" + to_string(File.getStreamByteSize(StreamIdx)) + " bytes)";
335
336 P.printString(Label, Value);
337 }
338 P.flush();
339 return Error::success();
340 }
341
342 static Error dumpStreamBlocks(ScopedPrinter &P, PDBFile &File) {
343 if (!opts::DumpStreamBlocks)
344 return Error::success();
345
346 ListScope L(P, "StreamBlocks");
347 uint32_t StreamCount = File.getNumStreams();
348 for (uint32_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
349 std::string Name("Stream ");
350 Name += to_string(StreamIdx);
351 auto StreamBlocks = File.getStreamBlockList(StreamIdx);
352 P.printList(Name, StreamBlocks);
353 }
354 return Error::success();
355 }
356
357 static Error dumpStreamData(ScopedPrinter &P, PDBFile &File) {
358 uint32_t StreamCount = File.getNumStreams();
359 StringRef DumpStreamStr = opts::DumpStreamDataIdx;
360 uint32_t DumpStreamNum;
361 if (DumpStreamStr.getAsInteger(/*Radix=*/0U, DumpStreamNum) ||
362 DumpStreamNum >= StreamCount)
363 return Error::success();
364
365 MappedBlockStream S(DumpStreamNum, File);
366 codeview::StreamReader R(S);
367 while (R.bytesRemaining() > 0) {
368 ArrayRef Data;
369 uint32_t BytesToReadInBlock = std::min(
370 R.bytesRemaining(), static_cast(File.getBlockSize()));
371 if (auto EC = R.readBytes(Data, BytesToReadInBlock))
372 return EC;
373 P.printBinaryBlock(
374 "Data",
375 StringRef(reinterpret_cast(Data.begin()), Data.size()));
376 }
377 return Error::success();
378 }
379
380 static Error dumpInfoStream(ScopedPrinter &P, PDBFile &File) {
381 if (!opts::DumpHeaders)
382 return Error::success();
383 auto InfoS = File.getPDBInfoStream();
384 if (auto EC = InfoS.takeError())
385 return EC;
386
387 InfoStream &IS = InfoS.get();
388
389 DictScope D(P, "PDB Stream");
390 P.printNumber("Version", IS.getVersion());
391 P.printHex("Signature", IS.getSignature());
392 P.printNumber("Age", IS.getAge());
393 P.printObject("Guid", IS.getGuid());
394 return Error::success();
395 }
396
397 static Error dumpNamedStream(ScopedPrinter &P, PDBFile &File) {
398 if (opts::DumpStreamDataName.empty())
399 return Error::success();
400
401 auto InfoS = File.getPDBInfoStream();
402 if (auto EC = InfoS.takeError())
403 return EC;
404 InfoStream &IS = InfoS.get();
405
406 uint32_t NameStreamIndex = IS.getNamedStreamIndex(opts::DumpStreamDataName);
407
408 if (NameStreamIndex != 0) {
409 std::string Name("Stream '");
410 Name += opts::DumpStreamDataName;
411 Name += "'";
412 DictScope D(P, Name);
413 P.printNumber("Index", NameStreamIndex);
414
415 MappedBlockStream NameStream(NameStreamIndex, File);
416 codeview::StreamReader Reader(NameStream);
417
418 NameHashTable NameTable;
419 if (auto EC = NameTable.load(Reader))
420 return EC;
421
422 P.printHex("Signature", NameTable.getSignature());
423 P.printNumber("Version", NameTable.getHashVersion());
424 P.printNumber("Name Count", NameTable.getNameCount());
425 ListScope L(P, "Names");
426 for (uint32_t ID : NameTable.name_ids()) {
427 StringRef Str = NameTable.getStringForID(ID);
428 if (!Str.empty())
429 P.printString(to_string(ID), Str);
430 }
431 }
432 return Error::success();
433 }
434
435 static Error dumpDbiStream(ScopedPrinter &P, PDBFile &File,
436 codeview::CVTypeDumper &TD) {
437 bool DumpModules = opts::DumpModules || opts::DumpModuleSyms ||
438 opts::DumpModuleFiles || opts::DumpLineInfo;
439 if (!opts::DumpHeaders && !DumpModules)
440 return Error::success();
441
442 auto DbiS = File.getPDBDbiStream();
443 if (auto EC = DbiS.takeError())
444 return EC;
445 DbiStream &DS = DbiS.get();
446
447 DictScope D(P, "DBI Stream");
448 P.printNumber("Dbi Version", DS.getDbiVersion());
449 P.printNumber("Age", DS.getAge());
450 P.printBoolean("Incremental Linking", DS.isIncrementallyLinked());
451 P.printBoolean("Has CTypes", DS.hasCTypes());
452 P.printBoolean("Is Stripped", DS.isStripped());
453 P.printObject("Machine Type", DS.getMachineType());
454 P.printNumber("Symbol Record Stream Index", DS.getSymRecordStreamIndex());
455 P.printNumber("Public Symbol Stream Index", DS.getPublicSymbolStreamIndex());
456 P.printNumber("Global Symbol Stream Index", DS.getGlobalSymbolStreamIndex());
457
458 uint16_t Major = DS.getBuildMajorVersion();
459 uint16_t Minor = DS.getBuildMinorVersion();
460 P.printVersion("Toolchain Version", Major, Minor);
461
462 std::string DllName;
463 raw_string_ostream DllStream(DllName);
464 DllStream << "mspdb" << Major << Minor << ".dll version";
465 DllStream.flush();
466 P.printVersion(DllName, Major, Minor, DS.getPdbDllVersion());
467
468 if (DumpModules) {
469 ListScope L(P, "Modules");
470 for (auto &Modi : DS.modules()) {
471 DictScope DD(P);
472 P.printString("Name", Modi.Info.getModuleName().str());
473 P.printNumber("Debug Stream Index", Modi.Info.getModuleStreamIndex());
474 P.printString("Object File Name", Modi.Info.getObjFileName().str());
475 P.printNumber("Num Files", Modi.Info.getNumberOfFiles());
476 P.printNumber("Source File Name Idx", Modi.Info.getSourceFileNameIndex());
477 P.printNumber("Pdb File Name Idx", Modi.Info.getPdbFilePathNameIndex());
478 P.printNumber("Line Info Byte Size", Modi.Info.getLineInfoByteSize());
479 P.printNumber("C13 Line Info Byte Size",
480 Modi.Info.getC13LineInfoByteSize());
481 P.printNumber("Symbol Byte Size", Modi.Info.getSymbolDebugInfoByteSize());
482 P.printNumber("Type Server Index", Modi.Info.getTypeServerIndex());
483 P.printBoolean("Has EC Info", Modi.Info.hasECInfo());
484 if (opts::DumpModuleFiles) {
485 std::string FileListName =
486 to_string(Modi.SourceFiles.size()) + " Contributing Source Files";
487 ListScope LL(P, FileListName);
488 for (auto File : Modi.SourceFiles)
489 P.printString(File.str());
490 }
491 bool HasModuleDI =
492 (Modi.Info.getModuleStreamIndex() < File.getNumStreams());
493 bool ShouldDumpSymbols =
494 (opts::DumpModuleSyms || opts::DumpSymRecordBytes);
495 if (HasModuleDI && (ShouldDumpSymbols || opts::DumpLineInfo)) {
496 ModStream ModS(File, Modi.Info);
497 if (auto EC = ModS.reload())
498 return EC;
499
500 if (ShouldDumpSymbols) {
501 ListScope SS(P, "Symbols");
502 codeview::CVSymbolDumper SD(P, TD, nullptr, false);
503 bool HadError = false;
504 for (const auto &S : ModS.symbols(&HadError)) {
505 DictScope DD(P, "");
506
507 if (opts::DumpModuleSyms)
508 SD.dump(S);
509 if (opts::DumpSymRecordBytes)
510 P.printBinaryBlock("Bytes", S.Data);
511 }
512 if (HadError)
513 return make_error(
514 raw_error_code::corrupt_file,
515 "DBI stream contained corrupt symbol record");
516 }
517 if (opts::DumpLineInfo) {
518 ListScope SS(P, "LineInfo");
519 bool HadError = false;
520 // Define a locally scoped visitor to print the different
521 // substream types types.
522 class RecordVisitor : public codeview::IModuleSubstreamVisitor {
523 public:
524 RecordVisitor(ScopedPrinter &P, PDBFile &F) : P(P), F(F) {}
525 Error visitUnknown(ModuleSubstreamKind Kind,
526 StreamRef Stream) override {
527 DictScope DD(P, "Unknown");
528 ArrayRef Data;
529 StreamReader R(Stream);
530 if (auto EC = R.readBytes(Data, R.bytesRemaining())) {
531 return make_error(
532 raw_error_code::corrupt_file,
533 "DBI stream contained corrupt line info record");
534 }
535 P.printBinaryBlock("Data", Data);
536 return Error::success();
537 }
538 Error
539 visitFileChecksums(StreamRef Data,
540 const FileChecksumArray &Checksums) override {
541 DictScope DD(P, "FileChecksums");
542 for (const auto &C : Checksums) {
543 DictScope DDD(P, "Checksum");
544 if (auto Result = getFileNameForOffset(C.FileNameOffset))
545 P.printString("FileName", Result.get());
546 else
547 return Result.takeError();
548 P.flush();
549 P.printEnum("Kind", uint8_t(C.Kind), getFileChecksumNames());
550 P.printBinaryBlock("Checksum", C.Checksum);
551 }
552 return Error::success();
553 }
554
555 Error visitLines(StreamRef Data, const LineSubstreamHeader *Header,
556 const LineInfoArray &Lines) override {
557 DictScope DD(P, "Lines");
558 for (const auto &L : Lines) {
559 if (auto Result = getFileNameForOffset2(L.NameIndex))
560 P.printString("FileName", Result.get());
561 else
562 return Result.takeError();
563 P.flush();
564 for (const auto &N : L.LineNumbers) {
565 DictScope DDD(P, "Line");
566 LineInfo LI(N.Flags);
567 P.printNumber("Offset", N.Offset);
568 if (LI.isAlwaysStepInto())
569 P.printString("StepInto", StringRef("Always"));
570 else if (LI.isNeverStepInto())
571 P.printString("StepInto", StringRef("Never"));
572 else
573 P.printNumber("LineNumberStart", LI.getStartLine());
574 P.printNumber("EndDelta", LI.getLineDelta());
575 P.printBoolean("IsStatement", LI.isStatement());
576 }
577 for (const auto &C : L.Columns) {
578 DictScope DDD(P, "Column");
579 P.printNumber("Start", C.StartColumn);
580 P.printNumber("End", C.EndColumn);
581 }
582 }
583 return Error::success();
584 }
585
586 private:
587 Expected getFileNameForOffset(uint32_t Offset) {
588 auto StringT = F.getStringTable();
589 if (auto EC = StringT.takeError())
590 return std::move(EC);
591 NameHashTable &ST = StringT.get();
592 return ST.getStringForID(Offset);
593 }
594 Expected getFileNameForOffset2(uint32_t Offset) {
595 auto DbiS = F.getPDBDbiStream();
596 if (auto EC = DbiS.takeError())
597 return std::move(EC);
598 auto &DS = DbiS.get();
599 return DS.getFileNameForIndex(Offset);
600 }
601 ScopedPrinter &P;
602 PDBFile &F;
603 };
604
605 RecordVisitor V(P, File);
606 for (const auto &L : ModS.lines(&HadError)) {
607 if (auto EC = codeview::visitModuleSubstream(L, V))
608 return EC;
609 }
610 }
611 }
612 }
613 }
614 return Error::success();
615 }
616
617 static Error dumpSectionContribs(ScopedPrinter &P, PDBFile &File) {
618 if (!opts::DumpSectionContribs)
619 return Error::success();
620
621 auto DbiS = File.getPDBDbiStream();
622 if (auto EC = DbiS.takeError())
623 return EC;
624 DbiStream &DS = DbiS.get();
625 ListScope L(P, "Section Contributions");
626 class Visitor : public ISectionContribVisitor {
627 public:
628 Visitor(ScopedPrinter &P, DbiStream &DS) : P(P), DS(DS) {}
629 void visit(const SectionContrib &SC) override {
630 DictScope D(P, "Contribution");
631 P.printNumber("ISect", SC.ISect);
632 P.printNumber("Off", SC.Off);
633 P.printNumber("Size", SC.Size);
634 P.printFlags("Characteristics", SC.Characteristics,
635 codeview::getImageSectionCharacteristicNames(),
636 COFF::SectionCharacteristics(0x00F00000));
637 {
638 DictScope DD(P, "Module");
639 P.printNumber("Index", SC.Imod);
640 auto M = DS.modules();
641 if (M.size() > SC.Imod) {
642 P.printString("Name", M[SC.Imod].Info.getModuleName());
643 }
644 }
645 P.printNumber("Data CRC", SC.DataCrc);
646 P.printNumber("Reloc CRC", SC.RelocCrc);
647 P.flush();
648 }
649 void visit(const SectionContrib2 &SC) override {
650 visit(SC.Base);
651 P.printNumber("ISect Coff", SC.ISectCoff);
652 P.flush();
653 }
654
655 private:
656 ScopedPrinter &P;
657 DbiStream &DS;
658 };
659 Visitor V(P, DS);
660 DS.visitSectionContributions(V);
661 return Error::success();
662 }
663
664 static Error dumpSectionMap(ScopedPrinter &P, PDBFile &File) {
665 if (!opts::DumpSectionMap)
666 return Error::success();
667
668 auto DbiS = File.getPDBDbiStream();
669 if (auto EC = DbiS.takeError())
670 return EC;
671 DbiStream &DS = DbiS.get();
672 ListScope L(P, "Section Map");
673 for (auto &M : DS.getSectionMap()) {
674 DictScope D(P, "Entry");
675 P.printFlags("Flags", M.Flags, getOMFSegMapDescFlagNames());
676 P.printNumber("Flags", M.Flags);
677 P.printNumber("Ovl", M.Ovl);
678 P.printNumber("Group", M.Group);
679 P.printNumber("Frame", M.Frame);
680 P.printNumber("SecName", M.SecName);
681 P.printNumber("ClassName", M.ClassName);
682 P.printNumber("Offset", M.Offset);
683 P.printNumber("SecByteLength", M.SecByteLength);
684 P.flush();
685 }
686 return Error::success();
687 }
688
689 static Error dumpTpiStream(ScopedPrinter &P, PDBFile &File,
690 codeview::CVTypeDumper &TD, uint32_t StreamIdx) {
691 assert(StreamIdx == StreamTPI || StreamIdx == StreamIPI);
692
693 bool DumpRecordBytes = false;
694 bool DumpRecords = false;
695 StringRef Label;
696 StringRef VerLabel;
697 if (StreamIdx == StreamTPI) {
698 DumpRecordBytes = opts::DumpTpiRecordBytes;
699 DumpRecords = opts::DumpTpiRecords;
700 Label = "Type Info Stream (TPI)";
701 VerLabel = "TPI Version";
702 } else if (StreamIdx == StreamIPI) {
703 DumpRecordBytes = opts::DumpIpiRecordBytes;
704 DumpRecords = opts::DumpIpiRecords;
705 Label = "Type Info Stream (IPI)";
706 VerLabel = "IPI Version";
707 }
708 if (!DumpRecordBytes && !DumpRecords && !opts::DumpModuleSyms)
709 return Error::success();
710
711 auto TpiS = (StreamIdx == StreamTPI) ? File.getPDBTpiStream()
712 : File.getPDBIpiStream();
713 if (auto EC = TpiS.takeError())
714 return EC;
715 TpiStream &Tpi = TpiS.get();
716
717 if (DumpRecords || DumpRecordBytes) {
718 DictScope D(P, Label);
719
720 P.printNumber(VerLabel, Tpi.getTpiVersion());
721 P.printNumber("Record count", Tpi.NumTypeRecords());
722
723 ListScope L(P, "Records");
724
725 bool HadError = false;
726 for (auto &Type : Tpi.types(&HadError)) {
727 DictScope DD(P, "");
728
729 if (DumpRecords)
730 TD.dump(Type);
731
732 if (DumpRecordBytes)
733 P.printBinaryBlock("Bytes", Type.Data);
734 }
735 if (HadError)
736 return make_error(raw_error_code::corrupt_file,
737 "TPI stream contained corrupt record");
738 } else if (opts::DumpModuleSyms) {
739 // Even if the user doesn't want to dump type records, we still need to
740 // iterate them in order to build the list of types so that we can print
741 // them when dumping module symbols. So when they want to dump symbols
742 // but not types, use a null output stream.
743 ScopedPrinter *OldP = TD.getPrinter();
744 TD.setPrinter(nullptr);
745
746 bool HadError = false;
747 for (auto &Type : Tpi.types(&HadError))
748 TD.dump(Type);
749
750 TD.setPrinter(OldP);
751 if (HadError)
752 return make_error(raw_error_code::corrupt_file,
753 "TPI stream contained corrupt record");
754 }
755 P.flush();
756 return Error::success();
757 }
758
759 static void printSectionOffset(llvm::raw_ostream &OS,
760 const SectionOffset &Off) {
761 OS << Off.Off << ", " << Off.Isect;
762 }
763
764 static Error dumpPublicsStream(ScopedPrinter &P, PDBFile &File,
765 codeview::CVTypeDumper &TD) {
766 if (!opts::DumpPublics)
767 return Error::success();
768
769 DictScope D(P, "Publics Stream");
770 auto PublicsS = File.getPDBPublicsStream();
771 if (auto EC = PublicsS.takeError())
772 return EC;
773 PublicsStream &Publics = PublicsS.get();
774 P.printNumber("Stream number", Publics.getStreamNum());
775 P.printNumber("SymHash", Publics.getSymHash());
776 P.printNumber("AddrMap", Publics.getAddrMap());
777 P.printNumber("Number of buckets", Publics.getNumBuckets());
778 P.printList("Hash Buckets", Publics.getHashBuckets());
779 P.printList("Address Map", Publics.getAddressMap());
780 P.printList("Thunk Map", Publics.getThunkMap());
781 P.printList("Section Offsets", Publics.getSectionOffsets(),
782 printSectionOffset);
783 ListScope L(P, "Symbols");
784 codeview::CVSymbolDumper SD(P, TD, nullptr, false);
785 bool HadError = false;
786 for (auto S : Publics.getSymbols(&HadError)) {
787 DictScope DD(P, "");
788
789 SD.dump(S);
790 if (opts::DumpSymRecordBytes)
791 P.printBinaryBlock("Bytes", S.Data);
792 }
793 if (HadError)
794 return make_error(
795 raw_error_code::corrupt_file,
796 "Public symbol stream contained corrupt record");
797
798 return Error::success();
799 }
800
801 static Error dumpSectionHeaders(ScopedPrinter &P, PDBFile &File,
802 codeview::CVTypeDumper &TD) {
803 if (!opts::DumpSectionHeaders)
804 return Error::success();
805
806 auto DbiS = File.getPDBDbiStream();
807 if (auto EC = DbiS.takeError())
808 return EC;
809 DbiStream &DS = DbiS.get();
810
811 ListScope D(P, "Section Headers");
812 for (const object::coff_section &Section : DS.getSectionHeaders()) {
813 DictScope DD(P, "");
814
815 // If a name is 8 characters long, there is no NUL character at end.
816 StringRef Name(Section.Name, strnlen(Section.Name, sizeof(Section.Name)));
817 P.printString("Name", Name);
818 P.printNumber("Virtual Size", Section.VirtualSize);
819 P.printNumber("Virtual Address", Section.VirtualAddress);
820 P.printNumber("Size of Raw Data", Section.SizeOfRawData);
821 P.printNumber("File Pointer to Raw Data", Section.PointerToRawData);
822 P.printNumber("File Pointer to Relocations", Section.PointerToRelocations);
823 P.printNumber("File Pointer to Linenumbers", Section.PointerToLinenumbers);
824 P.printNumber("Number of Relocations", Section.NumberOfRelocations);
825 P.printNumber("Number of Linenumbers", Section.NumberOfLinenumbers);
826 P.printNumber("Characteristics", Section.Characteristics);
827 }
828 return Error::success();
829 }
830
831203 static Error dumpStructure(RawSession &RS) {
832204 PDBFile &File = RS.getPDBFile();
833 ScopedPrinter P(outs());
834
835 if (auto EC = dumpFileHeaders(P, File))
836 return EC;
837
838 if (auto EC = dumpStreamSummary(P, File))
839 return EC;
840
841 if (auto EC = dumpStreamBlocks(P, File))
842 return EC;
843
844 if (auto EC = dumpStreamData(P, File))
845 return EC;
846
847 if (auto EC = dumpInfoStream(P, File))
848 return EC;
849
850 if (auto EC = dumpNamedStream(P, File))
851 return EC;
852
853 codeview::CVTypeDumper TD(&P, false);
854 if (auto EC = dumpTpiStream(P, File, TD, StreamTPI))
855 return EC;
856
857 if (auto EC = dumpTpiStream(P, File, TD, StreamIPI))
858 return EC;
859
860 if (auto EC = dumpDbiStream(P, File, TD))
861 return EC;
862
863 if (auto EC = dumpSectionContribs(P, File))
864 return EC;
865
866 if (auto EC = dumpSectionMap(P, File))
867 return EC;
868
869 if (auto EC = dumpPublicsStream(P, File, TD))
870 return EC;
871
872 if (auto EC = dumpSectionHeaders(P, File, TD))
205 std::unique_ptr O;
206 if (opts::RawOutputStyle == opts::OutputStyleTy::LLVM)
207 O = llvm::make_unique(File);
208 else
209 return make_error(raw_error_code::feature_unsupported,
210 "Requested output style unsupported");
211
212 if (auto EC = O->dumpFileHeaders())
213 return EC;
214
215 if (auto EC = O->dumpStreamSummary())
216 return EC;
217
218 if (auto EC = O->dumpStreamBlocks())
219 return EC;
220
221 if (auto EC = O->dumpStreamData())
222 return EC;
223
224 if (auto EC = O->dumpInfoStream())
225 return EC;
226
227 if (auto EC = O->dumpNamedStream())
228 return EC;
229
230 if (auto EC = O->dumpTpiStream(StreamTPI))
231 return EC;
232
233 if (auto EC = O->dumpTpiStream(StreamIPI))
234 return EC;
235
236 if (auto EC = O->dumpDbiStream())
237 return EC;
238
239 if (auto EC = O->dumpSectionContribs())
240 return EC;
241
242 if (auto EC = O->dumpSectionMap())
243 return EC;
244
245 if (auto EC = O->dumpPublicsStream())
246 return EC;
247
248 if (auto EC = O->dumpSectionHeaders())
873249 return EC;
874250 return Error::success();
875251 }
1313 #include "llvm/Support/raw_ostream.h"
1414
1515 namespace opts {
16
17 enum OutputStyleTy { LLVM, YAML };
18
1619 extern llvm::cl::opt Compilands;
1720 extern llvm::cl::opt Symbols;
1821 extern llvm::cl::opt Globals;
1922 extern llvm::cl::opt Types;
2023 extern llvm::cl::opt All;
24
25 extern llvm::cl::opt RawOutputStyle;
26 extern llvm::cl::opt DumpHeaders;
27 extern llvm::cl::opt DumpStreamBlocks;
28 extern llvm::cl::opt DumpStreamSummary;
29 extern llvm::cl::opt DumpTpiRecords;
30 extern llvm::cl::opt DumpTpiRecordBytes;
31 extern llvm::cl::opt DumpIpiRecords;
32 extern llvm::cl::opt DumpIpiRecordBytes;
33 extern llvm::cl::opt DumpStreamDataIdx;
34 extern llvm::cl::opt DumpStreamDataName;
35 extern llvm::cl::opt DumpModules;
36 extern llvm::cl::opt DumpModuleFiles;
37 extern llvm::cl::opt DumpModuleSyms;
38 extern llvm::cl::opt DumpPublics;
39 extern llvm::cl::opt DumpSectionContribs;
40 extern llvm::cl::opt DumpLineInfo;
41 extern llvm::cl::opt DumpSectionMap;
42 extern llvm::cl::opt DumpSymRecordBytes;
43 extern llvm::cl::opt DumpSectionHeaders;
2144
2245 extern llvm::cl::opt ExcludeCompilerGenerated;
2346