From 7724dc63a78d409d486c2a1a7273ddbbbcba6299 Mon Sep 17 00:00:00 2001 From: Zachary Turner Date: Wed, 12 Apr 2017 23:18:21 +0000 Subject: [PATCH] [llvm-pdbdump] More advanced class definition dumping. Previously the dumping of class definitions was very primitive, and it made it hard to do more than the most trivial of output formats when dumping. As such, we would only dump one line for each field, and then dump non-layout items like nested types and enums. With this patch, we do a complete analysis of the object hierarchy including aggregate types, bases, virtual bases, vftable analysis, etc. The only immediately visible effects of this are that a) we can now dump a line for the vfptr where before we would treat that as padding, and b) we now don't treat virtual bases that come at the end of a class as padding since we have a more detailed analysis of the class's storage usage. In subsequent patches, we should be able to use this analysis to display a complete graphical view of a class's layout including recursing arbitrarily deep into an object's base class / aggregate member hierarchy. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@300133 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h | 1 + include/llvm/DebugInfo/PDB/DIA/DIASession.h | 2 +- include/llvm/DebugInfo/PDB/IPDBRawSymbol.h | 5 + include/llvm/DebugInfo/PDB/IPDBSession.h | 12 +- .../DebugInfo/PDB/Native/NativeRawSymbol.h | 1 + .../llvm/DebugInfo/PDB/Native/NativeSession.h | 2 +- include/llvm/DebugInfo/PDB/PDBSymbol.h | 18 +- include/llvm/DebugInfo/PDB/PDBSymbolExe.h | 2 + .../DebugInfo/PDB/PDBSymbolTypeBaseClass.h | 3 + include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h | 8 + .../llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h | 1 + include/llvm/DebugInfo/PDB/UDTLayout.h | 145 +++++++++++++ include/llvm/Support/Casting.h | 2 +- lib/DebugInfo/PDB/CMakeLists.txt | 1 + lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp | 15 ++ lib/DebugInfo/PDB/DIA/DIASession.cpp | 2 +- lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp | 7 + lib/DebugInfo/PDB/Native/NativeSession.cpp | 5 +- lib/DebugInfo/PDB/PDBSymbol.cpp | 9 +- lib/DebugInfo/PDB/PDBSymbolExe.cpp | 11 + lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp | 8 + lib/DebugInfo/PDB/UDTLayout.cpp | 194 ++++++++++++++++++ .../PDB/DIA/pdbdump-symbol-format.test | 4 +- test/DebugInfo/PDB/Inputs/symbolformat.pdb | Bin 44032 -> 110592 bytes .../llvm-pdbdump/Inputs/SimplePaddingTest.cpp | 122 +++++++++++ .../llvm-pdbdump/Inputs/SimplePaddingTest.pdb | Bin 0 -> 110592 bytes test/tools/llvm-pdbdump/class-layout.test | 23 ++- test/tools/llvm-pdbdump/enum-layout.test | 2 +- test/tools/llvm-pdbdump/simple-padding.test | 94 +++++++++ .../PrettyClassDefinitionDumper.cpp | 131 +++++------- .../PrettyClassDefinitionDumper.h | 6 + tools/llvm-pdbdump/PrettyFunctionDumper.cpp | 2 +- tools/llvm-pdbdump/PrettyTypeDumper.cpp | 34 ++- tools/llvm-pdbdump/PrettyTypedefDumper.cpp | 2 +- tools/llvm-pdbdump/PrettyVariableDumper.cpp | 23 ++- tools/llvm-pdbdump/PrettyVariableDumper.h | 1 + tools/llvm-pdbdump/llvm-pdbdump.cpp | 21 +- tools/llvm-pdbdump/llvm-pdbdump.h | 2 +- unittests/DebugInfo/PDB/PDBApiTest.cpp | 3 +- 39 files changed, 769 insertions(+), 155 deletions(-) create mode 100644 include/llvm/DebugInfo/PDB/UDTLayout.h create mode 100644 lib/DebugInfo/PDB/UDTLayout.cpp create mode 100644 test/tools/llvm-pdbdump/Inputs/SimplePaddingTest.cpp create mode 100644 test/tools/llvm-pdbdump/Inputs/SimplePaddingTest.pdb create mode 100644 test/tools/llvm-pdbdump/simple-padding.test diff --git a/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h b/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h index 1e40c46f8a2..c0633cbdfa5 100644 --- a/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h +++ b/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h @@ -102,6 +102,7 @@ public: uint32_t getVirtualBaseDispIndex() const override; uint32_t getVirtualBaseOffset() const override; uint32_t getVirtualTableShapeId() const override; + std::unique_ptr getVirtualBaseTableType() const override; PDB_DataKind getDataKind() const override; PDB_SymType getSymTag() const override; PDB_UniqueId getGuid() const override; diff --git a/include/llvm/DebugInfo/PDB/DIA/DIASession.h b/include/llvm/DebugInfo/PDB/DIA/DIASession.h index 350442556be..3f5818631e7 100644 --- a/include/llvm/DebugInfo/PDB/DIA/DIASession.h +++ b/include/llvm/DebugInfo/PDB/DIA/DIASession.h @@ -31,7 +31,7 @@ public: uint64_t getLoadAddress() const override; void setLoadAddress(uint64_t Address) override; - std::unique_ptr getGlobalScope() override; + std::unique_ptr getGlobalScope() const override; std::unique_ptr getSymbolById(uint32_t SymbolId) const override; std::unique_ptr diff --git a/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h b/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h index 49866b8bb2f..4c28e194bc7 100644 --- a/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h +++ b/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h @@ -21,6 +21,9 @@ class raw_ostream; namespace pdb { +class PDBSymbolTypeVTable; +class PDBSymbolTypeVTableShape; + /// IPDBRawSymbol defines an interface used to represent an arbitrary symbol. /// It exposes a monolithic interface consisting of accessors for the union of /// all properties that are valid for any symbol type. This interface is then @@ -110,6 +113,8 @@ public: virtual Variant getValue() const = 0; virtual uint32_t getVirtualBaseDispIndex() const = 0; virtual uint32_t getVirtualBaseOffset() const = 0; + virtual std::unique_ptr + getVirtualBaseTableType() const = 0; virtual uint32_t getVirtualTableShapeId() const = 0; virtual PDB_DataKind getDataKind() const = 0; virtual PDB_SymType getSymTag() const = 0; diff --git a/include/llvm/DebugInfo/PDB/IPDBSession.h b/include/llvm/DebugInfo/PDB/IPDBSession.h index 696736a907a..85d9fe12485 100644 --- a/include/llvm/DebugInfo/PDB/IPDBSession.h +++ b/include/llvm/DebugInfo/PDB/IPDBSession.h @@ -29,20 +29,12 @@ public: virtual uint64_t getLoadAddress() const = 0; virtual void setLoadAddress(uint64_t Address) = 0; - virtual std::unique_ptr getGlobalScope() = 0; + virtual std::unique_ptr getGlobalScope() const = 0; virtual std::unique_ptr getSymbolById(uint32_t SymbolId) const = 0; template std::unique_ptr getConcreteSymbolById(uint32_t SymbolId) const { - auto Symbol(getSymbolById(SymbolId)); - if (!Symbol) - return nullptr; - - T *ConcreteSymbol = dyn_cast(Symbol.get()); - if (!ConcreteSymbol) - return nullptr; - (void)Symbol.release(); - return std::unique_ptr(ConcreteSymbol); + return unique_dyn_cast_or_null(getSymbolById(SymbolId)); } virtual std::unique_ptr diff --git a/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h b/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h index 655bed9ac17..cffb5d09d22 100644 --- a/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h +++ b/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h @@ -101,6 +101,7 @@ public: uint32_t getVirtualBaseDispIndex() const override; uint32_t getVirtualBaseOffset() const override; uint32_t getVirtualTableShapeId() const override; + std::unique_ptr getVirtualBaseTableType() const override; PDB_DataKind getDataKind() const override; PDB_SymType getSymTag() const override; PDB_UniqueId getGuid() const override; diff --git a/include/llvm/DebugInfo/PDB/Native/NativeSession.h b/include/llvm/DebugInfo/PDB/Native/NativeSession.h index bbe207738e0..e6da266f796 100644 --- a/include/llvm/DebugInfo/PDB/Native/NativeSession.h +++ b/include/llvm/DebugInfo/PDB/Native/NativeSession.h @@ -32,7 +32,7 @@ public: uint64_t getLoadAddress() const override; void setLoadAddress(uint64_t Address) override; - std::unique_ptr getGlobalScope() override; + std::unique_ptr getGlobalScope() const override; std::unique_ptr getSymbolById(uint32_t SymbolId) const override; std::unique_ptr diff --git a/include/llvm/DebugInfo/PDB/PDBSymbol.h b/include/llvm/DebugInfo/PDB/PDBSymbol.h index 652f2136105..b114b7afb0b 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbol.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbol.h @@ -62,6 +62,7 @@ class PDBSymbol { protected: PDBSymbol(const IPDBSession &PDBSession, std::unique_ptr Symbol); + PDBSymbol(PDBSymbol &Symbol); public: static std::unique_ptr @@ -91,12 +92,6 @@ public: return Enumerator->getNext(); } - template T *cast() { return llvm::dyn_cast(this); } - - template const T *cast() const { - return llvm::dyn_cast(this); - } - std::unique_ptr clone() const; template @@ -128,18 +123,11 @@ protected: template std::unique_ptr getConcreteSymbolByIdHelper(uint32_t Id) const { - auto Sym = getSymbolByIdHelper(Id); - if (!Sym) - return nullptr; - ConcreteType *Result = Sym->cast(); - if (!Result) - return nullptr; - Sym.release(); - return std::unique_ptr(Result); + return unique_dyn_cast_or_null(getSymbolByIdHelper(Id)); } const IPDBSession &Session; - const std::unique_ptr RawSymbol; + std::unique_ptr RawSymbol; }; } // namespace llvm diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolExe.h b/include/llvm/DebugInfo/PDB/PDBSymbolExe.h index 5b3f50d153e..2c2d7466504 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolExe.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolExe.h @@ -37,6 +37,8 @@ public: FORWARD_SYMBOL_METHOD(getSignature) FORWARD_SYMBOL_METHOD(getSymbolsFileName) + uint32_t getPointerByteSize() const; + private: void dumpChildren(raw_ostream &OS, StringRef Label, PDB_SymType ChildType, int Indent) const; diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h index 0924efb8aa9..d607a3d8117 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h @@ -13,6 +13,9 @@ #include "PDBSymbol.h" #include "PDBTypes.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h" + namespace llvm { class raw_ostream; diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h index 47a4525a47b..e9e7fe8c986 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h @@ -10,7 +10,9 @@ #ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEUDT_H #define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEUDT_H +#include "IPDBSession.h" #include "PDBSymbol.h" +#include "PDBSymbolTypeBaseClass.h" #include "PDBTypes.h" namespace llvm { @@ -18,11 +20,17 @@ namespace llvm { class raw_ostream; namespace pdb { + class PDBSymbolTypeUDT : public PDBSymbol { public: PDBSymbolTypeUDT(const IPDBSession &PDBSession, std::unique_ptr UDTSymbol); + std::unique_ptr clone() const { + return getSession().getConcreteSymbolById( + getSymIndexId()); + } + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::UDT) void dump(PDBSymDumper &Dumper) const override; diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h index 17612ff4606..e270c2b7eb9 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h @@ -28,6 +28,7 @@ public: void dump(PDBSymDumper &Dumper) const override; FORWARD_SYMBOL_ID_METHOD(getClassParent) + FORWARD_SYMBOL_METHOD(getOffset) FORWARD_SYMBOL_METHOD(isConstType) FORWARD_SYMBOL_ID_METHOD(getLexicalParent) FORWARD_SYMBOL_ID_METHOD(getType) diff --git a/include/llvm/DebugInfo/PDB/UDTLayout.h b/include/llvm/DebugInfo/PDB/UDTLayout.h new file mode 100644 index 00000000000..20b70340f33 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/UDTLayout.h @@ -0,0 +1,145 @@ +//===- UDTLayout.h - UDT layout info ----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_UDTLAYOUT_H +#define LLVM_DEBUGINFO_PDB_UDTLAYOUT_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/BitVector.h" + +#include +#include + +namespace llvm { + +class raw_ostream; + +namespace pdb { + +class PDBSymTypeBaseClass; +class PDBSymbolData; +class PDBSymbolTypeUDT; +class PDBSymbolTypeVTable; + +class ClassLayout; +class BaseClassLayout; +class StorageItemBase; +class UDTLayoutBase; + +class StorageItemBase { +public: + StorageItemBase(const UDTLayoutBase &Parent, const PDBSymbol &Symbol, + const std::string &Name, uint32_t OffsetInParent, + uint32_t Size); + virtual ~StorageItemBase() {} + + virtual uint32_t deepPaddingSize() const; + + const UDTLayoutBase &getParent() const { return Parent; } + StringRef getName() const { return Name; } + uint32_t getOffsetInParent() const { return OffsetInParent; } + uint32_t getSize() const { return SizeOf; } + const PDBSymbol &getSymbol() const { return Symbol; } + +protected: + const UDTLayoutBase &Parent; + const PDBSymbol &Symbol; + BitVector UsedBytes; + std::string Name; + uint32_t OffsetInParent = 0; + uint32_t SizeOf = 0; +}; + +class DataMemberLayoutItem : public StorageItemBase { +public: + DataMemberLayoutItem(const UDTLayoutBase &Parent, + std::unique_ptr DataMember); + + virtual uint32_t deepPaddingSize() const; + + const PDBSymbolData &getDataMember(); + +private: + std::unique_ptr DataMember; + std::unique_ptr UdtLayout; +}; + +class VTableLayoutItem : public StorageItemBase { +public: + VTableLayoutItem(const UDTLayoutBase &Parent, + std::unique_ptr VTable); + +private: + std::unique_ptr VTable; + std::vector> VTableFuncs; +}; + +class UDTLayoutBase { +public: + UDTLayoutBase(const PDBSymbol &Symbol, const std::string &Name, + uint32_t Size); + + uint32_t shallowPaddingSize() const; + uint32_t deepPaddingSize() const; + + const BitVector &usedBytes() const { return UsedBytes; } + + uint32_t getClassSize() const { return SizeOf; } + + const PDBSymbol &getSymbol() const { return Symbol; } + + ArrayRef> layout_items() const { + return ChildStorage; + } + + ArrayRef> other_items() const { + return NonStorageItems; + } + +protected: + void initializeChildren(const PDBSymbol &Sym); + + void addChildToLayout(std::unique_ptr Child); + + uint32_t SizeOf = 0; + std::string Name; + + const PDBSymbol &Symbol; + BitVector UsedBytes; + std::vector> NonStorageItems; + std::vector> ChildStorage; + std::vector> ChildrenPerByte; + std::vector BaseClasses; + VTableLayoutItem *VTable = nullptr; +}; + +class ClassLayout : public UDTLayoutBase { +public: + explicit ClassLayout(std::unique_ptr UDT); + +private: + std::unique_ptr Type; +}; + +class BaseClassLayout : public UDTLayoutBase, public StorageItemBase { +public: + BaseClassLayout(const UDTLayoutBase &Parent, + std::unique_ptr Base); + +private: + std::unique_ptr Base; + bool IsVirtualBase; +}; +} +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_UDTLAYOUT_H diff --git a/include/llvm/Support/Casting.h b/include/llvm/Support/Casting.h index 3a0c5536c01..89d2af052dc 100644 --- a/include/llvm/Support/Casting.h +++ b/include/llvm/Support/Casting.h @@ -384,7 +384,7 @@ LLVM_NODISCARD inline auto unique_dyn_cast_or_null(std::unique_ptr &Val) -> decltype(cast(Val)) { if (!Val) return nullptr; - return unique_dyn_cast(Val); + return unique_dyn_cast(Val); } template diff --git a/lib/DebugInfo/PDB/CMakeLists.txt b/lib/DebugInfo/PDB/CMakeLists.txt index 1295d2a19ce..f87a0b0a72e 100644 --- a/lib/DebugInfo/PDB/CMakeLists.txt +++ b/lib/DebugInfo/PDB/CMakeLists.txt @@ -101,6 +101,7 @@ add_llvm_library(LLVMDebugInfoPDB PDBSymbolUnknown.cpp PDBSymbolUsingNamespace.cpp PDBSymDumper.cpp + UDTLayout.cpp ${PDB_IMPL_SOURCES} ADDITIONAL_HEADER_DIRS diff --git a/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp b/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp index 6182dab213c..5e8c0bdc171 100644 --- a/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp +++ b/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp @@ -14,6 +14,9 @@ #include "llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h" #include "llvm/DebugInfo/PDB/DIA/DIASession.h" #include "llvm/DebugInfo/PDB/PDBExtras.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/raw_ostream.h" @@ -717,6 +720,18 @@ uint32_t DIARawSymbol::getVirtualTableShapeId() const { return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_virtualTableShapeId); } +std::unique_ptr +DIARawSymbol::getVirtualBaseTableType() const { + CComPtr TableType; + if (FAILED(Symbol->get_virtualBaseTableType(&TableType)) || !TableType) + return nullptr; + + auto RawVT = llvm::make_unique(Session, TableType); + auto Pointer = + llvm::make_unique(Session, std::move(RawVT)); + return unique_dyn_cast(Pointer->getPointeeType()); +} + PDB_DataKind DIARawSymbol::getDataKind() const { return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_dataKind); diff --git a/lib/DebugInfo/PDB/DIA/DIASession.cpp b/lib/DebugInfo/PDB/DIA/DIASession.cpp index 7077bda4a53..6ecf335812b 100644 --- a/lib/DebugInfo/PDB/DIA/DIASession.cpp +++ b/lib/DebugInfo/PDB/DIA/DIASession.cpp @@ -140,7 +140,7 @@ void DIASession::setLoadAddress(uint64_t Address) { Session->put_loadAddress(Address); } -std::unique_ptr DIASession::getGlobalScope() { +std::unique_ptr DIASession::getGlobalScope() const { CComPtr GlobalScope; if (S_OK != Session->get_globalScope(&GlobalScope)) return nullptr; diff --git a/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp b/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp index 4841ded7410..3aba35adb53 100644 --- a/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp +++ b/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp @@ -13,6 +13,8 @@ #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" #include "llvm/DebugInfo/PDB/Native/NativeSession.h" #include "llvm/DebugInfo/PDB/PDBExtras.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/raw_ostream.h" @@ -318,6 +320,11 @@ uint32_t NativeRawSymbol::getVirtualTableShapeId() const { return 0; } +std::unique_ptr +NativeRawSymbol::getVirtualBaseTableType() const { + return nullptr; +} + PDB_DataKind NativeRawSymbol::getDataKind() const { return PDB_DataKind::Unknown; } diff --git a/lib/DebugInfo/PDB/Native/NativeSession.cpp b/lib/DebugInfo/PDB/Native/NativeSession.cpp index 3a83a326cfe..7e6843bceb7 100644 --- a/lib/DebugInfo/PDB/Native/NativeSession.cpp +++ b/lib/DebugInfo/PDB/Native/NativeSession.cpp @@ -70,8 +70,9 @@ uint64_t NativeSession::getLoadAddress() const { return 0; } void NativeSession::setLoadAddress(uint64_t Address) {} -std::unique_ptr NativeSession::getGlobalScope() { - auto RawSymbol = llvm::make_unique(*this); +std::unique_ptr NativeSession::getGlobalScope() const { + auto RawSymbol = + llvm::make_unique(const_cast(*this)); auto PdbSymbol(PDBSymbol::create(*this, std::move(RawSymbol))); std::unique_ptr ExeSymbol( static_cast(PdbSymbol.release())); diff --git a/lib/DebugInfo/PDB/PDBSymbol.cpp b/lib/DebugInfo/PDB/PDBSymbol.cpp index 2c8438f9c23..14eb6ba8ad8 100644 --- a/lib/DebugInfo/PDB/PDBSymbol.cpp +++ b/lib/DebugInfo/PDB/PDBSymbol.cpp @@ -54,6 +54,9 @@ PDBSymbol::PDBSymbol(const IPDBSession &PDBSession, std::unique_ptr Symbol) : Session(PDBSession), RawSymbol(std::move(Symbol)) {} +PDBSymbol::PDBSymbol(PDBSymbol &Symbol) + : Session(Symbol.Session), RawSymbol(std::move(Symbol.RawSymbol)) {} + PDBSymbol::~PDBSymbol() = default; #define FACTORY_SYMTAG_CASE(Tag, Type) \ @@ -100,12 +103,6 @@ PDBSymbol::create(const IPDBSession &PDBSession, } } -#define TRY_DUMP_TYPE(Type) \ - if (const Type *DerivedThis = this->cast()) \ - Dumper.dump(OS, Indent, *DerivedThis); - -#define ELSE_TRY_DUMP_TYPE(Type, Dumper) else TRY_DUMP_TYPE(Type, Dumper) - void PDBSymbol::defaultDump(raw_ostream &OS, int Indent) const { RawSymbol->dump(OS, Indent); } diff --git a/lib/DebugInfo/PDB/PDBSymbolExe.cpp b/lib/DebugInfo/PDB/PDBSymbolExe.cpp index b9fcac78c36..7417167b61a 100644 --- a/lib/DebugInfo/PDB/PDBSymbolExe.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolExe.cpp @@ -10,6 +10,7 @@ #include "llvm/DebugInfo/PDB/PDBSymbolExe.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h" #include @@ -23,3 +24,13 @@ PDBSymbolExe::PDBSymbolExe(const IPDBSession &PDBSession, } void PDBSymbolExe::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } + +uint32_t PDBSymbolExe::getPointerByteSize() const { + auto Pointer = findOneChild(); + if (Pointer) + return Pointer->getLength(); + + if (getMachineType() == PDB_Machine::x86) + return 4; + return 8; +} diff --git a/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp index 4a9a9ed5fda..15dc1535216 100644 --- a/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp @@ -9,7 +9,15 @@ #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" +#include "llvm/DebugInfo/PDB/IPDBSession.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" +#include "llvm/DebugInfo/PDB/PDBSymbolData.h" +#include "llvm/DebugInfo/PDB/PDBSymbolExe.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h" +#include "llvm/DebugInfo/PDB/UDTLayout.h" #include diff --git a/lib/DebugInfo/PDB/UDTLayout.cpp b/lib/DebugInfo/PDB/UDTLayout.cpp new file mode 100644 index 00000000000..71443fe7587 --- /dev/null +++ b/lib/DebugInfo/PDB/UDTLayout.cpp @@ -0,0 +1,194 @@ +//===- UDTLayout.cpp --------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/PDB/UDTLayout.h" + +#include "llvm/DebugInfo/PDB/IPDBSession.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" +#include "llvm/DebugInfo/PDB/PDBSymbolData.h" +#include "llvm/DebugInfo/PDB/PDBSymbolExe.h" +#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h" + +#include + +using namespace llvm; +using namespace llvm::pdb; + +static std::unique_ptr getSymbolType(const PDBSymbol &Symbol) { + const IPDBSession &Session = Symbol.getSession(); + const IPDBRawSymbol &RawSymbol = Symbol.getRawSymbol(); + uint32_t TypeId = RawSymbol.getTypeId(); + return Session.getSymbolById(TypeId); +} + +static uint32_t getTypeLength(const PDBSymbol &Symbol) { + auto SymbolType = getSymbolType(Symbol); + const IPDBRawSymbol &RawType = SymbolType->getRawSymbol(); + + return RawType.getLength(); +} + +StorageItemBase::StorageItemBase(const UDTLayoutBase &Parent, + const PDBSymbol &Symbol, + const std::string &Name, + uint32_t OffsetInParent, uint32_t Size) + : Parent(Parent), Symbol(Symbol), Name(Name), SizeOf(Size), + OffsetInParent(OffsetInParent) { + UsedBytes.resize(SizeOf, true); +} + +uint32_t StorageItemBase::deepPaddingSize() const { + // sizeof(Field) - sizeof(typeof(Field)) is trailing padding. + return SizeOf - getTypeLength(Symbol); +} + +DataMemberLayoutItem::DataMemberLayoutItem( + const UDTLayoutBase &Parent, std::unique_ptr DataMember) + : StorageItemBase(Parent, *DataMember, DataMember->getName(), + DataMember->getOffset(), getTypeLength(*DataMember)), + DataMember(std::move(DataMember)) { + auto Type = this->DataMember->getType(); + if (auto UDT = unique_dyn_cast(Type)) { + // UDT data members might have padding in between fields, but otherwise + // a member should occupy its entire storage. + UsedBytes.resize(SizeOf, false); + UdtLayout = llvm::make_unique(std::move(UDT)); + } +} + +const PDBSymbolData &DataMemberLayoutItem::getDataMember() { + return *dyn_cast(&Symbol); +} + +uint32_t DataMemberLayoutItem::deepPaddingSize() const { + uint32_t Result = StorageItemBase::deepPaddingSize(); + if (UdtLayout) + Result += UdtLayout->deepPaddingSize(); + return Result; +} + +VTableLayoutItem::VTableLayoutItem(const UDTLayoutBase &Parent, + std::unique_ptr VTable) + : StorageItemBase(Parent, *VTable, "", 0, getTypeLength(*VTable)), + VTable(std::move(VTable)) { + // initialize vtbl methods. + auto VTableType = cast(this->VTable->getType()); + uint32_t PointerSize = VTableType->getLength(); + + if (auto Shape = unique_dyn_cast( + VTableType->getPointeeType())) { + VTableFuncs.resize(Shape->getCount()); + + auto ParentFunctions = Parent.getSymbol().findAllChildren(); + while (auto Func = ParentFunctions->getNext()) { + if (Func->isVirtual()) { + uint32_t Index = Func->getVirtualBaseOffset(); + assert(Index % PointerSize == 0); + Index /= PointerSize; + + // Don't allow a compiler generated function to overwrite a user + // function in the VTable. Not sure why this happens, but a function + // named __vecDelDtor sometimes shows up on top of the destructor. + if (Func->isCompilerGenerated() && VTableFuncs[Index]) + continue; + VTableFuncs[Index] = std::move(Func); + } + } + } +} + +UDTLayoutBase::UDTLayoutBase(const PDBSymbol &Symbol, const std::string &Name, + uint32_t Size) + : Symbol(Symbol), Name(Name), SizeOf(Size) { + UsedBytes.resize(Size); + ChildrenPerByte.resize(Size); + initializeChildren(Symbol); +} + +ClassLayout::ClassLayout(std::unique_ptr UDT) + : UDTLayoutBase(*UDT, UDT->getName(), UDT->getLength()), + Type(std::move(UDT)) {} + +BaseClassLayout::BaseClassLayout(const UDTLayoutBase &Parent, + std::unique_ptr Base) + : UDTLayoutBase(*Base, Base->getName(), Base->getLength()), + StorageItemBase(Parent, *Base, Base->getName(), Base->getOffset(), + Base->getLength()), + Base(std::move(Base)) { + IsVirtualBase = this->Base->isVirtualBaseClass(); +} + +uint32_t UDTLayoutBase::shallowPaddingSize() const { + return UsedBytes.size() - UsedBytes.count(); +} + +uint32_t UDTLayoutBase::deepPaddingSize() const { + uint32_t Result = shallowPaddingSize(); + for (auto &Child : ChildStorage) + Result += Child->deepPaddingSize(); + return Result; +} + +void UDTLayoutBase::initializeChildren(const PDBSymbol &Sym) { + auto Children = Sym.findAllChildren(); + while (auto Child = Children->getNext()) { + if (auto Data = unique_dyn_cast(Child)) { + if (Data->getDataKind() == PDB_DataKind::Member) { + auto DM = + llvm::make_unique(*this, std::move(Data)); + + addChildToLayout(std::move(DM)); + } else { + NonStorageItems.push_back(std::move(Data)); + } + continue; + } + + if (auto Base = unique_dyn_cast(Child)) { + auto BL = llvm::make_unique(*this, std::move(Base)); + BaseClasses.push_back(BL.get()); + + addChildToLayout(std::move(BL)); + continue; + } + + if (auto VT = unique_dyn_cast(Child)) { + auto VTLayout = llvm::make_unique(*this, std::move(VT)); + + VTable = VTLayout.get(); + + addChildToLayout(std::move(VTLayout)); + continue; + } + + NonStorageItems.push_back(std::move(Child)); + } +} + +void UDTLayoutBase::addChildToLayout(std::unique_ptr Child) { + uint32_t Begin = Child->getOffsetInParent(); + uint32_t End = Begin + Child->getSize(); + UsedBytes.set(Begin, End); + while (Begin != End) { + ChildrenPerByte[Begin].push_back(Child.get()); + ++Begin; + } + + auto Loc = std::upper_bound( + ChildStorage.begin(), ChildStorage.end(), Begin, + [](uint32_t Off, const std::unique_ptr &Item) { + return Off < Item->getOffsetInParent(); + }); + + ChildStorage.insert(Loc, std::move(Child)); +} \ No newline at end of file diff --git a/test/DebugInfo/PDB/DIA/pdbdump-symbol-format.test b/test/DebugInfo/PDB/DIA/pdbdump-symbol-format.test index 60a19534687..0bb3e001d3a 100644 --- a/test/DebugInfo/PDB/DIA/pdbdump-symbol-format.test +++ b/test/DebugInfo/PDB/DIA/pdbdump-symbol-format.test @@ -32,14 +32,14 @@ ; TYPES_FORMAT-DAG: typedef class A ClassAType ; TYPES_1: Classes -; TYPES_1: struct A { +; TYPES_1: struct A [sizeof = 4] { ; TYPES_1: virtual void PureFunc() = 0 ; TYPES_1: virtual void VirtualFunc() ; TYPES_1: void RegularFunc() ; TYPES_1: } ; TYPES_2: Classes -; TYPES_2: struct MemberTest { +; TYPES_2: struct MemberTest [sizeof = 96] { ; TYPES_2: data +0x00 [sizeof=4] MemberTest::NestedEnum m_nested_enum ; TYPES_2: data +0x04 [sizeof=4] int m_typedef ; TYPES_2: data +0x08 [sizeof=1] bool m_bool diff --git a/test/DebugInfo/PDB/Inputs/symbolformat.pdb b/test/DebugInfo/PDB/Inputs/symbolformat.pdb index 0e509f3a93c33fa65471692bb69155effebdb7d4..9272f318258bc06dc115475b9e0d4188edd75331 100644 GIT binary patch literal 110592 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 E2Q^Rqod5s; literal 44032 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 A>;M1& diff --git a/test/tools/llvm-pdbdump/Inputs/SimplePaddingTest.cpp b/test/tools/llvm-pdbdump/Inputs/SimplePaddingTest.cpp new file mode 100644 index 00000000000..b10839beea2 --- /dev/null +++ b/test/tools/llvm-pdbdump/Inputs/SimplePaddingTest.cpp @@ -0,0 +1,122 @@ +// Compile with "cl /c /Zi /GR- SimplePaddingTest.cpp" +// Link with "link SimplePaddingTest.obj /debug /nodefaultlib /entry:main" + +#include + +extern "C" using at_exit_handler = void(); + +int atexit(at_exit_handler handler) { return 0; } + +struct SimplePadNoPadding { + int32_t X; + int32_t Y; + // No padding anywhere, sizeof(T) = 8 +} A; + +struct SimplePadUnion { + union { + int32_t X; + int64_t Y; + struct { + int32_t X; + // 4 bytes of padding here + int64_t Y; + } Z; + }; + // Since the padding occurs at a location that is occupied by other storage + // (namely the Y member), the storage will still be considered used, and so + // there will be no unused bytes in the larger class. But in the debug + // info for the nested struct, we should see padding. + // sizeof(SimplePadUnion) == sizeof(Z) == 16 +} B; + +struct SimplePadNoPadding2 { + bool A; + bool B; + bool C; + bool D; + // No padding anywhere, sizeof(T) = 4 +} C; + +struct alignas(4) SimplePadFields1 { + char A; + char B; + char C; + // 1 byte of padding here, sizeof(T) = 4 +} E; + +struct SimplePadFields2 { + int32_t Y; + char X; +} F; + +struct SimplePadBase { + // Make sure this class is 4 bytes, and the derived class requires 8 byte + // alignment, so that padding is inserted between base and derived. + int32_t X; + // No padding here +} G; + +struct SimplePadDerived : public SimplePadBase { + // 4 bytes of padding here due to Y requiring 8 byte alignment. + // Thus, sizeof(T) = 16 + int64_t Y; +} H; + +struct SimplePadEmptyBase1 {}; +struct SimplePadEmptyBase2 {}; + +struct SimplePadEmpty : public SimplePadEmptyBase1, SimplePadEmptyBase2 { + // Bases have to occupy at least 1 byte of storage, so this requires + // 2 bytes of padding, plus 1 byte for each base, yielding sizeof(T) = 8 + int32_t X; +} I; + +struct SimplePadVfptr { + virtual ~SimplePadVfptr() {} + static void operator delete(void *ptr, size_t sz) {} + int32_t X; +} J; + +struct NonEmptyBase1 { + bool X; +}; + +struct NonEmptyBase2 { + bool Y; +}; + +struct SimplePadMultiInherit : public NonEmptyBase1, public NonEmptyBase2 { + // X and Y from the 2 bases will get squished together, leaving 2 bytes + // of padding necessary for proper alignment of an int32. + // Therefore, sizeof(T) = 2 + 2 + 4 = 8 + int32_t X; +} K; + +struct SimplePadMultiInherit2 : public SimplePadFields1, SimplePadFields2 { + // There should be 1 byte of padding after the first class, and + // 3 bytes of padding after the second class. + int32_t X; +} L; + +struct OneLevelInherit : public NonEmptyBase1 { + short Y; +}; + +struct SimplePadTwoLevelInherit : public OneLevelInherit { + // OneLevelInherit has nested padding because of its base, + // and then padding again because of this class. So each + // class should be 4 bytes, yielding sizeof(T) = 12. + int64_t Z; +} M; + +struct SimplePadAggregate { + NonEmptyBase1 X; + int32_t Y; + // the presence of X will cause 3 bytes of padding to be injected. +} N; + +int main(int argc, char **argv) { + + return 0; +} diff --git a/test/tools/llvm-pdbdump/Inputs/SimplePaddingTest.pdb b/test/tools/llvm-pdbdump/Inputs/SimplePaddingTest.pdb new file mode 100644 index 0000000000000000000000000000000000000000..44207d601935da652b2b241b81aa334f5c8dc88f GIT binary patch literal 110592 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 literal 0 HcmV?d00001 diff --git a/test/tools/llvm-pdbdump/class-layout.test b/test/tools/llvm-pdbdump/class-layout.test index e2921d298fc..c0083d176ea 100644 --- a/test/tools/llvm-pdbdump/class-layout.test +++ b/test/tools/llvm-pdbdump/class-layout.test @@ -14,38 +14,39 @@ ; GLOBALS_TEST-DAG: GlobalsTest::Enum GlobalsTest::EnumVar ; MEMBERS_TEST: ---TYPES--- -; MEMBERS_TEST: class MembersTest::A { +; MEMBERS_TEST: class MembersTest::A [sizeof = 16] { ; MEMBERS_TEST-DAG: typedef int NestedTypedef ; MEMBERS_TEST-DAG: enum NestedEnum ; MEMBERS_TEST: void MemberFunc() -; MEMBERS_TEST-DAG: int IntMemberVar -; MEMBERS_TEST-DAG: double DoubleMemberVar +; MEMBERS_TEST-DAG: data +0x00 [sizeof=4] int IntMemberVar +; MEMBERS_TEST-NEXT: (4 bytes) +; MEMBERS_TEST-NEXT: data +0x08 [sizeof=8] double DoubleMemberVar ; MEMBERS_TEST: } ; BASE_CLASS_A: ---TYPES--- -; BASE_CLASS_A: class BaseClassTest::A {} +; BASE_CLASS_A: class BaseClassTest::A [sizeof = 1] {} ; BASE_CLASS_B: ---TYPES--- -; BASE_CLASS_B: class BaseClassTest::B +; BASE_CLASS_B: class BaseClassTest::B [sizeof = 4] ; BASE_CLASS_B-NEXT: : public virtual BaseClassTest::A { ; BASE_CLASS_C: ---TYPES--- -; BASE_CLASS_C: class BaseClassTest::C +; BASE_CLASS_C: class BaseClassTest::C [sizeof = 4] ; BASE_CLASS_C-NEXT: : public virtual BaseClassTest::A { ; BASE_CLASS_D: ---TYPES--- -; BASE_CLASS_D: class BaseClassTest::D +; BASE_CLASS_D: class BaseClassTest::D [sizeof = 8] ; BASE_CLASS_D-DAG: protected BaseClassTest::B ; BASE_CLASS_D-DAG: private BaseClassTest::C ; BASE_CLASS_D-DAG: protected virtual BaseClassTest::A ; UDT_KIND_TEST: ---TYPES--- -; UDT_KIND_TEST-DAG: union UdtKindTest::C {} -; UDT_KIND_TEST-DAG: class UdtKindTest::B {} -; UDT_KIND_TEST-DAG: struct UdtKindTest::A {} +; UDT_KIND_TEST-DAG: union UdtKindTest::C [sizeof = 1] {} +; UDT_KIND_TEST-DAG: class UdtKindTest::B [sizeof = 1] {} +; UDT_KIND_TEST-DAG: struct UdtKindTest::A [sizeof = 1] {} ; BITFIELD_TEST: ---TYPES--- -; BITFIELD_TEST: struct BitFieldTest::A { +; BITFIELD_TEST: struct BitFieldTest::A [sizeof = 8] { ; BITFIELD_TEST-NEXT: +0x00 [sizeof=4] int Bits1 : 1 ; BITFIELD_TEST-NEXT: +0x00 [sizeof=4] int Bits2 : 2 ; BITFIELD_TEST-NEXT: +0x00 [sizeof=4] int Bits3 : 3 diff --git a/test/tools/llvm-pdbdump/enum-layout.test b/test/tools/llvm-pdbdump/enum-layout.test index 21e1867175f..df447c65bba 100644 --- a/test/tools/llvm-pdbdump/enum-layout.test +++ b/test/tools/llvm-pdbdump/enum-layout.test @@ -10,7 +10,7 @@ ; MEMBER_ENUM: ---TYPES--- ; MEMBER_ENUM: Classes: -; MEMBER_ENUM: struct __vc_attributes::threadingAttribute { +; MEMBER_ENUM: struct __vc_attributes::threadingAttribute [sizeof = 4] { ; MEMBER_ENUM-NEXT: enum threading_e { ; MEMBER_ENUM-NEXT: apartment = 1 ; MEMBER_ENUM-NEXT: single = 2 diff --git a/test/tools/llvm-pdbdump/simple-padding.test b/test/tools/llvm-pdbdump/simple-padding.test new file mode 100644 index 00000000000..4096d287a56 --- /dev/null +++ b/test/tools/llvm-pdbdump/simple-padding.test @@ -0,0 +1,94 @@ +; RUN: llvm-pdbdump pretty -classes -class-definitions=layout \ +; RUN: -include-types=SimplePad %p/Inputs/SimplePaddingTest.pdb > %t + +; RUN: FileCheck -input-file=%t %s -check-prefix=NO_PADDING +; RUN: FileCheck -input-file=%t %s -check-prefix=UNION +; RUN: FileCheck -input-file=%t %s -check-prefix=NESTED_UNION +; RUN: FileCheck -input-file=%t %s -check-prefix=PAD_FROM_FIELDS1 +; RUN: FileCheck -input-file=%t %s -check-prefix=PAD_FROM_FIELDS2 +; RUN: FileCheck -input-file=%t %s -check-prefix=NO_PAD_IN_BASE +; RUN: FileCheck -input-file=%t %s -check-prefix=PAD_IN_DERIVED +; RUN: FileCheck -input-file=%t %s -check-prefix=EMPTY_BASE +; RUN: FileCheck -input-file=%t %s -check-prefix=VFPTR +; RUN: FileCheck -input-file=%t %s -check-prefix=MULTIPLE_INHERIT +; RUN: FileCheck -input-file=%t %s -check-prefix=MULTIPLE_INHERIT2 +; RUN: FileCheck -input-file=%t %s -check-prefix=DEEP_INHERIT +; RUN: FileCheck -input-file=%t %s -check-prefix=AGGREGATE + +; NO_PADDING: struct SimplePadNoPadding [sizeof = 8] { +; NO_PADDING-NEXT: data +0x00 [sizeof=4] int X +; NO_PADDING-NEXT: data +0x04 [sizeof=4] int Y +; NO_PADDING-NEXT: } + +; UNION: struct SimplePadUnion [sizeof = 16] { +; UNION-NEXT: data +0x00 [sizeof=4] int X +; UNION-NEXT: data +0x00 [sizeof=8] __int64 Y +; UNION-NEXT: data +0x00 [sizeof=16] SimplePadUnion:: +; UNION-NEXT: } + +; NESTED_UNION: struct {{SimplePadUnion::.*}} [sizeof = 16] { +; NESTED_UNION-NEXT: data +0x00 [sizeof=4] int X +; NESTED_UNION-NEXT: (4 bytes) +; NESTED_UNION-NEXT: data +0x08 [sizeof=8] __int64 Y +; NESTED_UNION-NEXT: } + +; PAD_FROM_FIELDS1: struct SimplePadFields1 [sizeof = 4] { +; PAD_FROM_FIELDS1-NEXT: data +0x00 [sizeof=1] char A +; PAD_FROM_FIELDS1-NEXT: data +0x01 [sizeof=1] char B +; PAD_FROM_FIELDS1-NEXT: data +0x02 [sizeof=1] char C +; PAD_FROM_FIELDS1-NEXT: (1 bytes) +; PAD_FROM_FIELDS1-NEXT: } + +; PAD_FROM_FIELDS2: struct SimplePadFields2 [sizeof = 8] { +; PAD_FROM_FIELDS2-NEXT: data +0x00 [sizeof=4] int Y +; PAD_FROM_FIELDS2-NEXT: data +0x04 [sizeof=1] char X +; PAD_FROM_FIELDS2-NEXT: (3 bytes) +; PAD_FROM_FIELDS2-NEXT: } + +; NO_PAD_IN_BASE: struct SimplePadBase [sizeof = 4] { +; NO_PAD_IN_BASE-NEXT: data +0x00 [sizeof=4] int X +; NO_PAD_IN_BASE-NEXT: } + +; PAD_IN_DERIVED: struct SimplePadDerived [sizeof = 16] +; PAD_IN_DERIVED-NEXT: public SimplePadBase { +; PAD_IN_DERIVED-NEXT: (4 bytes) +; PAD_IN_DERIVED-NEXT: data +0x08 [sizeof=8] __int64 Y +; PAD_IN_DERIVED-NEXT: } + +; EMPTY_BASE: struct SimplePadEmpty [sizeof = 8] +; EMPTY_BASE-NEXT: : public SimplePadEmptyBase1 +; EMPTY_BASE-NEXT: , public SimplePadEmptyBase2 { +; EMPTY_BASE-NEXT: (2 bytes) +; EMPTY_BASE-NEXT: data +0x04 [sizeof=4] int X +; EMPTY_BASE-NEXT: } + +; VFPTR: struct SimplePadVfptr [sizeof = 8] { +; VFPTR-NEXT: data +0x00 [sizeof=4] __vfptr +; VFPTR-NEXT: data +0x04 [sizeof=4] int X +; VFPTR-NEXT: } + +; MULTIPLE_INHERIT: struct SimplePadMultiInherit [sizeof = 8] +; MULTIPLE_INHERIT-NEXT: : public NonEmptyBase1 +; MULTIPLE_INHERIT-NEXT: , public NonEmptyBase2 { +; MULTIPLE_INHERIT-NEXT: (2 bytes) +; MULTIPLE_INHERIT-NEXT: data +0x04 [sizeof=4] int X +; MULTIPLE_INHERIT-NEXT: } + +; MULTIPLE_INHERIT2: SimplePadMultiInherit2 [sizeof = 16] +; MULTIPLE_INHERIT2-NEXT: : public SimplePadFields1 +; MULTIPLE_INHERIT2-NEXT: , public SimplePadFields2 { +; MULTIPLE_INHERIT2-NEXT: data +0x0c [sizeof=4] int X +; MULTIPLE_INHERIT2-NEXT: } + +; DEEP_INHERIT: struct SimplePadTwoLevelInherit [sizeof = 16] +; DEEP_INHERIT-NEXT: : public OneLevelInherit { +; DEEP_INHERIT-NEXT: (4 bytes) +; DEEP_INHERIT-NEXT: data +0x08 [sizeof=8] __int64 Z +; DEEP_INHERIT-NEXT: } + + +; AGGREGATE: struct SimplePadAggregate [sizeof = 8] { +; AGGREGATE-NEXT: data +0x00 [sizeof=1] NonEmptyBase1 X +; AGGREGATE-NEXT: (3 bytes) +; AGGREGATE-NEXT: data +0x04 [sizeof=4] int Y +; AGGREGATE-NEXT: } diff --git a/tools/llvm-pdbdump/PrettyClassDefinitionDumper.cpp b/tools/llvm-pdbdump/PrettyClassDefinitionDumper.cpp index b48ed23c1c7..2e1e54e4db1 100644 --- a/tools/llvm-pdbdump/PrettyClassDefinitionDumper.cpp +++ b/tools/llvm-pdbdump/PrettyClassDefinitionDumper.cpp @@ -28,7 +28,8 @@ #include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h" #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" #include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h" -#include "llvm/Support/Compiler.h" +#include "llvm/DebugInfo/PDB/UDTLayout.h" + #include "llvm/Support/Format.h" using namespace llvm; @@ -37,58 +38,23 @@ using namespace llvm::pdb; ClassDefinitionDumper::ClassDefinitionDumper(LinePrinter &P) : PDBSymDumper(true), Printer(P) {} -static void analyzePadding(const PDBSymbolTypeUDT &Class, BitVector &Padding, - uint32_t &FirstFieldOffset) { - Padding.resize(Class.getLength(), true); - auto Children = Class.findAllChildren(); - bool IsFirst = true; - FirstFieldOffset = Class.getLength(); - - while (auto Data = Children->getNext()) { - // Ignore data members which are not relative to this. Usually these are - // static data members or constexpr and occupy no space. We also need to - // handle BitFields since the PDB doesn't consider them ThisRel, but they - // still occupy space in the record layout. - auto LocType = Data->getLocationType(); - if (LocType != PDB_LocType::ThisRel && LocType != PDB_LocType::BitField) - continue; - - uint64_t Start = Data->getOffset(); - if (IsFirst) { - FirstFieldOffset = Start; - IsFirst = false; - } - - auto VarType = Data->getType(); - uint64_t Size = VarType->getRawSymbol().getLength(); - Padding.reset(Start, Start + Size); - } - - // Unmark anything that comes before the first field so it doesn't get - // counted as padding. In reality this is going to be vptrs or base class - // members, but we don't correctly handle that yet. - // FIXME: Handle it. - Padding.reset(0, FirstFieldOffset); -} - void ClassDefinitionDumper::start(const PDBSymbolTypeUDT &Class) { assert(opts::pretty::ClassFormat != opts::pretty::ClassDefinitionFormat::None); uint32_t Size = Class.getLength(); - uint32_t FirstFieldOffset = 0; - BitVector Padding; - analyzePadding(Class, Padding, FirstFieldOffset); - if (opts::pretty::OnlyPaddingClasses && (Padding.count() == 0)) + ClassLayout Layout(Class.clone()); + + if (opts::pretty::OnlyPaddingClasses && (Layout.shallowPaddingSize() == 0)) return; Printer.NewLine(); - WithColor(Printer, PDB_ColorItem::Comment).get() << "// sizeof = " << Size; - Printer.NewLine(); WithColor(Printer, PDB_ColorItem::Keyword).get() << Class.getUdtKind() << " "; WithColor(Printer, PDB_ColorItem::Type).get() << Class.getName(); + WithColor(Printer, PDB_ColorItem::Comment).get() << " [sizeof = " << Size + << "]"; auto Bases = Class.findAllChildren(); if (Bases->getChildCount() > 0) { @@ -111,60 +77,54 @@ void ClassDefinitionDumper::start(const PDBSymbolTypeUDT &Class) { } Printer << " {"; - auto Children = Class.findAllChildren(); Printer.Indent(); - int DumpedCount = 0; - - int NextPaddingByte = Padding.find_first(); - while (auto Child = Children->getNext()) { - if (auto Data = llvm::dyn_cast(Child.get())) { - if (Data->getDataKind() == PDB_DataKind::Member && NextPaddingByte >= 0) { - // If there are padding bytes remaining, see if this field is the first - // to cross a padding boundary, and print a padding field indicator if - // so. - int Off = Data->getOffset(); - if (Off > NextPaddingByte) { - uint32_t Amount = Off - NextPaddingByte; - Printer.NewLine(); - WithColor(Printer, PDB_ColorItem::Padding).get() - << " (" << Amount << " bytes)"; - assert(Padding.find_next_unset(NextPaddingByte) == Off); - NextPaddingByte = Padding.find_next(Off); - } - } - } - if (auto Func = Child->cast()) { - if (Func->isCompilerGenerated() && opts::pretty::ExcludeCompilerGenerated) - continue; + // Dump non-layout items first, but only if we're not in layout-only mode. + if (opts::pretty::ClassFormat != + opts::pretty::ClassDefinitionFormat::Layout) { + for (auto &Other : Layout.other_items()) + Other->dump(*this); + } - if (Func->getLength() == 0 && !Func->isPureVirtual() && - !Func->isIntroVirtualFunction()) - continue; + const BitVector &UseMap = Layout.usedBytes(); + int NextUnusedByte = Layout.usedBytes().find_first_unset(); + // Next dump items which affect class layout. + for (auto &LayoutItem : Layout.layout_items()) { + if (NextUnusedByte >= 0) { + // If there are padding bytes remaining, see if this field is the first to + // cross a padding boundary, and print a padding field indicator if so. + int Off = LayoutItem->getOffsetInParent(); + if (Off > NextUnusedByte) { + uint32_t Amount = Off - NextUnusedByte; + Printer.NewLine(); + WithColor(Printer, PDB_ColorItem::Padding).get() << " (" + << Amount << " bytes)"; + assert(UseMap.find_next(NextUnusedByte) == Off); + NextUnusedByte = UseMap.find_next_unset(Off); + } } - - ++DumpedCount; - Child->dump(*this); + LayoutItem->getSymbol().dump(*this); } - if (NextPaddingByte >= 0) { - uint32_t Amount = Size - NextPaddingByte; + if (NextUnusedByte >= 0 && Layout.getClassSize() > 1) { + uint32_t Amount = Layout.getClassSize() - NextUnusedByte; Printer.NewLine(); WithColor(Printer, PDB_ColorItem::Padding).get() << " (" << Amount << " bytes)"; + DumpedAnything = true; } + Printer.Unindent(); - if (DumpedCount > 0) + if (DumpedAnything) Printer.NewLine(); Printer << "}"; Printer.NewLine(); - if (Padding.count() > 0) { - APFloat Pct(100.0 * (double)Padding.count() / - (double)(Size - FirstFieldOffset)); + if (Layout.deepPaddingSize() > 0) { + APFloat Pct(100.0 * (double)Layout.deepPaddingSize() / (double)Size); SmallString<8> PctStr; Pct.toString(PctStr, 4); WithColor(Printer, PDB_ColorItem::Padding).get() - << "Total padding " << Padding.count() << " bytes (" << PctStr + << "Total padding " << Layout.deepPaddingSize() << " bytes (" << PctStr << "% of class size)"; Printer.NewLine(); } @@ -175,23 +135,35 @@ void ClassDefinitionDumper::dump(const PDBSymbolTypeBaseClass &Symbol) {} void ClassDefinitionDumper::dump(const PDBSymbolData &Symbol) { VariableDumper Dumper(Printer); Dumper.start(Symbol); + DumpedAnything = true; } void ClassDefinitionDumper::dump(const PDBSymbolFunc &Symbol) { if (Printer.IsSymbolExcluded(Symbol.getName())) return; + if (Symbol.isCompilerGenerated() && opts::pretty::ExcludeCompilerGenerated) + return; + if (Symbol.getLength() == 0 && !Symbol.isPureVirtual() && + !Symbol.isIntroVirtualFunction()) + return; + DumpedAnything = true; Printer.NewLine(); FunctionDumper Dumper(Printer); Dumper.start(Symbol, FunctionDumper::PointerType::None); } -void ClassDefinitionDumper::dump(const PDBSymbolTypeVTable &Symbol) {} +void ClassDefinitionDumper::dump(const PDBSymbolTypeVTable &Symbol) { + VariableDumper Dumper(Printer); + Dumper.start(Symbol); + DumpedAnything = true; +} void ClassDefinitionDumper::dump(const PDBSymbolTypeEnum &Symbol) { if (Printer.IsTypeExcluded(Symbol.getName())) return; + DumpedAnything = true; Printer.NewLine(); EnumDumper Dumper(Printer); Dumper.start(Symbol); @@ -201,6 +173,7 @@ void ClassDefinitionDumper::dump(const PDBSymbolTypeTypedef &Symbol) { if (Printer.IsTypeExcluded(Symbol.getName())) return; + DumpedAnything = true; Printer.NewLine(); TypedefDumper Dumper(Printer); Dumper.start(Symbol); diff --git a/tools/llvm-pdbdump/PrettyClassDefinitionDumper.h b/tools/llvm-pdbdump/PrettyClassDefinitionDumper.h index 8f0c35cba81..94ae07d345d 100644 --- a/tools/llvm-pdbdump/PrettyClassDefinitionDumper.h +++ b/tools/llvm-pdbdump/PrettyClassDefinitionDumper.h @@ -21,6 +21,8 @@ #include namespace llvm { +class BitVector; + namespace pdb { class LinePrinter; @@ -40,6 +42,10 @@ public: void dump(const PDBSymbolTypeVTable &Symbol) override; private: + bool maybeDumpSymbol(std::unique_ptr Data, + const BitVector &Padding, int &NextUnusedByte); + bool maybeDumpSymbol(std::unique_ptr Data); + bool DumpedAnything = false; LinePrinter &Printer; }; } diff --git a/tools/llvm-pdbdump/PrettyFunctionDumper.cpp b/tools/llvm-pdbdump/PrettyFunctionDumper.cpp index 0e0da026e56..b0be33c157c 100644 --- a/tools/llvm-pdbdump/PrettyFunctionDumper.cpp +++ b/tools/llvm-pdbdump/PrettyFunctionDumper.cpp @@ -233,7 +233,7 @@ void FunctionDumper::dump(const PDBSymbolTypePointer &Symbol) { if (!PointeeType) return; - if (auto FuncSig = PointeeType->cast()) { + if (auto FuncSig = unique_dyn_cast(PointeeType)) { FunctionDumper NestedDumper(Printer); PointerType Pointer = Symbol.isReference() ? PointerType::Reference : PointerType::Pointer; diff --git a/tools/llvm-pdbdump/PrettyTypeDumper.cpp b/tools/llvm-pdbdump/PrettyTypeDumper.cpp index 12a47d24f79..2857b07078c 100644 --- a/tools/llvm-pdbdump/PrettyTypeDumper.cpp +++ b/tools/llvm-pdbdump/PrettyTypeDumper.cpp @@ -26,6 +26,23 @@ using namespace llvm; using namespace llvm::pdb; +template +static std::vector> +filterClassDefs(LinePrinter &Printer, Enumerator &E) { + std::vector> Filtered; + while (auto Class = E.getNext()) { + if (Class->getUnmodifiedTypeId() != 0) + continue; + + if (Printer.IsTypeExcluded(Class->getName())) + continue; + + Filtered.push_back(std::move(Class)); + } + + return Filtered; +} + TypeDumper::TypeDumper(LinePrinter &P) : PDBSymDumper(true), Printer(P) {} void TypeDumper::start(const PDBSymbolExe &Exe) { @@ -53,11 +70,19 @@ void TypeDumper::start(const PDBSymbolExe &Exe) { if (opts::pretty::Classes) { auto Classes = Exe.findAllChildren(); + auto Filtered = filterClassDefs(Printer, *Classes); + Printer.NewLine(); + uint32_t Shown = Filtered.size(); + uint32_t All = Classes->getChildCount(); + WithColor(Printer, PDB_ColorItem::Identifier).get() << "Classes"; - Printer << ": (" << Classes->getChildCount() << " items)"; + Printer << ": (Showing " << Shown << " items"; + if (Shown < All) + Printer << ", " << (All - Shown) << " filtered"; + Printer << ")"; Printer.Indent(); - while (auto Class = Classes->getNext()) + for (auto &Class : Filtered) Class->dump(*this); Printer.Unindent(); } @@ -91,11 +116,6 @@ void TypeDumper::dump(const PDBSymbolTypeTypedef &Symbol) { void TypeDumper::dump(const PDBSymbolTypeUDT &Symbol) { assert(opts::pretty::Classes); - if (Symbol.getUnmodifiedTypeId() != 0) - return; - if (Printer.IsTypeExcluded(Symbol.getName())) - return; - if (opts::pretty::ClassFormat == opts::pretty::ClassDefinitionFormat::None) { Printer.NewLine(); WithColor(Printer, PDB_ColorItem::Keyword).get() << "class "; diff --git a/tools/llvm-pdbdump/PrettyTypedefDumper.cpp b/tools/llvm-pdbdump/PrettyTypedefDumper.cpp index 861f7e28b38..2d8e915d760 100644 --- a/tools/llvm-pdbdump/PrettyTypedefDumper.cpp +++ b/tools/llvm-pdbdump/PrettyTypedefDumper.cpp @@ -54,7 +54,7 @@ void TypedefDumper::dump(const PDBSymbolTypePointer &Symbol) { if (Symbol.isVolatileType()) WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile "; auto PointeeType = Symbol.getPointeeType(); - if (auto FuncSig = PointeeType->cast()) { + if (auto FuncSig = unique_dyn_cast(PointeeType)) { FunctionDumper::PointerType Pointer = FunctionDumper::PointerType::Pointer; if (Symbol.isReference()) Pointer = FunctionDumper::PointerType::Reference; diff --git a/tools/llvm-pdbdump/PrettyVariableDumper.cpp b/tools/llvm-pdbdump/PrettyVariableDumper.cpp index 65f0139dfbc..ef9a9b51bd0 100644 --- a/tools/llvm-pdbdump/PrettyVariableDumper.cpp +++ b/tools/llvm-pdbdump/PrettyVariableDumper.cpp @@ -91,6 +91,19 @@ void VariableDumper::start(const PDBSymbolData &Var) { } } +void VariableDumper::start(const PDBSymbolTypeVTable &Var) { + Printer.NewLine(); + Printer << "data "; + auto VTableType = cast(Var.getType()); + uint32_t PointerSize = VTableType->getLength(); + + WithColor(Printer, PDB_ColorItem::Offset).get() + << "+" << format_hex(Var.getOffset(), 4) << " [sizeof=" << PointerSize + << "] "; + + WithColor(Printer, PDB_ColorItem::Identifier).get() << " __vfptr"; +} + void VariableDumper::dump(const PDBSymbolTypeArray &Symbol) { auto ElementType = Symbol.getElementType(); assert(ElementType); @@ -157,12 +170,12 @@ void VariableDumper::dump(const PDBSymbolTypePointer &Symbol) { if (!PointeeType) return; PointeeType->dump(*this); - if (auto Func = PointeeType->cast()) { + if (auto FuncSig = unique_dyn_cast(PointeeType)) { // A hack to get the calling convention in the right spot. Printer << " ("; - PDB_CallingConv CC = Func->getCallingConvention(); + PDB_CallingConv CC = FuncSig->getCallingConvention(); WithColor(Printer, PDB_ColorItem::Keyword).get() << CC << " "; - } else if (isa(PointeeType.get())) { + } else if (isa(PointeeType)) { Printer << " ("; } Printer << (Symbol.isReference() ? "&" : "*"); @@ -177,8 +190,8 @@ void VariableDumper::dumpRight(const PDBSymbolTypePointer &Symbol) { assert(PointeeType); if (!PointeeType) return; - if (isa(PointeeType.get()) || - isa(PointeeType.get())) { + if (isa(PointeeType) || + isa(PointeeType)) { Printer << ")"; } PointeeType->dumpRight(*this); diff --git a/tools/llvm-pdbdump/PrettyVariableDumper.h b/tools/llvm-pdbdump/PrettyVariableDumper.h index eec389b1707..ba9fdb17655 100644 --- a/tools/llvm-pdbdump/PrettyVariableDumper.h +++ b/tools/llvm-pdbdump/PrettyVariableDumper.h @@ -25,6 +25,7 @@ public: VariableDumper(LinePrinter &P); void start(const PDBSymbolData &Var); + void start(const PDBSymbolTypeVTable &Var); void dump(const PDBSymbolTypeArray &Symbol) override; void dump(const PDBSymbolTypeBuiltin &Symbol) override; diff --git a/tools/llvm-pdbdump/llvm-pdbdump.cpp b/tools/llvm-pdbdump/llvm-pdbdump.cpp index 8a749bab98e..a486c8a0730 100644 --- a/tools/llvm-pdbdump/llvm-pdbdump.cpp +++ b/tools/llvm-pdbdump/llvm-pdbdump.cpp @@ -96,7 +96,7 @@ cl::SubCommand "Analyze various aspects of a PDB's structure"); cl::OptionCategory TypeCategory("Symbol Type Options"); -cl::OptionCategory FilterCategory("Filtering Options"); +cl::OptionCategory FilterCategory("Filtering and Sorting Options"); cl::OptionCategory OtherOptions("Other Options"); namespace pretty { @@ -122,14 +122,17 @@ cl::opt Enums("enums", cl::desc("Display enum types"), cl::cat(TypeCategory), cl::sub(PrettySubcommand)); cl::opt Typedefs("typedefs", cl::desc("Display typedef types"), cl::cat(TypeCategory), cl::sub(PrettySubcommand)); -cl::opt - ClassFormat("class-definitions", cl::desc("Class definition format"), - cl::init(ClassDefinitionFormat::Standard), - cl::values(clEnumValN(ClassDefinitionFormat::Standard, "full", - "Display complete class definition"), - clEnumValN(ClassDefinitionFormat::None, "none", - "Don't display class definitions")), - cl::cat(TypeCategory), cl::sub(PrettySubcommand)); +cl::opt ClassFormat( + "class-definitions", cl::desc("Class definition format"), + cl::init(ClassDefinitionFormat::Standard), + cl::values( + clEnumValN(ClassDefinitionFormat::Standard, "full", + "Display complete class definition"), + clEnumValN(ClassDefinitionFormat::Layout, "layout", + "Only display members that contribute to class size."), + clEnumValN(ClassDefinitionFormat::None, "none", + "Don't display class definitions")), + cl::cat(TypeCategory), cl::sub(PrettySubcommand)); cl::opt Lines("lines", cl::desc("Line tables"), cl::cat(TypeCategory), cl::sub(PrettySubcommand)); diff --git a/tools/llvm-pdbdump/llvm-pdbdump.h b/tools/llvm-pdbdump/llvm-pdbdump.h index a335d30c4cf..c572176f76d 100644 --- a/tools/llvm-pdbdump/llvm-pdbdump.h +++ b/tools/llvm-pdbdump/llvm-pdbdump.h @@ -18,7 +18,7 @@ namespace opts { namespace pretty { -enum class ClassDefinitionFormat { None, Standard }; +enum class ClassDefinitionFormat { None, Layout, Standard }; extern llvm::cl::opt Compilands; extern llvm::cl::opt Symbols; diff --git a/unittests/DebugInfo/PDB/PDBApiTest.cpp b/unittests/DebugInfo/PDB/PDBApiTest.cpp index ba09a8e2842..6afe83cd90d 100644 --- a/unittests/DebugInfo/PDB/PDBApiTest.cpp +++ b/unittests/DebugInfo/PDB/PDBApiTest.cpp @@ -63,7 +63,7 @@ namespace { class MockSession : public IPDBSession { uint64_t getLoadAddress() const override { return 0; } void setLoadAddress(uint64_t Address) override {} - std::unique_ptr getGlobalScope() override { + std::unique_ptr getGlobalScope() const override { return nullptr; } std::unique_ptr getSymbolById(uint32_t SymbolId) const override { @@ -226,6 +226,7 @@ public: MOCK_SYMBOL_ACCESSOR(getMachineType) MOCK_SYMBOL_ACCESSOR(getThunkOrdinal) MOCK_SYMBOL_ACCESSOR(getLength) + MOCK_SYMBOL_ACCESSOR(getVirtualBaseTableType) MOCK_SYMBOL_ACCESSOR(getLiveRangeLength) MOCK_SYMBOL_ACCESSOR(getVirtualAddress) MOCK_SYMBOL_ACCESSOR(getUdtKind) -- 2.40.0