diff --git a/llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h b/llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h index 28bff142f320..29062d68f482 100644 --- a/llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h +++ b/llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h @@ -86,9 +86,9 @@ public: const IPDBSession &getSession() const { return Session; } -protected: std::unique_ptr getChildStats(TagStats &Stats) const; +protected: const IPDBSession &Session; const std::unique_ptr RawSymbol; }; diff --git a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolData.h b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolData.h index 87dd6ac4c0d8..8b9a65708ab5 100644 --- a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolData.h +++ b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolData.h @@ -24,6 +24,8 @@ public: DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Data) + std::unique_ptr getType() const; + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; FORWARD_SYMBOL_METHOD(getAccess) diff --git a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h index be40af9cfdb1..22ae6e0cd4eb 100644 --- a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h +++ b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h @@ -25,6 +25,8 @@ public: void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; std::unique_ptr getSignature() const; + std::unique_ptr getClassParent() const; + std::unique_ptr> getArguments() const; DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Function) @@ -32,6 +34,7 @@ public: FORWARD_SYMBOL_METHOD(getAddressOffset) FORWARD_SYMBOL_METHOD(getAddressSection) FORWARD_SYMBOL_METHOD(getClassParentId) + FORWARD_SYMBOL_METHOD(isCompilerGenerated) FORWARD_SYMBOL_METHOD(isConstType) FORWARD_SYMBOL_METHOD(hasCustomCallingConvention) FORWARD_SYMBOL_METHOD(hasFarReturn) diff --git a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h index 602d9d5878e3..ca925f9f054b 100644 --- a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h +++ b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h @@ -24,6 +24,8 @@ public: DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::ArrayType) + std::unique_ptr getElementType() const; + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; FORWARD_SYMBOL_METHOD(getArrayIndexTypeId) diff --git a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h index 2cc1bf830e0a..2479f46c6101 100644 --- a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h +++ b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h @@ -28,6 +28,7 @@ public: FORWARD_SYMBOL_METHOD(getBuiltinType) FORWARD_SYMBOL_METHOD(getClassParentId) + FORWARD_SYMBOL_METHOD(getUnmodifiedTypeId) FORWARD_SYMBOL_METHOD(hasConstructor) FORWARD_SYMBOL_METHOD(isConstType) FORWARD_SYMBOL_METHOD(hasAssignmentOperator) diff --git a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h index b544d6b6a553..82bb1fda413e 100644 --- a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h +++ b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h @@ -33,6 +33,7 @@ public: FORWARD_SYMBOL_METHOD(getCallingConvention) FORWARD_SYMBOL_METHOD(getClassParentId) + FORWARD_SYMBOL_METHOD(getUnmodifiedTypeId) FORWARD_SYMBOL_METHOD(isConstType) FORWARD_SYMBOL_METHOD(getCount) FORWARD_SYMBOL_METHOD(getLexicalParentId) diff --git a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h index 702ea6d8fac3..8b2806fc49af 100644 --- a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h +++ b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h @@ -24,6 +24,8 @@ public: DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::PointerType) + std::unique_ptr getPointeeType() const; + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; FORWARD_SYMBOL_METHOD(isConstType) diff --git a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h index 8c826330c149..bf912b855c1a 100644 --- a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h +++ b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h @@ -27,6 +27,7 @@ public: void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; FORWARD_SYMBOL_METHOD(getClassParentId) + FORWARD_SYMBOL_METHOD(getUnmodifiedTypeId) FORWARD_SYMBOL_METHOD(hasConstructor) FORWARD_SYMBOL_METHOD(isConstType) FORWARD_SYMBOL_METHOD(hasAssignmentOperator) diff --git a/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp b/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp index 5ed1624bfd4f..0ce3df528e18 100644 --- a/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp +++ b/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp @@ -127,8 +127,9 @@ void DumpDIAValue(llvm::raw_ostream &OS, int Indent, StringRef Name, HRESULT (__stdcall IDiaSymbol::*Method)(ArgType *)) { ArgType Value; if (S_OK == (Symbol->*Method)(&Value)) { + OS << "\n"; OS.indent(Indent); - OS << Name << ": " << Value << "\n"; + OS << Name << ": " << Value; } } @@ -142,8 +143,9 @@ void DumpDIAValue(llvm::raw_ostream &OS, int Indent, StringRef Name, ArrayRef ByteArray(Bytes, ::SysStringByteLen(Value)); std::string Result; if (llvm::convertUTF16ToUTF8String(ByteArray, Result)) { + OS << "\n"; OS.indent(Indent); - OS << Name << ": " << Result << "\n"; + OS << Name << ": " << Result; } ::SysFreeString(Value); } @@ -155,8 +157,9 @@ void DumpDIAValue(llvm::raw_ostream &OS, int Indent, StringRef Name, Value.vt = VT_EMPTY; if (S_OK != (Symbol->*Method)(&Value)) return; - Variant V = VariantFromVARIANT(Value); + OS << "\n"; OS.indent(Indent); + Variant V = VariantFromVARIANT(Value); OS << V; } } @@ -201,7 +204,6 @@ void DIARawSymbol::dump(raw_ostream &OS, int Indent, RAW_METHOD_DUMP(OS, get_frontEndMinor) RAW_METHOD_DUMP(OS, get_frontEndBuild) RAW_METHOD_DUMP(OS, get_frontEndQFE) - RAW_METHOD_DUMP(OS, get_count) RAW_METHOD_DUMP(OS, get_lexicalParentId) RAW_METHOD_DUMP(OS, get_libraryName) RAW_METHOD_DUMP(OS, get_liveRangeStartAddressOffset) diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolData.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolData.cpp index 09b96bc6c9bf..6bf7e0f9529a 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbolData.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBSymbolData.cpp @@ -9,6 +9,7 @@ #include "llvm/DebugInfo/PDB/PDBSymbolData.h" +#include "llvm/DebugInfo/PDB/IPDBSession.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" #include @@ -19,6 +20,10 @@ PDBSymbolData::PDBSymbolData(const IPDBSession &PDBSession, std::unique_ptr DataSymbol) : PDBSymbol(PDBSession, std::move(DataSymbol)) {} +std::unique_ptr PDBSymbolData::getType() const { + return Session.getSymbolById(getTypeId()); +} + void PDBSymbolData::dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const { Dumper.dump(*this, OS, Indent); diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolFunc.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolFunc.cpp index 4702d6dac210..e2d859f94a8f 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbolFunc.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBSymbolFunc.cpp @@ -9,13 +9,78 @@ #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" +#include "llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" #include "llvm/DebugInfo/PDB/IPDBSession.h" +#include "llvm/DebugInfo/PDB/PDBSymbolData.h" #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" +#include "llvm/DebugInfo/PDB/PDBTypes.h" +#include #include +#include using namespace llvm; + +namespace { +class FunctionArgEnumerator : public IPDBEnumChildren { +public: + typedef ConcreteSymbolEnumerator ArgEnumeratorType; + + FunctionArgEnumerator(const IPDBSession &PDBSession, + const PDBSymbolFunc &PDBFunc) + : Session(PDBSession), Func(PDBFunc) { + // Arguments can appear multiple times if they have live range + // information, so we only take the first occurrence. + std::unordered_set SeenNames; + auto DataChildren = Func.findAllChildren(); + while (auto Child = DataChildren->getNext()) { + if (Child->getDataKind() == PDB_DataKind::Param) { + std::string Name = Child->getName(); + if (SeenNames.find(Name) != SeenNames.end()) + continue; + Args.push_back(std::move(Child)); + SeenNames.insert(Name); + } + } + reset(); + } + + uint32_t getChildCount() const { return Args.size(); } + + std::unique_ptr getChildAtIndex(uint32_t Index) const { + if (Index >= Args.size()) + return nullptr; + + return Session.getConcreteSymbolById( + Args[Index]->getSymIndexId()); + } + + std::unique_ptr getNext() { + if (CurIter == Args.end()) + return nullptr; + const auto &Result = **CurIter; + ++CurIter; + return Session.getConcreteSymbolById(Result.getSymIndexId()); + } + + void reset() { CurIter = Args.empty() ? Args.end() : Args.begin(); } + + FunctionArgEnumerator *clone() const { + return new FunctionArgEnumerator(Session, Func); + } + +private: + typedef std::vector> ArgListType; + const IPDBSession &Session; + const PDBSymbolFunc &Func; + ArgListType Args; + ArgListType::const_iterator CurIter; +}; +} + PDBSymbolFunc::PDBSymbolFunc(const IPDBSession &PDBSession, std::unique_ptr Symbol) : PDBSymbol(PDBSession, std::move(Symbol)) {} @@ -24,6 +89,15 @@ std::unique_ptr PDBSymbolFunc::getSignature() const { return Session.getConcreteSymbolById(getTypeId()); } +std::unique_ptr> +PDBSymbolFunc::getArguments() const { + return llvm::make_unique(Session, *this); +} + +std::unique_ptr PDBSymbolFunc::getClassParent() const { + return Session.getConcreteSymbolById(getClassParentId()); +} + void PDBSymbolFunc::dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const { Dumper.dump(*this, OS, Indent); diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp index 1759bd8ead5f..ffe6c80e0909 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp @@ -9,6 +9,7 @@ #include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h" +#include "llvm/DebugInfo/PDB/IPDBSession.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" #include @@ -19,6 +20,10 @@ PDBSymbolTypeArray::PDBSymbolTypeArray(const IPDBSession &PDBSession, std::unique_ptr Symbol) : PDBSymbol(PDBSession, std::move(Symbol)) {} +std::unique_ptr PDBSymbolTypeArray::getElementType() const { + return Session.getSymbolById(getTypeId()); +} + void PDBSymbolTypeArray::dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const { Dumper.dump(*this, OS, Indent); diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp index cac23f737e52..d274bf5619d4 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp @@ -9,6 +9,7 @@ #include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h" +#include "llvm/DebugInfo/PDB/IPDBSession.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" #include @@ -19,6 +20,10 @@ PDBSymbolTypePointer::PDBSymbolTypePointer( const IPDBSession &PDBSession, std::unique_ptr Symbol) : PDBSymbol(PDBSession, std::move(Symbol)) {} +std::unique_ptr PDBSymbolTypePointer::getPointeeType() const { + return Session.getSymbolById(getTypeId()); +} + void PDBSymbolTypePointer::dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const { Dumper.dump(*this, OS, Indent); diff --git a/llvm/test/DebugInfo/PDB/Inputs/symbolformat.cpp b/llvm/test/DebugInfo/PDB/Inputs/symbolformat.cpp index 1aa865214fb3..c069a35c7b9c 100644 --- a/llvm/test/DebugInfo/PDB/Inputs/symbolformat.cpp +++ b/llvm/test/DebugInfo/PDB/Inputs/symbolformat.cpp @@ -5,20 +5,49 @@ int __cdecl _purecall(void) { return 0; } +enum TestEnum { + Value, + Value10 = 10 +}; + +enum class TestEnumClass { + Value, + Value10 = 10 +}; + struct A { virtual void PureFunc() = 0 {} virtual void VirtualFunc() {} void RegularFunc() {} }; -struct B : public A { - void PureFunc() override {} +struct VirtualBase { }; +struct B : public A, protected virtual VirtualBase { + void PureFunc() override {} + + enum NestedEnum { + FirstVal, + SecondVal + }; + + typedef int NestedTypedef; + NestedEnum EnumVar; + NestedTypedef TypedefVar; +}; + +typedef int IntType; +typedef A ClassAType; + int main(int argc, char **argv) { B b; auto PureAddr = &B::PureFunc; auto VirtualAddr = &A::PureFunc; auto RegularAddr = &A::RegularFunc; + TestEnum Enum = Value; + TestEnumClass EnumClass = TestEnumClass::Value10; + IntType Int = 12; + ClassAType *ClassA = &b; return 0; } diff --git a/llvm/test/DebugInfo/PDB/Inputs/symbolformat.pdb b/llvm/test/DebugInfo/PDB/Inputs/symbolformat.pdb index 3bbc7bb1389e..183870aa164f 100644 Binary files a/llvm/test/DebugInfo/PDB/Inputs/symbolformat.pdb and b/llvm/test/DebugInfo/PDB/Inputs/symbolformat.pdb differ diff --git a/llvm/test/DebugInfo/PDB/pdbdump-symbol-format.test b/llvm/test/DebugInfo/PDB/pdbdump-symbol-format.test index 9d50ae226db9..1540e167dbed 100644 --- a/llvm/test/DebugInfo/PDB/pdbdump-symbol-format.test +++ b/llvm/test/DebugInfo/PDB/pdbdump-symbol-format.test @@ -1,27 +1,49 @@ ; RUN: llvm-pdbdump -symbols %p/Inputs/symbolformat.pdb | FileCheck --check-prefix=SYM_FORMAT %s ; RUN: llvm-pdbdump -types %p/Inputs/symbolformat.pdb | FileCheck --check-prefix=TYPES_FORMAT %s +; RUN: llvm-pdbdump -types -class-definitions %p/Inputs/symbolformat.pdb | FileCheck --check-prefix=FULL_CLASS %s ; The format is func [0x+ - 0x-] ; SYM_FORMAT: symbolformat-fpo.obj -; SYM_FORMAT-DAG: func [0x001130+0 - 0x001137-1] (FPO) uint32_t __cdecl fpo_func(uint32_t) +; SYM_FORMAT-DAG: func [0x001130+0 - 0x001137-1] (FPO) uint32_t __cdecl fpo_func(uint32_t n) ; SYM_FORMAT: symbolformat.obj -; SYM_FORMAT-DAG: func [0x001060+3 - 0x001067-2] (EBP) int32_t __cdecl _purecall() -; SYM_FORMAT-DAG: func [0x001070+6 - 0x001099-4] (EBP) int32_t __cdecl main(int32_t, char**) -; SYM_FORMAT-DAG: func [0x0010b0+7 - 0x0010c7-4] (EBP) void __thiscall A::A() -; SYM_FORMAT-DAG: func [0x0010d0+7 - 0x0010ef-4] (EBP) void __thiscall B::B() +; SYM_FORMAT-DAG: func [0x001140+3 - 0x001147-2] (EBP) int32_t __cdecl _purecall() +; SYM_FORMAT-DAG: func [0x001150+6 - 0x0011b6-4] (EBP) int32_t __cdecl main(int32_t argc, char** argv) +; SYM_FORMAT-DAG: func [0x0010b0+7 - 0x0010c7-4] (EBP) void A::A() +; SYM_FORMAT-DAG: func [0x0011c0+7 - 0x0011f1-6] (EBP) void B::B() ; SYM_FORMAT-DAG: thunk [0x000010f6 - 0x000010fa] (Pcode) B::`vcall'{0}' -; SYM_FORMAT-DAG: func [0x001100+7 - 0x00110b-4] (EBP) virtual void __thiscall B::PureFunc() -; SYM_FORMAT-DAG: func [0x001110+7 - 0x00111b-4] (EBP) void __thiscall A::RegularFunc() -; SYM_FORMAT-DAG: func [0x001120+7 - 0x00112b-4] (EBP) virtual void __thiscall A::VirtualFunc() +; SYM_FORMAT-DAG: func [0x001100+7 - 0x00110b-4] (EBP) virtual void B::PureFunc() +; SYM_FORMAT-DAG: func [0x001110+7 - 0x00111b-4] (EBP) void A::RegularFunc() +; SYM_FORMAT-DAG: func [0x001120+7 - 0x00112b-4] (EBP) virtual void A::VirtualFunc() +; TYPES_FORMAT: Enums +; TYPES_FORMAT-DAG: enum TestEnum +; TYPES_FORMAT-DAG: enum TestEnumClass ; TYPES_FORMAT: Function Signatures ; TYPES_FORMAT-DAG: int32_t __cdecl () ; TYPES_FORMAT-DAG: int32_t __cdecl (int32_t, char**) -; TYPES_FORMAT-DAG: void __thiscall (A::)() -; TYPES_FORMAT-DAG: void __thiscall (B::)() -; TYPES_FORMAT-DAG: void __thiscall (B::)(B&) -; TYPES_FORMAT-DAG: void __thiscall (B::)() -; TYPES_FORMAT-DAG: B& __thiscall (B::)(B&) -; TYPES_FORMAT-DAG: void __thiscall (A::)(A&) -; TYPES_FORMAT-DAG: void __thiscall (A::)() -; TYPES_FORMAT-DAG: A& __thiscall (A::)(A&) +; TYPES_FORMAT-DAG: void (A::)() +; TYPES_FORMAT-DAG: void (B::)() +; TYPES_FORMAT-DAG: void (B::)(B&) +; TYPES_FORMAT-DAG: void (B::)() +; TYPES_FORMAT-DAG: B& (B::)(B&) +; TYPES_FORMAT-DAG: void (A::)(A&) +; TYPES_FORMAT-DAG: void (A::)() +; TYPES_FORMAT-DAG: A& (A::)(A&) +; TYPES_FORMAT: Typedefs +; TYPES_FORMAT-DAG: typedef int32_t IntType +; TYPES_FORMAT-DAG: typedef class A ClassAType +; TYPES_FORMAT: Classes +; TYPES_FORMAT-DAG: class A +; TYPES_FORMAT-DAG: class B + +; FULL_CLASS: Classes +; FULL_CLASS-DAG: class A { +; FULL_CLASS: public: +; FULL_CLASS: virtual void PureFunc() = 0 +; FULL_CLASS: virtual void VirtualFunc() +; FULL_CLASS: void RegularFunc() +; FULL_CLASS: } +; FULL_CLASS-DAG: class B { +; FULL_CLASS: public: +; FULL_CLASS: virtual void PureFunc() +; FULL_CLASS: } \ No newline at end of file diff --git a/llvm/tools/llvm-pdbdump/CMakeLists.txt b/llvm/tools/llvm-pdbdump/CMakeLists.txt index 64b3d6208372..0519bf0634c6 100644 --- a/llvm/tools/llvm-pdbdump/CMakeLists.txt +++ b/llvm/tools/llvm-pdbdump/CMakeLists.txt @@ -5,8 +5,10 @@ set(LLVM_LINK_COMPONENTS add_llvm_tool(llvm-pdbdump llvm-pdbdump.cpp + ClassDefinitionDumper.cpp CompilandDumper.cpp FunctionDumper.cpp TypeDumper.cpp TypedefDumper.cpp + VariableDumper.cpp ) diff --git a/llvm/tools/llvm-pdbdump/ClassDefinitionDumper.cpp b/llvm/tools/llvm-pdbdump/ClassDefinitionDumper.cpp new file mode 100644 index 000000000000..f6bb6958d8bd --- /dev/null +++ b/llvm/tools/llvm-pdbdump/ClassDefinitionDumper.cpp @@ -0,0 +1,154 @@ +//===- 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((PDB_MemberAccess)0, SymbolGroup())); + Groups.insert(std::make_pair(PDB_MemberAccess::Private, SymbolGroup())); + Groups.insert(std::make_pair(PDB_MemberAccess::Protected, SymbolGroup())); + Groups.insert(std::make_pair(PDB_MemberAccess::Public, SymbolGroup())); + + while (auto Child = Children->getNext()) { + PDB_MemberAccess Access = Child->getRawSymbol().getAccess(); + if (isa(*Child)) + continue; + + SymbolGroup *InsertGroup = nullptr; + auto &AccessGroup = Groups.find(Access)->second; + + if (auto Func = dyn_cast(Child.get())) { + if (Func->isCompilerGenerated()) + continue; + if (Func->getLength() == 0 && !Func->isPureVirtual()) + continue; + Child.release(); + AccessGroup.Functions.push_back(std::unique_ptr(Func)); + } else if (auto Data = dyn_cast(Child.get())) { + Child.release(); + AccessGroup.Data.push_back(std::unique_ptr(Data)); + } else { + AccessGroup.Unknown.push_back(std::move(Child)); + } + } + + int Count = 0; + Count += dumpAccessGroup((PDB_MemberAccess)0, Groups[(PDB_MemberAccess)0], OS, + Indent); + Count += dumpAccessGroup(PDB_MemberAccess::Public, + Groups[PDB_MemberAccess::Public], OS, Indent); + Count += dumpAccessGroup(PDB_MemberAccess::Protected, + Groups[PDB_MemberAccess::Protected], OS, Indent); + Count += dumpAccessGroup(PDB_MemberAccess::Private, + Groups[PDB_MemberAccess::Private], OS, Indent); + + if (Count > 0) + OS << newline(Indent); + OS << "}"; + OS.flush(); +} + +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); + OS.flush(); +} + +void ClassDefinitionDumper::dump(const PDBSymbolTypeUDT &Symbol, + raw_ostream &OS, int Indent) {} diff --git a/llvm/tools/llvm-pdbdump/ClassDefinitionDumper.h b/llvm/tools/llvm-pdbdump/ClassDefinitionDumper.h new file mode 100644 index 000000000000..f82d9760bcc6 --- /dev/null +++ b/llvm/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 +#include +#include + +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> Functions; + std::list> Data; + std::list> Unknown; + SymbolGroup(const SymbolGroup &other) = delete; + SymbolGroup &operator=(const SymbolGroup &other) = delete; + }; + typedef std::unordered_map SymbolGroupByAccess; + + int dumpAccessGroup(PDB_MemberAccess Access, const SymbolGroup &Group, + raw_ostream &OS, int Indent); +}; +} + +#endif diff --git a/llvm/tools/llvm-pdbdump/CompilandDumper.cpp b/llvm/tools/llvm-pdbdump/CompilandDumper.cpp index ee55228309d9..852ddfa02a5a 100644 --- a/llvm/tools/llvm-pdbdump/CompilandDumper.cpp +++ b/llvm/tools/llvm-pdbdump/CompilandDumper.cpp @@ -75,26 +75,11 @@ void CompilandDumper::dump(const PDBSymbolData &Symbol, raw_ostream &OS, void CompilandDumper::dump(const PDBSymbolFunc &Symbol, raw_ostream &OS, int Indent) { - uint32_t FuncStart = Symbol.getRelativeVirtualAddress(); - uint32_t FuncEnd = FuncStart + Symbol.getLength(); - OS << newline(Indent) << "func [" << format_hex(FuncStart, 8); - if (auto DebugStart = Symbol.findOneChild()) - OS << "+" << DebugStart->getRelativeVirtualAddress() - FuncStart; - OS << " - " << format_hex(FuncEnd, 8); - if (auto DebugEnd = Symbol.findOneChild()) - OS << "-" << FuncEnd - DebugEnd->getRelativeVirtualAddress(); - OS << "] "; - - if (Symbol.hasFramePointer()) - OS << "(" << Symbol.getLocalBasePointerRegisterId() << ")"; - else - OS << "(FPO)"; - - OS << " "; + if (Symbol.getLength() == 0) + return; FunctionDumper Dumper; - Dumper.start(Symbol, OS); - OS.flush(); + Dumper.start(Symbol, FunctionDumper::PointerType::None, OS, Indent); } void CompilandDumper::dump(const PDBSymbolLabel &Symbol, raw_ostream &OS, diff --git a/llvm/tools/llvm-pdbdump/FunctionDumper.cpp b/llvm/tools/llvm-pdbdump/FunctionDumper.cpp index 955d6499f9d9..1bd201b8f69d 100644 --- a/llvm/tools/llvm-pdbdump/FunctionDumper.cpp +++ b/llvm/tools/llvm-pdbdump/FunctionDumper.cpp @@ -8,9 +8,13 @@ //===----------------------------------------------------------------------===// #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" @@ -19,6 +23,7 @@ #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; @@ -49,12 +54,23 @@ void FunctionDumper::start(const PDBSymbolTypeFunctionSig &Symbol, Symbol.getSession().getConcreteSymbolById( 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) { - OS << Symbol.getCallingConvention() << " "; + if (ShouldDumpCallingConvention) + OS << CC << " "; if (ClassParent) OS << "(" << ClassParent->getName() << "::)"; } else { - OS << "(" << Symbol.getCallingConvention() << " "; + OS << "("; + if (ShouldDumpCallingConvention) + OS << CC << " "; + OS << Symbol.getCallingConvention() << " "; if (ClassParent) OS << ClassParent->getName() << "::"; if (Pointer == PointerType::Reference) @@ -81,33 +97,74 @@ void FunctionDumper::start(const PDBSymbolTypeFunctionSig &Symbol, OS << " volatile"; } -void FunctionDumper::start(const PDBSymbolFunc &Symbol, raw_ostream &OS) { +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()) + OS << "+" << DebugStart->getRelativeVirtualAddress() - FuncStart; + OS << " - " << format_hex(FuncEnd, 8); + if (auto DebugEnd = Symbol.findOneChild()) + 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 << " "; - OS << " " << Signature->getCallingConvention() << " "; + 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 ChildEnum = Signature->getArguments()) { + if (auto Arguments = Symbol.getArguments()) { uint32_t Index = 0; - while (auto Arg = ChildEnum->getNext()) { - Arg->dump(OS, 0, *this); - if (++Index < ChildEnum->getChildCount()) + while (auto Arg = Arguments->getNext()) { + auto ArgType = Arg->getType(); + ArgType->dump(OS, 0, *this); + OS << " " << Arg->getName(); + if (++Index < Arguments->getChildCount()) OS << ", "; } } + OS.flush(); OS << ")"; - if (Symbol.isConstType()) OS << " const"; if (Symbol.isVolatileType()) @@ -144,8 +201,9 @@ void FunctionDumper::dump(const PDBSymbolTypeEnum &Symbol, raw_ostream &OS, 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. + // through to the real thing and dump it. + Symbol.defaultDump(OS, Indent, PDB_DumpLevel::Detailed); + OS.flush(); uint32_t TypeId = Symbol.getTypeId(); auto Type = Symbol.getSession().getSymbolById(TypeId); if (!Type) diff --git a/llvm/tools/llvm-pdbdump/FunctionDumper.h b/llvm/tools/llvm-pdbdump/FunctionDumper.h index 287a79c02c26..f9338cb87644 100644 --- a/llvm/tools/llvm-pdbdump/FunctionDumper.h +++ b/llvm/tools/llvm-pdbdump/FunctionDumper.h @@ -22,7 +22,8 @@ public: void start(const PDBSymbolTypeFunctionSig &Symbol, PointerType Pointer, raw_ostream &OS); - void start(const PDBSymbolFunc &Symbol, 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; diff --git a/llvm/tools/llvm-pdbdump/TypeDumper.cpp b/llvm/tools/llvm-pdbdump/TypeDumper.cpp index 72171b0f3188..c4e2eabda905 100644 --- a/llvm/tools/llvm-pdbdump/TypeDumper.cpp +++ b/llvm/tools/llvm-pdbdump/TypeDumper.cpp @@ -9,6 +9,7 @@ #include "TypeDumper.h" +#include "ClassDefinitionDumper.h" #include "FunctionDumper.h" #include "llvm-pdbdump.h" #include "TypedefDumper.h" @@ -18,10 +19,12 @@ #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() : PDBSymDumper(true) {} +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(); @@ -40,24 +43,55 @@ void TypeDumper::start(const PDBSymbolExe &Exe, raw_ostream &OS, int Indent) { << " items)"; while (auto Typedef = Typedefs->getNext()) Typedef->dump(OS, Indent + 2, *this); + + auto Classes = Exe.findAllChildren(); + 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) { - OS << newline(Indent) << "enum " << Symbol.getName(); + 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) { - OS << newline(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) { - OS << newline(Indent); + if (!InlineDump) + OS << newline(Indent); + TypedefDumper Dumper; Dumper.start(Symbol, OS, Indent); OS.flush(); } + +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/llvm/tools/llvm-pdbdump/TypeDumper.h b/llvm/tools/llvm-pdbdump/TypeDumper.h index 6c51d155df8b..d96c24c87fa8 100644 --- a/llvm/tools/llvm-pdbdump/TypeDumper.h +++ b/llvm/tools/llvm-pdbdump/TypeDumper.h @@ -16,7 +16,7 @@ namespace llvm { class TypeDumper : public PDBSymDumper { public: - TypeDumper(); + TypeDumper(bool Inline, bool ClassDefs); void start(const PDBSymbolExe &Exe, raw_ostream &OS, int Indent); @@ -26,6 +26,12 @@ public: 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; }; } diff --git a/llvm/tools/llvm-pdbdump/TypedefDumper.cpp b/llvm/tools/llvm-pdbdump/TypedefDumper.cpp index 55fcb1a3ade8..e3ac76a63b36 100644 --- a/llvm/tools/llvm-pdbdump/TypedefDumper.cpp +++ b/llvm/tools/llvm-pdbdump/TypedefDumper.cpp @@ -27,10 +27,11 @@ TypedefDumper::TypedefDumper() : PDBSymDumper(true) {} void TypedefDumper::start(const PDBSymbolTypeTypedef &Symbol, raw_ostream &OS, int Indent) { - OS << "typedef:" << Symbol.getName() << " -> "; + 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, diff --git a/llvm/tools/llvm-pdbdump/VariableDumper.cpp b/llvm/tools/llvm-pdbdump/VariableDumper.cpp new file mode 100644 index 000000000000..cb9c66a94b93 --- /dev/null +++ b/llvm/tools/llvm-pdbdump/VariableDumper.cpp @@ -0,0 +1,125 @@ +//===- 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: { + int Offset = Var.getOffset(); + OS << "+" << format_hex(Var.getOffset(), 4) << " "; + OS.flush(); + 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) { + uint32_t PointeeId = Symbol.getTypeId(); + auto PointeeType = Symbol.getPointeeType(); + if (!PointeeType) + return; + + if (auto Func = dyn_cast(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(&Type)) { + bool Done = false; + std::string IndexSpec; + raw_string_ostream IndexStream(IndexSpec); + std::unique_ptr ElementType = ArrayType->getElementType(); + while (auto NestedArray = dyn_cast(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/llvm/tools/llvm-pdbdump/VariableDumper.h b/llvm/tools/llvm-pdbdump/VariableDumper.h new file mode 100644 index 000000000000..e6e71faca314 --- /dev/null +++ b/llvm/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/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp b/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp index cf305d3328ed..e33e71562d35 100644 --- a/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp +++ b/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp @@ -54,6 +54,8 @@ cl::opt DumpCompilands("compilands", cl::desc("Display compilands")); cl::opt DumpSymbols("symbols", cl::desc("Display symbols (implies --compilands")); cl::opt DumpTypes("types", cl::desc("Display types")); +cl::opt DumpClassDefs("class-definitions", + cl::desc("Display full class definitions")); } static void dumpInput(StringRef Path) { @@ -85,7 +87,7 @@ static void dumpInput(StringRef Path) { if (opts::DumpTypes) { outs() << "\nDumping types"; - TypeDumper Dumper; + TypeDumper Dumper(false, opts::DumpClassDefs); Dumper.start(*GlobalScope, outs(), 2); }