blob: 50e212356a8859d09593ab369d5c5a33053ff78e [file] [log] [blame]
Zachary Turnerfcb14ad2015-01-27 20:46:21 +00001//===- 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
Zachary Turner9a818ad2015-02-22 22:03:38 +000016#include "llvm-pdbdump.h"
17#include "CompilandDumper.h"
Zachary Turnere5cb2692015-05-01 20:24:26 +000018#include "ExternalSymbolDumper.h"
Zachary Turnerdb18f5c2015-02-27 09:15:18 +000019#include "FunctionDumper.h"
Zachary Turner2d11c202015-02-27 09:15:59 +000020#include "LinePrinter.h"
Zachary Turner9a818ad2015-02-22 22:03:38 +000021#include "TypeDumper.h"
Zachary Turnerdb18f5c2015-02-27 09:15:18 +000022#include "VariableDumper.h"
Zachary Turner9a818ad2015-02-22 22:03:38 +000023
Zachary Turnerfcb14ad2015-01-27 20:46:21 +000024#include "llvm/ADT/ArrayRef.h"
David Majnemer6e081262015-10-15 01:27:19 +000025#include "llvm/ADT/BitVector.h"
26#include "llvm/ADT/DenseMap.h"
Zachary Turnerfcb14ad2015-01-27 20:46:21 +000027#include "llvm/ADT/StringExtras.h"
Zachary Turner8d7fa9b2015-02-10 22:47:14 +000028#include "llvm/Config/config.h"
Zachary Turnerd5d37dc2016-05-25 20:37:03 +000029#include "llvm/DebugInfo/CodeView/StreamReader.h"
Zachary Turnercac29ae2016-05-24 17:30:25 +000030#include "llvm/DebugInfo/CodeView/SymbolDumper.h"
Zachary Turner5a1b5ef2016-05-06 22:15:42 +000031#include "llvm/DebugInfo/CodeView/TypeDumper.h"
Zachary Turner819e77d2016-05-06 20:51:57 +000032#include "llvm/DebugInfo/PDB/GenericError.h"
Zachary Turnera5549172015-02-10 22:43:25 +000033#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
Zachary Turnera5549172015-02-10 22:43:25 +000034#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"
Chandler Carruth71f308a2015-02-13 09:09:03 +000035#include "llvm/DebugInfo/PDB/IPDBSession.h"
36#include "llvm/DebugInfo/PDB/PDB.h"
Zachary Turnera5549172015-02-10 22:43:25 +000037#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
Zachary Turnerdb18f5c2015-02-27 09:15:18 +000038#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
Chandler Carruth71f308a2015-02-13 09:09:03 +000039#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
Zachary Turnerdb18f5c2015-02-27 09:15:18 +000040#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
41#include "llvm/DebugInfo/PDB/PDBSymbolThunk.h"
Zachary Turner2f09b502016-04-29 17:28:47 +000042#include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
43#include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
Zachary Turner6ba65de2016-04-29 17:22:58 +000044#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
Zachary Turner1822af542016-04-27 23:41:42 +000045#include "llvm/DebugInfo/PDB/Raw/ModInfo.h"
Zachary Turner06c2b4b2016-05-09 17:45:21 +000046#include "llvm/DebugInfo/PDB/Raw/ModStream.h"
Zachary Turner0eace0b2016-05-02 18:09:14 +000047#include "llvm/DebugInfo/PDB/Raw/NameHashTable.h"
Zachary Turner0a43efe2016-04-25 17:38:08 +000048#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
Rui Ueyama1f6b6e22016-05-13 21:21:53 +000049#include "llvm/DebugInfo/PDB/Raw/PublicsStream.h"
Reid Klecknerce5196e2016-05-12 23:26:23 +000050#include "llvm/DebugInfo/PDB/Raw/RawError.h"
Zachary Turner0a43efe2016-04-25 17:38:08 +000051#include "llvm/DebugInfo/PDB/Raw/RawSession.h"
Zachary Turnerf5c59652016-05-03 00:28:21 +000052#include "llvm/DebugInfo/PDB/Raw/TpiStream.h"
Zachary Turnerfcb14ad2015-01-27 20:46:21 +000053#include "llvm/Support/CommandLine.h"
54#include "llvm/Support/ConvertUTF.h"
Zachary Turner9a818ad2015-02-22 22:03:38 +000055#include "llvm/Support/FileSystem.h"
Zachary Turnerfcb14ad2015-01-27 20:46:21 +000056#include "llvm/Support/Format.h"
57#include "llvm/Support/ManagedStatic.h"
David Majnemer6e081262015-10-15 01:27:19 +000058#include "llvm/Support/MemoryBuffer.h"
Zachary Turnerfcb14ad2015-01-27 20:46:21 +000059#include "llvm/Support/PrettyStackTrace.h"
Chandler Carruth71f308a2015-02-13 09:09:03 +000060#include "llvm/Support/Process.h"
Reid Klecknerb0345262016-05-04 16:09:04 +000061#include "llvm/Support/ScopedPrinter.h"
Daniel Sandersd41718e2016-04-22 12:04:42 +000062#include "llvm/Support/Signals.h"
Zachary Turner0a43efe2016-04-25 17:38:08 +000063#include "llvm/Support/raw_ostream.h"
Zachary Turnerfcb14ad2015-01-27 20:46:21 +000064
Zachary Turner8d7fa9b2015-02-10 22:47:14 +000065#if defined(HAVE_DIA_SDK)
Benjamin Kramer4b4a9362015-10-15 09:38:45 +000066#ifndef NOMINMAX
67#define NOMINMAX
68#endif
Zachary Turnera5549172015-02-10 22:43:25 +000069#include <Windows.h>
Zachary Turner8d7fa9b2015-02-10 22:47:14 +000070#endif
Zachary Turnerfcb14ad2015-01-27 20:46:21 +000071
72using namespace llvm;
Zachary Turner2f09b502016-04-29 17:28:47 +000073using namespace llvm::pdb;
Zachary Turnerfcb14ad2015-01-27 20:46:21 +000074
75namespace opts {
Zachary Turnerc0acf682015-02-15 20:27:53 +000076
77enum class PDB_DumpType { ByType, ByObjFile, Both };
78
Zachary Turnerfcb14ad2015-01-27 20:46:21 +000079cl::list<std::string> InputFilenames(cl::Positional,
80 cl::desc("<input PDB files>"),
81 cl::OneOrMore);
82
Zachary Turner7797c722015-03-02 04:39:56 +000083cl::OptionCategory TypeCategory("Symbol Type Options");
84cl::OptionCategory FilterCategory("Filtering Options");
Zachary Turnere5cb2692015-05-01 20:24:26 +000085cl::OptionCategory OtherOptions("Other Options");
Rui Ueyama18695f92016-05-26 23:01:05 +000086cl::OptionCategory NativeOptions("Native Options");
Zachary Turner7797c722015-03-02 04:39:56 +000087
88cl::opt<bool> Compilands("compilands", cl::desc("Display compilands"),
89 cl::cat(TypeCategory));
90cl::opt<bool> Symbols("symbols", cl::desc("Display symbols for each compiland"),
91 cl::cat(TypeCategory));
92cl::opt<bool> Globals("globals", cl::desc("Dump global symbols"),
93 cl::cat(TypeCategory));
Zachary Turnere5cb2692015-05-01 20:24:26 +000094cl::opt<bool> Externals("externals", cl::desc("Dump external symbols"),
95 cl::cat(TypeCategory));
Zachary Turner7797c722015-03-02 04:39:56 +000096cl::opt<bool> Types("types", cl::desc("Display types"), cl::cat(TypeCategory));
Zachary Turnera99000d2016-03-08 21:42:24 +000097cl::opt<bool> Lines("lines", cl::desc("Line tables"), cl::cat(TypeCategory));
Zachary Turner7797c722015-03-02 04:39:56 +000098cl::opt<bool>
Zachary Turner7797c722015-03-02 04:39:56 +000099 All("all", cl::desc("Implies all other options in 'Symbol Types' category"),
100 cl::cat(TypeCategory));
Zachary Turnerf5abda22015-03-01 06:49:49 +0000101
Zachary Turnere5cb2692015-05-01 20:24:26 +0000102cl::opt<uint64_t> LoadAddress(
103 "load-address",
104 cl::desc("Assume the module is loaded at the specified address"),
105 cl::cat(OtherOptions));
106
Zachary Turner96e60f72016-05-24 20:31:48 +0000107cl::opt<bool> DumpHeaders("raw-headers", cl::desc("dump PDB headers"),
Rui Ueyama18695f92016-05-26 23:01:05 +0000108 cl::cat(NativeOptions));
Zachary Turner96e60f72016-05-24 20:31:48 +0000109cl::opt<bool> DumpStreamBlocks("raw-stream-blocks",
David Majnemer6e081262015-10-15 01:27:19 +0000110 cl::desc("dump PDB stream blocks"),
Rui Ueyama18695f92016-05-26 23:01:05 +0000111 cl::cat(NativeOptions));
Zachary Turner85ed80b2016-05-25 03:43:17 +0000112cl::opt<bool> DumpStreamSummary("raw-stream-summary",
113 cl::desc("dump summary of the PDB streams"),
Rui Ueyama18695f92016-05-26 23:01:05 +0000114 cl::cat(NativeOptions));
Reid Klecknerb0345262016-05-04 16:09:04 +0000115cl::opt<bool>
Zachary Turnerc9972c62016-05-25 04:35:22 +0000116 DumpTpiRecords("raw-tpi-records",
117 cl::desc("dump CodeView type records from TPI stream"),
Rui Ueyama18695f92016-05-26 23:01:05 +0000118 cl::cat(NativeOptions));
Zachary Turnerc9972c62016-05-25 04:35:22 +0000119cl::opt<bool> DumpTpiRecordBytes(
120 "raw-tpi-record-bytes",
121 cl::desc("dump CodeView type record raw bytes from TPI stream"),
Rui Ueyama18695f92016-05-26 23:01:05 +0000122 cl::cat(NativeOptions));
Zachary Turnerc9972c62016-05-25 04:35:22 +0000123cl::opt<bool>
124 DumpIpiRecords("raw-ipi-records",
125 cl::desc("dump CodeView type records from IPI stream"),
Rui Ueyama18695f92016-05-26 23:01:05 +0000126 cl::cat(NativeOptions));
Zachary Turnerc9972c62016-05-25 04:35:22 +0000127cl::opt<bool> DumpIpiRecordBytes(
128 "raw-ipi-record-bytes",
129 cl::desc("dump CodeView type record raw bytes from IPI stream"),
Rui Ueyama18695f92016-05-26 23:01:05 +0000130 cl::cat(NativeOptions));
Zachary Turner96e60f72016-05-24 20:31:48 +0000131cl::opt<std::string> DumpStreamDataIdx("raw-stream",
132 cl::desc("dump stream data"),
Rui Ueyama18695f92016-05-26 23:01:05 +0000133 cl::cat(NativeOptions));
Zachary Turner96e60f72016-05-24 20:31:48 +0000134cl::opt<std::string> DumpStreamDataName("raw-stream-name",
135 cl::desc("dump stream data"),
Rui Ueyama18695f92016-05-26 23:01:05 +0000136 cl::cat(NativeOptions));
Zachary Turner96e60f72016-05-24 20:31:48 +0000137cl::opt<bool> DumpModules("raw-modules", cl::desc("dump compiland information"),
Rui Ueyama18695f92016-05-26 23:01:05 +0000138 cl::cat(NativeOptions));
Zachary Turner96e60f72016-05-24 20:31:48 +0000139cl::opt<bool> DumpModuleFiles("raw-module-files",
140 cl::desc("dump file information"),
Rui Ueyama18695f92016-05-26 23:01:05 +0000141 cl::cat(NativeOptions));
Zachary Turner96e60f72016-05-24 20:31:48 +0000142cl::opt<bool> DumpModuleSyms("raw-module-syms", cl::desc("dump module symbols"),
Rui Ueyama18695f92016-05-26 23:01:05 +0000143 cl::cat(NativeOptions));
Zachary Turner96e60f72016-05-24 20:31:48 +0000144cl::opt<bool> DumpPublics("raw-publics", cl::desc("dump Publics stream data"),
Rui Ueyama18695f92016-05-26 23:01:05 +0000145 cl::cat(NativeOptions));
Zachary Turnercac29ae2016-05-24 17:30:25 +0000146cl::opt<bool>
Zachary Turner96e60f72016-05-24 20:31:48 +0000147 DumpSymRecordBytes("raw-sym-record-bytes",
Zachary Turnercac29ae2016-05-24 17:30:25 +0000148 cl::desc("dump CodeView symbol record raw bytes"),
Rui Ueyama18695f92016-05-26 23:01:05 +0000149 cl::cat(NativeOptions));
Rui Ueyama9dc034d2016-05-26 23:26:55 +0000150cl::opt<bool>
151 RawAll("raw-all",
152 cl::desc("Implies most other options in 'Native Options' category"),
153 cl::cat(NativeOptions));
David Majnemer6e081262015-10-15 01:27:19 +0000154
Zachary Turnerf5abda22015-03-01 06:49:49 +0000155cl::list<std::string>
156 ExcludeTypes("exclude-types",
157 cl::desc("Exclude types by regular expression"),
Zachary Turner7797c722015-03-02 04:39:56 +0000158 cl::ZeroOrMore, cl::cat(FilterCategory));
Zachary Turnerf5abda22015-03-01 06:49:49 +0000159cl::list<std::string>
160 ExcludeSymbols("exclude-symbols",
161 cl::desc("Exclude symbols by regular expression"),
Zachary Turner7797c722015-03-02 04:39:56 +0000162 cl::ZeroOrMore, cl::cat(FilterCategory));
Zachary Turnerf5abda22015-03-01 06:49:49 +0000163cl::list<std::string>
164 ExcludeCompilands("exclude-compilands",
165 cl::desc("Exclude compilands by regular expression"),
Zachary Turner7797c722015-03-02 04:39:56 +0000166 cl::ZeroOrMore, cl::cat(FilterCategory));
Zachary Turner4dddcc62015-09-29 19:49:06 +0000167
168cl::list<std::string> IncludeTypes(
169 "include-types",
170 cl::desc("Include only types which match a regular expression"),
171 cl::ZeroOrMore, cl::cat(FilterCategory));
172cl::list<std::string> IncludeSymbols(
173 "include-symbols",
174 cl::desc("Include only symbols which match a regular expression"),
175 cl::ZeroOrMore, cl::cat(FilterCategory));
176cl::list<std::string> IncludeCompilands(
177 "include-compilands",
178 cl::desc("Include only compilands those which match a regular expression"),
179 cl::ZeroOrMore, cl::cat(FilterCategory));
180
Zachary Turner7797c722015-03-02 04:39:56 +0000181cl::opt<bool> ExcludeCompilerGenerated(
182 "no-compiler-generated",
183 cl::desc("Don't show compiler generated types and symbols"),
184 cl::cat(FilterCategory));
185cl::opt<bool>
186 ExcludeSystemLibraries("no-system-libs",
187 cl::desc("Don't show symbols from system libraries"),
188 cl::cat(FilterCategory));
Zachary Turner65323652015-03-04 06:09:53 +0000189cl::opt<bool> NoClassDefs("no-class-definitions",
190 cl::desc("Don't display full class definitions"),
191 cl::cat(FilterCategory));
192cl::opt<bool> NoEnumDefs("no-enum-definitions",
193 cl::desc("Don't display full enum definitions"),
194 cl::cat(FilterCategory));
Zachary Turner49693b42015-01-28 01:22:33 +0000195}
196
Zachary Turner819e77d2016-05-06 20:51:57 +0000197static Error dumpFileHeaders(ScopedPrinter &P, PDBFile &File) {
Reid Klecknerb0345262016-05-04 16:09:04 +0000198 if (!opts::DumpHeaders)
Zachary Turner819e77d2016-05-06 20:51:57 +0000199 return Error::success();
200
Reid Klecknerb0345262016-05-04 16:09:04 +0000201 DictScope D(P, "FileHeaders");
202 P.printNumber("BlockSize", File.getBlockSize());
203 P.printNumber("Unknown0", File.getUnknown0());
204 P.printNumber("NumBlocks", File.getBlockCount());
205 P.printNumber("NumDirectoryBytes", File.getNumDirectoryBytes());
206 P.printNumber("Unknown1", File.getUnknown1());
207 P.printNumber("BlockMapAddr", File.getBlockMapIndex());
208 P.printNumber("NumDirectoryBlocks", File.getNumDirectoryBlocks());
209 P.printNumber("BlockMapOffset", File.getBlockMapOffset());
Zachary Turnercdd313c2016-05-04 15:05:12 +0000210
Chad Rosier20dbbf32016-05-04 15:25:06 +0000211 // The directory is not contiguous. Instead, the block map contains a
212 // contiguous list of block numbers whose contents, when concatenated in
213 // order, make up the directory.
Reid Klecknerb0345262016-05-04 16:09:04 +0000214 P.printList("DirectoryBlocks", File.getDirectoryBlockArray());
215 P.printNumber("NumStreams", File.getNumStreams());
Zachary Turner819e77d2016-05-06 20:51:57 +0000216 return Error::success();
Reid Klecknerb0345262016-05-04 16:09:04 +0000217}
Zachary Turnercdd313c2016-05-04 15:05:12 +0000218
Zachary Turner85ed80b2016-05-25 03:43:17 +0000219static Error dumpStreamSummary(ScopedPrinter &P, PDBFile &File) {
220 if (!opts::DumpStreamSummary)
Zachary Turner819e77d2016-05-06 20:51:57 +0000221 return Error::success();
Zachary Turnercdd313c2016-05-04 15:05:12 +0000222
Zachary Turner85ed80b2016-05-25 03:43:17 +0000223 auto DbiS = File.getPDBDbiStream();
224 if (auto EC = DbiS.takeError())
225 return EC;
226 auto TpiS = File.getPDBTpiStream();
227 if (auto EC = TpiS.takeError())
228 return EC;
Zachary Turnerc9972c62016-05-25 04:35:22 +0000229 auto IpiS = File.getPDBIpiStream();
230 if (auto EC = IpiS.takeError())
231 return EC;
Zachary Turner85ed80b2016-05-25 03:43:17 +0000232 auto InfoS = File.getPDBInfoStream();
233 if (auto EC = InfoS.takeError())
234 return EC;
235 DbiStream &DS = DbiS.get();
236 TpiStream &TS = TpiS.get();
Zachary Turnerc9972c62016-05-25 04:35:22 +0000237 TpiStream &TIS = IpiS.get();
Zachary Turner85ed80b2016-05-25 03:43:17 +0000238 InfoStream &IS = InfoS.get();
239
240 ListScope L(P, "Streams");
Chad Rosier20dbbf32016-05-04 15:25:06 +0000241 uint32_t StreamCount = File.getNumStreams();
Zachary Turner85ed80b2016-05-25 03:43:17 +0000242 std::unordered_map<uint16_t, const ModuleInfoEx *> ModStreams;
243 std::unordered_map<uint16_t, std::string> NamedStreams;
244
245 for (auto &ModI : DS.modules()) {
246 uint16_t SN = ModI.Info.getModuleStreamIndex();
247 ModStreams[SN] = &ModI;
Chad Rosier20dbbf32016-05-04 15:25:06 +0000248 }
Zachary Turner85ed80b2016-05-25 03:43:17 +0000249 for (auto &NSE : IS.named_streams()) {
250 NamedStreams[NSE.second] = NSE.first();
251 }
252
253 for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
254 std::string Label("Stream ");
255 Label += to_string(StreamIdx);
256 std::string Value;
Rui Ueyama68163672016-05-27 00:32:07 +0000257 if (StreamIdx == OldMSFDirectory)
258 Value = "Old MSF Directory";
259 else if (StreamIdx == StreamPDB)
Zachary Turner85ed80b2016-05-25 03:43:17 +0000260 Value = "PDB Stream";
261 else if (StreamIdx == StreamDBI)
262 Value = "DBI Stream";
263 else if (StreamIdx == StreamTPI)
264 Value = "TPI Stream";
265 else if (StreamIdx == StreamIPI)
266 Value = "IPI Stream";
267 else if (StreamIdx == DS.getGlobalSymbolStreamIndex())
268 Value = "Global Symbol Hash";
269 else if (StreamIdx == DS.getPublicSymbolStreamIndex())
270 Value = "Public Symbol Hash";
271 else if (StreamIdx == DS.getSymRecordStreamIndex())
272 Value = "Public Symbol Records";
273 else if (StreamIdx == TS.getTypeHashStreamIndex())
274 Value = "TPI Hash";
275 else if (StreamIdx == TS.getTypeHashStreamAuxIndex())
276 Value = "TPI Aux Hash";
Zachary Turnerc9972c62016-05-25 04:35:22 +0000277 else if (StreamIdx == TIS.getTypeHashStreamIndex())
278 Value = "IPI Hash";
279 else if (StreamIdx == TIS.getTypeHashStreamAuxIndex())
280 Value = "IPI Aux Hash";
Zachary Turnerd3076ab2016-05-25 05:49:48 +0000281 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::Exception))
282 Value = "Exception Data";
283 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::Fixup))
284 Value = "Fixup Data";
285 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::FPO))
286 Value = "FPO Data";
287 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::NewFPO))
288 Value = "New FPO Data";
289 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::OmapFromSrc))
290 Value = "Omap From Source Data";
291 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::OmapToSrc))
292 Value = "Omap To Source Data";
293 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::Pdata))
294 Value = "Pdata";
295 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::SectionHdr))
296 Value = "Section Header Data";
297 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::SectionHdrOrig))
298 Value = "Section Header Original Data";
299 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::TokenRidMap))
300 Value = "Token Rid Data";
301 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::Xdata))
302 Value = "Xdata";
Zachary Turner85ed80b2016-05-25 03:43:17 +0000303 else {
304 auto ModIter = ModStreams.find(StreamIdx);
305 auto NSIter = NamedStreams.find(StreamIdx);
306 if (ModIter != ModStreams.end()) {
307 Value = "Module \"";
Zachary Turner8dbe3622016-05-27 01:54:44 +0000308 Value += ModIter->second->Info.getModuleName().str();
Zachary Turner85ed80b2016-05-25 03:43:17 +0000309 Value += "\"";
310 } else if (NSIter != NamedStreams.end()) {
311 Value = "Named Stream \"";
312 Value += NSIter->second;
313 Value += "\"";
314 } else {
315 Value = "???";
316 }
317 }
318 Value = "[" + Value + "]";
319 Value =
320 Value + " (" + to_string(File.getStreamByteSize(StreamIdx)) + " bytes)";
321
322 P.printString(Label, Value);
323 }
324 P.flush();
Zachary Turner819e77d2016-05-06 20:51:57 +0000325 return Error::success();
Reid Klecknerb0345262016-05-04 16:09:04 +0000326}
Zachary Turnercdd313c2016-05-04 15:05:12 +0000327
Zachary Turner819e77d2016-05-06 20:51:57 +0000328static Error dumpStreamBlocks(ScopedPrinter &P, PDBFile &File) {
Reid Klecknerb0345262016-05-04 16:09:04 +0000329 if (!opts::DumpStreamBlocks)
Zachary Turner819e77d2016-05-06 20:51:57 +0000330 return Error::success();
Reid Klecknerb0345262016-05-04 16:09:04 +0000331
332 ListScope L(P, "StreamBlocks");
333 uint32_t StreamCount = File.getNumStreams();
334 for (uint32_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
335 std::string Name("Stream ");
336 Name += to_string(StreamIdx);
337 auto StreamBlocks = File.getStreamBlockList(StreamIdx);
338 P.printList(Name, StreamBlocks);
Chad Rosier20dbbf32016-05-04 15:25:06 +0000339 }
Zachary Turner819e77d2016-05-06 20:51:57 +0000340 return Error::success();
Reid Klecknerb0345262016-05-04 16:09:04 +0000341}
Zachary Turnercdd313c2016-05-04 15:05:12 +0000342
Zachary Turner819e77d2016-05-06 20:51:57 +0000343static Error dumpStreamData(ScopedPrinter &P, PDBFile &File) {
Reid Klecknerb0345262016-05-04 16:09:04 +0000344 uint32_t StreamCount = File.getNumStreams();
Zachary Turner96e60f72016-05-24 20:31:48 +0000345 StringRef DumpStreamStr = opts::DumpStreamDataIdx;
Chad Rosier20dbbf32016-05-04 15:25:06 +0000346 uint32_t DumpStreamNum;
Reid Klecknerb0345262016-05-04 16:09:04 +0000347 if (DumpStreamStr.getAsInteger(/*Radix=*/0U, DumpStreamNum) ||
348 DumpStreamNum >= StreamCount)
Zachary Turner819e77d2016-05-06 20:51:57 +0000349 return Error::success();
Chad Rosier20dbbf32016-05-04 15:25:06 +0000350
Zachary Turner96e60f72016-05-24 20:31:48 +0000351 MappedBlockStream S(DumpStreamNum, File);
Zachary Turnerd5d37dc2016-05-25 20:37:03 +0000352 codeview::StreamReader R(S);
Zachary Turner96e60f72016-05-24 20:31:48 +0000353 while (R.bytesRemaining() > 0) {
354 ArrayRef<uint8_t> Data;
Reid Klecknerb0345262016-05-04 16:09:04 +0000355 uint32_t BytesToReadInBlock = std::min(
Zachary Turner96e60f72016-05-24 20:31:48 +0000356 R.bytesRemaining(), static_cast<uint32_t>(File.getBlockSize()));
Zachary Turner8dbe3622016-05-27 01:54:44 +0000357 if (auto EC = R.readBytes(BytesToReadInBlock, Data))
Zachary Turner96e60f72016-05-24 20:31:48 +0000358 return EC;
Zachary Turnerd8ca0522016-05-25 18:32:07 +0000359 P.printBinaryBlock(
360 "Data",
361 StringRef(reinterpret_cast<const char *>(Data.begin()), Data.size()));
Chad Rosier20dbbf32016-05-04 15:25:06 +0000362 }
Zachary Turner819e77d2016-05-06 20:51:57 +0000363 return Error::success();
Reid Klecknerb0345262016-05-04 16:09:04 +0000364}
Chad Rosier20dbbf32016-05-04 15:25:06 +0000365
Zachary Turner819e77d2016-05-06 20:51:57 +0000366static Error dumpInfoStream(ScopedPrinter &P, PDBFile &File) {
Zachary Turnerc59261c2016-05-25 03:53:16 +0000367 if (!opts::DumpHeaders)
368 return Error::success();
Zachary Turner819e77d2016-05-06 20:51:57 +0000369 auto InfoS = File.getPDBInfoStream();
370 if (auto EC = InfoS.takeError())
371 return EC;
372
373 InfoStream &IS = InfoS.get();
Chad Rosier20dbbf32016-05-04 15:25:06 +0000374
Reid Klecknerb0345262016-05-04 16:09:04 +0000375 DictScope D(P, "PDB Stream");
376 P.printNumber("Version", IS.getVersion());
377 P.printHex("Signature", IS.getSignature());
378 P.printNumber("Age", IS.getAge());
379 P.printObject("Guid", IS.getGuid());
Zachary Turner819e77d2016-05-06 20:51:57 +0000380 return Error::success();
Reid Klecknerb0345262016-05-04 16:09:04 +0000381}
382
Zachary Turner96e60f72016-05-24 20:31:48 +0000383static Error dumpNamedStream(ScopedPrinter &P, PDBFile &File) {
384 if (opts::DumpStreamDataName.empty())
385 return Error::success();
386
Zachary Turner819e77d2016-05-06 20:51:57 +0000387 auto InfoS = File.getPDBInfoStream();
388 if (auto EC = InfoS.takeError())
389 return EC;
390 InfoStream &IS = InfoS.get();
391
Zachary Turner96e60f72016-05-24 20:31:48 +0000392 uint32_t NameStreamIndex = IS.getNamedStreamIndex(opts::DumpStreamDataName);
Reid Klecknerb0345262016-05-04 16:09:04 +0000393
Chad Rosier20dbbf32016-05-04 15:25:06 +0000394 if (NameStreamIndex != 0) {
Reid Klecknerb0345262016-05-04 16:09:04 +0000395 std::string Name("Stream '");
Zachary Turner96e60f72016-05-24 20:31:48 +0000396 Name += opts::DumpStreamDataName;
Reid Klecknerb0345262016-05-04 16:09:04 +0000397 Name += "'";
398 DictScope D(P, Name);
399 P.printNumber("Index", NameStreamIndex);
400
Chad Rosier20dbbf32016-05-04 15:25:06 +0000401 MappedBlockStream NameStream(NameStreamIndex, File);
Zachary Turnerd5d37dc2016-05-25 20:37:03 +0000402 codeview::StreamReader Reader(NameStream);
Chad Rosier20dbbf32016-05-04 15:25:06 +0000403
Chad Rosier20dbbf32016-05-04 15:25:06 +0000404 NameHashTable NameTable;
Zachary Turner819e77d2016-05-06 20:51:57 +0000405 if (auto EC = NameTable.load(Reader))
406 return EC;
407
Reid Klecknerb0345262016-05-04 16:09:04 +0000408 P.printHex("Signature", NameTable.getSignature());
409 P.printNumber("Version", NameTable.getHashVersion());
410 P.printNumber("Name Count", NameTable.getNameCount());
411 ListScope L(P, "Names");
Chad Rosier20dbbf32016-05-04 15:25:06 +0000412 for (uint32_t ID : NameTable.name_ids()) {
Reid Klecknerb0345262016-05-04 16:09:04 +0000413 StringRef Str = NameTable.getStringForID(ID);
414 if (!Str.empty())
415 P.printString(Str);
Chad Rosier20dbbf32016-05-04 15:25:06 +0000416 }
417 }
Zachary Turner819e77d2016-05-06 20:51:57 +0000418 return Error::success();
Reid Klecknerb0345262016-05-04 16:09:04 +0000419}
Chad Rosier20dbbf32016-05-04 15:25:06 +0000420
Zachary Turnercac29ae2016-05-24 17:30:25 +0000421static Error dumpDbiStream(ScopedPrinter &P, PDBFile &File,
422 codeview::CVTypeDumper &TD) {
Zachary Turnerc59261c2016-05-25 03:53:16 +0000423 bool DumpModules =
424 opts::DumpModules || opts::DumpModuleSyms || opts::DumpModuleFiles;
425 if (!opts::DumpHeaders && !DumpModules)
426 return Error::success();
427
Zachary Turner819e77d2016-05-06 20:51:57 +0000428 auto DbiS = File.getPDBDbiStream();
429 if (auto EC = DbiS.takeError())
430 return EC;
431 DbiStream &DS = DbiS.get();
Reid Klecknerb0345262016-05-04 16:09:04 +0000432
433 DictScope D(P, "DBI Stream");
434 P.printNumber("Dbi Version", DS.getDbiVersion());
435 P.printNumber("Age", DS.getAge());
436 P.printBoolean("Incremental Linking", DS.isIncrementallyLinked());
437 P.printBoolean("Has CTypes", DS.hasCTypes());
438 P.printBoolean("Is Stripped", DS.isStripped());
439 P.printObject("Machine Type", DS.getMachineType());
Rui Ueyama0376b1a2016-05-19 18:05:58 +0000440 P.printNumber("Symbol Record Stream Index", DS.getSymRecordStreamIndex());
Zachary Turner96e60f72016-05-24 20:31:48 +0000441 P.printNumber("Public Symbol Stream Index", DS.getPublicSymbolStreamIndex());
442 P.printNumber("Global Symbol Stream Index", DS.getGlobalSymbolStreamIndex());
Chad Rosier20dbbf32016-05-04 15:25:06 +0000443
444 uint16_t Major = DS.getBuildMajorVersion();
445 uint16_t Minor = DS.getBuildMinorVersion();
Reid Klecknerb0345262016-05-04 16:09:04 +0000446 P.printVersion("Toolchain Version", Major, Minor);
Chad Rosier20dbbf32016-05-04 15:25:06 +0000447
Reid Klecknerb0345262016-05-04 16:09:04 +0000448 std::string DllName;
449 raw_string_ostream DllStream(DllName);
450 DllStream << "mspdb" << Major << Minor << ".dll version";
451 DllStream.flush();
452 P.printVersion(DllName, Major, Minor, DS.getPdbDllVersion());
453
Zachary Turnerc59261c2016-05-25 03:53:16 +0000454 if (DumpModules) {
Zachary Turner96e60f72016-05-24 20:31:48 +0000455 ListScope L(P, "Modules");
456 for (auto &Modi : DS.modules()) {
457 DictScope DD(P);
Zachary Turner8dbe3622016-05-27 01:54:44 +0000458 P.printString("Name", Modi.Info.getModuleName().str());
Zachary Turner96e60f72016-05-24 20:31:48 +0000459 P.printNumber("Debug Stream Index", Modi.Info.getModuleStreamIndex());
Zachary Turner8dbe3622016-05-27 01:54:44 +0000460 P.printString("Object File Name", Modi.Info.getObjFileName().str());
Zachary Turner96e60f72016-05-24 20:31:48 +0000461 P.printNumber("Num Files", Modi.Info.getNumberOfFiles());
462 P.printNumber("Source File Name Idx", Modi.Info.getSourceFileNameIndex());
463 P.printNumber("Pdb File Name Idx", Modi.Info.getPdbFilePathNameIndex());
464 P.printNumber("Line Info Byte Size", Modi.Info.getLineInfoByteSize());
465 P.printNumber("C13 Line Info Byte Size",
466 Modi.Info.getC13LineInfoByteSize());
467 P.printNumber("Symbol Byte Size", Modi.Info.getSymbolDebugInfoByteSize());
468 P.printNumber("Type Server Index", Modi.Info.getTypeServerIndex());
469 P.printBoolean("Has EC Info", Modi.Info.hasECInfo());
470 if (opts::DumpModuleFiles) {
471 std::string FileListName =
472 to_string(Modi.SourceFiles.size()) + " Contributing Source Files";
473 ListScope LL(P, FileListName);
474 for (auto File : Modi.SourceFiles)
Zachary Turner8dbe3622016-05-27 01:54:44 +0000475 P.printString(File.str());
Zachary Turner96e60f72016-05-24 20:31:48 +0000476 }
477 bool HasModuleDI =
478 (Modi.Info.getModuleStreamIndex() < File.getNumStreams());
479 bool ShouldDumpSymbols =
480 (opts::DumpModuleSyms || opts::DumpSymRecordBytes);
481 if (HasModuleDI && ShouldDumpSymbols) {
482 ListScope SS(P, "Symbols");
483 ModStream ModS(File, Modi.Info);
484 if (auto EC = ModS.reload())
485 return EC;
Zachary Turner06c2b4b2016-05-09 17:45:21 +0000486
Zachary Turner96e60f72016-05-24 20:31:48 +0000487 codeview::CVSymbolDumper SD(P, TD, nullptr, false);
488 for (auto &S : ModS.symbols()) {
489 DictScope DD(P, "");
Zachary Turnercac29ae2016-05-24 17:30:25 +0000490
Zachary Turner96e60f72016-05-24 20:31:48 +0000491 if (opts::DumpModuleSyms)
492 SD.dump(S);
493 if (opts::DumpSymRecordBytes)
494 P.printBinaryBlock("Bytes", S.Data);
495 }
Zachary Turner06c2b4b2016-05-09 17:45:21 +0000496 }
497 }
Chad Rosier20dbbf32016-05-04 15:25:06 +0000498 }
Zachary Turner819e77d2016-05-06 20:51:57 +0000499 return Error::success();
Reid Klecknerb0345262016-05-04 16:09:04 +0000500}
501
Zachary Turnercac29ae2016-05-24 17:30:25 +0000502static Error dumpTpiStream(ScopedPrinter &P, PDBFile &File,
Zachary Turnerc9972c62016-05-25 04:35:22 +0000503 codeview::CVTypeDumper &TD, uint32_t StreamIdx) {
504 assert(StreamIdx == StreamTPI || StreamIdx == StreamIPI);
Reid Klecknerb0345262016-05-04 16:09:04 +0000505
Zachary Turnerc9972c62016-05-25 04:35:22 +0000506 bool DumpRecordBytes = false;
507 bool DumpRecords = false;
508 StringRef Label;
509 StringRef VerLabel;
510 if (StreamIdx == StreamTPI) {
511 DumpRecordBytes = opts::DumpTpiRecordBytes;
512 DumpRecords = opts::DumpTpiRecordBytes;
513 Label = "Type Info Stream (TPI)";
514 VerLabel = "TPI Version";
515 } else if (StreamIdx == StreamIPI) {
516 DumpRecordBytes = opts::DumpIpiRecordBytes;
517 DumpRecords = opts::DumpIpiRecords;
518 Label = "Type Info Stream (IPI)";
519 VerLabel = "IPI Version";
520 }
521 if (!DumpRecordBytes && !DumpRecords && !opts::DumpModuleSyms)
522 return Error::success();
Zachary Turnercac29ae2016-05-24 17:30:25 +0000523
Zachary Turnerc9972c62016-05-25 04:35:22 +0000524 auto TpiS = (StreamIdx == StreamTPI) ? File.getPDBTpiStream()
525 : File.getPDBIpiStream();
Zachary Turnercac29ae2016-05-24 17:30:25 +0000526 if (auto EC = TpiS.takeError())
527 return EC;
528 TpiStream &Tpi = TpiS.get();
529
Zachary Turnerc9972c62016-05-25 04:35:22 +0000530 if (DumpRecords || DumpRecordBytes) {
531 DictScope D(P, Label);
532
533 P.printNumber(VerLabel, Tpi.getTpiVersion());
Zachary Turnercac29ae2016-05-24 17:30:25 +0000534 P.printNumber("Record count", Tpi.NumTypeRecords());
535
Zachary Turner5a1b5ef2016-05-06 22:15:42 +0000536 ListScope L(P, "Records");
Reid Klecknerb0345262016-05-04 16:09:04 +0000537
Reid Klecknerce5196e2016-05-12 23:26:23 +0000538 bool HadError = false;
539 for (auto &Type : Tpi.types(&HadError)) {
Zachary Turner5a1b5ef2016-05-06 22:15:42 +0000540 DictScope DD(P, "");
541
Zachary Turnerc9972c62016-05-25 04:35:22 +0000542 if (DumpRecords)
Zachary Turner5a1b5ef2016-05-06 22:15:42 +0000543 TD.dump(Type);
544
Zachary Turnerc9972c62016-05-25 04:35:22 +0000545 if (DumpRecordBytes)
Zachary Turner9073ed62016-05-09 17:44:58 +0000546 P.printBinaryBlock("Bytes", Type.Data);
Zachary Turner5a1b5ef2016-05-06 22:15:42 +0000547 }
Reid Klecknerce5196e2016-05-12 23:26:23 +0000548 if (HadError)
549 return make_error<RawError>(raw_error_code::corrupt_file,
550 "TPI stream contained corrupt record");
Zachary Turnercac29ae2016-05-24 17:30:25 +0000551 } else if (opts::DumpModuleSyms) {
552 // Even if the user doesn't want to dump type records, we still need to
553 // iterate them in order to build the list of types so that we can print
554 // them when dumping module symbols. So when they want to dump symbols
555 // but not types, use a null output stream.
556 ScopedPrinter *OldP = TD.getPrinter();
557 TD.setPrinter(nullptr);
Zachary Turnerc9972c62016-05-25 04:35:22 +0000558
Zachary Turnercac29ae2016-05-24 17:30:25 +0000559 bool HadError = false;
560 for (auto &Type : Tpi.types(&HadError))
561 TD.dump(Type);
562
563 TD.setPrinter(OldP);
564 if (HadError)
565 return make_error<RawError>(raw_error_code::corrupt_file,
566 "TPI stream contained corrupt record");
Chad Rosier20dbbf32016-05-04 15:25:06 +0000567 }
Zachary Turnerc9972c62016-05-25 04:35:22 +0000568 P.flush();
Zachary Turner819e77d2016-05-06 20:51:57 +0000569 return Error::success();
Zachary Turnercdd313c2016-05-04 15:05:12 +0000570}
571
Zachary Turnerb393d952016-05-27 03:51:53 +0000572static void printSectionOffset(llvm::raw_ostream &OS,
573 const SectionOffset &Off) {
574 OS << Off.Off << ", " << Off.Isect;
575}
576
Zachary Turner9e33e6f2016-05-24 18:55:14 +0000577static Error dumpPublicsStream(ScopedPrinter &P, PDBFile &File,
578 codeview::CVTypeDumper &TD) {
Rui Ueyama1f6b6e22016-05-13 21:21:53 +0000579 if (!opts::DumpPublics)
580 return Error::success();
581
582 DictScope D(P, "Publics Stream");
583 auto PublicsS = File.getPDBPublicsStream();
584 if (auto EC = PublicsS.takeError())
585 return EC;
586 PublicsStream &Publics = PublicsS.get();
587 P.printNumber("Stream number", Publics.getStreamNum());
588 P.printNumber("SymHash", Publics.getSymHash());
589 P.printNumber("AddrMap", Publics.getAddrMap());
590 P.printNumber("Number of buckets", Publics.getNumBuckets());
Rui Ueyama8dc18c52016-05-17 23:07:48 +0000591 P.printList("Hash Buckets", Publics.getHashBuckets());
592 P.printList("Address Map", Publics.getAddressMap());
593 P.printList("Thunk Map", Publics.getThunkMap());
Zachary Turnerb393d952016-05-27 03:51:53 +0000594 P.printList("Section Offsets", Publics.getSectionOffsets(),
595 printSectionOffset);
Zachary Turner9e33e6f2016-05-24 18:55:14 +0000596 ListScope L(P, "Symbols");
597 codeview::CVSymbolDumper SD(P, TD, nullptr, false);
598 for (auto S : Publics.getSymbols()) {
599 DictScope DD(P, "");
600
601 SD.dump(S);
602 if (opts::DumpSymRecordBytes)
603 P.printBinaryBlock("Bytes", S.Data);
604 }
Rui Ueyama1f6b6e22016-05-13 21:21:53 +0000605 return Error::success();
606}
607
Zachary Turner819e77d2016-05-06 20:51:57 +0000608static Error dumpStructure(RawSession &RS) {
Reid Klecknerb0345262016-05-04 16:09:04 +0000609 PDBFile &File = RS.getPDBFile();
610 ScopedPrinter P(outs());
611
Zachary Turner819e77d2016-05-06 20:51:57 +0000612 if (auto EC = dumpFileHeaders(P, File))
613 return EC;
Reid Klecknerb0345262016-05-04 16:09:04 +0000614
Zachary Turner85ed80b2016-05-25 03:43:17 +0000615 if (auto EC = dumpStreamSummary(P, File))
Zachary Turner819e77d2016-05-06 20:51:57 +0000616 return EC;
Reid Klecknerb0345262016-05-04 16:09:04 +0000617
Zachary Turner819e77d2016-05-06 20:51:57 +0000618 if (auto EC = dumpStreamBlocks(P, File))
619 return EC;
Reid Klecknerb0345262016-05-04 16:09:04 +0000620
Zachary Turner819e77d2016-05-06 20:51:57 +0000621 if (auto EC = dumpStreamData(P, File))
622 return EC;
Reid Klecknerb0345262016-05-04 16:09:04 +0000623
Zachary Turner819e77d2016-05-06 20:51:57 +0000624 if (auto EC = dumpInfoStream(P, File))
625 return EC;
Reid Klecknerb0345262016-05-04 16:09:04 +0000626
Zachary Turner96e60f72016-05-24 20:31:48 +0000627 if (auto EC = dumpNamedStream(P, File))
Zachary Turner819e77d2016-05-06 20:51:57 +0000628 return EC;
Reid Klecknerb0345262016-05-04 16:09:04 +0000629
Zachary Turnercac29ae2016-05-24 17:30:25 +0000630 codeview::CVTypeDumper TD(P, false);
Zachary Turnerc9972c62016-05-25 04:35:22 +0000631 if (auto EC = dumpTpiStream(P, File, TD, StreamTPI))
632 return EC;
633 if (auto EC = dumpTpiStream(P, File, TD, StreamIPI))
Zachary Turner819e77d2016-05-06 20:51:57 +0000634 return EC;
Reid Klecknerb0345262016-05-04 16:09:04 +0000635
Zachary Turnercac29ae2016-05-24 17:30:25 +0000636 if (auto EC = dumpDbiStream(P, File, TD))
Zachary Turner819e77d2016-05-06 20:51:57 +0000637 return EC;
Rui Ueyama1f6b6e22016-05-13 21:21:53 +0000638
Zachary Turner9e33e6f2016-05-24 18:55:14 +0000639 if (auto EC = dumpPublicsStream(P, File, TD))
Rui Ueyama1f6b6e22016-05-13 21:21:53 +0000640 return EC;
Zachary Turner96e60f72016-05-24 20:31:48 +0000641 return Error::success();
642}
643
644bool isRawDumpEnabled() {
645 if (opts::DumpHeaders)
646 return true;
647 if (opts::DumpModules)
648 return true;
649 if (opts::DumpModuleFiles)
650 return true;
651 if (opts::DumpModuleSyms)
652 return true;
653 if (!opts::DumpStreamDataIdx.empty())
654 return true;
655 if (!opts::DumpStreamDataName.empty())
656 return true;
657 if (opts::DumpPublics)
658 return true;
Zachary Turner85ed80b2016-05-25 03:43:17 +0000659 if (opts::DumpStreamSummary)
Zachary Turner96e60f72016-05-24 20:31:48 +0000660 return true;
Zachary Turner85ed80b2016-05-25 03:43:17 +0000661 if (opts::DumpStreamBlocks)
Zachary Turner96e60f72016-05-24 20:31:48 +0000662 return true;
663 if (opts::DumpSymRecordBytes)
664 return true;
665 if (opts::DumpTpiRecordBytes)
666 return true;
667 if (opts::DumpTpiRecords)
668 return true;
Zachary Turnerc9972c62016-05-25 04:35:22 +0000669 if (opts::DumpIpiRecords)
670 return true;
671 if (opts::DumpIpiRecordBytes)
672 return true;
Zachary Turner96e60f72016-05-24 20:31:48 +0000673 return false;
David Majnemer1573b242016-04-28 23:47:27 +0000674}
675
676static void dumpInput(StringRef Path) {
677 std::unique_ptr<IPDBSession> Session;
Zachary Turner96e60f72016-05-24 20:31:48 +0000678 if (isRawDumpEnabled()) {
Zachary Turner819e77d2016-05-06 20:51:57 +0000679 auto E = loadDataForPDB(PDB_ReaderType::Raw, Path, Session);
680 if (!E) {
David Majnemer1573b242016-04-28 23:47:27 +0000681 RawSession *RS = static_cast<RawSession *>(Session.get());
Zachary Turner819e77d2016-05-06 20:51:57 +0000682 E = dumpStructure(*RS);
David Majnemer1573b242016-04-28 23:47:27 +0000683 }
684
Zachary Turner819e77d2016-05-06 20:51:57 +0000685 if (E)
686 logAllUnhandledErrors(std::move(E), outs(), "");
687
David Majnemer1573b242016-04-28 23:47:27 +0000688 return;
689 }
690
Zachary Turner819e77d2016-05-06 20:51:57 +0000691 Error E = loadDataForPDB(PDB_ReaderType::DIA, Path, Session);
692 if (E) {
693 logAllUnhandledErrors(std::move(E), outs(), "");
David Majnemer1573b242016-04-28 23:47:27 +0000694 return;
695 }
696
Zachary Turnere5cb2692015-05-01 20:24:26 +0000697 if (opts::LoadAddress)
698 Session->setLoadAddress(opts::LoadAddress);
Zachary Turner7058dfc2015-01-27 22:40:14 +0000699
Zachary Turner2d11c202015-02-27 09:15:59 +0000700 LinePrinter Printer(2, outs());
701
Zachary Turnera5549172015-02-10 22:43:25 +0000702 auto GlobalScope(Session->getGlobalScope());
Zachary Turner9a818ad2015-02-22 22:03:38 +0000703 std::string FileName(GlobalScope->getSymbolsFileName());
704
Zachary Turner2d11c202015-02-27 09:15:59 +0000705 WithColor(Printer, PDB_ColorItem::None).get() << "Summary for ";
706 WithColor(Printer, PDB_ColorItem::Path).get() << FileName;
707 Printer.Indent();
Zachary Turner9a818ad2015-02-22 22:03:38 +0000708 uint64_t FileSize = 0;
Zachary Turner9a818ad2015-02-22 22:03:38 +0000709
Zachary Turner2d11c202015-02-27 09:15:59 +0000710 Printer.NewLine();
711 WithColor(Printer, PDB_ColorItem::Identifier).get() << "Size";
David Majnemer6e081262015-10-15 01:27:19 +0000712 if (!sys::fs::file_size(FileName, FileSize)) {
Zachary Turner2d11c202015-02-27 09:15:59 +0000713 Printer << ": " << FileSize << " bytes";
714 } else {
715 Printer << ": (Unable to obtain file size)";
716 }
717
718 Printer.NewLine();
719 WithColor(Printer, PDB_ColorItem::Identifier).get() << "Guid";
720 Printer << ": " << GlobalScope->getGuid();
721
722 Printer.NewLine();
723 WithColor(Printer, PDB_ColorItem::Identifier).get() << "Age";
724 Printer << ": " << GlobalScope->getAge();
725
726 Printer.NewLine();
727 WithColor(Printer, PDB_ColorItem::Identifier).get() << "Attributes";
728 Printer << ": ";
Zachary Turner9a818ad2015-02-22 22:03:38 +0000729 if (GlobalScope->hasCTypes())
730 outs() << "HasCTypes ";
731 if (GlobalScope->hasPrivateSymbols())
732 outs() << "HasPrivateSymbols ";
Zachary Turner2d11c202015-02-27 09:15:59 +0000733 Printer.Unindent();
Zachary Turner9a818ad2015-02-22 22:03:38 +0000734
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000735 if (opts::Compilands) {
Zachary Turner2d11c202015-02-27 09:15:59 +0000736 Printer.NewLine();
737 WithColor(Printer, PDB_ColorItem::SectionHeader).get()
738 << "---COMPILANDS---";
739 Printer.Indent();
Zachary Turnerc074de02015-02-12 21:09:24 +0000740 auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>();
Zachary Turner2d11c202015-02-27 09:15:59 +0000741 CompilandDumper Dumper(Printer);
Zachary Turnera99000d2016-03-08 21:42:24 +0000742 CompilandDumpFlags options = CompilandDumper::Flags::None;
743 if (opts::Lines)
744 options = options | CompilandDumper::Flags::Lines;
Zachary Turner9a818ad2015-02-22 22:03:38 +0000745 while (auto Compiland = Compilands->getNext())
Zachary Turnera99000d2016-03-08 21:42:24 +0000746 Dumper.start(*Compiland, options);
Zachary Turner2d11c202015-02-27 09:15:59 +0000747 Printer.Unindent();
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000748 }
749
750 if (opts::Types) {
Zachary Turner2d11c202015-02-27 09:15:59 +0000751 Printer.NewLine();
752 WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---TYPES---";
753 Printer.Indent();
Zachary Turner65323652015-03-04 06:09:53 +0000754 TypeDumper Dumper(Printer);
Zachary Turnerb52d08d2015-03-01 06:51:29 +0000755 Dumper.start(*GlobalScope);
Zachary Turner2d11c202015-02-27 09:15:59 +0000756 Printer.Unindent();
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000757 }
758
759 if (opts::Symbols) {
Zachary Turner2d11c202015-02-27 09:15:59 +0000760 Printer.NewLine();
761 WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---SYMBOLS---";
762 Printer.Indent();
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000763 auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>();
Zachary Turner2d11c202015-02-27 09:15:59 +0000764 CompilandDumper Dumper(Printer);
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000765 while (auto Compiland = Compilands->getNext())
Zachary Turnerb52d08d2015-03-01 06:51:29 +0000766 Dumper.start(*Compiland, true);
Zachary Turner2d11c202015-02-27 09:15:59 +0000767 Printer.Unindent();
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000768 }
769
770 if (opts::Globals) {
Zachary Turner2d11c202015-02-27 09:15:59 +0000771 Printer.NewLine();
772 WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---GLOBALS---";
773 Printer.Indent();
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000774 {
Zachary Turner2d11c202015-02-27 09:15:59 +0000775 FunctionDumper Dumper(Printer);
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000776 auto Functions = GlobalScope->findAllChildren<PDBSymbolFunc>();
Zachary Turner2d11c202015-02-27 09:15:59 +0000777 while (auto Function = Functions->getNext()) {
778 Printer.NewLine();
Zachary Turnerb52d08d2015-03-01 06:51:29 +0000779 Dumper.start(*Function, FunctionDumper::PointerType::None);
Zachary Turner2d11c202015-02-27 09:15:59 +0000780 }
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000781 }
782 {
783 auto Vars = GlobalScope->findAllChildren<PDBSymbolData>();
Zachary Turner2d11c202015-02-27 09:15:59 +0000784 VariableDumper Dumper(Printer);
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000785 while (auto Var = Vars->getNext())
Zachary Turnerb52d08d2015-03-01 06:51:29 +0000786 Dumper.start(*Var);
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000787 }
788 {
789 auto Thunks = GlobalScope->findAllChildren<PDBSymbolThunk>();
Zachary Turner2d11c202015-02-27 09:15:59 +0000790 CompilandDumper Dumper(Printer);
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000791 while (auto Thunk = Thunks->getNext())
Zachary Turnerb52d08d2015-03-01 06:51:29 +0000792 Dumper.dump(*Thunk);
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000793 }
Zachary Turner2d11c202015-02-27 09:15:59 +0000794 Printer.Unindent();
Zachary Turner7058dfc2015-01-27 22:40:14 +0000795 }
Zachary Turnere5cb2692015-05-01 20:24:26 +0000796 if (opts::Externals) {
797 Printer.NewLine();
798 WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---EXTERNALS---";
799 Printer.Indent();
800 ExternalSymbolDumper Dumper(Printer);
801 Dumper.start(*GlobalScope);
802 }
Zachary Turnera99000d2016-03-08 21:42:24 +0000803 if (opts::Lines) {
804 Printer.NewLine();
805 }
Zachary Turnera5549172015-02-10 22:43:25 +0000806 outs().flush();
Zachary Turnerfcb14ad2015-01-27 20:46:21 +0000807}
808
809int main(int argc_, const char *argv_[]) {
810 // Print a stack trace if we signal out.
811 sys::PrintStackTraceOnErrorSignal();
812 PrettyStackTraceProgram X(argc_, argv_);
813
814 SmallVector<const char *, 256> argv;
David Majnemer6e081262015-10-15 01:27:19 +0000815 SpecificBumpPtrAllocator<char> ArgAllocator;
816 std::error_code EC = sys::Process::GetArgumentVector(
817 argv, makeArrayRef(argv_, argc_), ArgAllocator);
Zachary Turnerfcb14ad2015-01-27 20:46:21 +0000818 if (EC) {
David Majnemer6e081262015-10-15 01:27:19 +0000819 errs() << "error: couldn't get arguments: " << EC.message() << '\n';
Zachary Turnerfcb14ad2015-01-27 20:46:21 +0000820 return 1;
821 }
822
823 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
824
825 cl::ParseCommandLineOptions(argv.size(), argv.data(), "LLVM PDB Dumper\n");
Zachary Turnera99000d2016-03-08 21:42:24 +0000826 if (opts::Lines)
827 opts::Compilands = true;
828
Zachary Turner7797c722015-03-02 04:39:56 +0000829 if (opts::All) {
830 opts::Compilands = true;
831 opts::Symbols = true;
832 opts::Globals = true;
833 opts::Types = true;
Zachary Turnere5cb2692015-05-01 20:24:26 +0000834 opts::Externals = true;
Zachary Turnera99000d2016-03-08 21:42:24 +0000835 opts::Lines = true;
Zachary Turner7797c722015-03-02 04:39:56 +0000836 }
Zachary Turnera99000d2016-03-08 21:42:24 +0000837
Rui Ueyama9dc034d2016-05-26 23:26:55 +0000838 if (opts::RawAll) {
839 opts::DumpHeaders = true;
840 opts::DumpModules = true;
841 opts::DumpModuleFiles = true;
842 opts::DumpModuleSyms = true;
843 opts::DumpPublics = true;
844 opts::DumpStreamSummary = true;
845 opts::DumpStreamBlocks = true;
846 opts::DumpTpiRecords = true;
847 opts::DumpIpiRecords = true;
848 }
849
Zachary Turnera99000d2016-03-08 21:42:24 +0000850 // When adding filters for excluded compilands and types, we need to remember
851 // that these are regexes. So special characters such as * and \ need to be
852 // escaped in the regex. In the case of a literal \, this means it needs to
853 // be escaped again in the C++. So matching a single \ in the input requires
854 // 4 \es in the C++.
Zachary Turner7797c722015-03-02 04:39:56 +0000855 if (opts::ExcludeCompilerGenerated) {
856 opts::ExcludeTypes.push_back("__vc_attributes");
Zachary Turnera99000d2016-03-08 21:42:24 +0000857 opts::ExcludeCompilands.push_back("\\* Linker \\*");
Zachary Turner7797c722015-03-02 04:39:56 +0000858 }
859 if (opts::ExcludeSystemLibraries) {
860 opts::ExcludeCompilands.push_back(
Zachary Turnera99000d2016-03-08 21:42:24 +0000861 "f:\\\\binaries\\\\Intermediate\\\\vctools\\\\crt_bld");
862 opts::ExcludeCompilands.push_back("f:\\\\dd\\\\vctools\\\\crt");
863 opts::ExcludeCompilands.push_back("d:\\\\th.obj.x86fre\\\\minkernel");
Zachary Turner7797c722015-03-02 04:39:56 +0000864 }
Zachary Turnerfcb14ad2015-01-27 20:46:21 +0000865
Zachary Turner8d7fa9b2015-02-10 22:47:14 +0000866#if defined(HAVE_DIA_SDK)
Zachary Turnerfcb14ad2015-01-27 20:46:21 +0000867 CoInitializeEx(nullptr, COINIT_MULTITHREADED);
Zachary Turner8d7fa9b2015-02-10 22:47:14 +0000868#endif
Zachary Turnerfcb14ad2015-01-27 20:46:21 +0000869
870 std::for_each(opts::InputFilenames.begin(), opts::InputFilenames.end(),
871 dumpInput);
872
Zachary Turner8d7fa9b2015-02-10 22:47:14 +0000873#if defined(HAVE_DIA_SDK)
Zachary Turnerfcb14ad2015-01-27 20:46:21 +0000874 CoUninitialize();
Zachary Turner8d7fa9b2015-02-10 22:47:14 +0000875#endif
Zachary Turner819e77d2016-05-06 20:51:57 +0000876 outs().flush();
Zachary Turnerfcb14ad2015-01-27 20:46:21 +0000877 return 0;
878}