llvm-pdbdump.cpp revision 283625
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 "LinePrinter.h" 21#include "TypeDumper.h" 22#include "VariableDumper.h" 23 24#include "llvm/ADT/ArrayRef.h" 25#include "llvm/ADT/StringExtras.h" 26#include "llvm/Config/config.h" 27#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" 28#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h" 29#include "llvm/DebugInfo/PDB/IPDBSession.h" 30#include "llvm/DebugInfo/PDB/PDB.h" 31#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h" 32#include "llvm/DebugInfo/PDB/PDBSymbolData.h" 33#include "llvm/DebugInfo/PDB/PDBSymbolExe.h" 34#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" 35#include "llvm/DebugInfo/PDB/PDBSymbolThunk.h" 36#include "llvm/Support/CommandLine.h" 37#include "llvm/Support/ConvertUTF.h" 38#include "llvm/Support/FileSystem.h" 39#include "llvm/Support/Format.h" 40#include "llvm/Support/ManagedStatic.h" 41#include "llvm/Support/PrettyStackTrace.h" 42#include "llvm/Support/Process.h" 43#include "llvm/Support/raw_ostream.h" 44#include "llvm/Support/Signals.h" 45 46#if defined(HAVE_DIA_SDK) 47#include <Windows.h> 48#endif 49 50using namespace llvm; 51 52namespace opts { 53 54enum class PDB_DumpType { ByType, ByObjFile, Both }; 55 56cl::list<std::string> InputFilenames(cl::Positional, 57 cl::desc("<input PDB files>"), 58 cl::OneOrMore); 59 60cl::OptionCategory TypeCategory("Symbol Type Options"); 61cl::OptionCategory FilterCategory("Filtering Options"); 62cl::OptionCategory OtherOptions("Other Options"); 63 64cl::opt<bool> Compilands("compilands", cl::desc("Display compilands"), 65 cl::cat(TypeCategory)); 66cl::opt<bool> Symbols("symbols", cl::desc("Display symbols for each compiland"), 67 cl::cat(TypeCategory)); 68cl::opt<bool> Globals("globals", cl::desc("Dump global symbols"), 69 cl::cat(TypeCategory)); 70cl::opt<bool> Externals("externals", cl::desc("Dump external symbols"), 71 cl::cat(TypeCategory)); 72cl::opt<bool> Types("types", cl::desc("Display types"), cl::cat(TypeCategory)); 73cl::opt<bool> 74 All("all", cl::desc("Implies all other options in 'Symbol Types' category"), 75 cl::cat(TypeCategory)); 76 77cl::opt<uint64_t> LoadAddress( 78 "load-address", 79 cl::desc("Assume the module is loaded at the specified address"), 80 cl::cat(OtherOptions)); 81 82cl::list<std::string> 83 ExcludeTypes("exclude-types", 84 cl::desc("Exclude types by regular expression"), 85 cl::ZeroOrMore, cl::cat(FilterCategory)); 86cl::list<std::string> 87 ExcludeSymbols("exclude-symbols", 88 cl::desc("Exclude symbols by regular expression"), 89 cl::ZeroOrMore, cl::cat(FilterCategory)); 90cl::list<std::string> 91 ExcludeCompilands("exclude-compilands", 92 cl::desc("Exclude compilands by regular expression"), 93 cl::ZeroOrMore, cl::cat(FilterCategory)); 94cl::opt<bool> ExcludeCompilerGenerated( 95 "no-compiler-generated", 96 cl::desc("Don't show compiler generated types and symbols"), 97 cl::cat(FilterCategory)); 98cl::opt<bool> 99 ExcludeSystemLibraries("no-system-libs", 100 cl::desc("Don't show symbols from system libraries"), 101 cl::cat(FilterCategory)); 102cl::opt<bool> NoClassDefs("no-class-definitions", 103 cl::desc("Don't display full class definitions"), 104 cl::cat(FilterCategory)); 105cl::opt<bool> NoEnumDefs("no-enum-definitions", 106 cl::desc("Don't display full enum definitions"), 107 cl::cat(FilterCategory)); 108} 109 110static void dumpInput(StringRef Path) { 111 std::unique_ptr<IPDBSession> Session; 112 PDB_ErrorCode Error = 113 llvm::loadDataForPDB(PDB_ReaderType::DIA, Path, Session); 114 switch (Error) { 115 case PDB_ErrorCode::Success: 116 break; 117 case PDB_ErrorCode::NoPdbImpl: 118 outs() << "Reading PDBs is not supported on this platform.\n"; 119 return; 120 case PDB_ErrorCode::InvalidPath: 121 outs() << "Unable to load PDB at '" << Path 122 << "'. Check that the file exists and is readable.\n"; 123 return; 124 case PDB_ErrorCode::InvalidFileFormat: 125 outs() << "Unable to load PDB at '" << Path 126 << "'. The file has an unrecognized format.\n"; 127 return; 128 default: 129 outs() << "Unable to load PDB at '" << Path 130 << "'. An unknown error occured.\n"; 131 return; 132 } 133 if (opts::LoadAddress) 134 Session->setLoadAddress(opts::LoadAddress); 135 136 LinePrinter Printer(2, outs()); 137 138 auto GlobalScope(Session->getGlobalScope()); 139 std::string FileName(GlobalScope->getSymbolsFileName()); 140 141 WithColor(Printer, PDB_ColorItem::None).get() << "Summary for "; 142 WithColor(Printer, PDB_ColorItem::Path).get() << FileName; 143 Printer.Indent(); 144 uint64_t FileSize = 0; 145 146 Printer.NewLine(); 147 WithColor(Printer, PDB_ColorItem::Identifier).get() << "Size"; 148 if (!llvm::sys::fs::file_size(FileName, FileSize)) { 149 Printer << ": " << FileSize << " bytes"; 150 } else { 151 Printer << ": (Unable to obtain file size)"; 152 } 153 154 Printer.NewLine(); 155 WithColor(Printer, PDB_ColorItem::Identifier).get() << "Guid"; 156 Printer << ": " << GlobalScope->getGuid(); 157 158 Printer.NewLine(); 159 WithColor(Printer, PDB_ColorItem::Identifier).get() << "Age"; 160 Printer << ": " << GlobalScope->getAge(); 161 162 Printer.NewLine(); 163 WithColor(Printer, PDB_ColorItem::Identifier).get() << "Attributes"; 164 Printer << ": "; 165 if (GlobalScope->hasCTypes()) 166 outs() << "HasCTypes "; 167 if (GlobalScope->hasPrivateSymbols()) 168 outs() << "HasPrivateSymbols "; 169 Printer.Unindent(); 170 171 if (opts::Compilands) { 172 Printer.NewLine(); 173 WithColor(Printer, PDB_ColorItem::SectionHeader).get() 174 << "---COMPILANDS---"; 175 Printer.Indent(); 176 auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>(); 177 CompilandDumper Dumper(Printer); 178 while (auto Compiland = Compilands->getNext()) 179 Dumper.start(*Compiland, false); 180 Printer.Unindent(); 181 } 182 183 if (opts::Types) { 184 Printer.NewLine(); 185 WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---TYPES---"; 186 Printer.Indent(); 187 TypeDumper Dumper(Printer); 188 Dumper.start(*GlobalScope); 189 Printer.Unindent(); 190 } 191 192 if (opts::Symbols) { 193 Printer.NewLine(); 194 WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---SYMBOLS---"; 195 Printer.Indent(); 196 auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>(); 197 CompilandDumper Dumper(Printer); 198 while (auto Compiland = Compilands->getNext()) 199 Dumper.start(*Compiland, true); 200 Printer.Unindent(); 201 } 202 203 if (opts::Globals) { 204 Printer.NewLine(); 205 WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---GLOBALS---"; 206 Printer.Indent(); 207 { 208 FunctionDumper Dumper(Printer); 209 auto Functions = GlobalScope->findAllChildren<PDBSymbolFunc>(); 210 while (auto Function = Functions->getNext()) { 211 Printer.NewLine(); 212 Dumper.start(*Function, FunctionDumper::PointerType::None); 213 } 214 } 215 { 216 auto Vars = GlobalScope->findAllChildren<PDBSymbolData>(); 217 VariableDumper Dumper(Printer); 218 while (auto Var = Vars->getNext()) 219 Dumper.start(*Var); 220 } 221 { 222 auto Thunks = GlobalScope->findAllChildren<PDBSymbolThunk>(); 223 CompilandDumper Dumper(Printer); 224 while (auto Thunk = Thunks->getNext()) 225 Dumper.dump(*Thunk); 226 } 227 Printer.Unindent(); 228 } 229 if (opts::Externals) { 230 Printer.NewLine(); 231 WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---EXTERNALS---"; 232 Printer.Indent(); 233 ExternalSymbolDumper Dumper(Printer); 234 Dumper.start(*GlobalScope); 235 } 236 outs().flush(); 237} 238 239int main(int argc_, const char *argv_[]) { 240 // Print a stack trace if we signal out. 241 sys::PrintStackTraceOnErrorSignal(); 242 PrettyStackTraceProgram X(argc_, argv_); 243 244 SmallVector<const char *, 256> argv; 245 llvm::SpecificBumpPtrAllocator<char> ArgAllocator; 246 std::error_code EC = llvm::sys::Process::GetArgumentVector( 247 argv, llvm::makeArrayRef(argv_, argc_), ArgAllocator); 248 if (EC) { 249 llvm::errs() << "error: couldn't get arguments: " << EC.message() << '\n'; 250 return 1; 251 } 252 253 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. 254 255 cl::ParseCommandLineOptions(argv.size(), argv.data(), "LLVM PDB Dumper\n"); 256 if (opts::All) { 257 opts::Compilands = true; 258 opts::Symbols = true; 259 opts::Globals = true; 260 opts::Types = true; 261 opts::Externals = true; 262 } 263 if (opts::ExcludeCompilerGenerated) { 264 opts::ExcludeTypes.push_back("__vc_attributes"); 265 opts::ExcludeCompilands.push_back("* Linker *"); 266 } 267 if (opts::ExcludeSystemLibraries) { 268 opts::ExcludeCompilands.push_back( 269 "f:\\binaries\\Intermediate\\vctools\\crt_bld"); 270 } 271 272#if defined(HAVE_DIA_SDK) 273 CoInitializeEx(nullptr, COINIT_MULTITHREADED); 274#endif 275 276 std::for_each(opts::InputFilenames.begin(), opts::InputFilenames.end(), 277 dumpInput); 278 279#if defined(HAVE_DIA_SDK) 280 CoUninitialize(); 281#endif 282 283 return 0; 284} 285