1 //===- llvm-pdbdump.cpp - Dump debug info from a PDB file -------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Dumps debug information present in PDB files. This utility makes use of
11 // the Microsoft Windows SDK, so will not compile or run on non-Windows
12 // platforms.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #include "llvm-pdbdump.h"
17 #include "CompilandDumper.h"
18 #include "ExternalSymbolDumper.h"
19 #include "FunctionDumper.h"
20 #include "LLVMOutputStyle.h"
21 #include "LinePrinter.h"
22 #include "OutputStyle.h"
23 #include "TypeDumper.h"
24 #include "VariableDumper.h"
25 #include "YAMLOutputStyle.h"
26
27 #include "llvm/ADT/ArrayRef.h"
28 #include "llvm/ADT/BitVector.h"
29 #include "llvm/ADT/DenseMap.h"
30 #include "llvm/ADT/StringExtras.h"
31 #include "llvm/Config/config.h"
32 #include "llvm/DebugInfo/CodeView/ByteStream.h"
33 #include "llvm/DebugInfo/PDB/GenericError.h"
34 #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
35 #include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"
36 #include "llvm/DebugInfo/PDB/IPDBSession.h"
37 #include "llvm/DebugInfo/PDB/PDB.h"
38 #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
39 #include "llvm/DebugInfo/PDB/PDBSymbolData.h"
40 #include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
41 #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
42 #include "llvm/DebugInfo/PDB/PDBSymbolThunk.h"
43 #include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
44 #include "llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h"
45 #include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
46 #include "llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h"
47 #include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
48 #include "llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h"
49 #include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
50 #include "llvm/DebugInfo/PDB/Raw/RawError.h"
51 #include "llvm/DebugInfo/PDB/Raw/RawSession.h"
52 #include "llvm/Support/COM.h"
53 #include "llvm/Support/CommandLine.h"
54 #include "llvm/Support/ConvertUTF.h"
55 #include "llvm/Support/FileOutputBuffer.h"
56 #include "llvm/Support/FileSystem.h"
57 #include "llvm/Support/Format.h"
58 #include "llvm/Support/ManagedStatic.h"
59 #include "llvm/Support/MemoryBuffer.h"
60 #include "llvm/Support/PrettyStackTrace.h"
61 #include "llvm/Support/Process.h"
62 #include "llvm/Support/ScopedPrinter.h"
63 #include "llvm/Support/Signals.h"
64 #include "llvm/Support/raw_ostream.h"
65
66 using namespace llvm;
67 using namespace llvm::codeview;
68 using namespace llvm::pdb;
69
70 namespace {
71 // A simple adapter that acts like a ByteStream but holds ownership over
72 // and underlying FileOutputBuffer.
73 class FileBufferByteStream : public ByteStream<true> {
74 public:
FileBufferByteStream(std::unique_ptr<FileOutputBuffer> Buffer)75 FileBufferByteStream(std::unique_ptr<FileOutputBuffer> Buffer)
76 : ByteStream(MutableArrayRef<uint8_t>(Buffer->getBufferStart(),
77 Buffer->getBufferEnd())),
78 FileBuffer(std::move(Buffer)) {}
79
commit() const80 Error commit() const override {
81 if (FileBuffer->commit())
82 return llvm::make_error<RawError>(raw_error_code::not_writable);
83 return Error::success();
84 }
85
86 private:
87 std::unique_ptr<FileOutputBuffer> FileBuffer;
88 };
89 }
90
91 namespace opts {
92
93 cl::SubCommand RawSubcommand("raw", "Dump raw structure of the PDB file");
94 cl::SubCommand
95 PrettySubcommand("pretty",
96 "Dump semantic information about types and symbols");
97 cl::SubCommand
98 YamlToPdbSubcommand("yaml2pdb",
99 "Generate a PDB file from a YAML description");
100 cl::SubCommand
101 PdbToYamlSubcommand("pdb2yaml",
102 "Generate a detailed YAML description of a PDB File");
103
104 cl::OptionCategory TypeCategory("Symbol Type Options");
105 cl::OptionCategory FilterCategory("Filtering Options");
106 cl::OptionCategory OtherOptions("Other Options");
107
108 namespace pretty {
109 cl::list<std::string> InputFilenames(cl::Positional,
110 cl::desc("<input PDB files>"),
111 cl::OneOrMore, cl::sub(PrettySubcommand));
112
113 cl::opt<bool> Compilands("compilands", cl::desc("Display compilands"),
114 cl::cat(TypeCategory), cl::sub(PrettySubcommand));
115 cl::opt<bool> Symbols("symbols", cl::desc("Display symbols for each compiland"),
116 cl::cat(TypeCategory), cl::sub(PrettySubcommand));
117 cl::opt<bool> Globals("globals", cl::desc("Dump global symbols"),
118 cl::cat(TypeCategory), cl::sub(PrettySubcommand));
119 cl::opt<bool> Externals("externals", cl::desc("Dump external symbols"),
120 cl::cat(TypeCategory), cl::sub(PrettySubcommand));
121 cl::opt<bool> Types("types", cl::desc("Display types"), cl::cat(TypeCategory),
122 cl::sub(PrettySubcommand));
123 cl::opt<bool> Lines("lines", cl::desc("Line tables"), cl::cat(TypeCategory),
124 cl::sub(PrettySubcommand));
125 cl::opt<bool>
126 All("all", cl::desc("Implies all other options in 'Symbol Types' category"),
127 cl::cat(TypeCategory), cl::sub(PrettySubcommand));
128
129 cl::opt<uint64_t> LoadAddress(
130 "load-address",
131 cl::desc("Assume the module is loaded at the specified address"),
132 cl::cat(OtherOptions), cl::sub(PrettySubcommand));
133 cl::list<std::string> ExcludeTypes(
134 "exclude-types", cl::desc("Exclude types by regular expression"),
135 cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
136 cl::list<std::string> ExcludeSymbols(
137 "exclude-symbols", cl::desc("Exclude symbols by regular expression"),
138 cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
139 cl::list<std::string> ExcludeCompilands(
140 "exclude-compilands", cl::desc("Exclude compilands by regular expression"),
141 cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
142
143 cl::list<std::string> IncludeTypes(
144 "include-types",
145 cl::desc("Include only types which match a regular expression"),
146 cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
147 cl::list<std::string> IncludeSymbols(
148 "include-symbols",
149 cl::desc("Include only symbols which match a regular expression"),
150 cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
151 cl::list<std::string> IncludeCompilands(
152 "include-compilands",
153 cl::desc("Include only compilands those which match a regular expression"),
154 cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
155
156 cl::opt<bool> ExcludeCompilerGenerated(
157 "no-compiler-generated",
158 cl::desc("Don't show compiler generated types and symbols"),
159 cl::cat(FilterCategory), cl::sub(PrettySubcommand));
160 cl::opt<bool>
161 ExcludeSystemLibraries("no-system-libs",
162 cl::desc("Don't show symbols from system libraries"),
163 cl::cat(FilterCategory), cl::sub(PrettySubcommand));
164 cl::opt<bool> NoClassDefs("no-class-definitions",
165 cl::desc("Don't display full class definitions"),
166 cl::cat(FilterCategory), cl::sub(PrettySubcommand));
167 cl::opt<bool> NoEnumDefs("no-enum-definitions",
168 cl::desc("Don't display full enum definitions"),
169 cl::cat(FilterCategory), cl::sub(PrettySubcommand));
170 }
171
172 namespace raw {
173
174 cl::OptionCategory MsfOptions("MSF Container Options");
175 cl::OptionCategory TypeOptions("Type Record Options");
176 cl::OptionCategory FileOptions("Module & File Options");
177 cl::OptionCategory SymbolOptions("Symbol Options");
178 cl::OptionCategory MiscOptions("Miscellaneous Options");
179
180 // MSF OPTIONS
181 cl::opt<bool> DumpHeaders("headers", cl::desc("dump PDB headers"),
182 cl::cat(MsfOptions), cl::sub(RawSubcommand));
183 cl::opt<bool> DumpStreamBlocks("stream-blocks",
184 cl::desc("dump PDB stream blocks"),
185 cl::cat(MsfOptions), cl::sub(RawSubcommand));
186 cl::opt<bool> DumpStreamSummary("stream-summary",
187 cl::desc("dump summary of the PDB streams"),
188 cl::cat(MsfOptions), cl::sub(RawSubcommand));
189
190 // TYPE OPTIONS
191 cl::opt<bool>
192 DumpTpiRecords("tpi-records",
193 cl::desc("dump CodeView type records from TPI stream"),
194 cl::cat(TypeOptions), cl::sub(RawSubcommand));
195 cl::opt<bool> DumpTpiRecordBytes(
196 "tpi-record-bytes",
197 cl::desc("dump CodeView type record raw bytes from TPI stream"),
198 cl::cat(TypeOptions), cl::sub(RawSubcommand));
199 cl::opt<bool> DumpTpiHash("tpi-hash", cl::desc("dump CodeView TPI hash stream"),
200 cl::cat(TypeOptions), cl::sub(RawSubcommand));
201 cl::opt<bool>
202 DumpIpiRecords("ipi-records",
203 cl::desc("dump CodeView type records from IPI stream"),
204 cl::cat(TypeOptions), cl::sub(RawSubcommand));
205 cl::opt<bool> DumpIpiRecordBytes(
206 "ipi-record-bytes",
207 cl::desc("dump CodeView type record raw bytes from IPI stream"),
208 cl::cat(TypeOptions), cl::sub(RawSubcommand));
209
210 // MODULE & FILE OPTIONS
211 cl::opt<bool> DumpModules("modules", cl::desc("dump compiland information"),
212 cl::cat(FileOptions), cl::sub(RawSubcommand));
213 cl::opt<bool> DumpModuleFiles("module-files", cl::desc("dump file information"),
214 cl::cat(FileOptions), cl::sub(RawSubcommand));
215 cl::opt<bool> DumpLineInfo("line-info",
216 cl::desc("dump file and line information"),
217 cl::cat(FileOptions), cl::sub(RawSubcommand));
218
219 // SYMBOL OPTIONS
220 cl::opt<bool> DumpModuleSyms("module-syms", cl::desc("dump module symbols"),
221 cl::cat(SymbolOptions), cl::sub(RawSubcommand));
222 cl::opt<bool> DumpPublics("publics", cl::desc("dump Publics stream data"),
223 cl::cat(SymbolOptions), cl::sub(RawSubcommand));
224 cl::opt<bool>
225 DumpSymRecordBytes("sym-record-bytes",
226 cl::desc("dump CodeView symbol record raw bytes"),
227 cl::cat(SymbolOptions), cl::sub(RawSubcommand));
228
229 // MISCELLANEOUS OPTIONS
230 cl::opt<bool> DumpSectionContribs("section-contribs",
231 cl::desc("dump section contributions"),
232 cl::cat(MiscOptions), cl::sub(RawSubcommand));
233 cl::opt<bool> DumpSectionMap("section-map", cl::desc("dump section map"),
234 cl::cat(MiscOptions), cl::sub(RawSubcommand));
235 cl::opt<bool> DumpSectionHeaders("section-headers",
236 cl::desc("dump section headers"),
237 cl::cat(MiscOptions), cl::sub(RawSubcommand));
238 cl::opt<bool> DumpFpo("fpo", cl::desc("dump FPO records"), cl::cat(MiscOptions),
239 cl::sub(RawSubcommand));
240
241 cl::opt<std::string> DumpStreamDataIdx("stream", cl::desc("dump stream data"),
242 cl::cat(MiscOptions),
243 cl::sub(RawSubcommand));
244 cl::opt<std::string> DumpStreamDataName("stream-name",
245 cl::desc("dump stream data"),
246 cl::cat(MiscOptions),
247 cl::sub(RawSubcommand));
248
249 cl::opt<bool> RawAll("all", cl::desc("Implies most other options."),
250 cl::cat(MiscOptions), cl::sub(RawSubcommand));
251
252 cl::list<std::string> InputFilenames(cl::Positional,
253 cl::desc("<input PDB files>"),
254 cl::OneOrMore, cl::sub(RawSubcommand));
255 }
256
257 namespace yaml2pdb {
258 cl::opt<std::string>
259 YamlPdbOutputFile("pdb", cl::desc("the name of the PDB file to write"),
260 cl::sub(YamlToPdbSubcommand));
261
262 cl::list<std::string> InputFilename(cl::Positional,
263 cl::desc("<input YAML file>"), cl::Required,
264 cl::sub(YamlToPdbSubcommand));
265 }
266
267 namespace pdb2yaml {
268 cl::opt<bool>
269 NoFileHeaders("no-file-headers",
270 cl::desc("Do not dump MSF file headers (you will not be able "
271 "to generate a fresh PDB from the resulting YAML)"),
272 cl::sub(PdbToYamlSubcommand), cl::init(false));
273
274 cl::opt<bool> StreamMetadata(
275 "stream-metadata",
276 cl::desc("Dump the number of streams and each stream's size"),
277 cl::sub(PdbToYamlSubcommand), cl::init(false));
278 cl::opt<bool> StreamDirectory(
279 "stream-directory",
280 cl::desc("Dump each stream's block map (implies -stream-metadata)"),
281 cl::sub(PdbToYamlSubcommand), cl::init(false));
282 cl::opt<bool> PdbStream(
283 "pdb-stream",
284 cl::desc("Dump the PDB Stream (Stream 1) (implies -stream-metadata)"),
285 cl::sub(PdbToYamlSubcommand), cl::init(false));
286 cl::opt<bool> DbiStream(
287 "dbi-stream",
288 cl::desc("Dump the DBI Stream (Stream 2) (implies -stream-metadata)"),
289 cl::sub(PdbToYamlSubcommand), cl::init(false));
290
291 cl::list<std::string> InputFilename(cl::Positional,
292 cl::desc("<input PDB file>"), cl::Required,
293 cl::sub(PdbToYamlSubcommand));
294 }
295 }
296
297 static ExitOnError ExitOnErr;
298
yamlToPdb(StringRef Path)299 static void yamlToPdb(StringRef Path) {
300 ErrorOr<std::unique_ptr<MemoryBuffer>> ErrorOrBuffer =
301 MemoryBuffer::getFileOrSTDIN(Path, /*FileSize=*/-1,
302 /*RequiresNullTerminator=*/false);
303
304 if (ErrorOrBuffer.getError()) {
305 ExitOnErr(make_error<GenericError>(generic_error_code::invalid_path, Path));
306 }
307
308 std::unique_ptr<MemoryBuffer> &Buffer = ErrorOrBuffer.get();
309
310 llvm::yaml::Input In(Buffer->getBuffer());
311 pdb::yaml::PdbObject YamlObj;
312 In >> YamlObj;
313 if (!YamlObj.Headers.hasValue())
314 ExitOnErr(make_error<GenericError>(generic_error_code::unspecified,
315 "Yaml does not contain MSF headers"));
316
317 auto OutFileOrError = FileOutputBuffer::create(
318 opts::yaml2pdb::YamlPdbOutputFile, YamlObj.Headers->FileSize);
319 if (OutFileOrError.getError())
320 ExitOnErr(make_error<GenericError>(generic_error_code::invalid_path,
321 opts::yaml2pdb::YamlPdbOutputFile));
322
323 auto FileByteStream =
324 llvm::make_unique<FileBufferByteStream>(std::move(*OutFileOrError));
325 PDBFileBuilder Builder(std::move(FileByteStream));
326
327 ExitOnErr(Builder.setSuperBlock(YamlObj.Headers->SuperBlock));
328 if (YamlObj.StreamSizes.hasValue()) {
329 Builder.setStreamSizes(YamlObj.StreamSizes.getValue());
330 }
331 Builder.setDirectoryBlocks(YamlObj.Headers->DirectoryBlocks);
332
333 if (YamlObj.StreamMap.hasValue()) {
334 std::vector<ArrayRef<support::ulittle32_t>> StreamMap;
335 for (auto &E : YamlObj.StreamMap.getValue()) {
336 StreamMap.push_back(E.Blocks);
337 }
338 Builder.setStreamMap(StreamMap);
339 } else {
340 ExitOnErr(Builder.generateSimpleStreamMap());
341 }
342
343 if (YamlObj.PdbStream.hasValue()) {
344 auto &InfoBuilder = Builder.getInfoBuilder();
345 InfoBuilder.setAge(YamlObj.PdbStream->Age);
346 InfoBuilder.setGuid(YamlObj.PdbStream->Guid);
347 InfoBuilder.setSignature(YamlObj.PdbStream->Signature);
348 InfoBuilder.setVersion(YamlObj.PdbStream->Version);
349 }
350
351 if (YamlObj.DbiStream.hasValue()) {
352 auto &DbiBuilder = Builder.getDbiBuilder();
353 DbiBuilder.setAge(YamlObj.DbiStream->Age);
354 DbiBuilder.setBuildNumber(YamlObj.DbiStream->BuildNumber);
355 DbiBuilder.setFlags(YamlObj.DbiStream->Flags);
356 DbiBuilder.setMachineType(YamlObj.DbiStream->MachineType);
357 DbiBuilder.setPdbDllRbld(YamlObj.DbiStream->PdbDllRbld);
358 DbiBuilder.setPdbDllVersion(YamlObj.DbiStream->PdbDllVersion);
359 DbiBuilder.setVersionHeader(YamlObj.DbiStream->VerHeader);
360 }
361
362 auto Pdb = Builder.build();
363 ExitOnErr(Pdb.takeError());
364
365 auto &PdbFile = *Pdb;
366 ExitOnErr(PdbFile->commit());
367 }
368
pdb2Yaml(StringRef Path)369 static void pdb2Yaml(StringRef Path) {
370 std::unique_ptr<IPDBSession> Session;
371 ExitOnErr(loadDataForPDB(PDB_ReaderType::Raw, Path, Session));
372
373 RawSession *RS = static_cast<RawSession *>(Session.get());
374 PDBFile &File = RS->getPDBFile();
375 auto O = llvm::make_unique<YAMLOutputStyle>(File);
376 O = llvm::make_unique<YAMLOutputStyle>(File);
377
378 ExitOnErr(O->dump());
379 }
380
dumpRaw(StringRef Path)381 static void dumpRaw(StringRef Path) {
382 std::unique_ptr<IPDBSession> Session;
383 ExitOnErr(loadDataForPDB(PDB_ReaderType::Raw, Path, Session));
384
385 RawSession *RS = static_cast<RawSession *>(Session.get());
386 PDBFile &File = RS->getPDBFile();
387 auto O = llvm::make_unique<LLVMOutputStyle>(File);
388
389 ExitOnErr(O->dump());
390 }
391
dumpPretty(StringRef Path)392 static void dumpPretty(StringRef Path) {
393 std::unique_ptr<IPDBSession> Session;
394
395 ExitOnErr(loadDataForPDB(PDB_ReaderType::DIA, Path, Session));
396
397 if (opts::pretty::LoadAddress)
398 Session->setLoadAddress(opts::pretty::LoadAddress);
399
400 LinePrinter Printer(2, outs());
401
402 auto GlobalScope(Session->getGlobalScope());
403 std::string FileName(GlobalScope->getSymbolsFileName());
404
405 WithColor(Printer, PDB_ColorItem::None).get() << "Summary for ";
406 WithColor(Printer, PDB_ColorItem::Path).get() << FileName;
407 Printer.Indent();
408 uint64_t FileSize = 0;
409
410 Printer.NewLine();
411 WithColor(Printer, PDB_ColorItem::Identifier).get() << "Size";
412 if (!sys::fs::file_size(FileName, FileSize)) {
413 Printer << ": " << FileSize << " bytes";
414 } else {
415 Printer << ": (Unable to obtain file size)";
416 }
417
418 Printer.NewLine();
419 WithColor(Printer, PDB_ColorItem::Identifier).get() << "Guid";
420 Printer << ": " << GlobalScope->getGuid();
421
422 Printer.NewLine();
423 WithColor(Printer, PDB_ColorItem::Identifier).get() << "Age";
424 Printer << ": " << GlobalScope->getAge();
425
426 Printer.NewLine();
427 WithColor(Printer, PDB_ColorItem::Identifier).get() << "Attributes";
428 Printer << ": ";
429 if (GlobalScope->hasCTypes())
430 outs() << "HasCTypes ";
431 if (GlobalScope->hasPrivateSymbols())
432 outs() << "HasPrivateSymbols ";
433 Printer.Unindent();
434
435 if (opts::pretty::Compilands) {
436 Printer.NewLine();
437 WithColor(Printer, PDB_ColorItem::SectionHeader).get()
438 << "---COMPILANDS---";
439 Printer.Indent();
440 auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>();
441 CompilandDumper Dumper(Printer);
442 CompilandDumpFlags options = CompilandDumper::Flags::None;
443 if (opts::pretty::Lines)
444 options = options | CompilandDumper::Flags::Lines;
445 while (auto Compiland = Compilands->getNext())
446 Dumper.start(*Compiland, options);
447 Printer.Unindent();
448 }
449
450 if (opts::pretty::Types) {
451 Printer.NewLine();
452 WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---TYPES---";
453 Printer.Indent();
454 TypeDumper Dumper(Printer);
455 Dumper.start(*GlobalScope);
456 Printer.Unindent();
457 }
458
459 if (opts::pretty::Symbols) {
460 Printer.NewLine();
461 WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---SYMBOLS---";
462 Printer.Indent();
463 auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>();
464 CompilandDumper Dumper(Printer);
465 while (auto Compiland = Compilands->getNext())
466 Dumper.start(*Compiland, true);
467 Printer.Unindent();
468 }
469
470 if (opts::pretty::Globals) {
471 Printer.NewLine();
472 WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---GLOBALS---";
473 Printer.Indent();
474 {
475 FunctionDumper Dumper(Printer);
476 auto Functions = GlobalScope->findAllChildren<PDBSymbolFunc>();
477 while (auto Function = Functions->getNext()) {
478 Printer.NewLine();
479 Dumper.start(*Function, FunctionDumper::PointerType::None);
480 }
481 }
482 {
483 auto Vars = GlobalScope->findAllChildren<PDBSymbolData>();
484 VariableDumper Dumper(Printer);
485 while (auto Var = Vars->getNext())
486 Dumper.start(*Var);
487 }
488 {
489 auto Thunks = GlobalScope->findAllChildren<PDBSymbolThunk>();
490 CompilandDumper Dumper(Printer);
491 while (auto Thunk = Thunks->getNext())
492 Dumper.dump(*Thunk);
493 }
494 Printer.Unindent();
495 }
496 if (opts::pretty::Externals) {
497 Printer.NewLine();
498 WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---EXTERNALS---";
499 Printer.Indent();
500 ExternalSymbolDumper Dumper(Printer);
501 Dumper.start(*GlobalScope);
502 }
503 if (opts::pretty::Lines) {
504 Printer.NewLine();
505 }
506 outs().flush();
507 }
508
main(int argc_,const char * argv_[])509 int main(int argc_, const char *argv_[]) {
510 // Print a stack trace if we signal out.
511 sys::PrintStackTraceOnErrorSignal(argv_[0]);
512 PrettyStackTraceProgram X(argc_, argv_);
513
514 ExitOnErr.setBanner("llvm-pdbdump: ");
515
516 SmallVector<const char *, 256> argv;
517 SpecificBumpPtrAllocator<char> ArgAllocator;
518 ExitOnErr(errorCodeToError(sys::Process::GetArgumentVector(
519 argv, makeArrayRef(argv_, argc_), ArgAllocator)));
520
521 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
522
523 cl::ParseCommandLineOptions(argv.size(), argv.data(), "LLVM PDB Dumper\n");
524
525 // These options are shared by two subcommands.
526 if ((opts::PdbToYamlSubcommand || opts::RawSubcommand) && opts::raw::RawAll) {
527 opts::raw::DumpHeaders = true;
528 opts::raw::DumpModules = true;
529 opts::raw::DumpModuleFiles = true;
530 opts::raw::DumpModuleSyms = true;
531 opts::raw::DumpPublics = true;
532 opts::raw::DumpSectionHeaders = true;
533 opts::raw::DumpStreamSummary = true;
534 opts::raw::DumpStreamBlocks = true;
535 opts::raw::DumpTpiRecords = true;
536 opts::raw::DumpTpiHash = true;
537 opts::raw::DumpIpiRecords = true;
538 opts::raw::DumpSectionMap = true;
539 opts::raw::DumpSectionContribs = true;
540 opts::raw::DumpLineInfo = true;
541 opts::raw::DumpFpo = true;
542 }
543
544 llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded);
545
546 if (opts::PdbToYamlSubcommand) {
547 pdb2Yaml(opts::pdb2yaml::InputFilename.front());
548 } else if (opts::YamlToPdbSubcommand) {
549 yamlToPdb(opts::yaml2pdb::InputFilename.front());
550 } else if (opts::PrettySubcommand) {
551 if (opts::pretty::Lines)
552 opts::pretty::Compilands = true;
553
554 if (opts::pretty::All) {
555 opts::pretty::Compilands = true;
556 opts::pretty::Symbols = true;
557 opts::pretty::Globals = true;
558 opts::pretty::Types = true;
559 opts::pretty::Externals = true;
560 opts::pretty::Lines = true;
561 }
562
563 // When adding filters for excluded compilands and types, we need to
564 // remember
565 // that these are regexes. So special characters such as * and \ need to be
566 // escaped in the regex. In the case of a literal \, this means it needs to
567 // be escaped again in the C++. So matching a single \ in the input
568 // requires
569 // 4 \es in the C++.
570 if (opts::pretty::ExcludeCompilerGenerated) {
571 opts::pretty::ExcludeTypes.push_back("__vc_attributes");
572 opts::pretty::ExcludeCompilands.push_back("\\* Linker \\*");
573 }
574 if (opts::pretty::ExcludeSystemLibraries) {
575 opts::pretty::ExcludeCompilands.push_back(
576 "f:\\\\binaries\\\\Intermediate\\\\vctools\\\\crt_bld");
577 opts::pretty::ExcludeCompilands.push_back("f:\\\\dd\\\\vctools\\\\crt");
578 opts::pretty::ExcludeCompilands.push_back(
579 "d:\\\\th.obj.x86fre\\\\minkernel");
580 }
581 std::for_each(opts::pretty::InputFilenames.begin(),
582 opts::pretty::InputFilenames.end(), dumpPretty);
583 } else if (opts::RawSubcommand) {
584 std::for_each(opts::raw::InputFilenames.begin(),
585 opts::raw::InputFilenames.end(), dumpRaw);
586 }
587
588 outs().flush();
589 return 0;
590 }
591