blob: 30fe5995074530e56cfcf941ece5055318baad0a [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 Turner93839cb2016-06-02 05:07:49 +000029#include "llvm/DebugInfo/CodeView/EnumTables.h"
Zachary Turnera96cce62016-06-03 03:25:59 +000030#include "llvm/DebugInfo/CodeView/Line.h"
31#include "llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h"
Zachary Turnerd5d37dc2016-05-25 20:37:03 +000032#include "llvm/DebugInfo/CodeView/StreamReader.h"
Zachary Turnercac29ae2016-05-24 17:30:25 +000033#include "llvm/DebugInfo/CodeView/SymbolDumper.h"
Zachary Turner5a1b5ef2016-05-06 22:15:42 +000034#include "llvm/DebugInfo/CodeView/TypeDumper.h"
Zachary Turner819e77d2016-05-06 20:51:57 +000035#include "llvm/DebugInfo/PDB/GenericError.h"
Zachary Turnera5549172015-02-10 22:43:25 +000036#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
Zachary Turnera5549172015-02-10 22:43:25 +000037#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"
Chandler Carruth71f308a2015-02-13 09:09:03 +000038#include "llvm/DebugInfo/PDB/IPDBSession.h"
39#include "llvm/DebugInfo/PDB/PDB.h"
Zachary Turnera5549172015-02-10 22:43:25 +000040#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
Zachary Turnerdb18f5c2015-02-27 09:15:18 +000041#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
Chandler Carruth71f308a2015-02-13 09:09:03 +000042#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
Zachary Turnerdb18f5c2015-02-27 09:15:18 +000043#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
44#include "llvm/DebugInfo/PDB/PDBSymbolThunk.h"
Zachary Turner2f09b502016-04-29 17:28:47 +000045#include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
Zachary Turner93839cb2016-06-02 05:07:49 +000046#include "llvm/DebugInfo/PDB/Raw/EnumTables.h"
47#include "llvm/DebugInfo/PDB/Raw/ISectionContribVisitor.h"
Zachary Turner2f09b502016-04-29 17:28:47 +000048#include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
Zachary Turner6ba65de2016-04-29 17:22:58 +000049#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
Zachary Turner1822af542016-04-27 23:41:42 +000050#include "llvm/DebugInfo/PDB/Raw/ModInfo.h"
Zachary Turner06c2b4b2016-05-09 17:45:21 +000051#include "llvm/DebugInfo/PDB/Raw/ModStream.h"
Zachary Turner0eace0b2016-05-02 18:09:14 +000052#include "llvm/DebugInfo/PDB/Raw/NameHashTable.h"
Zachary Turner0a43efe2016-04-25 17:38:08 +000053#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
Rui Ueyama1f6b6e22016-05-13 21:21:53 +000054#include "llvm/DebugInfo/PDB/Raw/PublicsStream.h"
Reid Klecknerce5196e2016-05-12 23:26:23 +000055#include "llvm/DebugInfo/PDB/Raw/RawError.h"
Zachary Turner0a43efe2016-04-25 17:38:08 +000056#include "llvm/DebugInfo/PDB/Raw/RawSession.h"
Zachary Turnerf5c59652016-05-03 00:28:21 +000057#include "llvm/DebugInfo/PDB/Raw/TpiStream.h"
Rui Ueyama90db7882016-06-02 18:20:20 +000058#include "llvm/Object/COFF.h"
Zachary Turner93839cb2016-06-02 05:07:49 +000059#include "llvm/Support/COM.h"
Zachary Turnerfcb14ad2015-01-27 20:46:21 +000060#include "llvm/Support/CommandLine.h"
61#include "llvm/Support/ConvertUTF.h"
Zachary Turner9a818ad2015-02-22 22:03:38 +000062#include "llvm/Support/FileSystem.h"
Zachary Turnerfcb14ad2015-01-27 20:46:21 +000063#include "llvm/Support/Format.h"
64#include "llvm/Support/ManagedStatic.h"
David Majnemer6e081262015-10-15 01:27:19 +000065#include "llvm/Support/MemoryBuffer.h"
Zachary Turnerfcb14ad2015-01-27 20:46:21 +000066#include "llvm/Support/PrettyStackTrace.h"
Chandler Carruth71f308a2015-02-13 09:09:03 +000067#include "llvm/Support/Process.h"
Reid Klecknerb0345262016-05-04 16:09:04 +000068#include "llvm/Support/ScopedPrinter.h"
Daniel Sandersd41718e2016-04-22 12:04:42 +000069#include "llvm/Support/Signals.h"
Zachary Turner0a43efe2016-04-25 17:38:08 +000070#include "llvm/Support/raw_ostream.h"
Zachary Turnerfcb14ad2015-01-27 20:46:21 +000071
Zachary Turnerfcb14ad2015-01-27 20:46:21 +000072using namespace llvm;
Zachary Turnera96cce62016-06-03 03:25:59 +000073using namespace llvm::codeview;
Zachary Turner2f09b502016-04-29 17:28:47 +000074using namespace llvm::pdb;
Zachary Turnerfcb14ad2015-01-27 20:46:21 +000075
76namespace opts {
Zachary Turnerc0acf682015-02-15 20:27:53 +000077
78enum class PDB_DumpType { ByType, ByObjFile, Both };
79
Zachary Turnerfcb14ad2015-01-27 20:46:21 +000080cl::list<std::string> InputFilenames(cl::Positional,
81 cl::desc("<input PDB files>"),
82 cl::OneOrMore);
83
Zachary Turner7797c722015-03-02 04:39:56 +000084cl::OptionCategory TypeCategory("Symbol Type Options");
85cl::OptionCategory FilterCategory("Filtering Options");
Zachary Turnere5cb2692015-05-01 20:24:26 +000086cl::OptionCategory OtherOptions("Other Options");
Rui Ueyama18695f92016-05-26 23:01:05 +000087cl::OptionCategory NativeOptions("Native Options");
Zachary Turner7797c722015-03-02 04:39:56 +000088
89cl::opt<bool> Compilands("compilands", cl::desc("Display compilands"),
90 cl::cat(TypeCategory));
91cl::opt<bool> Symbols("symbols", cl::desc("Display symbols for each compiland"),
92 cl::cat(TypeCategory));
93cl::opt<bool> Globals("globals", cl::desc("Dump global symbols"),
94 cl::cat(TypeCategory));
Zachary Turnere5cb2692015-05-01 20:24:26 +000095cl::opt<bool> Externals("externals", cl::desc("Dump external symbols"),
96 cl::cat(TypeCategory));
Zachary Turner7797c722015-03-02 04:39:56 +000097cl::opt<bool> Types("types", cl::desc("Display types"), cl::cat(TypeCategory));
Zachary Turnera99000d2016-03-08 21:42:24 +000098cl::opt<bool> Lines("lines", cl::desc("Line tables"), cl::cat(TypeCategory));
Zachary Turner7797c722015-03-02 04:39:56 +000099cl::opt<bool>
Zachary Turner7797c722015-03-02 04:39:56 +0000100 All("all", cl::desc("Implies all other options in 'Symbol Types' category"),
101 cl::cat(TypeCategory));
Zachary Turnerf5abda22015-03-01 06:49:49 +0000102
Zachary Turnere5cb2692015-05-01 20:24:26 +0000103cl::opt<uint64_t> LoadAddress(
104 "load-address",
105 cl::desc("Assume the module is loaded at the specified address"),
106 cl::cat(OtherOptions));
107
Zachary Turner96e60f72016-05-24 20:31:48 +0000108cl::opt<bool> DumpHeaders("raw-headers", cl::desc("dump PDB headers"),
Rui Ueyama18695f92016-05-26 23:01:05 +0000109 cl::cat(NativeOptions));
Zachary Turner96e60f72016-05-24 20:31:48 +0000110cl::opt<bool> DumpStreamBlocks("raw-stream-blocks",
David Majnemer6e081262015-10-15 01:27:19 +0000111 cl::desc("dump PDB stream blocks"),
Rui Ueyama18695f92016-05-26 23:01:05 +0000112 cl::cat(NativeOptions));
Zachary Turner85ed80b2016-05-25 03:43:17 +0000113cl::opt<bool> DumpStreamSummary("raw-stream-summary",
114 cl::desc("dump summary of the PDB streams"),
Rui Ueyama18695f92016-05-26 23:01:05 +0000115 cl::cat(NativeOptions));
Reid Klecknerb0345262016-05-04 16:09:04 +0000116cl::opt<bool>
Zachary Turnerc9972c62016-05-25 04:35:22 +0000117 DumpTpiRecords("raw-tpi-records",
118 cl::desc("dump CodeView type records from TPI stream"),
Rui Ueyama18695f92016-05-26 23:01:05 +0000119 cl::cat(NativeOptions));
Zachary Turnerc9972c62016-05-25 04:35:22 +0000120cl::opt<bool> DumpTpiRecordBytes(
121 "raw-tpi-record-bytes",
122 cl::desc("dump CodeView type record raw bytes from TPI stream"),
Rui Ueyama18695f92016-05-26 23:01:05 +0000123 cl::cat(NativeOptions));
Zachary Turnerc9972c62016-05-25 04:35:22 +0000124cl::opt<bool>
125 DumpIpiRecords("raw-ipi-records",
126 cl::desc("dump CodeView type records from IPI stream"),
Rui Ueyama18695f92016-05-26 23:01:05 +0000127 cl::cat(NativeOptions));
Zachary Turnerc9972c62016-05-25 04:35:22 +0000128cl::opt<bool> DumpIpiRecordBytes(
129 "raw-ipi-record-bytes",
130 cl::desc("dump CodeView type record raw bytes from IPI stream"),
Rui Ueyama18695f92016-05-26 23:01:05 +0000131 cl::cat(NativeOptions));
Zachary Turner96e60f72016-05-24 20:31:48 +0000132cl::opt<std::string> DumpStreamDataIdx("raw-stream",
133 cl::desc("dump stream data"),
Rui Ueyama18695f92016-05-26 23:01:05 +0000134 cl::cat(NativeOptions));
Zachary Turner96e60f72016-05-24 20:31:48 +0000135cl::opt<std::string> DumpStreamDataName("raw-stream-name",
136 cl::desc("dump stream data"),
Rui Ueyama18695f92016-05-26 23:01:05 +0000137 cl::cat(NativeOptions));
Zachary Turner96e60f72016-05-24 20:31:48 +0000138cl::opt<bool> DumpModules("raw-modules", cl::desc("dump compiland information"),
Rui Ueyama18695f92016-05-26 23:01:05 +0000139 cl::cat(NativeOptions));
Zachary Turner96e60f72016-05-24 20:31:48 +0000140cl::opt<bool> DumpModuleFiles("raw-module-files",
141 cl::desc("dump file information"),
Rui Ueyama18695f92016-05-26 23:01:05 +0000142 cl::cat(NativeOptions));
Zachary Turner96e60f72016-05-24 20:31:48 +0000143cl::opt<bool> DumpModuleSyms("raw-module-syms", cl::desc("dump module symbols"),
Rui Ueyama18695f92016-05-26 23:01:05 +0000144 cl::cat(NativeOptions));
Zachary Turner96e60f72016-05-24 20:31:48 +0000145cl::opt<bool> DumpPublics("raw-publics", cl::desc("dump Publics stream data"),
Rui Ueyama18695f92016-05-26 23:01:05 +0000146 cl::cat(NativeOptions));
Zachary Turner93839cb2016-06-02 05:07:49 +0000147cl::opt<bool> DumpSectionContribs("raw-section-contribs",
148 cl::desc("dump section contributions"),
149 cl::cat(NativeOptions));
Zachary Turner7eb6d352016-06-02 20:11:22 +0000150cl::opt<bool> DumpLineInfo("raw-line-info",
151 cl::desc("dump file and line information"),
152 cl::cat(NativeOptions));
Zachary Turner93839cb2016-06-02 05:07:49 +0000153cl::opt<bool> DumpSectionMap("raw-section-map", cl::desc("dump section map"),
154 cl::cat(NativeOptions));
Zachary Turnercac29ae2016-05-24 17:30:25 +0000155cl::opt<bool>
Zachary Turner96e60f72016-05-24 20:31:48 +0000156 DumpSymRecordBytes("raw-sym-record-bytes",
Zachary Turnercac29ae2016-05-24 17:30:25 +0000157 cl::desc("dump CodeView symbol record raw bytes"),
Rui Ueyama18695f92016-05-26 23:01:05 +0000158 cl::cat(NativeOptions));
Rui Ueyama90db7882016-06-02 18:20:20 +0000159cl::opt<bool> DumpSectionHeaders("raw-section-headers",
160 cl::desc("dump section headers"),
161 cl::cat(NativeOptions));
162
Rui Ueyama9dc034d2016-05-26 23:26:55 +0000163cl::opt<bool>
164 RawAll("raw-all",
165 cl::desc("Implies most other options in 'Native Options' category"),
166 cl::cat(NativeOptions));
David Majnemer6e081262015-10-15 01:27:19 +0000167
Zachary Turnerf5abda22015-03-01 06:49:49 +0000168cl::list<std::string>
169 ExcludeTypes("exclude-types",
170 cl::desc("Exclude types by regular expression"),
Zachary Turner7797c722015-03-02 04:39:56 +0000171 cl::ZeroOrMore, cl::cat(FilterCategory));
Zachary Turnerf5abda22015-03-01 06:49:49 +0000172cl::list<std::string>
173 ExcludeSymbols("exclude-symbols",
174 cl::desc("Exclude symbols by regular expression"),
Zachary Turner7797c722015-03-02 04:39:56 +0000175 cl::ZeroOrMore, cl::cat(FilterCategory));
Zachary Turnerf5abda22015-03-01 06:49:49 +0000176cl::list<std::string>
177 ExcludeCompilands("exclude-compilands",
178 cl::desc("Exclude compilands by regular expression"),
Zachary Turner7797c722015-03-02 04:39:56 +0000179 cl::ZeroOrMore, cl::cat(FilterCategory));
Zachary Turner4dddcc62015-09-29 19:49:06 +0000180
181cl::list<std::string> IncludeTypes(
182 "include-types",
183 cl::desc("Include only types which match a regular expression"),
184 cl::ZeroOrMore, cl::cat(FilterCategory));
185cl::list<std::string> IncludeSymbols(
186 "include-symbols",
187 cl::desc("Include only symbols which match a regular expression"),
188 cl::ZeroOrMore, cl::cat(FilterCategory));
189cl::list<std::string> IncludeCompilands(
190 "include-compilands",
191 cl::desc("Include only compilands those which match a regular expression"),
192 cl::ZeroOrMore, cl::cat(FilterCategory));
193
Zachary Turner7797c722015-03-02 04:39:56 +0000194cl::opt<bool> ExcludeCompilerGenerated(
195 "no-compiler-generated",
196 cl::desc("Don't show compiler generated types and symbols"),
197 cl::cat(FilterCategory));
198cl::opt<bool>
199 ExcludeSystemLibraries("no-system-libs",
200 cl::desc("Don't show symbols from system libraries"),
201 cl::cat(FilterCategory));
Zachary Turner65323652015-03-04 06:09:53 +0000202cl::opt<bool> NoClassDefs("no-class-definitions",
203 cl::desc("Don't display full class definitions"),
204 cl::cat(FilterCategory));
205cl::opt<bool> NoEnumDefs("no-enum-definitions",
206 cl::desc("Don't display full enum definitions"),
207 cl::cat(FilterCategory));
Zachary Turner49693b42015-01-28 01:22:33 +0000208}
209
David Majnemerc165c882016-05-28 18:25:15 +0000210static ExitOnError ExitOnErr;
211
Zachary Turner819e77d2016-05-06 20:51:57 +0000212static Error dumpFileHeaders(ScopedPrinter &P, PDBFile &File) {
Reid Klecknerb0345262016-05-04 16:09:04 +0000213 if (!opts::DumpHeaders)
Zachary Turner819e77d2016-05-06 20:51:57 +0000214 return Error::success();
215
Reid Klecknerb0345262016-05-04 16:09:04 +0000216 DictScope D(P, "FileHeaders");
217 P.printNumber("BlockSize", File.getBlockSize());
218 P.printNumber("Unknown0", File.getUnknown0());
219 P.printNumber("NumBlocks", File.getBlockCount());
220 P.printNumber("NumDirectoryBytes", File.getNumDirectoryBytes());
221 P.printNumber("Unknown1", File.getUnknown1());
222 P.printNumber("BlockMapAddr", File.getBlockMapIndex());
223 P.printNumber("NumDirectoryBlocks", File.getNumDirectoryBlocks());
224 P.printNumber("BlockMapOffset", File.getBlockMapOffset());
Zachary Turnercdd313c2016-05-04 15:05:12 +0000225
Chad Rosier20dbbf32016-05-04 15:25:06 +0000226 // The directory is not contiguous. Instead, the block map contains a
227 // contiguous list of block numbers whose contents, when concatenated in
228 // order, make up the directory.
Reid Klecknerb0345262016-05-04 16:09:04 +0000229 P.printList("DirectoryBlocks", File.getDirectoryBlockArray());
230 P.printNumber("NumStreams", File.getNumStreams());
Zachary Turner819e77d2016-05-06 20:51:57 +0000231 return Error::success();
Reid Klecknerb0345262016-05-04 16:09:04 +0000232}
Zachary Turnercdd313c2016-05-04 15:05:12 +0000233
Zachary Turner85ed80b2016-05-25 03:43:17 +0000234static Error dumpStreamSummary(ScopedPrinter &P, PDBFile &File) {
235 if (!opts::DumpStreamSummary)
Zachary Turner819e77d2016-05-06 20:51:57 +0000236 return Error::success();
Zachary Turnercdd313c2016-05-04 15:05:12 +0000237
Zachary Turner85ed80b2016-05-25 03:43:17 +0000238 auto DbiS = File.getPDBDbiStream();
239 if (auto EC = DbiS.takeError())
240 return EC;
241 auto TpiS = File.getPDBTpiStream();
242 if (auto EC = TpiS.takeError())
243 return EC;
Zachary Turnerc9972c62016-05-25 04:35:22 +0000244 auto IpiS = File.getPDBIpiStream();
245 if (auto EC = IpiS.takeError())
246 return EC;
Zachary Turner85ed80b2016-05-25 03:43:17 +0000247 auto InfoS = File.getPDBInfoStream();
248 if (auto EC = InfoS.takeError())
249 return EC;
250 DbiStream &DS = DbiS.get();
251 TpiStream &TS = TpiS.get();
Zachary Turnerc9972c62016-05-25 04:35:22 +0000252 TpiStream &TIS = IpiS.get();
Zachary Turner85ed80b2016-05-25 03:43:17 +0000253 InfoStream &IS = InfoS.get();
254
255 ListScope L(P, "Streams");
Chad Rosier20dbbf32016-05-04 15:25:06 +0000256 uint32_t StreamCount = File.getNumStreams();
Zachary Turner85ed80b2016-05-25 03:43:17 +0000257 std::unordered_map<uint16_t, const ModuleInfoEx *> ModStreams;
258 std::unordered_map<uint16_t, std::string> NamedStreams;
259
260 for (auto &ModI : DS.modules()) {
261 uint16_t SN = ModI.Info.getModuleStreamIndex();
262 ModStreams[SN] = &ModI;
Chad Rosier20dbbf32016-05-04 15:25:06 +0000263 }
Zachary Turner85ed80b2016-05-25 03:43:17 +0000264 for (auto &NSE : IS.named_streams()) {
265 NamedStreams[NSE.second] = NSE.first();
266 }
267
268 for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
269 std::string Label("Stream ");
270 Label += to_string(StreamIdx);
271 std::string Value;
Rui Ueyama68163672016-05-27 00:32:07 +0000272 if (StreamIdx == OldMSFDirectory)
273 Value = "Old MSF Directory";
274 else if (StreamIdx == StreamPDB)
Zachary Turner85ed80b2016-05-25 03:43:17 +0000275 Value = "PDB Stream";
276 else if (StreamIdx == StreamDBI)
277 Value = "DBI Stream";
278 else if (StreamIdx == StreamTPI)
279 Value = "TPI Stream";
280 else if (StreamIdx == StreamIPI)
281 Value = "IPI Stream";
282 else if (StreamIdx == DS.getGlobalSymbolStreamIndex())
283 Value = "Global Symbol Hash";
284 else if (StreamIdx == DS.getPublicSymbolStreamIndex())
285 Value = "Public Symbol Hash";
286 else if (StreamIdx == DS.getSymRecordStreamIndex())
287 Value = "Public Symbol Records";
288 else if (StreamIdx == TS.getTypeHashStreamIndex())
289 Value = "TPI Hash";
290 else if (StreamIdx == TS.getTypeHashStreamAuxIndex())
291 Value = "TPI Aux Hash";
Zachary Turnerc9972c62016-05-25 04:35:22 +0000292 else if (StreamIdx == TIS.getTypeHashStreamIndex())
293 Value = "IPI Hash";
294 else if (StreamIdx == TIS.getTypeHashStreamAuxIndex())
295 Value = "IPI Aux Hash";
Zachary Turnerd3076ab2016-05-25 05:49:48 +0000296 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::Exception))
297 Value = "Exception Data";
298 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::Fixup))
299 Value = "Fixup Data";
300 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::FPO))
301 Value = "FPO Data";
302 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::NewFPO))
303 Value = "New FPO Data";
304 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::OmapFromSrc))
305 Value = "Omap From Source Data";
306 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::OmapToSrc))
307 Value = "Omap To Source Data";
308 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::Pdata))
309 Value = "Pdata";
310 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::SectionHdr))
311 Value = "Section Header Data";
312 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::SectionHdrOrig))
313 Value = "Section Header Original Data";
314 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::TokenRidMap))
315 Value = "Token Rid Data";
316 else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::Xdata))
317 Value = "Xdata";
Zachary Turner85ed80b2016-05-25 03:43:17 +0000318 else {
319 auto ModIter = ModStreams.find(StreamIdx);
320 auto NSIter = NamedStreams.find(StreamIdx);
321 if (ModIter != ModStreams.end()) {
322 Value = "Module \"";
Zachary Turner8dbe3622016-05-27 01:54:44 +0000323 Value += ModIter->second->Info.getModuleName().str();
Zachary Turner85ed80b2016-05-25 03:43:17 +0000324 Value += "\"";
325 } else if (NSIter != NamedStreams.end()) {
326 Value = "Named Stream \"";
327 Value += NSIter->second;
328 Value += "\"";
329 } else {
330 Value = "???";
331 }
332 }
333 Value = "[" + Value + "]";
334 Value =
335 Value + " (" + to_string(File.getStreamByteSize(StreamIdx)) + " bytes)";
336
337 P.printString(Label, Value);
338 }
339 P.flush();
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 dumpStreamBlocks(ScopedPrinter &P, PDBFile &File) {
Reid Klecknerb0345262016-05-04 16:09:04 +0000344 if (!opts::DumpStreamBlocks)
Zachary Turner819e77d2016-05-06 20:51:57 +0000345 return Error::success();
Reid Klecknerb0345262016-05-04 16:09:04 +0000346
347 ListScope L(P, "StreamBlocks");
348 uint32_t StreamCount = File.getNumStreams();
349 for (uint32_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
350 std::string Name("Stream ");
351 Name += to_string(StreamIdx);
352 auto StreamBlocks = File.getStreamBlockList(StreamIdx);
353 P.printList(Name, StreamBlocks);
Chad Rosier20dbbf32016-05-04 15:25:06 +0000354 }
Zachary Turner819e77d2016-05-06 20:51:57 +0000355 return Error::success();
Reid Klecknerb0345262016-05-04 16:09:04 +0000356}
Zachary Turnercdd313c2016-05-04 15:05:12 +0000357
Zachary Turner819e77d2016-05-06 20:51:57 +0000358static Error dumpStreamData(ScopedPrinter &P, PDBFile &File) {
Reid Klecknerb0345262016-05-04 16:09:04 +0000359 uint32_t StreamCount = File.getNumStreams();
Zachary Turner96e60f72016-05-24 20:31:48 +0000360 StringRef DumpStreamStr = opts::DumpStreamDataIdx;
Chad Rosier20dbbf32016-05-04 15:25:06 +0000361 uint32_t DumpStreamNum;
Reid Klecknerb0345262016-05-04 16:09:04 +0000362 if (DumpStreamStr.getAsInteger(/*Radix=*/0U, DumpStreamNum) ||
363 DumpStreamNum >= StreamCount)
Zachary Turner819e77d2016-05-06 20:51:57 +0000364 return Error::success();
Chad Rosier20dbbf32016-05-04 15:25:06 +0000365
Zachary Turner96e60f72016-05-24 20:31:48 +0000366 MappedBlockStream S(DumpStreamNum, File);
Zachary Turnerd5d37dc2016-05-25 20:37:03 +0000367 codeview::StreamReader R(S);
Zachary Turner96e60f72016-05-24 20:31:48 +0000368 while (R.bytesRemaining() > 0) {
369 ArrayRef<uint8_t> Data;
Reid Klecknerb0345262016-05-04 16:09:04 +0000370 uint32_t BytesToReadInBlock = std::min(
Zachary Turner96e60f72016-05-24 20:31:48 +0000371 R.bytesRemaining(), static_cast<uint32_t>(File.getBlockSize()));
Zachary Turner0d43c1c2016-05-28 05:21:57 +0000372 if (auto EC = R.readBytes(Data, BytesToReadInBlock))
Zachary Turner96e60f72016-05-24 20:31:48 +0000373 return EC;
Zachary Turnerd8ca0522016-05-25 18:32:07 +0000374 P.printBinaryBlock(
375 "Data",
376 StringRef(reinterpret_cast<const char *>(Data.begin()), Data.size()));
Chad Rosier20dbbf32016-05-04 15:25:06 +0000377 }
Zachary Turner819e77d2016-05-06 20:51:57 +0000378 return Error::success();
Reid Klecknerb0345262016-05-04 16:09:04 +0000379}
Chad Rosier20dbbf32016-05-04 15:25:06 +0000380
Zachary Turner819e77d2016-05-06 20:51:57 +0000381static Error dumpInfoStream(ScopedPrinter &P, PDBFile &File) {
Zachary Turnerc59261c2016-05-25 03:53:16 +0000382 if (!opts::DumpHeaders)
383 return Error::success();
Zachary Turner819e77d2016-05-06 20:51:57 +0000384 auto InfoS = File.getPDBInfoStream();
385 if (auto EC = InfoS.takeError())
386 return EC;
387
388 InfoStream &IS = InfoS.get();
Chad Rosier20dbbf32016-05-04 15:25:06 +0000389
Reid Klecknerb0345262016-05-04 16:09:04 +0000390 DictScope D(P, "PDB Stream");
391 P.printNumber("Version", IS.getVersion());
392 P.printHex("Signature", IS.getSignature());
393 P.printNumber("Age", IS.getAge());
394 P.printObject("Guid", IS.getGuid());
Zachary Turner819e77d2016-05-06 20:51:57 +0000395 return Error::success();
Reid Klecknerb0345262016-05-04 16:09:04 +0000396}
397
Zachary Turner96e60f72016-05-24 20:31:48 +0000398static Error dumpNamedStream(ScopedPrinter &P, PDBFile &File) {
399 if (opts::DumpStreamDataName.empty())
400 return Error::success();
401
Zachary Turner819e77d2016-05-06 20:51:57 +0000402 auto InfoS = File.getPDBInfoStream();
403 if (auto EC = InfoS.takeError())
404 return EC;
405 InfoStream &IS = InfoS.get();
406
Zachary Turner96e60f72016-05-24 20:31:48 +0000407 uint32_t NameStreamIndex = IS.getNamedStreamIndex(opts::DumpStreamDataName);
Reid Klecknerb0345262016-05-04 16:09:04 +0000408
Chad Rosier20dbbf32016-05-04 15:25:06 +0000409 if (NameStreamIndex != 0) {
Reid Klecknerb0345262016-05-04 16:09:04 +0000410 std::string Name("Stream '");
Zachary Turner96e60f72016-05-24 20:31:48 +0000411 Name += opts::DumpStreamDataName;
Reid Klecknerb0345262016-05-04 16:09:04 +0000412 Name += "'";
413 DictScope D(P, Name);
414 P.printNumber("Index", NameStreamIndex);
415
Chad Rosier20dbbf32016-05-04 15:25:06 +0000416 MappedBlockStream NameStream(NameStreamIndex, File);
Zachary Turnerd5d37dc2016-05-25 20:37:03 +0000417 codeview::StreamReader Reader(NameStream);
Chad Rosier20dbbf32016-05-04 15:25:06 +0000418
Chad Rosier20dbbf32016-05-04 15:25:06 +0000419 NameHashTable NameTable;
Zachary Turner819e77d2016-05-06 20:51:57 +0000420 if (auto EC = NameTable.load(Reader))
421 return EC;
422
Reid Klecknerb0345262016-05-04 16:09:04 +0000423 P.printHex("Signature", NameTable.getSignature());
424 P.printNumber("Version", NameTable.getHashVersion());
425 P.printNumber("Name Count", NameTable.getNameCount());
426 ListScope L(P, "Names");
Chad Rosier20dbbf32016-05-04 15:25:06 +0000427 for (uint32_t ID : NameTable.name_ids()) {
Reid Klecknerb0345262016-05-04 16:09:04 +0000428 StringRef Str = NameTable.getStringForID(ID);
429 if (!Str.empty())
430 P.printString(Str);
Chad Rosier20dbbf32016-05-04 15:25:06 +0000431 }
432 }
Zachary Turner819e77d2016-05-06 20:51:57 +0000433 return Error::success();
Reid Klecknerb0345262016-05-04 16:09:04 +0000434}
Chad Rosier20dbbf32016-05-04 15:25:06 +0000435
Zachary Turnercac29ae2016-05-24 17:30:25 +0000436static Error dumpDbiStream(ScopedPrinter &P, PDBFile &File,
437 codeview::CVTypeDumper &TD) {
Zachary Turner7eb6d352016-06-02 20:11:22 +0000438 bool DumpModules = opts::DumpModules || opts::DumpModuleSyms ||
439 opts::DumpModuleFiles || opts::DumpLineInfo;
Zachary Turnerc59261c2016-05-25 03:53:16 +0000440 if (!opts::DumpHeaders && !DumpModules)
441 return Error::success();
442
Zachary Turner819e77d2016-05-06 20:51:57 +0000443 auto DbiS = File.getPDBDbiStream();
444 if (auto EC = DbiS.takeError())
445 return EC;
446 DbiStream &DS = DbiS.get();
Reid Klecknerb0345262016-05-04 16:09:04 +0000447
448 DictScope D(P, "DBI Stream");
449 P.printNumber("Dbi Version", DS.getDbiVersion());
450 P.printNumber("Age", DS.getAge());
451 P.printBoolean("Incremental Linking", DS.isIncrementallyLinked());
452 P.printBoolean("Has CTypes", DS.hasCTypes());
453 P.printBoolean("Is Stripped", DS.isStripped());
454 P.printObject("Machine Type", DS.getMachineType());
Rui Ueyama0376b1a2016-05-19 18:05:58 +0000455 P.printNumber("Symbol Record Stream Index", DS.getSymRecordStreamIndex());
Zachary Turner96e60f72016-05-24 20:31:48 +0000456 P.printNumber("Public Symbol Stream Index", DS.getPublicSymbolStreamIndex());
457 P.printNumber("Global Symbol Stream Index", DS.getGlobalSymbolStreamIndex());
Chad Rosier20dbbf32016-05-04 15:25:06 +0000458
459 uint16_t Major = DS.getBuildMajorVersion();
460 uint16_t Minor = DS.getBuildMinorVersion();
Reid Klecknerb0345262016-05-04 16:09:04 +0000461 P.printVersion("Toolchain Version", Major, Minor);
Chad Rosier20dbbf32016-05-04 15:25:06 +0000462
Reid Klecknerb0345262016-05-04 16:09:04 +0000463 std::string DllName;
464 raw_string_ostream DllStream(DllName);
465 DllStream << "mspdb" << Major << Minor << ".dll version";
466 DllStream.flush();
467 P.printVersion(DllName, Major, Minor, DS.getPdbDllVersion());
468
Zachary Turnerc59261c2016-05-25 03:53:16 +0000469 if (DumpModules) {
Zachary Turner96e60f72016-05-24 20:31:48 +0000470 ListScope L(P, "Modules");
471 for (auto &Modi : DS.modules()) {
472 DictScope DD(P);
Zachary Turner8dbe3622016-05-27 01:54:44 +0000473 P.printString("Name", Modi.Info.getModuleName().str());
Zachary Turner96e60f72016-05-24 20:31:48 +0000474 P.printNumber("Debug Stream Index", Modi.Info.getModuleStreamIndex());
Zachary Turner8dbe3622016-05-27 01:54:44 +0000475 P.printString("Object File Name", Modi.Info.getObjFileName().str());
Zachary Turner96e60f72016-05-24 20:31:48 +0000476 P.printNumber("Num Files", Modi.Info.getNumberOfFiles());
477 P.printNumber("Source File Name Idx", Modi.Info.getSourceFileNameIndex());
478 P.printNumber("Pdb File Name Idx", Modi.Info.getPdbFilePathNameIndex());
479 P.printNumber("Line Info Byte Size", Modi.Info.getLineInfoByteSize());
480 P.printNumber("C13 Line Info Byte Size",
481 Modi.Info.getC13LineInfoByteSize());
482 P.printNumber("Symbol Byte Size", Modi.Info.getSymbolDebugInfoByteSize());
483 P.printNumber("Type Server Index", Modi.Info.getTypeServerIndex());
484 P.printBoolean("Has EC Info", Modi.Info.hasECInfo());
485 if (opts::DumpModuleFiles) {
486 std::string FileListName =
487 to_string(Modi.SourceFiles.size()) + " Contributing Source Files";
488 ListScope LL(P, FileListName);
489 for (auto File : Modi.SourceFiles)
Zachary Turner8dbe3622016-05-27 01:54:44 +0000490 P.printString(File.str());
Zachary Turner96e60f72016-05-24 20:31:48 +0000491 }
492 bool HasModuleDI =
493 (Modi.Info.getModuleStreamIndex() < File.getNumStreams());
494 bool ShouldDumpSymbols =
495 (opts::DumpModuleSyms || opts::DumpSymRecordBytes);
Zachary Turner7eb6d352016-06-02 20:11:22 +0000496 if (HasModuleDI && (ShouldDumpSymbols || opts::DumpLineInfo)) {
Zachary Turner96e60f72016-05-24 20:31:48 +0000497 ModStream ModS(File, Modi.Info);
498 if (auto EC = ModS.reload())
499 return EC;
Zachary Turner06c2b4b2016-05-09 17:45:21 +0000500
Zachary Turner7eb6d352016-06-02 20:11:22 +0000501 if (ShouldDumpSymbols) {
502 ListScope SS(P, "Symbols");
503 codeview::CVSymbolDumper SD(P, TD, nullptr, false);
504 bool HadError = false;
Zachary Turnera96cce62016-06-03 03:25:59 +0000505 for (const auto &S : ModS.symbols(&HadError)) {
Zachary Turner7eb6d352016-06-02 20:11:22 +0000506 DictScope DD(P, "");
Zachary Turnercac29ae2016-05-24 17:30:25 +0000507
Zachary Turner7eb6d352016-06-02 20:11:22 +0000508 if (opts::DumpModuleSyms)
509 SD.dump(S);
510 if (opts::DumpSymRecordBytes)
511 P.printBinaryBlock("Bytes", S.Data);
512 }
513 if (HadError)
514 return make_error<RawError>(
515 raw_error_code::corrupt_file,
516 "DBI stream contained corrupt symbol record");
Zachary Turner96e60f72016-05-24 20:31:48 +0000517 }
Zachary Turner7eb6d352016-06-02 20:11:22 +0000518 if (opts::DumpLineInfo) {
519 ListScope SS(P, "LineInfo");
520 bool HadError = false;
Zachary Turnera96cce62016-06-03 03:25:59 +0000521 // Define a locally scoped visitor to print the different
522 // substream types types.
523 class RecordVisitor : public codeview::IModuleSubstreamVisitor {
524 public:
525 RecordVisitor(ScopedPrinter &P) : P(P) {}
526 Error visitUnknown(ModuleSubstreamKind Kind,
527 StreamRef Data) override {
528 DictScope DD(P, "Unknown");
529 return printBinaryData(Data);
Zachary Turner7eb6d352016-06-02 20:11:22 +0000530 }
Zachary Turnera96cce62016-06-03 03:25:59 +0000531 Error visitFileChecksums(StreamRef Data) override {
532 DictScope DD(P, "FileChecksums");
533 return printBinaryData(Data);
534 }
535
536 Error visitLines(StreamRef Data, const LineSubstreamHeader *Header,
537 LineInfoArray Lines) override {
538 DictScope DD(P, "Lines");
539 for (const auto &L : Lines) {
540 P.printNumber("FileOffset", L.Offset);
541 for (const auto &N : L.LineNumbers) {
542 DictScope DDD(P, "Line");
543 LineInfo LI(N.Flags);
544 P.printNumber("Offset", N.Offset);
545 if (LI.isAlwaysStepInto())
546 P.printString("StepInto", StringRef("Always"));
547 else if (LI.isNeverStepInto())
548 P.printString("StepInto", StringRef("Never"));
549 else
550 P.printNumber("LineNumberStart", LI.getStartLine());
551 P.printNumber("EndDelta", LI.getLineDelta());
552 P.printBoolean("IsStatement", LI.isStatement());
553 }
554 for (const auto &C : L.Columns) {
555 DictScope DDD(P, "Column");
556 P.printNumber("Start", C.StartColumn);
557 P.printNumber("End", C.EndColumn);
558 }
559 }
560 return printBinaryData(Data);
561 }
562
563 private:
564 Error printBinaryData(StreamRef Stream) {
565 ArrayRef<uint8_t> Data;
566 StreamReader R(Stream);
567 if (auto EC = R.readBytes(Data, R.bytesRemaining())) {
568 return make_error<RawError>(
569 raw_error_code::corrupt_file,
570 "DBI stream contained corrupt line info record");
571 }
572 P.printBinaryBlock("Data", Data);
573 P.flush();
574 return Error::success();
575 }
576 ScopedPrinter &P;
577 };
578 RecordVisitor V(P);
579 for (const auto &L : ModS.lines(&HadError)) {
580 if (auto EC = codeview::visitModuleSubstream(L, V))
581 return EC;
Zachary Turner7eb6d352016-06-02 20:11:22 +0000582 }
583 }
Zachary Turner06c2b4b2016-05-09 17:45:21 +0000584 }
585 }
Chad Rosier20dbbf32016-05-04 15:25:06 +0000586 }
Zachary Turner819e77d2016-05-06 20:51:57 +0000587 return Error::success();
Reid Klecknerb0345262016-05-04 16:09:04 +0000588}
589
Zachary Turner93839cb2016-06-02 05:07:49 +0000590static Error dumpSectionContribs(ScopedPrinter &P, PDBFile &File) {
591 if (!opts::DumpSectionContribs)
592 return Error::success();
593
594 auto DbiS = File.getPDBDbiStream();
595 if (auto EC = DbiS.takeError())
596 return EC;
597 DbiStream &DS = DbiS.get();
598 ListScope L(P, "Section Contributions");
599 class Visitor : public ISectionContribVisitor {
600 public:
601 Visitor(ScopedPrinter &P, DbiStream &DS) : P(P), DS(DS) {}
602 void visit(const SectionContrib &SC) override {
603 DictScope D(P, "Contribution");
604 P.printNumber("ISect", SC.ISect);
605 P.printNumber("Off", SC.Off);
606 P.printNumber("Size", SC.Size);
607 P.printFlags("Characteristics", SC.Characteristics,
608 codeview::getImageSectionCharacteristicNames(),
609 COFF::SectionCharacteristics(0x00F00000));
610 {
611 DictScope DD(P, "Module");
612 P.printNumber("Index", SC.Imod);
613 auto M = DS.modules();
614 if (M.size() > SC.Imod) {
615 P.printString("Name", M[SC.Imod].Info.getModuleName());
616 }
617 }
618 P.printNumber("Data CRC", SC.DataCrc);
619 P.printNumber("Reloc CRC", SC.RelocCrc);
620 P.flush();
621 }
622 void visit(const SectionContrib2 &SC) override {
623 visit(SC.Base);
624 P.printNumber("ISect Coff", SC.ISectCoff);
625 P.flush();
626 }
627
628 private:
629 ScopedPrinter &P;
630 DbiStream &DS;
631 };
632 Visitor V(P, DS);
633 DS.visitSectionContributions(V);
634 return Error::success();
635}
636
637static Error dumpSectionMap(ScopedPrinter &P, PDBFile &File) {
638 if (!opts::DumpSectionMap)
639 return Error::success();
640
641 auto DbiS = File.getPDBDbiStream();
642 if (auto EC = DbiS.takeError())
643 return EC;
644 DbiStream &DS = DbiS.get();
645 ListScope L(P, "Section Map");
646 for (auto &M : DS.getSectionMap()) {
647 DictScope D(P, "Entry");
648 P.printFlags("Flags", M.Flags, getOMFSegMapDescFlagNames());
649 P.printNumber("Flags", M.Flags);
650 P.printNumber("Ovl", M.Ovl);
651 P.printNumber("Group", M.Group);
652 P.printNumber("Frame", M.Frame);
653 P.printNumber("SecName", M.SecName);
654 P.printNumber("ClassName", M.ClassName);
655 P.printNumber("Offset", M.Offset);
656 P.printNumber("SecByteLength", M.SecByteLength);
657 P.flush();
658 }
659 return Error::success();
660}
661
Zachary Turnercac29ae2016-05-24 17:30:25 +0000662static Error dumpTpiStream(ScopedPrinter &P, PDBFile &File,
Zachary Turnerc9972c62016-05-25 04:35:22 +0000663 codeview::CVTypeDumper &TD, uint32_t StreamIdx) {
664 assert(StreamIdx == StreamTPI || StreamIdx == StreamIPI);
Reid Klecknerb0345262016-05-04 16:09:04 +0000665
Zachary Turnerc9972c62016-05-25 04:35:22 +0000666 bool DumpRecordBytes = false;
667 bool DumpRecords = false;
668 StringRef Label;
669 StringRef VerLabel;
670 if (StreamIdx == StreamTPI) {
671 DumpRecordBytes = opts::DumpTpiRecordBytes;
Zachary Turner0d43c1c2016-05-28 05:21:57 +0000672 DumpRecords = opts::DumpTpiRecords;
Zachary Turnerc9972c62016-05-25 04:35:22 +0000673 Label = "Type Info Stream (TPI)";
674 VerLabel = "TPI Version";
675 } else if (StreamIdx == StreamIPI) {
676 DumpRecordBytes = opts::DumpIpiRecordBytes;
677 DumpRecords = opts::DumpIpiRecords;
678 Label = "Type Info Stream (IPI)";
679 VerLabel = "IPI Version";
680 }
681 if (!DumpRecordBytes && !DumpRecords && !opts::DumpModuleSyms)
682 return Error::success();
Zachary Turnercac29ae2016-05-24 17:30:25 +0000683
Zachary Turnerc9972c62016-05-25 04:35:22 +0000684 auto TpiS = (StreamIdx == StreamTPI) ? File.getPDBTpiStream()
685 : File.getPDBIpiStream();
Rui Ueyama11c06b32016-06-03 02:42:30 +0000686 if (auto EC = TpiS.takeError())
687 return EC;
688 TpiStream &Tpi = TpiS.get();
Zachary Turnercac29ae2016-05-24 17:30:25 +0000689
Rui Ueyama11c06b32016-06-03 02:42:30 +0000690 if (DumpRecords || DumpRecordBytes) {
691 DictScope D(P, Label);
Zachary Turnerc9972c62016-05-25 04:35:22 +0000692
Rui Ueyama11c06b32016-06-03 02:42:30 +0000693 P.printNumber(VerLabel, Tpi.getTpiVersion());
Zachary Turnercac29ae2016-05-24 17:30:25 +0000694 P.printNumber("Record count", Tpi.NumTypeRecords());
695
Zachary Turner5a1b5ef2016-05-06 22:15:42 +0000696 ListScope L(P, "Records");
Reid Klecknerb0345262016-05-04 16:09:04 +0000697
Reid Klecknerce5196e2016-05-12 23:26:23 +0000698 bool HadError = false;
699 for (auto &Type : Tpi.types(&HadError)) {
Zachary Turner5a1b5ef2016-05-06 22:15:42 +0000700 DictScope DD(P, "");
701
Zachary Turnerc9972c62016-05-25 04:35:22 +0000702 if (DumpRecords)
Zachary Turner5a1b5ef2016-05-06 22:15:42 +0000703 TD.dump(Type);
704
Zachary Turnerc9972c62016-05-25 04:35:22 +0000705 if (DumpRecordBytes)
Zachary Turner9073ed62016-05-09 17:44:58 +0000706 P.printBinaryBlock("Bytes", Type.Data);
Zachary Turner5a1b5ef2016-05-06 22:15:42 +0000707 }
Reid Klecknerce5196e2016-05-12 23:26:23 +0000708 if (HadError)
709 return make_error<RawError>(raw_error_code::corrupt_file,
710 "TPI stream contained corrupt record");
Zachary Turnercac29ae2016-05-24 17:30:25 +0000711 } else if (opts::DumpModuleSyms) {
712 // Even if the user doesn't want to dump type records, we still need to
713 // iterate them in order to build the list of types so that we can print
714 // them when dumping module symbols. So when they want to dump symbols
715 // but not types, use a null output stream.
716 ScopedPrinter *OldP = TD.getPrinter();
717 TD.setPrinter(nullptr);
Zachary Turnerc9972c62016-05-25 04:35:22 +0000718
Zachary Turnercac29ae2016-05-24 17:30:25 +0000719 bool HadError = false;
720 for (auto &Type : Tpi.types(&HadError))
721 TD.dump(Type);
722
723 TD.setPrinter(OldP);
724 if (HadError)
725 return make_error<RawError>(raw_error_code::corrupt_file,
726 "TPI stream contained corrupt record");
Chad Rosier20dbbf32016-05-04 15:25:06 +0000727 }
Zachary Turnerc9972c62016-05-25 04:35:22 +0000728 P.flush();
Zachary Turner819e77d2016-05-06 20:51:57 +0000729 return Error::success();
Zachary Turnercdd313c2016-05-04 15:05:12 +0000730}
731
Zachary Turnerb393d952016-05-27 03:51:53 +0000732static void printSectionOffset(llvm::raw_ostream &OS,
733 const SectionOffset &Off) {
734 OS << Off.Off << ", " << Off.Isect;
735}
736
Zachary Turner9e33e6f2016-05-24 18:55:14 +0000737static Error dumpPublicsStream(ScopedPrinter &P, PDBFile &File,
738 codeview::CVTypeDumper &TD) {
Rui Ueyama1f6b6e22016-05-13 21:21:53 +0000739 if (!opts::DumpPublics)
740 return Error::success();
741
742 DictScope D(P, "Publics Stream");
743 auto PublicsS = File.getPDBPublicsStream();
744 if (auto EC = PublicsS.takeError())
745 return EC;
746 PublicsStream &Publics = PublicsS.get();
747 P.printNumber("Stream number", Publics.getStreamNum());
748 P.printNumber("SymHash", Publics.getSymHash());
749 P.printNumber("AddrMap", Publics.getAddrMap());
750 P.printNumber("Number of buckets", Publics.getNumBuckets());
Rui Ueyama8dc18c52016-05-17 23:07:48 +0000751 P.printList("Hash Buckets", Publics.getHashBuckets());
752 P.printList("Address Map", Publics.getAddressMap());
753 P.printList("Thunk Map", Publics.getThunkMap());
Zachary Turnerb393d952016-05-27 03:51:53 +0000754 P.printList("Section Offsets", Publics.getSectionOffsets(),
755 printSectionOffset);
Zachary Turner9e33e6f2016-05-24 18:55:14 +0000756 ListScope L(P, "Symbols");
757 codeview::CVSymbolDumper SD(P, TD, nullptr, false);
Zachary Turner0d43c1c2016-05-28 05:21:57 +0000758 bool HadError = false;
759 for (auto S : Publics.getSymbols(&HadError)) {
Zachary Turner9e33e6f2016-05-24 18:55:14 +0000760 DictScope DD(P, "");
761
762 SD.dump(S);
763 if (opts::DumpSymRecordBytes)
764 P.printBinaryBlock("Bytes", S.Data);
765 }
Zachary Turner0d43c1c2016-05-28 05:21:57 +0000766 if (HadError)
767 return make_error<RawError>(
768 raw_error_code::corrupt_file,
769 "Public symbol stream contained corrupt record");
770
Rui Ueyama1f6b6e22016-05-13 21:21:53 +0000771 return Error::success();
772}
773
Rui Ueyama90db7882016-06-02 18:20:20 +0000774static Error dumpSectionHeaders(ScopedPrinter &P, PDBFile &File,
775 codeview::CVTypeDumper &TD) {
776 if (!opts::DumpSectionHeaders)
777 return Error::success();
778
779 auto DbiS = File.getPDBDbiStream();
780 if (auto EC = DbiS.takeError())
781 return EC;
782 DbiStream &DS = DbiS.get();
783
784 ListScope D(P, "Section Headers");
785 for (const object::coff_section &Section : DS.getSectionHeaders()) {
786 DictScope DD(P, "");
787
788 // If a name is 8 characters long, there is no NUL character at end.
789 StringRef Name(Section.Name, strnlen(Section.Name, sizeof(Section.Name)));
790 P.printString("Name", Name);
791 P.printNumber("Virtual Size", Section.VirtualSize);
792 P.printNumber("Virtual Address", Section.VirtualAddress);
793 P.printNumber("Size of Raw Data", Section.SizeOfRawData);
794 P.printNumber("File Pointer to Raw Data", Section.PointerToRawData);
795 P.printNumber("File Pointer to Relocations", Section.PointerToRelocations);
796 P.printNumber("File Pointer to Linenumbers", Section.PointerToLinenumbers);
797 P.printNumber("Number of Relocations", Section.NumberOfRelocations);
798 P.printNumber("Number of Linenumbers", Section.NumberOfLinenumbers);
799 P.printNumber("Characteristics", Section.Characteristics);
800 }
801 return Error::success();
802}
803
Zachary Turner819e77d2016-05-06 20:51:57 +0000804static Error dumpStructure(RawSession &RS) {
Reid Klecknerb0345262016-05-04 16:09:04 +0000805 PDBFile &File = RS.getPDBFile();
806 ScopedPrinter P(outs());
807
Zachary Turner819e77d2016-05-06 20:51:57 +0000808 if (auto EC = dumpFileHeaders(P, File))
809 return EC;
Reid Klecknerb0345262016-05-04 16:09:04 +0000810
Zachary Turner85ed80b2016-05-25 03:43:17 +0000811 if (auto EC = dumpStreamSummary(P, File))
Zachary Turner819e77d2016-05-06 20:51:57 +0000812 return EC;
Reid Klecknerb0345262016-05-04 16:09:04 +0000813
Zachary Turner819e77d2016-05-06 20:51:57 +0000814 if (auto EC = dumpStreamBlocks(P, File))
815 return EC;
Reid Klecknerb0345262016-05-04 16:09:04 +0000816
Zachary Turner819e77d2016-05-06 20:51:57 +0000817 if (auto EC = dumpStreamData(P, File))
818 return EC;
Reid Klecknerb0345262016-05-04 16:09:04 +0000819
Zachary Turner819e77d2016-05-06 20:51:57 +0000820 if (auto EC = dumpInfoStream(P, File))
821 return EC;
Reid Klecknerb0345262016-05-04 16:09:04 +0000822
Zachary Turner96e60f72016-05-24 20:31:48 +0000823 if (auto EC = dumpNamedStream(P, File))
Zachary Turner819e77d2016-05-06 20:51:57 +0000824 return EC;
Reid Klecknerb0345262016-05-04 16:09:04 +0000825
Reid Klecknerfbdbe9e2016-05-31 18:45:36 +0000826 codeview::CVTypeDumper TD(&P, false);
Zachary Turnerc9972c62016-05-25 04:35:22 +0000827 if (auto EC = dumpTpiStream(P, File, TD, StreamTPI))
828 return EC;
Rui Ueyama90db7882016-06-02 18:20:20 +0000829
Zachary Turnerc9972c62016-05-25 04:35:22 +0000830 if (auto EC = dumpTpiStream(P, File, TD, StreamIPI))
Zachary Turner819e77d2016-05-06 20:51:57 +0000831 return EC;
Reid Klecknerb0345262016-05-04 16:09:04 +0000832
Zachary Turnercac29ae2016-05-24 17:30:25 +0000833 if (auto EC = dumpDbiStream(P, File, TD))
Zachary Turner819e77d2016-05-06 20:51:57 +0000834 return EC;
Rui Ueyama1f6b6e22016-05-13 21:21:53 +0000835
Zachary Turner93839cb2016-06-02 05:07:49 +0000836 if (auto EC = dumpSectionContribs(P, File))
837 return EC;
838
839 if (auto EC = dumpSectionMap(P, File))
840 return EC;
841
Zachary Turner9e33e6f2016-05-24 18:55:14 +0000842 if (auto EC = dumpPublicsStream(P, File, TD))
Rui Ueyama1f6b6e22016-05-13 21:21:53 +0000843 return EC;
Zachary Turner93839cb2016-06-02 05:07:49 +0000844
Rui Ueyama90db7882016-06-02 18:20:20 +0000845 if (auto EC = dumpSectionHeaders(P, File, TD))
846 return EC;
Zachary Turner96e60f72016-05-24 20:31:48 +0000847 return Error::success();
848}
849
850bool isRawDumpEnabled() {
851 if (opts::DumpHeaders)
852 return true;
853 if (opts::DumpModules)
854 return true;
855 if (opts::DumpModuleFiles)
856 return true;
857 if (opts::DumpModuleSyms)
858 return true;
859 if (!opts::DumpStreamDataIdx.empty())
860 return true;
861 if (!opts::DumpStreamDataName.empty())
862 return true;
863 if (opts::DumpPublics)
864 return true;
Zachary Turner85ed80b2016-05-25 03:43:17 +0000865 if (opts::DumpStreamSummary)
Zachary Turner96e60f72016-05-24 20:31:48 +0000866 return true;
Zachary Turner85ed80b2016-05-25 03:43:17 +0000867 if (opts::DumpStreamBlocks)
Zachary Turner96e60f72016-05-24 20:31:48 +0000868 return true;
869 if (opts::DumpSymRecordBytes)
870 return true;
871 if (opts::DumpTpiRecordBytes)
872 return true;
873 if (opts::DumpTpiRecords)
874 return true;
Zachary Turnerc9972c62016-05-25 04:35:22 +0000875 if (opts::DumpIpiRecords)
876 return true;
877 if (opts::DumpIpiRecordBytes)
878 return true;
Zachary Turner93839cb2016-06-02 05:07:49 +0000879 if (opts::DumpSectionContribs)
880 return true;
881 if (opts::DumpSectionMap)
882 return true;
Zachary Turner7eb6d352016-06-02 20:11:22 +0000883 if (opts::DumpLineInfo)
884 return true;
Zachary Turner96e60f72016-05-24 20:31:48 +0000885 return false;
David Majnemer1573b242016-04-28 23:47:27 +0000886}
887
888static void dumpInput(StringRef Path) {
889 std::unique_ptr<IPDBSession> Session;
Zachary Turner96e60f72016-05-24 20:31:48 +0000890 if (isRawDumpEnabled()) {
David Majnemerc165c882016-05-28 18:25:15 +0000891 ExitOnErr(loadDataForPDB(PDB_ReaderType::Raw, Path, Session));
David Majnemer1573b242016-04-28 23:47:27 +0000892
David Majnemerc165c882016-05-28 18:25:15 +0000893 RawSession *RS = static_cast<RawSession *>(Session.get());
894 ExitOnErr(dumpStructure(*RS));
David Majnemer1573b242016-04-28 23:47:27 +0000895 return;
896 }
897
David Majnemerc165c882016-05-28 18:25:15 +0000898 ExitOnErr(loadDataForPDB(PDB_ReaderType::DIA, Path, Session));
David Majnemer1573b242016-04-28 23:47:27 +0000899
Zachary Turnere5cb2692015-05-01 20:24:26 +0000900 if (opts::LoadAddress)
901 Session->setLoadAddress(opts::LoadAddress);
Zachary Turner7058dfc2015-01-27 22:40:14 +0000902
Zachary Turner2d11c202015-02-27 09:15:59 +0000903 LinePrinter Printer(2, outs());
904
Zachary Turnera5549172015-02-10 22:43:25 +0000905 auto GlobalScope(Session->getGlobalScope());
Zachary Turner9a818ad2015-02-22 22:03:38 +0000906 std::string FileName(GlobalScope->getSymbolsFileName());
907
Zachary Turner2d11c202015-02-27 09:15:59 +0000908 WithColor(Printer, PDB_ColorItem::None).get() << "Summary for ";
909 WithColor(Printer, PDB_ColorItem::Path).get() << FileName;
910 Printer.Indent();
Zachary Turner9a818ad2015-02-22 22:03:38 +0000911 uint64_t FileSize = 0;
Zachary Turner9a818ad2015-02-22 22:03:38 +0000912
Zachary Turner2d11c202015-02-27 09:15:59 +0000913 Printer.NewLine();
914 WithColor(Printer, PDB_ColorItem::Identifier).get() << "Size";
David Majnemer6e081262015-10-15 01:27:19 +0000915 if (!sys::fs::file_size(FileName, FileSize)) {
Zachary Turner2d11c202015-02-27 09:15:59 +0000916 Printer << ": " << FileSize << " bytes";
917 } else {
918 Printer << ": (Unable to obtain file size)";
919 }
920
921 Printer.NewLine();
922 WithColor(Printer, PDB_ColorItem::Identifier).get() << "Guid";
923 Printer << ": " << GlobalScope->getGuid();
924
925 Printer.NewLine();
926 WithColor(Printer, PDB_ColorItem::Identifier).get() << "Age";
927 Printer << ": " << GlobalScope->getAge();
928
929 Printer.NewLine();
930 WithColor(Printer, PDB_ColorItem::Identifier).get() << "Attributes";
931 Printer << ": ";
Zachary Turner9a818ad2015-02-22 22:03:38 +0000932 if (GlobalScope->hasCTypes())
933 outs() << "HasCTypes ";
934 if (GlobalScope->hasPrivateSymbols())
935 outs() << "HasPrivateSymbols ";
Zachary Turner2d11c202015-02-27 09:15:59 +0000936 Printer.Unindent();
Zachary Turner9a818ad2015-02-22 22:03:38 +0000937
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000938 if (opts::Compilands) {
Zachary Turner2d11c202015-02-27 09:15:59 +0000939 Printer.NewLine();
940 WithColor(Printer, PDB_ColorItem::SectionHeader).get()
941 << "---COMPILANDS---";
942 Printer.Indent();
Zachary Turnerc074de02015-02-12 21:09:24 +0000943 auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>();
Zachary Turner2d11c202015-02-27 09:15:59 +0000944 CompilandDumper Dumper(Printer);
Zachary Turnera99000d2016-03-08 21:42:24 +0000945 CompilandDumpFlags options = CompilandDumper::Flags::None;
946 if (opts::Lines)
947 options = options | CompilandDumper::Flags::Lines;
Zachary Turner9a818ad2015-02-22 22:03:38 +0000948 while (auto Compiland = Compilands->getNext())
Zachary Turnera99000d2016-03-08 21:42:24 +0000949 Dumper.start(*Compiland, options);
Zachary Turner2d11c202015-02-27 09:15:59 +0000950 Printer.Unindent();
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000951 }
952
953 if (opts::Types) {
Zachary Turner2d11c202015-02-27 09:15:59 +0000954 Printer.NewLine();
955 WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---TYPES---";
956 Printer.Indent();
Zachary Turner65323652015-03-04 06:09:53 +0000957 TypeDumper Dumper(Printer);
Zachary Turnerb52d08d2015-03-01 06:51:29 +0000958 Dumper.start(*GlobalScope);
Zachary Turner2d11c202015-02-27 09:15:59 +0000959 Printer.Unindent();
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000960 }
961
962 if (opts::Symbols) {
Zachary Turner2d11c202015-02-27 09:15:59 +0000963 Printer.NewLine();
964 WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---SYMBOLS---";
965 Printer.Indent();
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000966 auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>();
Zachary Turner2d11c202015-02-27 09:15:59 +0000967 CompilandDumper Dumper(Printer);
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000968 while (auto Compiland = Compilands->getNext())
Zachary Turnerb52d08d2015-03-01 06:51:29 +0000969 Dumper.start(*Compiland, true);
Zachary Turner2d11c202015-02-27 09:15:59 +0000970 Printer.Unindent();
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000971 }
972
973 if (opts::Globals) {
Zachary Turner2d11c202015-02-27 09:15:59 +0000974 Printer.NewLine();
975 WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---GLOBALS---";
976 Printer.Indent();
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000977 {
Zachary Turner2d11c202015-02-27 09:15:59 +0000978 FunctionDumper Dumper(Printer);
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000979 auto Functions = GlobalScope->findAllChildren<PDBSymbolFunc>();
Zachary Turner2d11c202015-02-27 09:15:59 +0000980 while (auto Function = Functions->getNext()) {
981 Printer.NewLine();
Zachary Turnerb52d08d2015-03-01 06:51:29 +0000982 Dumper.start(*Function, FunctionDumper::PointerType::None);
Zachary Turner2d11c202015-02-27 09:15:59 +0000983 }
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000984 }
985 {
986 auto Vars = GlobalScope->findAllChildren<PDBSymbolData>();
Zachary Turner2d11c202015-02-27 09:15:59 +0000987 VariableDumper Dumper(Printer);
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000988 while (auto Var = Vars->getNext())
Zachary Turnerb52d08d2015-03-01 06:51:29 +0000989 Dumper.start(*Var);
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000990 }
991 {
992 auto Thunks = GlobalScope->findAllChildren<PDBSymbolThunk>();
Zachary Turner2d11c202015-02-27 09:15:59 +0000993 CompilandDumper Dumper(Printer);
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000994 while (auto Thunk = Thunks->getNext())
Zachary Turnerb52d08d2015-03-01 06:51:29 +0000995 Dumper.dump(*Thunk);
Zachary Turnerdb18f5c2015-02-27 09:15:18 +0000996 }
Zachary Turner2d11c202015-02-27 09:15:59 +0000997 Printer.Unindent();
Zachary Turner7058dfc2015-01-27 22:40:14 +0000998 }
Zachary Turnere5cb2692015-05-01 20:24:26 +0000999 if (opts::Externals) {
1000 Printer.NewLine();
1001 WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---EXTERNALS---";
1002 Printer.Indent();
1003 ExternalSymbolDumper Dumper(Printer);
1004 Dumper.start(*GlobalScope);
1005 }
Zachary Turnera99000d2016-03-08 21:42:24 +00001006 if (opts::Lines) {
1007 Printer.NewLine();
1008 }
Zachary Turnera5549172015-02-10 22:43:25 +00001009 outs().flush();
Zachary Turnerfcb14ad2015-01-27 20:46:21 +00001010}
1011
1012int main(int argc_, const char *argv_[]) {
1013 // Print a stack trace if we signal out.
1014 sys::PrintStackTraceOnErrorSignal();
1015 PrettyStackTraceProgram X(argc_, argv_);
1016
David Majnemerc165c882016-05-28 18:25:15 +00001017 ExitOnErr.setBanner("llvm-pdbdump: ");
1018
Zachary Turnerfcb14ad2015-01-27 20:46:21 +00001019 SmallVector<const char *, 256> argv;
David Majnemer6e081262015-10-15 01:27:19 +00001020 SpecificBumpPtrAllocator<char> ArgAllocator;
David Majnemerc165c882016-05-28 18:25:15 +00001021 ExitOnErr(errorCodeToError(sys::Process::GetArgumentVector(
1022 argv, makeArrayRef(argv_, argc_), ArgAllocator)));
Zachary Turnerfcb14ad2015-01-27 20:46:21 +00001023
1024 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
1025
1026 cl::ParseCommandLineOptions(argv.size(), argv.data(), "LLVM PDB Dumper\n");
Zachary Turnera99000d2016-03-08 21:42:24 +00001027 if (opts::Lines)
1028 opts::Compilands = true;
1029
Zachary Turner7797c722015-03-02 04:39:56 +00001030 if (opts::All) {
1031 opts::Compilands = true;
1032 opts::Symbols = true;
1033 opts::Globals = true;
1034 opts::Types = true;
Zachary Turnere5cb2692015-05-01 20:24:26 +00001035 opts::Externals = true;
Zachary Turnera99000d2016-03-08 21:42:24 +00001036 opts::Lines = true;
Zachary Turner7797c722015-03-02 04:39:56 +00001037 }
Zachary Turnera99000d2016-03-08 21:42:24 +00001038
Rui Ueyama9dc034d2016-05-26 23:26:55 +00001039 if (opts::RawAll) {
1040 opts::DumpHeaders = true;
1041 opts::DumpModules = true;
1042 opts::DumpModuleFiles = true;
1043 opts::DumpModuleSyms = true;
1044 opts::DumpPublics = true;
Rui Ueyama90db7882016-06-02 18:20:20 +00001045 opts::DumpSectionHeaders = true;
Rui Ueyama9dc034d2016-05-26 23:26:55 +00001046 opts::DumpStreamSummary = true;
1047 opts::DumpStreamBlocks = true;
1048 opts::DumpTpiRecords = true;
1049 opts::DumpIpiRecords = true;
Zachary Turner93839cb2016-06-02 05:07:49 +00001050 opts::DumpSectionMap = true;
1051 opts::DumpSectionContribs = true;
Zachary Turner7eb6d352016-06-02 20:11:22 +00001052 opts::DumpLineInfo = true;
Rui Ueyama9dc034d2016-05-26 23:26:55 +00001053 }
1054
Zachary Turnera99000d2016-03-08 21:42:24 +00001055 // When adding filters for excluded compilands and types, we need to remember
1056 // that these are regexes. So special characters such as * and \ need to be
1057 // escaped in the regex. In the case of a literal \, this means it needs to
1058 // be escaped again in the C++. So matching a single \ in the input requires
1059 // 4 \es in the C++.
Zachary Turner7797c722015-03-02 04:39:56 +00001060 if (opts::ExcludeCompilerGenerated) {
1061 opts::ExcludeTypes.push_back("__vc_attributes");
Zachary Turnera99000d2016-03-08 21:42:24 +00001062 opts::ExcludeCompilands.push_back("\\* Linker \\*");
Zachary Turner7797c722015-03-02 04:39:56 +00001063 }
1064 if (opts::ExcludeSystemLibraries) {
1065 opts::ExcludeCompilands.push_back(
Zachary Turnera99000d2016-03-08 21:42:24 +00001066 "f:\\\\binaries\\\\Intermediate\\\\vctools\\\\crt_bld");
1067 opts::ExcludeCompilands.push_back("f:\\\\dd\\\\vctools\\\\crt");
1068 opts::ExcludeCompilands.push_back("d:\\\\th.obj.x86fre\\\\minkernel");
Zachary Turner7797c722015-03-02 04:39:56 +00001069 }
Zachary Turnerfcb14ad2015-01-27 20:46:21 +00001070
Zachary Turner93839cb2016-06-02 05:07:49 +00001071 llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded);
Zachary Turnerfcb14ad2015-01-27 20:46:21 +00001072
1073 std::for_each(opts::InputFilenames.begin(), opts::InputFilenames.end(),
1074 dumpInput);
1075
Zachary Turner819e77d2016-05-06 20:51:57 +00001076 outs().flush();
Zachary Turnerfcb14ad2015-01-27 20:46:21 +00001077 return 0;
1078}