1 //===- llvm-pdbdump.cpp - Dump debug info from a PDB file -------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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
14 //===----------------------------------------------------------------------===//
16 #include "llvm/ADT/ArrayRef.h"
17 #include "llvm/ADT/StringExtras.h"
18 #include "llvm/Config/config.h"
19 #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
20 #include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"
21 #include "llvm/DebugInfo/PDB/IPDBSession.h"
22 #include "llvm/DebugInfo/PDB/PDB.h"
23 #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
24 #include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
25 #include "llvm/Support/CommandLine.h"
26 #include "llvm/Support/ConvertUTF.h"
27 #include "llvm/Support/Format.h"
28 #include "llvm/Support/ManagedStatic.h"
29 #include "llvm/Support/PrettyStackTrace.h"
30 #include "llvm/Support/Process.h"
31 #include "llvm/Support/Signals.h"
32 #include "llvm/Support/raw_ostream.h"
34 #if defined(HAVE_DIA_SDK)
42 enum class PDB_DumpType { ByType, ByObjFile, Both };
44 cl::list<std::string> InputFilenames(cl::Positional,
45 cl::desc("<input PDB files>"),
48 cl::opt<bool> DumpHidden(
50 cl::desc("Attempt to find hidden symbols. This can find additional\n"
51 "symbols that cannot be found otherwise. For example, vtables\n"
52 "can only be found with an exhaustive search such as this. Be\n"
53 "warned that the performance can be prohibitive on large PDB "
56 cl::opt<bool> DumpAll(
58 cl::desc("Specifies all other options except -hidden and -group-by"));
59 cl::opt<bool> DumpObjFiles("compilands", cl::desc("Display object files"));
60 cl::opt<bool> DumpFuncs("functions", cl::desc("Display function information"));
61 cl::opt<bool> DumpData(
63 cl::desc("Display global, class, and constant variable information."));
64 cl::opt<bool> DumpLabels("labels", cl::desc("Display labels"));
65 cl::opt<bool> DumpPublic("public", cl::desc("Display public symbols"));
66 cl::opt<bool> DumpClasses("classes", cl::desc("Display class type information"));
67 cl::opt<bool> DumpEnums("enums", cl::desc("Display enum information"));
68 cl::opt<bool> DumpFuncsigs("funcsigs",
69 cl::desc("Display unique function signatures"));
70 cl::opt<bool> DumpTypedefs("typedefs", cl::desc("Display typedefs"));
71 cl::opt<bool> DumpThunks("thunks", cl::desc("Display thunks"));
72 cl::opt<bool> DumpVtables(
74 cl::desc("Display virtual function tables (only with --exhaustive)"));
76 static cl::opt<PDB_DumpType> DumpMode(
77 "group-by", cl::init(PDB_DumpType::ByType), cl::desc("Dump mode:"),
79 clEnumValN(PDB_DumpType::ByType, "type",
80 "(Default) Display symbols grouped by type"),
81 clEnumValN(PDB_DumpType::ByObjFile, "compiland",
82 "Display symbols grouped under their containing object "
85 PDB_DumpType::Both, "both",
86 "Display symbols grouped by type, and then by object file.")));
89 #define SET_DUMP_FLAG_FROM_OPT(Var, Flag, Opt) \
93 PDB_DumpFlags CalculateDumpFlags() {
94 PDB_DumpFlags Flags = PDB_DF_None;
96 SET_DUMP_FLAG_FROM_OPT(Flags, PDB_DF_Hidden, DumpHidden)
99 return Flags | PDB_DF_All;
101 SET_DUMP_FLAG_FROM_OPT(Flags, PDB_DF_ObjFiles, DumpObjFiles)
102 SET_DUMP_FLAG_FROM_OPT(Flags, PDB_DF_Functions, DumpFuncs)
103 SET_DUMP_FLAG_FROM_OPT(Flags, PDB_DF_Data, DumpData)
104 SET_DUMP_FLAG_FROM_OPT(Flags, PDB_DF_Labels, DumpLabels)
105 SET_DUMP_FLAG_FROM_OPT(Flags, PDB_DF_PublicSyms, DumpPublic)
106 SET_DUMP_FLAG_FROM_OPT(Flags, PDB_DF_Classes, DumpClasses)
107 SET_DUMP_FLAG_FROM_OPT(Flags, PDB_DF_Enums, DumpEnums)
108 SET_DUMP_FLAG_FROM_OPT(Flags, PDB_DF_Funcsigs, DumpFuncsigs)
109 SET_DUMP_FLAG_FROM_OPT(Flags, PDB_DF_Typedefs, DumpTypedefs)
110 SET_DUMP_FLAG_FROM_OPT(Flags, PDB_DF_Thunks, DumpThunks)
111 SET_DUMP_FLAG_FROM_OPT(Flags, PDB_DF_VTables, DumpVtables)
115 static void dumpInput(StringRef Path) {
116 std::unique_ptr<IPDBSession> Session(
117 llvm::createPDBReader(PDB_ReaderType::DIA, Path));
119 outs() << "Unable to create PDB reader. Check that a valid implementation";
120 outs() << " is available for your platform.";
123 PDB_DumpFlags Flags = CalculateDumpFlags();
125 if (opts::DumpMode != opts::PDB_DumpType::ByObjFile)
126 Flags |= PDB_DF_Children;
127 auto GlobalScope(Session->getGlobalScope());
128 GlobalScope->dump(outs(), 0, PDB_DumpLevel::Normal, Flags);
131 if (opts::DumpMode != opts::PDB_DumpType::ByType) {
132 auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>();
133 while (auto Compiland = Compilands->getNext()) {
134 Compiland->dump(outs(), 0, PDB_DumpLevel::Detailed,
135 Flags | PDB_DF_Children);
142 int main(int argc_, const char *argv_[]) {
143 // Print a stack trace if we signal out.
144 sys::PrintStackTraceOnErrorSignal();
145 PrettyStackTraceProgram X(argc_, argv_);
147 SmallVector<const char *, 256> argv;
148 llvm::SpecificBumpPtrAllocator<char> ArgAllocator;
149 std::error_code EC = llvm::sys::Process::GetArgumentVector(
150 argv, llvm::makeArrayRef(argv_, argc_), ArgAllocator);
152 llvm::errs() << "error: couldn't get arguments: " << EC.message() << '\n';
156 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
158 cl::ParseCommandLineOptions(argv.size(), argv.data(), "LLVM PDB Dumper\n");
160 #if defined(HAVE_DIA_SDK)
161 CoInitializeEx(nullptr, COINIT_MULTITHREADED);
164 std::for_each(opts::InputFilenames.begin(), opts::InputFilenames.end(),
167 #if defined(HAVE_DIA_SDK)