diff options
Diffstat (limited to 'tools/llvm-pdbdump')
-rw-r--r-- | tools/llvm-pdbdump/Android.mk | 34 | ||||
-rw-r--r-- | tools/llvm-pdbdump/CMakeLists.txt | 14 | ||||
-rw-r--r-- | tools/llvm-pdbdump/ClassDefinitionDumper.cpp | 152 | ||||
-rw-r--r-- | tools/llvm-pdbdump/ClassDefinitionDumper.h | 64 | ||||
-rw-r--r-- | tools/llvm-pdbdump/CompilandDumper.cpp | 117 | ||||
-rw-r--r-- | tools/llvm-pdbdump/CompilandDumper.h | 39 | ||||
-rw-r--r-- | tools/llvm-pdbdump/FunctionDumper.cpp | 243 | ||||
-rw-r--r-- | tools/llvm-pdbdump/FunctionDumper.h | 45 | ||||
-rw-r--r-- | tools/llvm-pdbdump/LLVMBuild.txt | 23 | ||||
-rw-r--r-- | tools/llvm-pdbdump/Makefile | 17 | ||||
-rw-r--r-- | tools/llvm-pdbdump/TypeDumper.cpp | 96 | ||||
-rw-r--r-- | tools/llvm-pdbdump/TypeDumper.h | 38 | ||||
-rw-r--r-- | tools/llvm-pdbdump/TypedefDumper.cpp | 84 | ||||
-rw-r--r-- | tools/llvm-pdbdump/TypedefDumper.h | 38 | ||||
-rw-r--r-- | tools/llvm-pdbdump/VariableDumper.cpp | 120 | ||||
-rw-r--r-- | tools/llvm-pdbdump/VariableDumper.h | 43 | ||||
-rw-r--r-- | tools/llvm-pdbdump/llvm-pdbdump.cpp | 134 | ||||
-rw-r--r-- | tools/llvm-pdbdump/llvm-pdbdump.h | 28 |
18 files changed, 1329 insertions, 0 deletions
diff --git a/tools/llvm-pdbdump/Android.mk b/tools/llvm-pdbdump/Android.mk new file mode 100644 index 0000000..82a406a --- /dev/null +++ b/tools/llvm-pdbdump/Android.mk @@ -0,0 +1,34 @@ +LOCAL_PATH := $(call my-dir) + +LLVM_ROOT_PATH := $(LOCAL_PATH)/../.. +include $(LLVM_ROOT_PATH)/llvm.mk + +llvm_pdbdump_SRC_FILES := \ + ClassDefinitionDumper.cpp \ + CompilandDumper.cpp \ + FunctionDumper.cpp \ + llvm-pdbdump.cpp \ + TypedefDumper.cpp \ + TypeDumper.cpp \ + VariableDumper.cpp + +llvm_pdbdump_STATIC_LIBRARIES := \ + libLLVMDebugInfoPDB \ + libLLVMSupport + +include $(CLEAR_VARS) + +LOCAL_MODULE := llvm-pdbdump +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_CLASS := EXECUTABLES +LOCAL_IS_HOST_MODULE := true + +LOCAL_SRC_FILES := $(llvm_pdbdump_SRC_FILES) + +LOCAL_STATIC_LIBRARIES := $(llvm_pdbdump_STATIC_LIBRARIES) + +LOCAL_LDLIBS += -lpthread -lm -ldl + +include $(LLVM_HOST_BUILD_MK) +include $(LLVM_GEN_INTRINSICS_MK) +include $(BUILD_HOST_EXECUTABLE) 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 |