From 92d755ea659704476da1e2aaa6ebb5c153ac0f93 Mon Sep 17 00:00:00 2001 From: Zachary Turner Date: Mon, 23 Feb 2015 05:58:34 +0000 Subject: [PATCH] [llvm-pdbdump] Add an option to dump full class definitions. This adds the --class-definitions flag. If specified, when dumping types, instead of "class Foo" you will see the full class definition, with member functions, constructors, access specifiers. NOTE: Using this option can be very slow, as generating a full class definition requires accessing many different parts of the PDB. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@230203 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/DebugInfo/PDB/PDBSymbol.h | 2 +- include/llvm/DebugInfo/PDB/PDBSymbolData.h | 2 + include/llvm/DebugInfo/PDB/PDBSymbolFunc.h | 3 + .../llvm/DebugInfo/PDB/PDBSymbolTypeArray.h | 2 + .../llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h | 1 + .../DebugInfo/PDB/PDBSymbolTypeFunctionSig.h | 1 + .../llvm/DebugInfo/PDB/PDBSymbolTypePointer.h | 2 + include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h | 1 + lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp | 10 +- lib/DebugInfo/PDB/PDBSymbolData.cpp | 5 + lib/DebugInfo/PDB/PDBSymbolFunc.cpp | 74 +++++++++ lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp | 5 + lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp | 5 + test/DebugInfo/PDB/Inputs/symbolformat.cpp | 31 +++- test/DebugInfo/PDB/Inputs/symbolformat.pdb | Bin 110592 -> 143360 bytes test/DebugInfo/PDB/pdbdump-symbol-format.test | 54 ++++-- tools/llvm-pdbdump/CMakeLists.txt | 2 + tools/llvm-pdbdump/ClassDefinitionDumper.cpp | 154 ++++++++++++++++++ tools/llvm-pdbdump/ClassDefinitionDumper.h | 64 ++++++++ tools/llvm-pdbdump/CompilandDumper.cpp | 21 +-- tools/llvm-pdbdump/FunctionDumper.cpp | 80 +++++++-- tools/llvm-pdbdump/FunctionDumper.h | 3 +- tools/llvm-pdbdump/TypeDumper.cpp | 42 ++++- tools/llvm-pdbdump/TypeDumper.h | 8 +- tools/llvm-pdbdump/TypedefDumper.cpp | 3 +- tools/llvm-pdbdump/VariableDumper.cpp | 125 ++++++++++++++ tools/llvm-pdbdump/VariableDumper.h | 43 +++++ tools/llvm-pdbdump/llvm-pdbdump.cpp | 4 +- 28 files changed, 688 insertions(+), 59 deletions(-) create mode 100644 tools/llvm-pdbdump/ClassDefinitionDumper.cpp create mode 100644 tools/llvm-pdbdump/ClassDefinitionDumper.h create mode 100644 tools/llvm-pdbdump/VariableDumper.cpp create mode 100644 tools/llvm-pdbdump/VariableDumper.h diff --git a/include/llvm/DebugInfo/PDB/PDBSymbol.h b/include/llvm/DebugInfo/PDB/PDBSymbol.h index 28bff142f32..29062d68f48 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbol.h +++ b/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/include/llvm/DebugInfo/PDB/PDBSymbolData.h b/include/llvm/DebugInfo/PDB/PDBSymbolData.h index 87dd6ac4c0d..8b9a65708ab 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolData.h +++ b/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/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h b/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h index be40af9cfdb..22ae6e0cd4e 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h +++ b/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/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h index 602d9d5878e..ca925f9f054 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h +++ b/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/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h index 2cc1bf830e0..2479f46c610 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h +++ b/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/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h index b544d6b6a55..82bb1fda413 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h +++ b/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/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h index 702ea6d8fac..8b2806fc49a 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h +++ b/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/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h index 8c826330c14..bf912b855c1 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h +++ b/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/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp b/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp index 5ed1624bfd4..0ce3df528e1 100644 --- a/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp +++ b/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/lib/DebugInfo/PDB/PDBSymbolData.cpp b/lib/DebugInfo/PDB/PDBSymbolData.cpp index 09b96bc6c9b..6bf7e0f9529 100644 --- a/lib/DebugInfo/PDB/PDBSymbolData.cpp +++ b/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/lib/DebugInfo/PDB/PDBSymbolFunc.cpp b/lib/DebugInfo/PDB/PDBSymbolFunc.cpp index 4702d6dac21..e2d859f94a8 100644 --- a/lib/DebugInfo/PDB/PDBSymbolFunc.cpp +++ b/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/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp index 1759bd8ead5..ffe6c80e090 100644 --- a/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp +++ b/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/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp b/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp index cac23f737e5..d274bf5619d 100644 --- a/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp +++ b/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/test/DebugInfo/PDB/Inputs/symbolformat.cpp b/test/DebugInfo/PDB/Inputs/symbolformat.cpp index 1aa865214fb..c069a35c7b9 100644 --- a/test/DebugInfo/PDB/Inputs/symbolformat.cpp +++ b/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 { +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/test/DebugInfo/PDB/Inputs/symbolformat.pdb b/test/DebugInfo/PDB/Inputs/symbolformat.pdb index 3bbc7bb1389e43354d8d692788a7b933b7186013..183870aa164fd1dc971159b602cca4b8ceefbd49 100644 GIT binary patch delta 6329 zcmeHLdr*|u6~Fge9=pr34`2~_xq{#ucc~(wir*p_F+PYAH8Is)WF0WPE?pV59$8P}(i`DIf)hFA&X7SdcQ zo*O9=4|+{;@f$fy00&gKz2D|3;;-J>%OL9|xoFTBP{2C|ngVPF%-mX;TfR>Bo4j9m zdb2JLyz&-fq~8VvE1V~domiY=$CIGFsf^`7RS&5`J0dZbu3>B~c+_s7wS(H=fCiuf zc$3B;*9+1CIujIAm|z3$oED*lPzq+rg$i~6pLs7~5d^2RbOTL8&{fh2&uL7ti94TinZ(`G6zn=Tf;krJrbX6o`8I7Na(6#J4UMMAdl z`fQTS#SeVNbI0&#YP$g1!zy6CIlNJv@p^Y{1IuIy=0d+SS3^as%2LsQ$DJGQwT-Ou)WAT7!^hTY(y&1MmU8KtC{q z3#C}!)sv^83&GK2Qvzg`c(P}m8Yh`;V%$R;A^UzACp@?a#yHs8!4N2|iSHWR#F?lZoXxrDpx&YAtmb4~MP7 z0xw4iG`hYd<}505Qiz9n)go{{F(V1qNUWr&h)%((wuYV1pQ%cC#qjwVd_?dI)9z%& zt7$|2Hkhg|ypW8gWm8Z|Y{iNlg(b4Qv_wW1x5tznF-dL8=cx@i>vUZsS}R>ZI2+%I zMMBYH=T5=b$3@1-G%m!Fk%cpiY=l;TMiD|g>rMAlS7}OGQsS&=Wtc+}v|n^_+E|5) z`U{Q@ZU~Q>mwL%Qgm^?|FBPOr0YPXW_=$4BS$3odr39MbhO~nhv2O$S?!%0k> z2H4Eu2Q(K1FQH2c#S^0sieHZ!#OtH!V%13MV&x(Dx!r0X zk-~7J7^H2{0j)dhT4B#r4FPI;=iNzud39l z@_!$NlR00!JoH;sEW$J#D{h>P#R<(5{ljA$_hDuoW?TaH1EoMZpfu0{;8oxXkOYl( zK)J3F#QnfYoH0A74A_7QOYr)IQNux*+YWkp&!fbrYkYkBJ32UM3@RZXzMsi;S+-2Go z>kFrgPYTL{wt^wuX)|Aza=0#s>pH!Z88iu!m7*)0gXq6L{NG_`qoI5jYek?*l$RP{ zZKbEB^;XH0x5Bw)@dTDEv(UWHnZqWC%kp&g>1Zf{N#;kOc(<3cO`x&#P~j}Jc5be1 zZf$edmAG3xH1m;heLO|axS1BkA+Lvy7R=Sdpsbq)t*UKqX@ylRL`FfoXJ=zWH8H|Q zX%(Z|Fb~OcJ?!#SlV#ymuJ_E0Fys8=E}M?$*ZU<=|zqXsebLNY8*z%>}B3G`W;4ld!;i z$Y4n7P-RGtvvCf;%?7*@HmvhMW?4LTjl7^$YV^(SW*9>}@`8b>9@tz4K3p~xFX-U~ zx>>1_7tFW35ODgVzD!{%4jujQ@Sbd*7(9@_C%)@sd$8TU-&92zGgY@J^k1t~gGWlL zC0!niP9|fi^qFOV`wGS}a>R>Hy(^VzlA~ENxf##_(|~w@j%IAK8~^B4AO(`=f-?d?e;Th zngi)~L480CK#e}(B!Pbgv=r0@bO2MR-KdJnnT-gnfxKl>74;Hy6R3*n?Q>M{Uqwyf zsCXuZ`Mp0Xble(+V`XAFy%f>`qXk9|odG;@^DurQycCu9#yGhwmA6fToY*5Lc1EPX zs*a@7hG4EH(n0nfzoo_X%|1mSIK|o zY-_!SIUko;Mj76s_i=XZGl^Y0p<(Y67IJprryBNSl)Qg@inC(8m|LuzJ!D|)Sd7HB zAAve^z!_t_5&OgWl3K^s02s?@Lr2>gb2OaB0L$slrtNU7;rY4_{=`; I<2OwI0t!kMq5uE@ delta 1616 zcmbVMU1$_n6ux(y&2F-rnMpLsmRd70OQP1wZi>qqQe6Kqf{_K|4?c}W3QCPjZ8b%u zvu}c-?CwoVuoPBkDS{8tSzROwn{*$FKd=cXD$)jN5UJumD6JA%zcVwD5a^2szWL_f zbI;E`_nvD``^@Q@bf`gMjC}~C0g?|2T$gUC*_>=OY5%A~*EIP*#%8Ss?KzF=WBwZv z9;2n23s4mz+q?*0XS|TDSmh7(y{!u|lb2*`cC+ly8ggs}y!QZ<2n8pu1-t;IK*?}m zzHG>JaoSx;B@b79GySyr2fqYImfbFF`+j)j!MZ!f-*XmZ{r?_%hSx+mxuAgW=OUYw zYd139KmiYkRIyuZjjR4s-!j&S8L-$NKf@LAEZ(^mTQX@Kwq@3UJ>VDMAg~+I_)Pd- z-O@|Z`;$`_e_H0<(~PwucP?(_jN?i+8Q=%Rc&SUQPcB{%pD*yZy0+`OAn z#N|Ghn<&GNkyo7V|t`kLq_;B1DxI6EKy^Dr9{9~E18zgS!Rq&2`Q zm?fbEp=8?N6B^oL-vGPr-J6^lT44Z`uFet$jXOqu{u2aIm_~OT5`=1<*B$t+TJ9)pR^StnE_YVMmt~pH6J$x;Qb>+1$^i^8Z`$N9x%S#NQS7H|G) z_mrV(6`tuaF*K>5Q>K(F8t(~O(w34pTM2X=hF(UCX^2T4t5x#toGhI#dA-I9U8DT2 z%Dq-?_+K?L|8;DJeF=sQ3+(Cq31n{+A|}7-JZx9eJkKxZr0vSEv=?lsnMCh*^ct)H zjsZQ$<_0{@QaX^YQLq4#3R2-9gMg0A62Jh^i-+PQbl322K!+h)0xSl|uL?8)0YCxj j0Y5NTGdxa;{jSzw5^oA?p@u)I@*r_lEoiz_L6+KEyyR%; diff --git a/test/DebugInfo/PDB/pdbdump-symbol-format.test b/test/DebugInfo/PDB/pdbdump-symbol-format.test index 9d50ae226db..1540e167dbe 100644 --- a/test/DebugInfo/PDB/pdbdump-symbol-format.test +++ b/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/tools/llvm-pdbdump/CMakeLists.txt b/tools/llvm-pdbdump/CMakeLists.txt index 64b3d620837..0519bf0634c 100644 --- a/tools/llvm-pdbdump/CMakeLists.txt +++ b/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/tools/llvm-pdbdump/ClassDefinitionDumper.cpp b/tools/llvm-pdbdump/ClassDefinitionDumper.cpp new file mode 100644 index 00000000000..f6bb6958d8b --- /dev/null +++ b/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/tools/llvm-pdbdump/ClassDefinitionDumper.h b/tools/llvm-pdbdump/ClassDefinitionDumper.h new file mode 100644 index 00000000000..f82d9760bcc --- /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 +#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/tools/llvm-pdbdump/CompilandDumper.cpp b/tools/llvm-pdbdump/CompilandDumper.cpp index ee55228309d..852ddfa02a5 100644 --- a/tools/llvm-pdbdump/CompilandDumper.cpp +++ b/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/tools/llvm-pdbdump/FunctionDumper.cpp b/tools/llvm-pdbdump/FunctionDumper.cpp index 955d6499f9d..1bd201b8f69 100644 --- a/tools/llvm-pdbdump/FunctionDumper.cpp +++ b/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 << " "; + + auto ClassParent = Symbol.getClassParent(); + PDB_CallingConv CC = Signature->getCallingConvention(); + if (Pointer != FunctionDumper::PointerType::None) + OS << "("; - OS << " " << Signature->getCallingConvention() << " "; + 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/tools/llvm-pdbdump/FunctionDumper.h b/tools/llvm-pdbdump/FunctionDumper.h index 287a79c02c2..f9338cb8764 100644 --- a/tools/llvm-pdbdump/FunctionDumper.h +++ b/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/tools/llvm-pdbdump/TypeDumper.cpp b/tools/llvm-pdbdump/TypeDumper.cpp index 72171b0f318..c4e2eabda90 100644 --- a/tools/llvm-pdbdump/TypeDumper.cpp +++ b/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/tools/llvm-pdbdump/TypeDumper.h b/tools/llvm-pdbdump/TypeDumper.h index 6c51d155df8..d96c24c87fa 100644 --- a/tools/llvm-pdbdump/TypeDumper.h +++ b/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/tools/llvm-pdbdump/TypedefDumper.cpp b/tools/llvm-pdbdump/TypedefDumper.cpp index 55fcb1a3ade..e3ac76a63b3 100644 --- a/tools/llvm-pdbdump/TypedefDumper.cpp +++ b/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/tools/llvm-pdbdump/VariableDumper.cpp b/tools/llvm-pdbdump/VariableDumper.cpp new file mode 100644 index 00000000000..cb9c66a94b9 --- /dev/null +++ b/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/tools/llvm-pdbdump/VariableDumper.h b/tools/llvm-pdbdump/VariableDumper.h new file mode 100644 index 00000000000..e6e71faca31 --- /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 index cf305d3328e..e33e71562d3 100644 --- a/tools/llvm-pdbdump/llvm-pdbdump.cpp +++ b/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); } -- 2.34.1