aboutsummaryrefslogtreecommitdiffstats
path: root/tools/llvm-pdbdump
diff options
context:
space:
mode:
authorStephen Hines <srhines@google.com>2015-03-23 12:10:34 -0700
committerStephen Hines <srhines@google.com>2015-03-23 12:10:34 -0700
commitebe69fe11e48d322045d5949c83283927a0d790b (patch)
treec92f1907a6b8006628a4b01615f38264d29834ea /tools/llvm-pdbdump
parentb7d2e72b02a4cb8034f32f8247a2558d2434e121 (diff)
downloadexternal_llvm-ebe69fe11e48d322045d5949c83283927a0d790b.zip
external_llvm-ebe69fe11e48d322045d5949c83283927a0d790b.tar.gz
external_llvm-ebe69fe11e48d322045d5949c83283927a0d790b.tar.bz2
Update aosp/master LLVM for rebase to r230699.
Change-Id: I2b5be30509658cb8266be782de0ab24f9099f9b9
Diffstat (limited to 'tools/llvm-pdbdump')
-rw-r--r--tools/llvm-pdbdump/CMakeLists.txt14
-rw-r--r--tools/llvm-pdbdump/ClassDefinitionDumper.cpp152
-rw-r--r--tools/llvm-pdbdump/ClassDefinitionDumper.h64
-rw-r--r--tools/llvm-pdbdump/CompilandDumper.cpp117
-rw-r--r--tools/llvm-pdbdump/CompilandDumper.h39
-rw-r--r--tools/llvm-pdbdump/FunctionDumper.cpp243
-rw-r--r--tools/llvm-pdbdump/FunctionDumper.h45
-rw-r--r--tools/llvm-pdbdump/LLVMBuild.txt23
-rw-r--r--tools/llvm-pdbdump/Makefile17
-rw-r--r--tools/llvm-pdbdump/TypeDumper.cpp96
-rw-r--r--tools/llvm-pdbdump/TypeDumper.h38
-rw-r--r--tools/llvm-pdbdump/TypedefDumper.cpp84
-rw-r--r--tools/llvm-pdbdump/TypedefDumper.h38
-rw-r--r--tools/llvm-pdbdump/VariableDumper.cpp120
-rw-r--r--tools/llvm-pdbdump/VariableDumper.h43
-rw-r--r--tools/llvm-pdbdump/llvm-pdbdump.cpp134
-rw-r--r--tools/llvm-pdbdump/llvm-pdbdump.h28
17 files changed, 1295 insertions, 0 deletions
diff --git a/tools/llvm-pdbdump/CMakeLists.txt b/tools/llvm-pdbdump/CMakeLists.txt
new file mode 100644
index 0000000..0519bf0
--- /dev/null
+++ b/tools/llvm-pdbdump/CMakeLists.txt
@@ -0,0 +1,14 @@
+set(LLVM_LINK_COMPONENTS
+ Support
+ DebugInfoPDB
+ )
+
+add_llvm_tool(llvm-pdbdump
+ llvm-pdbdump.cpp
+ ClassDefinitionDumper.cpp
+ CompilandDumper.cpp
+ FunctionDumper.cpp
+ TypeDumper.cpp
+ TypedefDumper.cpp
+ VariableDumper.cpp
+ )
diff --git a/tools/llvm-pdbdump/ClassDefinitionDumper.cpp b/tools/llvm-pdbdump/ClassDefinitionDumper.cpp
new file mode 100644
index 0000000..edf6eb4
--- /dev/null
+++ b/tools/llvm-pdbdump/ClassDefinitionDumper.cpp
@@ -0,0 +1,152 @@
+//===- ClassDefinitionDumper.cpp --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClassDefinitionDumper.h"
+#include "FunctionDumper.h"
+#include "llvm-pdbdump.h"
+#include "TypedefDumper.h"
+#include "VariableDumper.h"
+
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/PDBExtras.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h"
+#include "llvm/Support/Format.h"
+
+using namespace llvm;
+
+ClassDefinitionDumper::ClassDefinitionDumper() : PDBSymDumper(true) {}
+
+void ClassDefinitionDumper::start(const PDBSymbolTypeUDT &Class,
+ raw_ostream &OS, int Indent) {
+ OS << "class " << Class.getName() << " {";
+ auto Children = Class.findAllChildren();
+ if (Children->getChildCount() == 0) {
+ OS << "}";
+ return;
+ }
+
+ // Try to dump symbols organized by member access level. Public members
+ // first, then protected, then private. This might be slow, so it's worth
+ // reconsidering the value of this if performance of large PDBs is a problem.
+ // NOTE: Access level of nested types is not recorded in the PDB, so we have
+ // a special case for them.
+ SymbolGroupByAccess Groups;
+ Groups.insert(std::make_pair(0, SymbolGroup()));
+ Groups.insert(std::make_pair((int)PDB_MemberAccess::Private, SymbolGroup()));
+ Groups.insert(
+ std::make_pair((int)PDB_MemberAccess::Protected, SymbolGroup()));
+ Groups.insert(std::make_pair((int)PDB_MemberAccess::Public, SymbolGroup()));
+
+ while (auto Child = Children->getNext()) {
+ PDB_MemberAccess Access = Child->getRawSymbol().getAccess();
+ if (isa<PDBSymbolTypeBaseClass>(*Child))
+ continue;
+
+ auto &AccessGroup = Groups.find((int)Access)->second;
+
+ if (auto Func = dyn_cast<PDBSymbolFunc>(Child.get())) {
+ if (Func->isCompilerGenerated())
+ continue;
+ if (Func->getLength() == 0 && !Func->isPureVirtual())
+ continue;
+ Child.release();
+ AccessGroup.Functions.push_back(std::unique_ptr<PDBSymbolFunc>(Func));
+ } else if (auto Data = dyn_cast<PDBSymbolData>(Child.get())) {
+ Child.release();
+ AccessGroup.Data.push_back(std::unique_ptr<PDBSymbolData>(Data));
+ } else {
+ AccessGroup.Unknown.push_back(std::move(Child));
+ }
+ }
+
+ int Count = 0;
+ Count += dumpAccessGroup((PDB_MemberAccess)0, Groups[0], OS, Indent);
+ Count += dumpAccessGroup(PDB_MemberAccess::Public,
+ Groups[(int)PDB_MemberAccess::Public], OS, Indent);
+ Count +=
+ dumpAccessGroup(PDB_MemberAccess::Protected,
+ Groups[(int)PDB_MemberAccess::Protected], OS, Indent);
+ Count += dumpAccessGroup(PDB_MemberAccess::Private,
+ Groups[(int)PDB_MemberAccess::Private], OS, Indent);
+
+ if (Count > 0)
+ OS << newline(Indent);
+ OS << "}";
+}
+
+int ClassDefinitionDumper::dumpAccessGroup(PDB_MemberAccess Access,
+ const SymbolGroup &Group,
+ raw_ostream &OS, int Indent) {
+ if (Group.Functions.empty() && Group.Data.empty() && Group.Unknown.empty())
+ return 0;
+
+ int Count = 0;
+ if (Access == PDB_MemberAccess::Private)
+ OS << newline(Indent) << "private:";
+ else if (Access == PDB_MemberAccess::Protected)
+ OS << newline(Indent) << "protected:";
+ else if (Access == PDB_MemberAccess::Public)
+ OS << newline(Indent) << "public:";
+ for (auto iter = Group.Functions.begin(), end = Group.Functions.end();
+ iter != end; ++iter) {
+ ++Count;
+ (*iter)->dump(OS, Indent + 2, *this);
+ }
+ for (auto iter = Group.Data.begin(), end = Group.Data.end(); iter != end;
+ ++iter) {
+ ++Count;
+ (*iter)->dump(OS, Indent + 2, *this);
+ }
+ for (auto iter = Group.Unknown.begin(), end = Group.Unknown.end();
+ iter != end; ++iter) {
+ ++Count;
+ (*iter)->dump(OS, Indent + 2, *this);
+ }
+ return Count;
+}
+
+void ClassDefinitionDumper::dump(const PDBSymbolTypeBaseClass &Symbol,
+ raw_ostream &OS, int Indent) {}
+
+void ClassDefinitionDumper::dump(const PDBSymbolData &Symbol, raw_ostream &OS,
+ int Indent) {
+ VariableDumper Dumper;
+ Dumper.start(Symbol, OS, Indent);
+}
+
+void ClassDefinitionDumper::dump(const PDBSymbolFunc &Symbol, raw_ostream &OS,
+ int Indent) {
+ FunctionDumper Dumper;
+ Dumper.start(Symbol, FunctionDumper::PointerType::None, OS, Indent);
+}
+
+void ClassDefinitionDumper::dump(const PDBSymbolTypeVTable &Symbol,
+ raw_ostream &OS, int Indent) {}
+
+void ClassDefinitionDumper::dump(const PDBSymbolTypeEnum &Symbol,
+ raw_ostream &OS, int Indent) {
+ OS << newline(Indent) << "enum " << Symbol.getName();
+}
+
+void ClassDefinitionDumper::dump(const PDBSymbolTypeTypedef &Symbol,
+ raw_ostream &OS, int Indent) {
+ OS << newline(Indent);
+ TypedefDumper Dumper;
+ Dumper.start(Symbol, OS, Indent);
+}
+
+void ClassDefinitionDumper::dump(const PDBSymbolTypeUDT &Symbol,
+ raw_ostream &OS, int Indent) {}
diff --git a/tools/llvm-pdbdump/ClassDefinitionDumper.h b/tools/llvm-pdbdump/ClassDefinitionDumper.h
new file mode 100644
index 0000000..aaf0376
--- /dev/null
+++ b/tools/llvm-pdbdump/ClassDefinitionDumper.h
@@ -0,0 +1,64 @@
+//===- ClassDefinitionDumper.h - --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_CLASSDEFINITIONDUMPER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_CLASSDEFINITIONDUMPER_H
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+
+#include <list>
+#include <memory>
+#include <unordered_map>
+
+namespace llvm {
+
+class ClassDefinitionDumper : public PDBSymDumper {
+public:
+ ClassDefinitionDumper();
+
+ void start(const PDBSymbolTypeUDT &Exe, raw_ostream &OS, int Indent);
+
+ void dump(const PDBSymbolTypeBaseClass &Symbol, raw_ostream &OS,
+ int Indent) override;
+ void dump(const PDBSymbolData &Symbol, raw_ostream &OS, int Indent) override;
+ void dump(const PDBSymbolTypeEnum &Symbol, raw_ostream &OS,
+ int Indent) override;
+ void dump(const PDBSymbolFunc &Symbol, raw_ostream &OS, int Indent) override;
+ void dump(const PDBSymbolTypeTypedef &Symbol, raw_ostream &OS,
+ int Indent) override;
+ void dump(const PDBSymbolTypeUDT &Symbol, raw_ostream &OS,
+ int Indent) override;
+ void dump(const PDBSymbolTypeVTable &Symbol, raw_ostream &OS,
+ int Indent) override;
+
+private:
+ struct SymbolGroup {
+ SymbolGroup() {}
+ SymbolGroup(SymbolGroup &&Other) {
+ Functions = std::move(Other.Functions);
+ Data = std::move(Other.Data);
+ Unknown = std::move(Other.Unknown);
+ }
+
+ std::list<std::unique_ptr<PDBSymbolFunc>> Functions;
+ std::list<std::unique_ptr<PDBSymbolData>> Data;
+ std::list<std::unique_ptr<PDBSymbol>> Unknown;
+ SymbolGroup(const SymbolGroup &other) = delete;
+ SymbolGroup &operator=(const SymbolGroup &other) = delete;
+ };
+ typedef std::unordered_map<int, SymbolGroup> SymbolGroupByAccess;
+
+ int dumpAccessGroup(PDB_MemberAccess Access, const SymbolGroup &Group,
+ raw_ostream &OS, int Indent);
+};
+}
+
+#endif
diff --git a/tools/llvm-pdbdump/CompilandDumper.cpp b/tools/llvm-pdbdump/CompilandDumper.cpp
new file mode 100644
index 0000000..852ddfa
--- /dev/null
+++ b/tools/llvm-pdbdump/CompilandDumper.cpp
@@ -0,0 +1,117 @@
+//===- CompilandDumper.cpp - llvm-pdbdump compiland symbol dumper *- C++ *-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CompilandDumper.h"
+#include "llvm-pdbdump.h"
+
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/PDBExtras.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolLabel.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolThunk.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolUnknown.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include "FunctionDumper.h"
+
+#include <utility>
+#include <vector>
+
+using namespace llvm;
+
+CompilandDumper::CompilandDumper() : PDBSymDumper(true) {}
+
+void CompilandDumper::dump(const PDBSymbolCompilandDetails &Symbol,
+ raw_ostream &OS, int Indent) {}
+
+void CompilandDumper::dump(const PDBSymbolCompilandEnv &Symbol, raw_ostream &OS,
+ int Indent) {}
+
+void CompilandDumper::start(const PDBSymbolCompiland &Symbol, raw_ostream &OS,
+ int Indent, bool Children) {
+ std::string FullName = Symbol.getName();
+ OS << newline(Indent) << FullName;
+ if (!Children)
+ return;
+
+ auto ChildrenEnum = Symbol.findAllChildren();
+ while (auto Child = ChildrenEnum->getNext())
+ Child->dump(OS, Indent + 2, *this);
+}
+
+void CompilandDumper::dump(const PDBSymbolData &Symbol, raw_ostream &OS,
+ int Indent) {
+ OS << newline(Indent);
+ switch (auto LocType = Symbol.getLocationType()) {
+ case PDB_LocType::Static:
+ OS << "data: [";
+ OS << format_hex(Symbol.getRelativeVirtualAddress(), 10);
+ OS << "]";
+ break;
+ case PDB_LocType::Constant:
+ OS << "constant: [" << Symbol.getValue() << "]";
+ break;
+ default:
+ OS << "data(unexpected type=" << LocType << ")";
+ }
+
+ OS << " " << Symbol.getName();
+}
+
+void CompilandDumper::dump(const PDBSymbolFunc &Symbol, raw_ostream &OS,
+ int Indent) {
+ if (Symbol.getLength() == 0)
+ return;
+
+ FunctionDumper Dumper;
+ Dumper.start(Symbol, FunctionDumper::PointerType::None, OS, Indent);
+}
+
+void CompilandDumper::dump(const PDBSymbolLabel &Symbol, raw_ostream &OS,
+ int Indent) {
+ OS << newline(Indent);
+ OS << "label [" << format_hex(Symbol.getRelativeVirtualAddress(), 10) << "] "
+ << Symbol.getName();
+}
+
+void CompilandDumper::dump(const PDBSymbolThunk &Symbol, raw_ostream &OS,
+ int Indent) {
+ OS << newline(Indent) << "thunk ";
+ PDB_ThunkOrdinal Ordinal = Symbol.getThunkOrdinal();
+ uint32_t RVA = Symbol.getRelativeVirtualAddress();
+ if (Ordinal == PDB_ThunkOrdinal::TrampIncremental) {
+ OS << format_hex(RVA, 10);
+ OS << " -> " << format_hex(Symbol.getTargetRelativeVirtualAddress(), 10);
+ } else {
+ OS << "[" << format_hex(RVA, 10);
+ OS << " - " << format_hex(RVA + Symbol.getLength(), 10) << "]";
+ }
+ OS << " (" << Ordinal << ") ";
+ std::string Name = Symbol.getName();
+ if (!Name.empty())
+ OS << Name;
+}
+
+void CompilandDumper::dump(const PDBSymbolTypeTypedef &Symbol, raw_ostream &OS,
+ int Indent) {}
+
+void CompilandDumper::dump(const PDBSymbolUnknown &Symbol, raw_ostream &OS,
+ int Indent) {
+ OS << newline(Indent);
+ OS << "unknown (" << Symbol.getSymTag() << ")";
+}
diff --git a/tools/llvm-pdbdump/CompilandDumper.h b/tools/llvm-pdbdump/CompilandDumper.h
new file mode 100644
index 0000000..abcebc2
--- /dev/null
+++ b/tools/llvm-pdbdump/CompilandDumper.h
@@ -0,0 +1,39 @@
+//===- CompilandDumper.h - llvm-pdbdump compiland symbol dumper *- C++ --*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_COMPILANDDUMPER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_COMPILANDDUMPER_H
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+namespace llvm {
+
+class CompilandDumper : public PDBSymDumper {
+public:
+ CompilandDumper();
+
+ void start(const PDBSymbolCompiland &Symbol, raw_ostream &OS, int Indent,
+ bool Children);
+
+ void dump(const PDBSymbolCompilandDetails &Symbol, raw_ostream &OS,
+ int Indent) override;
+ void dump(const PDBSymbolCompilandEnv &Symbol, raw_ostream &OS,
+ int Indent) override;
+ void dump(const PDBSymbolData &Symbol, raw_ostream &OS, int Indent) override;
+ void dump(const PDBSymbolFunc &Symbol, raw_ostream &OS, int Indent) override;
+ void dump(const PDBSymbolLabel &Symbol, raw_ostream &OS, int Indent) override;
+ void dump(const PDBSymbolThunk &Symbol, raw_ostream &OS, int Indent) override;
+ void dump(const PDBSymbolTypeTypedef &Symbol, raw_ostream &OS,
+ int Indent) override;
+ void dump(const PDBSymbolUnknown &Symbol, raw_ostream &OS,
+ int Indent) override;
+};
+}
+
+#endif
diff --git a/tools/llvm-pdbdump/FunctionDumper.cpp b/tools/llvm-pdbdump/FunctionDumper.cpp
new file mode 100644
index 0000000..e659830
--- /dev/null
+++ b/tools/llvm-pdbdump/FunctionDumper.cpp
@@ -0,0 +1,243 @@
+//===- FunctionDumper.cpp ------------------------------------ *- C++ *-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "FunctionDumper.h"
+#include "llvm-pdbdump.h"
+
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+#include "llvm/Support/Format.h"
+
+using namespace llvm;
+
+namespace {
+template <class T>
+void dumpClassParentWithScopeOperator(const T &Symbol, llvm::raw_ostream &OS,
+ llvm::FunctionDumper &Dumper) {
+ uint32_t ClassParentId = Symbol.getClassParentId();
+ auto ClassParent =
+ Symbol.getSession().template getConcreteSymbolById<PDBSymbolTypeUDT>(
+ ClassParentId);
+ if (!ClassParent)
+ return;
+
+ OS << ClassParent->getName() << "::";
+}
+}
+
+FunctionDumper::FunctionDumper() : PDBSymDumper(true) {}
+
+void FunctionDumper::start(const PDBSymbolTypeFunctionSig &Symbol,
+ PointerType Pointer, raw_ostream &OS) {
+ auto ReturnType = Symbol.getReturnType();
+ ReturnType->dump(OS, 0, *this);
+ OS << " ";
+ uint32_t ClassParentId = Symbol.getClassParentId();
+ auto ClassParent =
+ Symbol.getSession().getConcreteSymbolById<PDBSymbolTypeUDT>(
+ ClassParentId);
+
+ PDB_CallingConv CC = Symbol.getCallingConvention();
+ bool ShouldDumpCallingConvention = true;
+ if ((ClassParent && CC == PDB_CallingConv::Thiscall) ||
+ (!ClassParent && CC == PDB_CallingConv::NearStdcall)) {
+ ShouldDumpCallingConvention = false;
+ }
+
+ if (Pointer == PointerType::None) {
+ if (ShouldDumpCallingConvention)
+ OS << CC << " ";
+ if (ClassParent)
+ OS << "(" << ClassParent->getName() << "::)";
+ } else {
+ OS << "(";
+ if (ShouldDumpCallingConvention)
+ OS << CC << " ";
+ OS << Symbol.getCallingConvention() << " ";
+ if (ClassParent)
+ OS << ClassParent->getName() << "::";
+ if (Pointer == PointerType::Reference)
+ OS << "&";
+ else
+ OS << "*";
+ OS << ")";
+ }
+
+ OS << "(";
+ if (auto ChildEnum = Symbol.getArguments()) {
+ uint32_t Index = 0;
+ while (auto Arg = ChildEnum->getNext()) {
+ Arg->dump(OS, 0, *this);
+ if (++Index < ChildEnum->getChildCount())
+ OS << ", ";
+ }
+ }
+ OS << ")";
+
+ if (Symbol.isConstType())
+ OS << " const";
+ if (Symbol.isVolatileType())
+ OS << " volatile";
+}
+
+void FunctionDumper::start(const PDBSymbolFunc &Symbol, PointerType Pointer,
+ raw_ostream &OS, int Indent) {
+ uint32_t FuncStart = Symbol.getRelativeVirtualAddress();
+ uint32_t FuncEnd = FuncStart + Symbol.getLength();
+
+ OS << newline(Indent);
+
+ OS << "func [" << format_hex(FuncStart, 8);
+ if (auto DebugStart = Symbol.findOneChild<PDBSymbolFuncDebugStart>())
+ OS << "+" << DebugStart->getRelativeVirtualAddress() - FuncStart;
+ OS << " - " << format_hex(FuncEnd, 8);
+ if (auto DebugEnd = Symbol.findOneChild<PDBSymbolFuncDebugEnd>())
+ OS << "-" << FuncEnd - DebugEnd->getRelativeVirtualAddress();
+ OS << "] ";
+
+ if (Symbol.hasFramePointer())
+ OS << "(" << Symbol.getLocalBasePointerRegisterId() << ")";
+ else
+ OS << "(FPO)";
+
+ OS << " ";
+ if (Symbol.isVirtual() || Symbol.isPureVirtual())
+ OS << "virtual ";
+
+ auto Signature = Symbol.getSignature();
+ if (!Signature) {
+ OS << Symbol.getName();
+ if (Pointer == PointerType::Pointer)
+ OS << "*";
+ else if (Pointer == FunctionDumper::PointerType::Reference)
+ OS << "&";
+ return;
+ }
+
+ auto ReturnType = Signature->getReturnType();
+ ReturnType->dump(OS, 0, *this);
+ OS << " ";
+
+ auto ClassParent = Symbol.getClassParent();
+ PDB_CallingConv CC = Signature->getCallingConvention();
+ if (Pointer != FunctionDumper::PointerType::None)
+ OS << "(";
+
+ if ((ClassParent && CC != PDB_CallingConv::Thiscall) ||
+ (!ClassParent && CC != PDB_CallingConv::NearStdcall))
+ OS << Signature->getCallingConvention() << " ";
+ OS << Symbol.getName();
+ if (Pointer != FunctionDumper::PointerType::None) {
+ if (Pointer == PointerType::Pointer)
+ OS << "*";
+ else if (Pointer == FunctionDumper::PointerType::Reference)
+ OS << "&";
+ OS << ")";
+ }
+
+ OS << "(";
+ if (auto Arguments = Symbol.getArguments()) {
+ uint32_t Index = 0;
+ while (auto Arg = Arguments->getNext()) {
+ auto ArgType = Arg->getType();
+ ArgType->dump(OS, 0, *this);
+ OS << " " << Arg->getName();
+ if (++Index < Arguments->getChildCount())
+ OS << ", ";
+ }
+ }
+ OS << ")";
+ if (Symbol.isConstType())
+ OS << " const";
+ if (Symbol.isVolatileType())
+ OS << " volatile";
+ if (Symbol.isPureVirtual())
+ OS << " = 0";
+}
+
+void FunctionDumper::dump(const PDBSymbolTypeArray &Symbol, raw_ostream &OS,
+ int Indent) {
+ uint32_t ElementTypeId = Symbol.getTypeId();
+ auto ElementType = Symbol.getSession().getSymbolById(ElementTypeId);
+ if (!ElementType)
+ return;
+
+ ElementType->dump(OS, 0, *this);
+ OS << "[" << Symbol.getLength() << "]";
+}
+
+void FunctionDumper::dump(const PDBSymbolTypeBuiltin &Symbol, raw_ostream &OS,
+ int Indent) {
+ PDB_BuiltinType Type = Symbol.getBuiltinType();
+ OS << Type;
+ if (Type == PDB_BuiltinType::UInt || Type == PDB_BuiltinType::Int)
+ OS << (8 * Symbol.getLength()) << "_t";
+}
+
+void FunctionDumper::dump(const PDBSymbolTypeEnum &Symbol, raw_ostream &OS,
+ int Indent) {
+ dumpClassParentWithScopeOperator(Symbol, OS, *this);
+ OS << Symbol.getName();
+}
+
+void FunctionDumper::dump(const PDBSymbolTypeFunctionArg &Symbol,
+ raw_ostream &OS, int Indent) {
+ // PDBSymbolTypeFunctionArg is just a shim over the real argument. Just drill
+ // through to the real thing and dump it.
+ Symbol.defaultDump(OS, Indent);
+ uint32_t TypeId = Symbol.getTypeId();
+ auto Type = Symbol.getSession().getSymbolById(TypeId);
+ if (!Type)
+ return;
+ Type->dump(OS, 0, *this);
+}
+
+void FunctionDumper::dump(const PDBSymbolTypeTypedef &Symbol, raw_ostream &OS,
+ int Indent) {
+ dumpClassParentWithScopeOperator(Symbol, OS, *this);
+ OS << Symbol.getName();
+}
+
+void FunctionDumper::dump(const PDBSymbolTypePointer &Symbol, raw_ostream &OS,
+ int Indent) {
+ uint32_t PointeeId = Symbol.getTypeId();
+ auto PointeeType = Symbol.getSession().getSymbolById(PointeeId);
+ if (!PointeeType)
+ return;
+
+ if (auto FuncSig = dyn_cast<PDBSymbolTypeFunctionSig>(PointeeType.get())) {
+ FunctionDumper NestedDumper;
+ PointerType Pointer =
+ Symbol.isReference() ? PointerType::Reference : PointerType::Pointer;
+ NestedDumper.start(*FuncSig, Pointer, OS);
+ } else {
+ if (Symbol.isConstType())
+ OS << "const ";
+ if (Symbol.isVolatileType())
+ OS << "volatile ";
+ PointeeType->dump(OS, Indent, *this);
+ OS << (Symbol.isReference() ? "&" : "*");
+ }
+}
+
+void FunctionDumper::dump(const PDBSymbolTypeUDT &Symbol, raw_ostream &OS,
+ int Indent) {
+ OS << Symbol.getName();
+}
diff --git a/tools/llvm-pdbdump/FunctionDumper.h b/tools/llvm-pdbdump/FunctionDumper.h
new file mode 100644
index 0000000..f9338cb
--- /dev/null
+++ b/tools/llvm-pdbdump/FunctionDumper.h
@@ -0,0 +1,45 @@
+//===- FunctionDumper.h --------------------------------------- *- C++ --*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_FUNCTIONDUMPER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_FUNCTIONDUMPER_H
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+namespace llvm {
+
+class FunctionDumper : public PDBSymDumper {
+public:
+ FunctionDumper();
+
+ enum class PointerType { None, Pointer, Reference };
+
+ void start(const PDBSymbolTypeFunctionSig &Symbol, PointerType Pointer,
+ raw_ostream &OS);
+ void start(const PDBSymbolFunc &Symbol, PointerType Pointer, raw_ostream &OS,
+ int Indent);
+
+ void dump(const PDBSymbolTypeArray &Symbol, raw_ostream &OS,
+ int Indent) override;
+ void dump(const PDBSymbolTypeBuiltin &Symbol, raw_ostream &OS,
+ int Indent) override;
+ void dump(const PDBSymbolTypeEnum &Symbol, raw_ostream &OS,
+ int Indent) override;
+ void dump(const PDBSymbolTypeFunctionArg &Symbol, raw_ostream &OS,
+ int Indent) override;
+ void dump(const PDBSymbolTypePointer &Symbol, raw_ostream &OS,
+ int Indent) override;
+ void dump(const PDBSymbolTypeTypedef &Symbol, raw_ostream &OS,
+ int Indent) override;
+ void dump(const PDBSymbolTypeUDT &Symbol, raw_ostream &OS,
+ int Indent) override;
+};
+}
+
+#endif
diff --git a/tools/llvm-pdbdump/LLVMBuild.txt b/tools/llvm-pdbdump/LLVMBuild.txt
new file mode 100644
index 0000000..4877689
--- /dev/null
+++ b/tools/llvm-pdbdump/LLVMBuild.txt
@@ -0,0 +1,23 @@
+;===- ./tools/llvm-pdbdump/LLVMBuild.txt -----------------------*- Conf -*--===;
+;
+; The LLVM Compiler Infrastructure
+;
+; This file is distributed under the University of Illinois Open Source
+; License. See LICENSE.TXT for details.
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+; http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[component_0]
+type = Tool
+name = llvm-pdbdump
+parent = Tools
+required_libraries = DebugInfoPDB
+
diff --git a/tools/llvm-pdbdump/Makefile b/tools/llvm-pdbdump/Makefile
new file mode 100644
index 0000000..18aafc4
--- /dev/null
+++ b/tools/llvm-pdbdump/Makefile
@@ -0,0 +1,17 @@
+##===- tools/llvm-pdbdump/Makefile -------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL := ../..
+TOOLNAME := llvm-pdbdump
+LINK_COMPONENTS := DebugInfoPDB Object
+
+# This tool has no plugins, optimize startup time.
+TOOL_NO_EXPORTS := 1
+
+include $(LEVEL)/Makefile.common
diff --git a/tools/llvm-pdbdump/TypeDumper.cpp b/tools/llvm-pdbdump/TypeDumper.cpp
new file mode 100644
index 0000000..3131e9f
--- /dev/null
+++ b/tools/llvm-pdbdump/TypeDumper.cpp
@@ -0,0 +1,96 @@
+//===- TypeDumper.cpp - PDBSymDumper implementation for types *----- C++ *-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TypeDumper.h"
+
+#include "ClassDefinitionDumper.h"
+#include "FunctionDumper.h"
+#include "llvm-pdbdump.h"
+#include "TypedefDumper.h"
+
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+
+using namespace llvm;
+
+TypeDumper::TypeDumper(bool Inline, bool ClassDefs)
+ : PDBSymDumper(true), InlineDump(Inline), FullClassDefs(ClassDefs) {}
+
+void TypeDumper::start(const PDBSymbolExe &Exe, raw_ostream &OS, int Indent) {
+ auto Enums = Exe.findAllChildren<PDBSymbolTypeEnum>();
+ OS << newline(Indent) << "Enums: (" << Enums->getChildCount() << " items)";
+ while (auto Enum = Enums->getNext())
+ Enum->dump(OS, Indent + 2, *this);
+
+ auto FuncSigs = Exe.findAllChildren<PDBSymbolTypeFunctionSig>();
+ OS << newline(Indent);
+ OS << "Function Signatures: (" << FuncSigs->getChildCount() << " items)";
+ while (auto Sig = FuncSigs->getNext())
+ Sig->dump(OS, Indent + 2, *this);
+
+ auto Typedefs = Exe.findAllChildren<PDBSymbolTypeTypedef>();
+ OS << newline(Indent) << "Typedefs: (" << Typedefs->getChildCount()
+ << " items)";
+ while (auto Typedef = Typedefs->getNext())
+ Typedef->dump(OS, Indent + 2, *this);
+
+ auto Classes = Exe.findAllChildren<PDBSymbolTypeUDT>();
+ OS << newline(Indent) << "Classes: (" << Classes->getChildCount()
+ << " items)";
+ while (auto Class = Classes->getNext())
+ Class->dump(OS, Indent + 2, *this);
+}
+
+void TypeDumper::dump(const PDBSymbolTypeEnum &Symbol, raw_ostream &OS,
+ int Indent) {
+ if (Symbol.getUnmodifiedTypeId() != 0)
+ return;
+
+ if (!InlineDump)
+ OS << newline(Indent);
+
+ OS << "enum " << Symbol.getName();
+}
+
+void TypeDumper::dump(const PDBSymbolTypeFunctionSig &Symbol, raw_ostream &OS,
+ int Indent) {
+ if (!InlineDump)
+ OS << newline(Indent);
+
+ FunctionDumper Dumper;
+ Dumper.start(Symbol, FunctionDumper::PointerType::None, OS);
+}
+
+void TypeDumper::dump(const PDBSymbolTypeTypedef &Symbol, raw_ostream &OS,
+ int Indent) {
+ if (!InlineDump)
+ OS << newline(Indent);
+
+ TypedefDumper Dumper;
+ Dumper.start(Symbol, OS, Indent);
+}
+
+void TypeDumper::dump(const PDBSymbolTypeUDT &Symbol, raw_ostream &OS,
+ int Indent) {
+ if (Symbol.getUnmodifiedTypeId() != 0)
+ return;
+ if (!InlineDump)
+ OS << newline(Indent);
+
+ if (FullClassDefs) {
+ ClassDefinitionDumper Dumper;
+ Dumper.start(Symbol, OS, Indent);
+ } else {
+ OS << "class " << Symbol.getName();
+ }
+}
diff --git a/tools/llvm-pdbdump/TypeDumper.h b/tools/llvm-pdbdump/TypeDumper.h
new file mode 100644
index 0000000..d96c24c
--- /dev/null
+++ b/tools/llvm-pdbdump/TypeDumper.h
@@ -0,0 +1,38 @@
+//===- TypeDumper.h - PDBSymDumper implementation for types *- C++ ------*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_TYPEDUMPER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_TYPEDUMPER_H
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+namespace llvm {
+
+class TypeDumper : public PDBSymDumper {
+public:
+ TypeDumper(bool Inline, bool ClassDefs);
+
+ void start(const PDBSymbolExe &Exe, raw_ostream &OS, int Indent);
+
+ void dump(const PDBSymbolTypeEnum &Symbol, raw_ostream &OS,
+ int Indent) override;
+ void dump(const PDBSymbolTypeFunctionSig &Symbol, raw_ostream &OS,
+ int Indent) override;
+ void dump(const PDBSymbolTypeTypedef &Symbol, raw_ostream &OS,
+ int Indent) override;
+ void dump(const PDBSymbolTypeUDT &Symbol, raw_ostream &OS,
+ int Indent) override;
+
+private:
+ bool InlineDump;
+ bool FullClassDefs;
+};
+}
+
+#endif
diff --git a/tools/llvm-pdbdump/TypedefDumper.cpp b/tools/llvm-pdbdump/TypedefDumper.cpp
new file mode 100644
index 0000000..6eea6b6
--- /dev/null
+++ b/tools/llvm-pdbdump/TypedefDumper.cpp
@@ -0,0 +1,84 @@
+//===- TypedefDumper.cpp - PDBSymDumper impl for typedefs -------- * C++ *-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TypedefDumper.h"
+
+#include "FunctionDumper.h"
+#include "llvm-pdbdump.h"
+
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/PDBExtras.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+
+using namespace llvm;
+
+TypedefDumper::TypedefDumper() : PDBSymDumper(true) {}
+
+void TypedefDumper::start(const PDBSymbolTypeTypedef &Symbol, raw_ostream &OS,
+ int Indent) {
+ OS << "typedef ";
+ uint32_t TargetId = Symbol.getTypeId();
+ if (auto TypeSymbol = Symbol.getSession().getSymbolById(TargetId))
+ TypeSymbol->dump(OS, 0, *this);
+ OS << " " << Symbol.getName();
+}
+
+void TypedefDumper::dump(const PDBSymbolTypeArray &Symbol, raw_ostream &OS,
+ int Indent) {}
+
+void TypedefDumper::dump(const PDBSymbolTypeBuiltin &Symbol, raw_ostream &OS,
+ int Indent) {
+ PDB_BuiltinType Type = Symbol.getBuiltinType();
+ OS << Type;
+ if (Type == PDB_BuiltinType::UInt || Type == PDB_BuiltinType::Int)
+ OS << (8 * Symbol.getLength()) << "_t";
+}
+
+void TypedefDumper::dump(const PDBSymbolTypeEnum &Symbol, raw_ostream &OS,
+ int Indent) {
+ OS << "enum " << Symbol.getName();
+}
+
+void TypedefDumper::dump(const PDBSymbolTypePointer &Symbol, raw_ostream &OS,
+ int Indent) {
+ if (Symbol.isConstType())
+ OS << "const ";
+ if (Symbol.isVolatileType())
+ OS << "volatile ";
+ uint32_t PointeeId = Symbol.getTypeId();
+ auto PointeeType = Symbol.getSession().getSymbolById(PointeeId);
+ if (!PointeeType)
+ return;
+ if (auto FuncSig = dyn_cast<PDBSymbolTypeFunctionSig>(PointeeType.get())) {
+ FunctionDumper::PointerType Pointer = FunctionDumper::PointerType::Pointer;
+ if (Symbol.isReference())
+ Pointer = FunctionDumper::PointerType::Reference;
+ FunctionDumper NestedDumper;
+ NestedDumper.start(*FuncSig, Pointer, OS);
+ } else {
+ PointeeType->dump(OS, Indent, *this);
+ OS << ((Symbol.isReference()) ? "&" : "*");
+ }
+}
+
+void TypedefDumper::dump(const PDBSymbolTypeFunctionSig &Symbol,
+ raw_ostream &OS, int Indent) {
+ FunctionDumper Dumper;
+ Dumper.start(Symbol, FunctionDumper::PointerType::None, OS);
+}
+
+void TypedefDumper::dump(const PDBSymbolTypeUDT &Symbol, raw_ostream &OS,
+ int Indent) {
+ OS << "class " << Symbol.getName();
+}
diff --git a/tools/llvm-pdbdump/TypedefDumper.h b/tools/llvm-pdbdump/TypedefDumper.h
new file mode 100644
index 0000000..e6211a8
--- /dev/null
+++ b/tools/llvm-pdbdump/TypedefDumper.h
@@ -0,0 +1,38 @@
+//===- TypedefDumper.h - llvm-pdbdump typedef dumper ---------*- C++ ----*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_TYPEDEFDUMPER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_TYPEDEFDUMPER_H
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+namespace llvm {
+
+class TypedefDumper : public PDBSymDumper {
+public:
+ TypedefDumper();
+
+ void start(const PDBSymbolTypeTypedef &Symbol, raw_ostream &OS, int Indent);
+
+ void dump(const PDBSymbolTypeArray &Symbol, raw_ostream &OS,
+ int Indent) override;
+ void dump(const PDBSymbolTypeBuiltin &Symbol, raw_ostream &OS,
+ int Indent) override;
+ void dump(const PDBSymbolTypeEnum &Symbol, raw_ostream &OS,
+ int Indent) override;
+ void dump(const PDBSymbolTypeFunctionSig &Symbol, raw_ostream &OS,
+ int Indent) override;
+ void dump(const PDBSymbolTypePointer &Symbol, raw_ostream &OS,
+ int Indent) override;
+ void dump(const PDBSymbolTypeUDT &Symbol, raw_ostream &OS,
+ int Indent) override;
+};
+}
+
+#endif
diff --git a/tools/llvm-pdbdump/VariableDumper.cpp b/tools/llvm-pdbdump/VariableDumper.cpp
new file mode 100644
index 0000000..913cfee
--- /dev/null
+++ b/tools/llvm-pdbdump/VariableDumper.cpp
@@ -0,0 +1,120 @@
+//===- VariableDumper.cpp - -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "VariableDumper.h"
+
+#include "llvm-pdbdump.h"
+#include "FunctionDumper.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+
+#include "llvm/Support/Format.h"
+
+using namespace llvm;
+
+VariableDumper::VariableDumper() : PDBSymDumper(true) {}
+
+void VariableDumper::start(const PDBSymbolData &Var, raw_ostream &OS,
+ int Indent) {
+ OS << newline(Indent);
+ OS << "data ";
+
+ auto VarType = Var.getType();
+
+ switch (auto LocType = Var.getLocationType()) {
+ case PDB_LocType::Static:
+ OS << "[" << format_hex(Var.getRelativeVirtualAddress(), 10) << "] ";
+ OS << "static ";
+ dumpSymbolTypeAndName(*VarType, Var.getName(), OS);
+ break;
+ case PDB_LocType::Constant:
+ OS << "const ";
+ dumpSymbolTypeAndName(*VarType, Var.getName(), OS);
+ OS << "[" << Var.getValue() << "]";
+ break;
+ case PDB_LocType::ThisRel:
+ OS << "+" << format_hex(Var.getOffset(), 4) << " ";
+ dumpSymbolTypeAndName(*VarType, Var.getName(), OS);
+ break;
+ default:
+ break;
+ OS << "unknown(" << LocType << ") " << Var.getName();
+ }
+}
+
+void VariableDumper::dump(const PDBSymbolTypeBuiltin &Symbol, raw_ostream &OS,
+ int Indent) {
+ OS << Symbol.getBuiltinType();
+}
+
+void VariableDumper::dump(const PDBSymbolTypeEnum &Symbol, raw_ostream &OS,
+ int Indent) {
+ OS << Symbol.getName();
+}
+
+void VariableDumper::dump(const PDBSymbolTypeFunctionSig &Symbol,
+ raw_ostream &OS, int Indent) {}
+
+void VariableDumper::dump(const PDBSymbolTypePointer &Symbol, raw_ostream &OS,
+ int Indent) {
+ auto PointeeType = Symbol.getPointeeType();
+ if (!PointeeType)
+ return;
+
+ if (auto Func = dyn_cast<PDBSymbolFunc>(PointeeType.get())) {
+ FunctionDumper NestedDumper;
+ FunctionDumper::PointerType Pointer =
+ Symbol.isReference() ? FunctionDumper::PointerType::Reference
+ : FunctionDumper::PointerType::Pointer;
+ NestedDumper.start(*Func, Pointer, OS, Indent);
+ } else {
+ if (Symbol.isConstType())
+ OS << "const ";
+ if (Symbol.isVolatileType())
+ OS << "volatile ";
+ PointeeType->dump(OS, Indent, *this);
+ OS << (Symbol.isReference() ? "&" : "*");
+ }
+}
+
+void VariableDumper::dump(const PDBSymbolTypeTypedef &Symbol, raw_ostream &OS,
+ int Indent) {
+ OS << "typedef " << Symbol.getName();
+}
+
+void VariableDumper::dump(const PDBSymbolTypeUDT &Symbol, raw_ostream &OS,
+ int Indent) {
+ OS << Symbol.getName();
+}
+
+void VariableDumper::dumpSymbolTypeAndName(const PDBSymbol &Type,
+ StringRef Name, raw_ostream &OS) {
+ if (auto *ArrayType = dyn_cast<PDBSymbolTypeArray>(&Type)) {
+ std::string IndexSpec;
+ raw_string_ostream IndexStream(IndexSpec);
+ std::unique_ptr<PDBSymbol> ElementType = ArrayType->getElementType();
+ while (auto NestedArray = dyn_cast<PDBSymbolTypeArray>(ElementType.get())) {
+ IndexStream << "[" << NestedArray->getCount() << "]";
+ ElementType = NestedArray->getElementType();
+ }
+ IndexStream << "[" << ArrayType->getCount() << "]";
+ ElementType->dump(OS, 0, *this);
+ OS << " " << Name << IndexStream.str();
+ } else {
+ Type.dump(OS, 0, *this);
+ OS << " " << Name;
+ }
+}
diff --git a/tools/llvm-pdbdump/VariableDumper.h b/tools/llvm-pdbdump/VariableDumper.h
new file mode 100644
index 0000000..e6e71fa
--- /dev/null
+++ b/tools/llvm-pdbdump/VariableDumper.h
@@ -0,0 +1,43 @@
+//===- VariableDumper.h - PDBSymDumper implementation for types -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_VARIABLEDUMPER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_VARIABLEDUMPER_H
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace llvm {
+
+class VariableDumper : public PDBSymDumper {
+public:
+ VariableDumper();
+
+ void start(const PDBSymbolData &Var, raw_ostream &OS, int Indent);
+
+ void dump(const PDBSymbolTypeBuiltin &Symbol, raw_ostream &OS,
+ int Indent) override;
+ void dump(const PDBSymbolTypeEnum &Symbol, raw_ostream &OS,
+ int Indent) override;
+ void dump(const PDBSymbolTypeFunctionSig &Symbol, raw_ostream &OS,
+ int Indent) override;
+ void dump(const PDBSymbolTypePointer &Symbol, raw_ostream &OS,
+ int Indent) override;
+ void dump(const PDBSymbolTypeTypedef &Symbol, raw_ostream &OS,
+ int Indent) override;
+ void dump(const PDBSymbolTypeUDT &Symbol, raw_ostream &OS,
+ int Indent) override;
+
+private:
+ void dumpSymbolTypeAndName(const PDBSymbol &Type, StringRef Name,
+ raw_ostream &OS);
+};
+}
+
+#endif
diff --git a/tools/llvm-pdbdump/llvm-pdbdump.cpp b/tools/llvm-pdbdump/llvm-pdbdump.cpp
new file mode 100644
index 0000000..e33e715
--- /dev/null
+++ b/tools/llvm-pdbdump/llvm-pdbdump.cpp
@@ -0,0 +1,134 @@
+//===- llvm-pdbdump.cpp - Dump debug info from a PDB file -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Dumps debug information present in PDB files. This utility makes use of
+// the Microsoft Windows SDK, so will not compile or run on non-Windows
+// platforms.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm-pdbdump.h"
+#include "CompilandDumper.h"
+#include "TypeDumper.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Config/config.h"
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/PDB.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ConvertUTF.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Process.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Signals.h"
+
+#if defined(HAVE_DIA_SDK)
+#include <Windows.h>
+#endif
+
+using namespace llvm;
+
+namespace opts {
+
+enum class PDB_DumpType { ByType, ByObjFile, Both };
+
+cl::list<std::string> InputFilenames(cl::Positional,
+ cl::desc("<input PDB files>"),
+ cl::OneOrMore);
+
+cl::opt<bool> DumpCompilands("compilands", cl::desc("Display compilands"));
+cl::opt<bool> DumpSymbols("symbols",
+ cl::desc("Display symbols (implies --compilands"));
+cl::opt<bool> DumpTypes("types", cl::desc("Display types"));
+cl::opt<bool> DumpClassDefs("class-definitions",
+ cl::desc("Display full class definitions"));
+}
+
+static void dumpInput(StringRef Path) {
+ std::unique_ptr<IPDBSession> Session(
+ llvm::createPDBReader(PDB_ReaderType::DIA, Path));
+ if (!Session) {
+ outs() << "Unable to create PDB reader. Check that a valid implementation";
+ outs() << " is available for your platform.";
+ return;
+ }
+
+ auto GlobalScope(Session->getGlobalScope());
+ std::string FileName(GlobalScope->getSymbolsFileName());
+
+ outs() << "Summary for " << FileName;
+ uint64_t FileSize = 0;
+ if (!llvm::sys::fs::file_size(FileName, FileSize))
+ outs() << newline(2) << "Size: " << FileSize << " bytes";
+ else
+ outs() << newline(2) << "Size: (Unable to obtain file size)";
+
+ outs() << newline(2) << "Guid: " << GlobalScope->getGuid();
+ outs() << newline(2) << "Age: " << GlobalScope->getAge();
+ outs() << newline(2) << "Attributes: ";
+ if (GlobalScope->hasCTypes())
+ outs() << "HasCTypes ";
+ if (GlobalScope->hasPrivateSymbols())
+ outs() << "HasPrivateSymbols ";
+
+ if (opts::DumpTypes) {
+ outs() << "\nDumping types";
+ TypeDumper Dumper(false, opts::DumpClassDefs);
+ Dumper.start(*GlobalScope, outs(), 2);
+ }
+
+ if (opts::DumpSymbols || opts::DumpCompilands) {
+ outs() << "\nDumping compilands";
+ auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>();
+ CompilandDumper Dumper;
+ while (auto Compiland = Compilands->getNext())
+ Dumper.start(*Compiland, outs(), 2, opts::DumpSymbols);
+ }
+ outs().flush();
+}
+
+int main(int argc_, const char *argv_[]) {
+ // Print a stack trace if we signal out.
+ sys::PrintStackTraceOnErrorSignal();
+ PrettyStackTraceProgram X(argc_, argv_);
+
+ SmallVector<const char *, 256> argv;
+ llvm::SpecificBumpPtrAllocator<char> ArgAllocator;
+ std::error_code EC = llvm::sys::Process::GetArgumentVector(
+ argv, llvm::makeArrayRef(argv_, argc_), ArgAllocator);
+ if (EC) {
+ llvm::errs() << "error: couldn't get arguments: " << EC.message() << '\n';
+ return 1;
+ }
+
+ llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+
+ cl::ParseCommandLineOptions(argv.size(), argv.data(), "LLVM PDB Dumper\n");
+
+#if defined(HAVE_DIA_SDK)
+ CoInitializeEx(nullptr, COINIT_MULTITHREADED);
+#endif
+
+ std::for_each(opts::InputFilenames.begin(), opts::InputFilenames.end(),
+ dumpInput);
+
+#if defined(HAVE_DIA_SDK)
+ CoUninitialize();
+#endif
+
+ return 0;
+}
diff --git a/tools/llvm-pdbdump/llvm-pdbdump.h b/tools/llvm-pdbdump/llvm-pdbdump.h
new file mode 100644
index 0000000..74a1718
--- /dev/null
+++ b/tools/llvm-pdbdump/llvm-pdbdump.h
@@ -0,0 +1,28 @@
+//===- llvm-pdbdump.h ----------------------------------------- *- C++ --*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_LLVMPDBDUMP_H
+#define LLVM_TOOLS_LLVMPDBDUMP_LLVMPDBDUMP_H
+
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+struct newline {
+ newline(int IndentWidth) : Width(IndentWidth) {}
+ int Width;
+};
+
+inline raw_ostream &operator<<(raw_ostream &OS, const newline &Indent) {
+ OS << "\n";
+ OS.indent(Indent.Width);
+ return OS;
+}
+}
+
+#endif \ No newline at end of file