blob: d8dcd3d407674a16fbe72706f0c2c58630d7cb2f [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 Turnercac29ae2016-05-24 17:30:25 +000029#include "llvm/DebugInfo/CodeView/SymbolDumper.h"
Zachary Turner5a1b5ef2016-05-06 22:15:42 +000030#include "llvm/DebugInfo/CodeView/TypeDumper.h"
Zachary Turner819e77d2016-05-06 20:51:57 +000031#include "llvm/DebugInfo/PDB/GenericError.h"
Zachary Turnera5549172015-02-10 22:43:25 +000032#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
Zachary Turnera5549172015-02-10 22:43:25 +000033#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"
Chandler Carruth71f308a2015-02-13 09:09:03 +000034#include "llvm/DebugInfo/PDB/IPDBSession.h"
35#include "llvm/DebugInfo/PDB/PDB.h"
Zachary Turnera5549172015-02-10 22:43:25 +000036#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
Zachary Turnerdb18f5c2015-02-27 09:15:18 +000037#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
Chandler Carruth71f308a2015-02-13 09:09:03 +000038#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
Zachary Turnerdb18f5c2015-02-27 09:15:18 +000039#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
40#include "llvm/DebugInfo/PDB/PDBSymbolThunk.h"
Zachary Turner2f09b502016-04-29 17:28:47 +000041#include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
42#include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
Zachary Turner6ba65de2016-04-29 17:22:58 +000043#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
Zachary Turner1822af542016-04-27 23:41:42 +000044#include "llvm/DebugInfo/PDB/Raw/ModInfo.h"
Zachary Turner06c2b4b2016-05-09 17:45:21 +000045#include "llvm/DebugInfo/PDB/Raw/ModStream.h"
Zachary Turner0eace0b2016-05-02 18:09:14 +000046#include "llvm/DebugInfo/PDB/Raw/NameHashTable.h"
Zachary Turner0a43efe2016-04-25 17:38:08 +000047#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
Rui Ueyama1f6b6e22016-05-13 21:21:53 +000048#include "llvm/DebugInfo/PDB/Raw/PublicsStream.h"
Reid Klecknerce5196e2016-05-12 23:26:23 +000049#include "llvm/DebugInfo/PDB/Raw/RawError.h"
Zachary Turner0a43efe2016-04-25 17:38:08 +000050#include "llvm/DebugInfo/PDB/Raw/RawSession.h"
Zachary Turner6ba65de2016-04-29 17:22:58 +000051#include "llvm/DebugInfo/PDB/Raw/StreamReader.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");
Zachary Turner06c2b4b2016-05-09 17:45:21 +000086cl::OptionCategory NativeOtions("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
David Majnemer6e081262015-10-15 01:27:19 +0000107cl::opt<bool> DumpHeaders("dump-headers", cl::desc("dump PDB headers"),
Zachary Turner06c2b4b2016-05-09 17:45:21 +0000108 cl::cat(NativeOtions));
David Majnemer6e081262015-10-15 01:27:19 +0000109cl::opt<bool> DumpStreamSizes("dump-stream-sizes",
110 cl::desc("dump PDB stream sizes"),
Zachary Turner06c2b4b2016-05-09 17:45:21 +0000111 cl::cat(NativeOtions));
David Majnemer6e081262015-10-15 01:27:19 +0000112cl::opt<bool> DumpStreamBlocks("dump-stream-blocks",
113 cl::desc("dump PDB stream blocks"),
Zachary Turner06c2b4b2016-05-09 17:45:21 +0000114 cl::cat(NativeOtions));
Zachary Turner5a1b5ef2016-05-06 22:15:42 +0000115cl::opt<bool> DumpTpiRecords("dump-tpi-records",
116 cl::desc("dump CodeView type records"),
Zachary Turner06c2b4b2016-05-09 17:45:21 +0000117 cl::cat(NativeOtions));
Reid Klecknerb0345262016-05-04 16:09:04 +0000118cl::opt<bool>
119 DumpTpiRecordBytes("dump-tpi-record-bytes",
120 cl::desc("dump CodeView type record raw bytes"),
Zachary Turner06c2b4b2016-05-09 17:45:21 +0000121 cl::cat(NativeOtions));
David Majnemer6e081262015-10-15 01:27:19 +0000122cl::opt<std::string> DumpStreamData("dump-stream", cl::desc("dump stream data"),
Zachary Turner06c2b4b2016-05-09 17:45:21 +0000123 cl::cat(NativeOtions));
124cl::opt<bool> DumpModuleSyms("dump-module-syms",
125 cl::desc("dump module symbols"),
126 cl::cat(NativeOtions));
Rui Ueyama1f6b6e22016-05-13 21:21:53 +0000127cl::opt<bool> DumpPublics("dump-publics",
128 cl::desc("dump Publics stream data"),
129 cl::cat(NativeOtions));
Zachary Turnercac29ae2016-05-24 17:30:25 +0000130cl::opt<bool>
131 DumpSymRecordBytes("dump-sym-record-bytes",
132 cl::desc("dump CodeView symbol record raw bytes"),
133 cl::cat(NativeOtions));
David Majnemer6e081262015-10-15 01:27:19 +0000134
Zachary Turnerf5abda22015-03-01 06:49:49 +0000135cl::list<std::string>
136 ExcludeTypes("exclude-types",
137 cl::desc("Exclude types by regular expression"),
Zachary Turner7797c722015-03-02 04:39:56 +0000138 cl::ZeroOrMore, cl::cat(FilterCategory));
Zachary Turnerf5abda22015-03-01 06:49:49 +0000139cl::list<std::string>
140 ExcludeSymbols("exclude-symbols",
141 cl::desc("Exclude symbols by regular expression"),
Zachary Turner7797c722015-03-02 04:39:56 +0000142 cl::ZeroOrMore, cl::cat(FilterCategory));
Zachary Turnerf5abda22015-03-01 06:49:49 +0000143cl::list<std::string>
144 ExcludeCompilands("exclude-compilands",
145 cl::desc("Exclude compilands by regular expression"),
Zachary Turner7797c722015-03-02 04:39:56 +0000146 cl::ZeroOrMore, cl::cat(FilterCategory));
Zachary Turner4dddcc62015-09-29 19:49:06 +0000147
148cl::list<std::string> IncludeTypes(
149 "include-types",
150 cl::desc("Include only types which match a regular expression"),
151 cl::ZeroOrMore, cl::cat(FilterCategory));
152cl::list<std::string> IncludeSymbols(
153 "include-symbols",
154 cl::desc("Include only symbols which match a regular expression"),
155 cl::ZeroOrMore, cl::cat(FilterCategory));
156cl::list<std::string> IncludeCompilands(
157 "include-compilands",
158 cl::desc("Include only compilands those which match a regular expression"),
159 cl::ZeroOrMore, cl::cat(FilterCategory));
160
Zachary Turner7797c722015-03-02 04:39:56 +0000161cl::opt<bool> ExcludeCompilerGenerated(
162 "no-compiler-generated",
163 cl::desc("Don't show compiler generated types and symbols"),
164 cl::cat(FilterCategory));
165cl::opt<bool>
166 ExcludeSystemLibraries("no-system-libs",
167 cl::desc("Don't show symbols from system libraries"),
168 cl::cat(FilterCategory));
Zachary Turner65323652015-03-04 06:09:53 +0000169cl::opt<bool> NoClassDefs("no-class-definitions",
170 cl::desc("Don't display full class definitions"),
171 cl::cat(FilterCategory));
172cl::opt<bool> NoEnumDefs("no-enum-definitions",
173 cl::desc("Don't display full enum definitions"),
174 cl::cat(FilterCategory));
Zachary Turner49693b42015-01-28 01:22:33 +0000175}
176
Zachary Turner819e77d2016-05-06 20:51:57 +0000177static Error dumpFileHeaders(ScopedPrinter &P, PDBFile &File) {
Reid Klecknerb0345262016-05-04 16:09:04 +0000178 if (!opts::DumpHeaders)
Zachary Turner819e77d2016-05-06 20:51:57 +0000179 return Error::success();
180
Reid Klecknerb0345262016-05-04 16:09:04 +0000181 DictScope D(P, "FileHeaders");
182 P.printNumber("BlockSize", File.getBlockSize());
183 P.printNumber("Unknown0", File.getUnknown0());
184 P.printNumber("NumBlocks", File.getBlockCount());
185 P.printNumber("NumDirectoryBytes", File.getNumDirectoryBytes());
186 P.printNumber("Unknown1", File.getUnknown1());
187 P.printNumber("BlockMapAddr", File.getBlockMapIndex());
188 P.printNumber("NumDirectoryBlocks", File.getNumDirectoryBlocks());
189 P.printNumber("BlockMapOffset", File.getBlockMapOffset());
Zachary Turnercdd313c2016-05-04 15:05:12 +0000190
Chad Rosier20dbbf32016-05-04 15:25:06 +0000191 // The directory is not contiguous. Instead, the block map contains a
192 // contiguous list of block numbers whose contents, when concatenated in
193 // order, make up the directory.
Reid Klecknerb0345262016-05-04 16:09:04 +0000194 P.printList("DirectoryBlocks", File.getDirectoryBlockArray());
195 P.printNumber("NumStreams", File.getNumStreams());
Zachary Turner819e77d2016-05-06 20:51:57 +0000196 return Error::success();
Reid Klecknerb0345262016-05-04 16:09:04 +0000197}
Zachary Turnercdd313c2016-05-04 15:05:12 +0000198
Zachary Turner819e77d2016-05-06 20:51:57 +0000199static Error dumpStreamSizes(ScopedPrinter &P, PDBFile &File) {
Reid Klecknerb0345262016-05-04 16:09:04 +0000200 if (!opts::DumpStreamSizes)
Zachary Turner819e77d2016-05-06 20:51:57 +0000201 return Error::success();
Zachary Turnercdd313c2016-05-04 15:05:12 +0000202
Reid Klecknerb0345262016-05-04 16:09:04 +0000203 ListScope L(P, "StreamSizes");
Chad Rosier20dbbf32016-05-04 15:25:06 +0000204 uint32_t StreamCount = File.getNumStreams();
Reid Klecknerb0345262016-05-04 16:09:04 +0000205 for (uint32_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
206 std::string Name("Stream ");
207 Name += to_string(StreamIdx);
208 P.printNumber(Name, File.getStreamByteSize(StreamIdx));
Chad Rosier20dbbf32016-05-04 15:25:06 +0000209 }
Zachary Turner819e77d2016-05-06 20:51:57 +0000210 return Error::success();
Reid Klecknerb0345262016-05-04 16:09:04 +0000211}
Zachary Turnercdd313c2016-05-04 15:05:12 +0000212
Zachary Turner819e77d2016-05-06 20:51:57 +0000213static Error dumpStreamBlocks(ScopedPrinter &P, PDBFile &File) {
Reid Klecknerb0345262016-05-04 16:09:04 +0000214 if (!opts::DumpStreamBlocks)
Zachary Turner819e77d2016-05-06 20:51:57 +0000215 return Error::success();
Reid Klecknerb0345262016-05-04 16:09:04 +0000216
217 ListScope L(P, "StreamBlocks");
218 uint32_t StreamCount = File.getNumStreams();
219 for (uint32_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
220 std::string Name("Stream ");
221 Name += to_string(StreamIdx);
222 auto StreamBlocks = File.getStreamBlockList(StreamIdx);
223 P.printList(Name, StreamBlocks);
Chad Rosier20dbbf32016-05-04 15:25:06 +0000224 }
Zachary Turner819e77d2016-05-06 20:51:57 +0000225 return Error::success();
Reid Klecknerb0345262016-05-04 16:09:04 +0000226}
Zachary Turnercdd313c2016-05-04 15:05:12 +0000227
Zachary Turner819e77d2016-05-06 20:51:57 +0000228static Error dumpStreamData(ScopedPrinter &P, PDBFile &File) {
Reid Klecknerb0345262016-05-04 16:09:04 +0000229 uint32_t StreamCount = File.getNumStreams();
Chad Rosier20dbbf32016-05-04 15:25:06 +0000230 StringRef DumpStreamStr = opts::DumpStreamData;
231 uint32_t DumpStreamNum;
Reid Klecknerb0345262016-05-04 16:09:04 +0000232 if (DumpStreamStr.getAsInteger(/*Radix=*/0U, DumpStreamNum) ||
233 DumpStreamNum >= StreamCount)
Zachary Turner819e77d2016-05-06 20:51:57 +0000234 return Error::success();
Chad Rosier20dbbf32016-05-04 15:25:06 +0000235
Reid Klecknerb0345262016-05-04 16:09:04 +0000236 uint32_t StreamBytesRead = 0;
237 uint32_t StreamSize = File.getStreamByteSize(DumpStreamNum);
238 auto StreamBlocks = File.getStreamBlockList(DumpStreamNum);
Chad Rosier20dbbf32016-05-04 15:25:06 +0000239
Reid Klecknerb0345262016-05-04 16:09:04 +0000240 for (uint32_t StreamBlockAddr : StreamBlocks) {
241 uint32_t BytesLeftToReadInStream = StreamSize - StreamBytesRead;
242 if (BytesLeftToReadInStream == 0)
243 break;
Chad Rosier20dbbf32016-05-04 15:25:06 +0000244
Reid Klecknerb0345262016-05-04 16:09:04 +0000245 uint32_t BytesToReadInBlock = std::min(
246 BytesLeftToReadInStream, static_cast<uint32_t>(File.getBlockSize()));
247 auto StreamBlockData =
248 File.getBlockData(StreamBlockAddr, BytesToReadInBlock);
249
250 outs() << StreamBlockData;
251 StreamBytesRead += StreamBlockData.size();
Chad Rosier20dbbf32016-05-04 15:25:06 +0000252 }
Zachary Turner819e77d2016-05-06 20:51:57 +0000253 return Error::success();
Reid Klecknerb0345262016-05-04 16:09:04 +0000254}
Chad Rosier20dbbf32016-05-04 15:25:06 +0000255
Zachary Turner819e77d2016-05-06 20:51:57 +0000256static Error dumpInfoStream(ScopedPrinter &P, PDBFile &File) {
257 auto InfoS = File.getPDBInfoStream();
258 if (auto EC = InfoS.takeError())
259 return EC;
260
261 InfoStream &IS = InfoS.get();
Chad Rosier20dbbf32016-05-04 15:25:06 +0000262
Reid Klecknerb0345262016-05-04 16:09:04 +0000263 DictScope D(P, "PDB Stream");
264 P.printNumber("Version", IS.getVersion());
265 P.printHex("Signature", IS.getSignature());
266 P.printNumber("Age", IS.getAge());
267 P.printObject("Guid", IS.getGuid());
Zachary Turner819e77d2016-05-06 20:51:57 +0000268 return Error::success();
Reid Klecknerb0345262016-05-04 16:09:04 +0000269}
270
Zachary Turner819e77d2016-05-06 20:51:57 +0000271static Error dumpNamedStream(ScopedPrinter &P, PDBFile &File,
272 StringRef Stream) {
273 auto InfoS = File.getPDBInfoStream();
274 if (auto EC = InfoS.takeError())
275 return EC;
276 InfoStream &IS = InfoS.get();
277
Reid Klecknerb0345262016-05-04 16:09:04 +0000278 uint32_t NameStreamIndex = IS.getNamedStreamIndex(Stream);
279
Chad Rosier20dbbf32016-05-04 15:25:06 +0000280 if (NameStreamIndex != 0) {
Reid Klecknerb0345262016-05-04 16:09:04 +0000281 std::string Name("Stream '");
282 Name += Stream;
283 Name += "'";
284 DictScope D(P, Name);
285 P.printNumber("Index", NameStreamIndex);
286
Chad Rosier20dbbf32016-05-04 15:25:06 +0000287 MappedBlockStream NameStream(NameStreamIndex, File);
288 StreamReader Reader(NameStream);
289
Chad Rosier20dbbf32016-05-04 15:25:06 +0000290 NameHashTable NameTable;
Zachary Turner819e77d2016-05-06 20:51:57 +0000291 if (auto EC = NameTable.load(Reader))
292 return EC;
293
Reid Klecknerb0345262016-05-04 16:09:04 +0000294 P.printHex("Signature", NameTable.getSignature());
295 P.printNumber("Version", NameTable.getHashVersion());
296 P.printNumber("Name Count", NameTable.getNameCount());
297 ListScope L(P, "Names");
Chad Rosier20dbbf32016-05-04 15:25:06 +0000298 for (uint32_t ID : NameTable.name_ids()) {
Reid Klecknerb0345262016-05-04 16:09:04 +0000299 StringRef Str = NameTable.getStringForID(ID);
300 if (!Str.empty())
301 P.printString(Str);
Chad Rosier20dbbf32016-05-04 15:25:06 +0000302 }
303 }
Zachary Turner819e77d2016-05-06 20:51:57 +0000304 return Error::success();
Reid Klecknerb0345262016-05-04 16:09:04 +0000305}
Chad Rosier20dbbf32016-05-04 15:25:06 +0000306
Zachary Turnercac29ae2016-05-24 17:30:25 +0000307static Error dumpDbiStream(ScopedPrinter &P, PDBFile &File,
308 codeview::CVTypeDumper &TD) {
Zachary Turner819e77d2016-05-06 20:51:57 +0000309 auto DbiS = File.getPDBDbiStream();
310 if (auto EC = DbiS.takeError())
311 return EC;
312 DbiStream &DS = DbiS.get();
Reid Klecknerb0345262016-05-04 16:09:04 +0000313
314 DictScope D(P, "DBI Stream");
315 P.printNumber("Dbi Version", DS.getDbiVersion());
316 P.printNumber("Age", DS.getAge());
317 P.printBoolean("Incremental Linking", DS.isIncrementallyLinked());
318 P.printBoolean("Has CTypes", DS.hasCTypes());
319 P.printBoolean("Is Stripped", DS.isStripped());
320 P.printObject("Machine Type", DS.getMachineType());
Rui Ueyama0376b1a2016-05-19 18:05:58 +0000321 P.printNumber("Symbol Record Stream Index", DS.getSymRecordStreamIndex());
Chad Rosier20dbbf32016-05-04 15:25:06 +0000322
323 uint16_t Major = DS.getBuildMajorVersion();
324 uint16_t Minor = DS.getBuildMinorVersion();
Reid Klecknerb0345262016-05-04 16:09:04 +0000325 P.printVersion("Toolchain Version", Major, Minor);
Chad Rosier20dbbf32016-05-04 15:25:06 +0000326
Reid Klecknerb0345262016-05-04 16:09:04 +0000327 std::string DllName;
328 raw_string_ostream DllStream(DllName);
329 DllStream << "mspdb" << Major << Minor << ".dll version";
330 DllStream.flush();
331 P.printVersion(DllName, Major, Minor, DS.getPdbDllVersion());
332
333 ListScope L(P, "Modules");
Chad Rosier20dbbf32016-05-04 15:25:06 +0000334 for (auto &Modi : DS.modules()) {
Reid Klecknerb0345262016-05-04 16:09:04 +0000335 DictScope DD(P);
336 P.printString("Name", Modi.Info.getModuleName());
337 P.printNumber("Debug Stream Index", Modi.Info.getModuleStreamIndex());
338 P.printString("Object File Name", Modi.Info.getObjFileName());
339 P.printNumber("Num Files", Modi.Info.getNumberOfFiles());
340 P.printNumber("Source File Name Idx", Modi.Info.getSourceFileNameIndex());
341 P.printNumber("Pdb File Name Idx", Modi.Info.getPdbFilePathNameIndex());
342 P.printNumber("Line Info Byte Size", Modi.Info.getLineInfoByteSize());
343 P.printNumber("C13 Line Info Byte Size",
344 Modi.Info.getC13LineInfoByteSize());
345 P.printNumber("Symbol Byte Size", Modi.Info.getSymbolDebugInfoByteSize());
346 P.printNumber("Type Server Index", Modi.Info.getTypeServerIndex());
347 P.printBoolean("Has EC Info", Modi.Info.hasECInfo());
Zachary Turner06c2b4b2016-05-09 17:45:21 +0000348 {
349 std::string FileListName =
350 to_string(Modi.SourceFiles.size()) + " Contributing Source Files";
351 ListScope LL(P, FileListName);
352 for (auto File : Modi.SourceFiles)
353 P.printString(File);
354 }
Zachary Turnercac29ae2016-05-24 17:30:25 +0000355 if (opts::DumpModuleSyms || opts::DumpSymRecordBytes) {
Zachary Turner06c2b4b2016-05-09 17:45:21 +0000356 ListScope SS(P, "Symbols");
357 ModStream ModS(File, Modi.Info);
358 if (auto EC = ModS.reload())
359 return EC;
360
Zachary Turnercac29ae2016-05-24 17:30:25 +0000361 codeview::CVSymbolDumper SD(P, TD, nullptr, false);
Zachary Turner06c2b4b2016-05-09 17:45:21 +0000362 for (auto &S : ModS.symbols()) {
Zachary Turnercac29ae2016-05-24 17:30:25 +0000363 DictScope DD(P, "");
364
365 if (opts::DumpModuleSyms)
366 SD.dump(S);
367 if (opts::DumpSymRecordBytes)
368 P.printBinaryBlock("Bytes", S.Data);
Zachary Turner06c2b4b2016-05-09 17:45:21 +0000369 }
370 }
Chad Rosier20dbbf32016-05-04 15:25:06 +0000371 }
Zachary Turner819e77d2016-05-06 20:51:57 +0000372 return Error::success();
Reid Klecknerb0345262016-05-04 16:09:04 +0000373}
374
Zachary Turnercac29ae2016-05-24 17:30:25 +0000375static Error dumpTpiStream(ScopedPrinter &P, PDBFile &File,
376 codeview::CVTypeDumper &TD) {
Reid Klecknerb0345262016-05-04 16:09:04 +0000377
Zachary Turner5a1b5ef2016-05-06 22:15:42 +0000378 if (opts::DumpTpiRecordBytes || opts::DumpTpiRecords) {
Zachary Turnercac29ae2016-05-24 17:30:25 +0000379 DictScope D(P, "Type Info Stream");
380
381 auto TpiS = File.getPDBTpiStream();
382 if (auto EC = TpiS.takeError())
383 return EC;
384 TpiStream &Tpi = TpiS.get();
385
386 P.printNumber("TPI Version", Tpi.getTpiVersion());
387 P.printNumber("Record count", Tpi.NumTypeRecords());
388
Zachary Turner5a1b5ef2016-05-06 22:15:42 +0000389 ListScope L(P, "Records");
Reid Klecknerb0345262016-05-04 16:09:04 +0000390
Reid Klecknerce5196e2016-05-12 23:26:23 +0000391 bool HadError = false;
392 for (auto &Type : Tpi.types(&HadError)) {
Zachary Turner5a1b5ef2016-05-06 22:15:42 +0000393 DictScope DD(P, "");
394
395 if (opts::DumpTpiRecords)
396 TD.dump(Type);
397
398 if (opts::DumpTpiRecordBytes)
Zachary Turner9073ed62016-05-09 17:44:58 +0000399 P.printBinaryBlock("Bytes", Type.Data);
Zachary Turner5a1b5ef2016-05-06 22:15:42 +0000400 }
Reid Klecknerce5196e2016-05-12 23:26:23 +0000401 if (HadError)
402 return make_error<RawError>(raw_error_code::corrupt_file,
403 "TPI stream contained corrupt record");
Zachary Turnercac29ae2016-05-24 17:30:25 +0000404 } else if (opts::DumpModuleSyms) {
405 // Even if the user doesn't want to dump type records, we still need to
406 // iterate them in order to build the list of types so that we can print
407 // them when dumping module symbols. So when they want to dump symbols
408 // but not types, use a null output stream.
409 ScopedPrinter *OldP = TD.getPrinter();
410 TD.setPrinter(nullptr);
411 auto TpiS = File.getPDBTpiStream();
412 if (auto EC = TpiS.takeError())
413 return EC;
414 TpiStream &Tpi = TpiS.get();
415 bool HadError = false;
416 for (auto &Type : Tpi.types(&HadError))
417 TD.dump(Type);
418
419 TD.setPrinter(OldP);
420 if (HadError)
421 return make_error<RawError>(raw_error_code::corrupt_file,
422 "TPI stream contained corrupt record");
Chad Rosier20dbbf32016-05-04 15:25:06 +0000423 }
Zachary Turnercac29ae2016-05-24 17:30:25 +0000424
Zachary Turner819e77d2016-05-06 20:51:57 +0000425 return Error::success();
Zachary Turnercdd313c2016-05-04 15:05:12 +0000426}
427
Zachary Turner9e33e6f2016-05-24 18:55:14 +0000428static Error dumpPublicsStream(ScopedPrinter &P, PDBFile &File,
429 codeview::CVTypeDumper &TD) {
Rui Ueyama1f6b6e22016-05-13 21:21:53 +0000430 if (!opts::DumpPublics)
431 return Error::success();
432
433 DictScope D(P, "Publics Stream");
434 auto PublicsS = File.getPDBPublicsStream();
435 if (auto EC = PublicsS.takeError())
436 return EC;
437 PublicsStream &Publics = PublicsS.get();
438 P.printNumber("Stream number", Publics.getStreamNum());
439 P.printNumber("SymHash", Publics.getSymHash());
440 P.printNumber("AddrMap", Publics.getAddrMap());
441 P.printNumber("Number of buckets", Publics.getNumBuckets());
Rui Ueyama8dc18c52016-05-17 23:07:48 +0000442 P.printList("Hash Buckets", Publics.getHashBuckets());
443 P.printList("Address Map", Publics.getAddressMap());
444 P.printList("Thunk Map", Publics.getThunkMap());
Rui Ueyama350b2982016-05-18 16:24:16 +0000445 P.printList("Section Offsets", Publics.getSectionOffsets());
Zachary Turner9e33e6f2016-05-24 18:55:14 +0000446 ListScope L(P, "Symbols");
447 codeview::CVSymbolDumper SD(P, TD, nullptr, false);
448 for (auto S : Publics.getSymbols()) {
449 DictScope DD(P, "");
450
451 SD.dump(S);
452 if (opts::DumpSymRecordBytes)
453 P.printBinaryBlock("Bytes", S.Data);
454 }
Rui Ueyama1f6b6e22016-05-13 21:21:53 +0000455 return Error::success();
456}
457
Zachary Turner819e77d2016-05-06 20:51:57 +0000458static Error dumpStructure(RawSession &RS) {
Reid Klecknerb0345262016-05-04 16:09:04 +0000459 PDBFile &File = RS.getPDBFile();
460 ScopedPrinter P(outs());
461
Zachary Turner819e77d2016-05-06 20:51:57 +0000462 if (auto EC = dumpFileHeaders(P, File))
463 return EC;
Reid Klecknerb0345262016-05-04 16:09:04 +0000464
Zachary Turner819e77d2016-05-06 20:51:57 +0000465 if (auto EC = dumpStreamSizes(P, File))
466 return EC;
Reid Klecknerb0345262016-05-04 16:09:04 +0000467
Zachary Turner819e77d2016-05-06 20:51:57 +0000468 if (auto EC = dumpStreamBlocks(P, File))
469 return EC;
Reid Klecknerb0345262016-05-04 16:09:04 +0000470
Zachary Turner819e77d2016-05-06 20:51:57 +0000471 if (auto EC = dumpStreamData(P, File))
472 return EC;
Reid Klecknerb0345262016-05-04 16:09:04 +0000473
Zachary Turner819e77d2016-05-06 20:51:57 +0000474 if (auto EC = dumpInfoStream(P, File))
475 return EC;
Reid Klecknerb0345262016-05-04 16:09:04 +0000476
Zachary Turner819e77d2016-05-06 20:51:57 +0000477 if (auto EC = dumpNamedStream(P, File, "/names"))
478 return EC;
Reid Klecknerb0345262016-05-04 16:09:04 +0000479
Zachary Turnercac29ae2016-05-24 17:30:25 +0000480 codeview::CVTypeDumper TD(P, false);
481 if (auto EC = dumpTpiStream(P, File, TD))
Zachary Turner819e77d2016-05-06 20:51:57 +0000482 return EC;
Reid Klecknerb0345262016-05-04 16:09:04 +0000483
Zachary Turnercac29ae2016-05-24 17:30:25 +0000484 if (auto EC = dumpDbiStream(P, File, TD))
Zachary Turner819e77d2016-05-06 20:51:57 +0000485 return EC;
Rui Ueyama1f6b6e22016-05-13 21:21:53 +0000486
Zachary Turner9e33e6f2016-05-24 18:55:14 +0000487 if (auto EC = dumpPublicsStream(P, File, TD))
Rui Ueyama1f6b6e22016-05-13 21:21:53 +0000488 return EC;
489return Error::success();
David Majnemer1573b242016-04-28 23:47:27 +0000490}
491
492static void dumpInput(StringRef Path) {
493 std::unique_ptr<IPDBSession> Session;
494 if (opts::DumpHeaders || !opts::DumpStreamData.empty()) {
Zachary Turner819e77d2016-05-06 20:51:57 +0000495 auto E = loadDataForPDB(PDB_ReaderType::Raw, Path, Session);
496 if (!E) {
David Majnemer1573b242016-04-28 23:47:27 +0000497 RawSession *RS = static_cast<RawSession *>(Session.get());
Zachary Turner819e77d2016-05-06 20:51:57 +0000498 E = dumpStructure(*RS);
David Majnemer1573b242016-04-28 23:47:27 +0000499 }
500
Zachary Turner819e77d2016-05-06 20:51:57 +0000501 if (E)
502 logAllUnhandledErrors(std::move(E), outs(), "");
503
David Majnemer1573b242016-04-28 23:47:27 +0000504 return;
505 }
506
Zachary Turner819e77d2016-05-06 20:51:57 +0000507 Error E = loadDataForPDB(PDB_ReaderType::DIA, Path, Session);
508 if (E) {
509 logAllUnhandledErrors(std::move(E), outs(), "");
David Majnemer1573b242016-04-28 23:47:27 +0000510 return;
511 }
512
Zachary Turnere5cb2692015-05-01 20:24:26 +0000513 if (opts::LoadAddress)
514 Session->setLoadAddress(opts::LoadAddress);
Zachary Turner7058dfc2015-01-27 22:40:14 +0000515
Zachary Turner2d11c202015-02-27 09:15:59 +0000516 LinePrinter Printer(2, outs());
517
Zachary Turnera5549172015-02-10 22:43:25 +0000518 auto GlobalScope(Session->getGlobalScope());
Zachary Turner9a818ad2015-02-22 22:03:38 +0000519 std::string FileName(GlobalScope->getSymbolsFileName());
520
Zachary Turner2d11c202015-02-27 09:15:59 +0000521 WithColor(Printer, PDB_ColorItem::None).get() << "Summary for ";
522 WithColor(Printer, PDB_ColorItem::Path).get() << FileName;
523 Printer.Indent();
Zachary Turner9a818ad2015-02-22 22:03:38 +0000524 uint64_t FileSize = 0;
Zachary Turner9a818ad2015-02-22 22:03:38 +0000525
Zachary Turner2d11c202015-02-27 09:15:59 +0000526 Printer.NewLine();
527 WithColor(Printer, PDB_ColorItem::Identifier).get() << "Size";
David Majnemer6e081262015-10-15 01:27:19 +0000528 if (!sys::fs::file_size(FileName, FileSize)) {
Zachary Turner2d11c202015-02-27 09:15:59 +0000529 Printer << ": " << FileSize << " bytes";
530 } else {
531 Printer << ": (Unable to obtain file size)";
532 }
533
534 Printer.NewLine();
535 WithColor(Printer, PDB_ColorItem::Identifier).get() << "Guid";
536 Printer << ": " << GlobalScope->getGuid();
537
538 Printer.NewLine();
539 WithColor(Printer, PDB_ColorItem::Identifier).get() << "Age";
540 Printer << ": " << GlobalScope->getAge();
541
542 Printer.NewLine();
543 WithColor(Printer, PDB_ColorItem::Identifier).get() << "Attributes";
544 Printer << ": ";
Zachary Turner9a818ad2015-02-22 22:03:38 +0000545 if (GlobalScope->hasCTypes())
546 outs() << "HasCTypes ";
547 if (GlobalScope->hasPrivateSymbols())
548 outs() << "HasPrivateSymbols ";
Zachary Turner2d11c202015-02-27 09:15:59 +0000549 Printer.Unindent();
Zachary Turner9a818ad2015-02-22 22:03:38 +0000550
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000551 if (opts::Compilands) {
Zachary Turner2d11c202015-02-27 09:15:59 +0000552 Printer.NewLine();
553 WithColor(Printer, PDB_ColorItem::SectionHeader).get()
554 << "---COMPILANDS---";
555 Printer.Indent();
Zachary Turnerc074de02015-02-12 21:09:24 +0000556 auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>();
Zachary Turner2d11c202015-02-27 09:15:59 +0000557 CompilandDumper Dumper(Printer);
Zachary Turnera99000d2016-03-08 21:42:24 +0000558 CompilandDumpFlags options = CompilandDumper::Flags::None;
559 if (opts::Lines)
560 options = options | CompilandDumper::Flags::Lines;
Zachary Turner9a818ad2015-02-22 22:03:38 +0000561 while (auto Compiland = Compilands->getNext())
Zachary Turnera99000d2016-03-08 21:42:24 +0000562 Dumper.start(*Compiland, options);
Zachary Turner2d11c202015-02-27 09:15:59 +0000563 Printer.Unindent();
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000564 }
565
566 if (opts::Types) {
Zachary Turner2d11c202015-02-27 09:15:59 +0000567 Printer.NewLine();
568 WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---TYPES---";
569 Printer.Indent();
Zachary Turner65323652015-03-04 06:09:53 +0000570 TypeDumper Dumper(Printer);
Zachary Turnerb52d08d2015-03-01 06:51:29 +0000571 Dumper.start(*GlobalScope);
Zachary Turner2d11c202015-02-27 09:15:59 +0000572 Printer.Unindent();
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000573 }
574
575 if (opts::Symbols) {
Zachary Turner2d11c202015-02-27 09:15:59 +0000576 Printer.NewLine();
577 WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---SYMBOLS---";
578 Printer.Indent();
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000579 auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>();
Zachary Turner2d11c202015-02-27 09:15:59 +0000580 CompilandDumper Dumper(Printer);
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000581 while (auto Compiland = Compilands->getNext())
Zachary Turnerb52d08d2015-03-01 06:51:29 +0000582 Dumper.start(*Compiland, true);
Zachary Turner2d11c202015-02-27 09:15:59 +0000583 Printer.Unindent();
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000584 }
585
586 if (opts::Globals) {
Zachary Turner2d11c202015-02-27 09:15:59 +0000587 Printer.NewLine();
588 WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---GLOBALS---";
589 Printer.Indent();
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000590 {
Zachary Turner2d11c202015-02-27 09:15:59 +0000591 FunctionDumper Dumper(Printer);
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000592 auto Functions = GlobalScope->findAllChildren<PDBSymbolFunc>();
Zachary Turner2d11c202015-02-27 09:15:59 +0000593 while (auto Function = Functions->getNext()) {
594 Printer.NewLine();
Zachary Turnerb52d08d2015-03-01 06:51:29 +0000595 Dumper.start(*Function, FunctionDumper::PointerType::None);
Zachary Turner2d11c202015-02-27 09:15:59 +0000596 }
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000597 }
598 {
599 auto Vars = GlobalScope->findAllChildren<PDBSymbolData>();
Zachary Turner2d11c202015-02-27 09:15:59 +0000600 VariableDumper Dumper(Printer);
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000601 while (auto Var = Vars->getNext())
Zachary Turnerb52d08d2015-03-01 06:51:29 +0000602 Dumper.start(*Var);
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000603 }
604 {
605 auto Thunks = GlobalScope->findAllChildren<PDBSymbolThunk>();
Zachary Turner2d11c202015-02-27 09:15:59 +0000606 CompilandDumper Dumper(Printer);
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000607 while (auto Thunk = Thunks->getNext())
Zachary Turnerb52d08d2015-03-01 06:51:29 +0000608 Dumper.dump(*Thunk);
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000609 }
Zachary Turner2d11c202015-02-27 09:15:59 +0000610 Printer.Unindent();
Zachary Turner7058dfc2015-01-27 22:40:14 +0000611 }
Zachary Turnere5cb2692015-05-01 20:24:26 +0000612 if (opts::Externals) {
613 Printer.NewLine();
614 WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---EXTERNALS---";
615 Printer.Indent();
616 ExternalSymbolDumper Dumper(Printer);
617 Dumper.start(*GlobalScope);
618 }
Zachary Turnera99000d2016-03-08 21:42:24 +0000619 if (opts::Lines) {
620 Printer.NewLine();
621 }
Zachary Turnera5549172015-02-10 22:43:25 +0000622 outs().flush();
Zachary Turnerfcb14ad2015-01-27 20:46:21 +0000623}
624
625int main(int argc_, const char *argv_[]) {
626 // Print a stack trace if we signal out.
627 sys::PrintStackTraceOnErrorSignal();
628 PrettyStackTraceProgram X(argc_, argv_);
629
630 SmallVector<const char *, 256> argv;
David Majnemer6e081262015-10-15 01:27:19 +0000631 SpecificBumpPtrAllocator<char> ArgAllocator;
632 std::error_code EC = sys::Process::GetArgumentVector(
633 argv, makeArrayRef(argv_, argc_), ArgAllocator);
Zachary Turnerfcb14ad2015-01-27 20:46:21 +0000634 if (EC) {
David Majnemer6e081262015-10-15 01:27:19 +0000635 errs() << "error: couldn't get arguments: " << EC.message() << '\n';
Zachary Turnerfcb14ad2015-01-27 20:46:21 +0000636 return 1;
637 }
638
639 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
640
641 cl::ParseCommandLineOptions(argv.size(), argv.data(), "LLVM PDB Dumper\n");
Zachary Turnera99000d2016-03-08 21:42:24 +0000642 if (opts::Lines)
643 opts::Compilands = true;
644
Zachary Turner7797c722015-03-02 04:39:56 +0000645 if (opts::All) {
646 opts::Compilands = true;
647 opts::Symbols = true;
648 opts::Globals = true;
649 opts::Types = true;
Zachary Turnere5cb2692015-05-01 20:24:26 +0000650 opts::Externals = true;
Zachary Turnera99000d2016-03-08 21:42:24 +0000651 opts::Lines = true;
Zachary Turner7797c722015-03-02 04:39:56 +0000652 }
Zachary Turnera99000d2016-03-08 21:42:24 +0000653
654 // When adding filters for excluded compilands and types, we need to remember
655 // that these are regexes. So special characters such as * and \ need to be
656 // escaped in the regex. In the case of a literal \, this means it needs to
657 // be escaped again in the C++. So matching a single \ in the input requires
658 // 4 \es in the C++.
Zachary Turner7797c722015-03-02 04:39:56 +0000659 if (opts::ExcludeCompilerGenerated) {
660 opts::ExcludeTypes.push_back("__vc_attributes");
Zachary Turnera99000d2016-03-08 21:42:24 +0000661 opts::ExcludeCompilands.push_back("\\* Linker \\*");
Zachary Turner7797c722015-03-02 04:39:56 +0000662 }
663 if (opts::ExcludeSystemLibraries) {
664 opts::ExcludeCompilands.push_back(
Zachary Turnera99000d2016-03-08 21:42:24 +0000665 "f:\\\\binaries\\\\Intermediate\\\\vctools\\\\crt_bld");
666 opts::ExcludeCompilands.push_back("f:\\\\dd\\\\vctools\\\\crt");
667 opts::ExcludeCompilands.push_back("d:\\\\th.obj.x86fre\\\\minkernel");
Zachary Turner7797c722015-03-02 04:39:56 +0000668 }
Zachary Turnerfcb14ad2015-01-27 20:46:21 +0000669
Zachary Turner8d7fa9b2015-02-10 22:47:14 +0000670#if defined(HAVE_DIA_SDK)
Zachary Turnerfcb14ad2015-01-27 20:46:21 +0000671 CoInitializeEx(nullptr, COINIT_MULTITHREADED);
Zachary Turner8d7fa9b2015-02-10 22:47:14 +0000672#endif
Zachary Turnerfcb14ad2015-01-27 20:46:21 +0000673
674 std::for_each(opts::InputFilenames.begin(), opts::InputFilenames.end(),
675 dumpInput);
676
Zachary Turner8d7fa9b2015-02-10 22:47:14 +0000677#if defined(HAVE_DIA_SDK)
Zachary Turnerfcb14ad2015-01-27 20:46:21 +0000678 CoUninitialize();
Zachary Turner8d7fa9b2015-02-10 22:47:14 +0000679#endif
Zachary Turner819e77d2016-05-06 20:51:57 +0000680 outs().flush();
Zachary Turnerfcb14ad2015-01-27 20:46:21 +0000681 return 0;
682}