1254a53a8d1aa42823e6fa66ec1ec35616ee530c
[oota-llvm.git] / tools / llvm-pdbdump / llvm-pdbdump.cpp
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/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"
33
34 #if defined(HAVE_DIA_SDK)
35 #include <Windows.h>
36 #endif
37
38 using namespace llvm;
39
40 namespace opts {
41
42 enum class PDB_DumpType { ByType, ByObjFile, Both };
43
44 cl::list<std::string> InputFilenames(cl::Positional,
45                                      cl::desc("<input PDB files>"),
46                                      cl::OneOrMore);
47
48 cl::opt<bool> DumpHidden(
49     "hidden",
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 "
54              "files."));
55
56 cl::opt<bool> DumpAll(
57     "all",
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(
62     "data",
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(
73     "vtables",
74     cl::desc("Display virtual function tables (only with --exhaustive)"));
75
76 static cl::opt<PDB_DumpType> DumpMode(
77     "group-by", cl::init(PDB_DumpType::ByType), cl::desc("Dump mode:"),
78     cl::values(
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 "
83                    "file."),
84         clEnumValN(
85             PDB_DumpType::Both, "both",
86             "Display symbols grouped by type, and then by object file.")));
87 }
88
89 #define SET_DUMP_FLAG_FROM_OPT(Var, Flag, Opt) \
90   if (opts::Opt) \
91     Var |= Flag;
92
93 PDB_DumpFlags CalculateDumpFlags() {
94   PDB_DumpFlags Flags = PDB_DF_None;
95
96   SET_DUMP_FLAG_FROM_OPT(Flags, PDB_DF_Hidden, DumpHidden)
97
98   if (opts::DumpAll)
99     return Flags | PDB_DF_All;
100
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)
112   return Flags;
113 }
114
115 static void dumpInput(StringRef Path) {
116   std::unique_ptr<IPDBSession> Session(
117       llvm::createPDBReader(PDB_ReaderType::DIA, Path));
118   if (!Session) {
119     outs() << "Unable to create PDB reader.  Check that a valid implementation";
120     outs() << " is available for your platform.";
121     return;
122   }
123   PDB_DumpFlags Flags = CalculateDumpFlags();
124
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);
129   outs() << "\n";
130
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);
136       outs() << "\n";
137     }
138   }
139   outs().flush();
140 }
141
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_);
146
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);
151   if (EC) {
152     llvm::errs() << "error: couldn't get arguments: " << EC.message() << '\n';
153     return 1;
154   }
155
156   llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
157
158   cl::ParseCommandLineOptions(argv.size(), argv.data(), "LLVM PDB Dumper\n");
159
160 #if defined(HAVE_DIA_SDK)
161   CoInitializeEx(nullptr, COINIT_MULTITHREADED);
162 #endif
163
164   std::for_each(opts::InputFilenames.begin(), opts::InputFilenames.end(),
165                 dumpInput);
166
167 #if defined(HAVE_DIA_SDK)
168   CoUninitialize();
169 #endif
170
171   return 0;
172 }