From c883a8c6dce207a494c6c3a54de1492635acb664 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. llvm-svn: 300133 --- llvm/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h | 1 + llvm/include/llvm/DebugInfo/PDB/DIA/DIASession.h | 2 +- llvm/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h | 5 + llvm/include/llvm/DebugInfo/PDB/IPDBSession.h | 12 +- .../llvm/DebugInfo/PDB/Native/NativeRawSymbol.h | 1 + .../llvm/DebugInfo/PDB/Native/NativeSession.h | 2 +- llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h | 18 +- llvm/include/llvm/DebugInfo/PDB/PDBSymbolExe.h | 2 + .../llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h | 3 + llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h | 8 + .../llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h | 1 + llvm/include/llvm/DebugInfo/PDB/UDTLayout.h | 145 +++++++++++++++ llvm/include/llvm/Support/Casting.h | 2 +- llvm/lib/DebugInfo/PDB/CMakeLists.txt | 1 + llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp | 15 ++ llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp | 2 +- llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp | 7 + llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp | 5 +- llvm/lib/DebugInfo/PDB/PDBSymbol.cpp | 9 +- llvm/lib/DebugInfo/PDB/PDBSymbolExe.cpp | 11 ++ llvm/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp | 8 + llvm/lib/DebugInfo/PDB/UDTLayout.cpp | 194 +++++++++++++++++++++ .../DebugInfo/PDB/DIA/pdbdump-symbol-format.test | 4 +- llvm/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 llvm/test/tools/llvm-pdbdump/class-layout.test | 23 +-- llvm/test/tools/llvm-pdbdump/enum-layout.test | 2 +- llvm/test/tools/llvm-pdbdump/simple-padding.test | 94 ++++++++++ .../llvm-pdbdump/PrettyClassDefinitionDumper.cpp | 131 ++++++-------- .../llvm-pdbdump/PrettyClassDefinitionDumper.h | 6 + llvm/tools/llvm-pdbdump/PrettyFunctionDumper.cpp | 2 +- llvm/tools/llvm-pdbdump/PrettyTypeDumper.cpp | 34 +++- llvm/tools/llvm-pdbdump/PrettyTypedefDumper.cpp | 2 +- llvm/tools/llvm-pdbdump/PrettyVariableDumper.cpp | 23 ++- llvm/tools/llvm-pdbdump/PrettyVariableDumper.h | 1 + llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp | 21 ++- llvm/tools/llvm-pdbdump/llvm-pdbdump.h | 2 +- llvm/unittests/DebugInfo/PDB/PDBApiTest.cpp | 3 +- 39 files changed, 769 insertions(+), 155 deletions(-) create mode 100644 llvm/include/llvm/DebugInfo/PDB/UDTLayout.h create mode 100644 llvm/lib/DebugInfo/PDB/UDTLayout.cpp create mode 100644 llvm/test/tools/llvm-pdbdump/Inputs/SimplePaddingTest.cpp create mode 100644 llvm/test/tools/llvm-pdbdump/Inputs/SimplePaddingTest.pdb create mode 100644 llvm/test/tools/llvm-pdbdump/simple-padding.test diff --git a/llvm/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h b/llvm/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h index 1e40c46..c0633cb 100644 --- a/llvm/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h +++ b/llvm/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/llvm/include/llvm/DebugInfo/PDB/DIA/DIASession.h b/llvm/include/llvm/DebugInfo/PDB/DIA/DIASession.h index 3504425..3f58186 100644 --- a/llvm/include/llvm/DebugInfo/PDB/DIA/DIASession.h +++ b/llvm/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/llvm/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h b/llvm/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h index 49866b8..4c28e19 100644 --- a/llvm/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h +++ b/llvm/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/llvm/include/llvm/DebugInfo/PDB/IPDBSession.h b/llvm/include/llvm/DebugInfo/PDB/IPDBSession.h index 696736a..85d9fe1 100644 --- a/llvm/include/llvm/DebugInfo/PDB/IPDBSession.h +++ b/llvm/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/llvm/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h index 655bed9..cffb5d0 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h +++ b/llvm/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/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h index bbe20773..e6da266 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h +++ b/llvm/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/llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h b/llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h index 652f213..b114b7a 100644 --- a/llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h +++ b/llvm/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/llvm/include/llvm/DebugInfo/PDB/PDBSymbolExe.h b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolExe.h index 5b3f50d..2c2d746 100644 --- a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolExe.h +++ b/llvm/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/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h index 0924efb..d607a3d 100644 --- a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h +++ b/llvm/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/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h index 47a4525..e9e7fe8 100644 --- a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h +++ b/llvm/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/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h index 17612ff..e270c2b 100644 --- a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h +++ b/llvm/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/llvm/include/llvm/DebugInfo/PDB/UDTLayout.h b/llvm/include/llvm/DebugInfo/PDB/UDTLayout.h new file mode 100644 index 0000000..20b7034 --- /dev/null +++ b/llvm/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/llvm/include/llvm/Support/Casting.h b/llvm/include/llvm/Support/Casting.h index 3a0c553..89d2af0 100644 --- a/llvm/include/llvm/Support/Casting.h +++ b/llvm/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/llvm/lib/DebugInfo/PDB/CMakeLists.txt b/llvm/lib/DebugInfo/PDB/CMakeLists.txt index 1295d2a..f87a0b0 100644 --- a/llvm/lib/DebugInfo/PDB/CMakeLists.txt +++ b/llvm/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/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp b/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp index 6182dab..5e8c0bd 100644 --- a/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp +++ b/llvm/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/llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp b/llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp index 7077bda..6ecf335 100644 --- a/llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp +++ b/llvm/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/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp index 4841ded..3aba35a 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp +++ b/llvm/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/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp index 3a83a32..7e6843b 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp +++ b/llvm/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/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp index 2c8438f..14eb6ba 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp +++ b/llvm/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/llvm/lib/DebugInfo/PDB/PDBSymbolExe.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolExe.cpp index b9fcac7..7417167 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbolExe.cpp +++ b/llvm/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/llvm/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp index 4a9a9ed..15dc153 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp +++ b/llvm/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/llvm/lib/DebugInfo/PDB/UDTLayout.cpp b/llvm/lib/DebugInfo/PDB/UDTLayout.cpp new file mode 100644 index 0000000..71443fe --- /dev/null +++ b/llvm/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/llvm/test/DebugInfo/PDB/DIA/pdbdump-symbol-format.test b/llvm/test/DebugInfo/PDB/DIA/pdbdump-symbol-format.test index 60a1953..0bb3e00 100644 --- a/llvm/test/DebugInfo/PDB/DIA/pdbdump-symbol-format.test +++ b/llvm/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/llvm/test/DebugInfo/PDB/Inputs/symbolformat.pdb b/llvm/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/llvm/test/tools/llvm-pdbdump/Inputs/SimplePaddingTest.cpp b/llvm/test/tools/llvm-pdbdump/Inputs/SimplePaddingTest.cpp new file mode 100644 index 0000000..b10839b --- /dev/null +++ b/llvm/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/llvm/test/tools/llvm-pdbdump/Inputs/SimplePaddingTest.pdb b/llvm/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/llvm/test/tools/llvm-pdbdump/class-layout.test b/llvm/test/tools/llvm-pdbdump/class-layout.test index e2921d2..c0083d1 100644 --- a/llvm/test/tools/llvm-pdbdump/class-layout.test +++ b/llvm/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/llvm/test/tools/llvm-pdbdump/enum-layout.test b/llvm/test/tools/llvm-pdbdump/enum-layout.test index 21e1867..df447c6 100644 --- a/llvm/test/tools/llvm-pdbdump/enum-layout.test +++ b/llvm/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/llvm/test/tools/llvm-pdbdump/simple-padding.test b/llvm/test/tools/llvm-pdbdump/simple-padding.test new file mode 100644 index 0000000..4096d28 --- /dev/null +++ b/llvm/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/llvm/tools/llvm-pdbdump/PrettyClassDefinitionDumper.cpp b/llvm/tools/llvm-pdbdump/PrettyClassDefinitionDumper.cpp index b48ed23..2e1e54e 100644 --- a/llvm/tools/llvm-pdbdump/PrettyClassDefinitionDumper.cpp +++ b/llvm/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/llvm/tools/llvm-pdbdump/PrettyClassDefinitionDumper.h b/llvm/tools/llvm-pdbdump/PrettyClassDefinitionDumper.h index 8f0c35c..94ae07d 100644 --- a/llvm/tools/llvm-pdbdump/PrettyClassDefinitionDumper.h +++ b/llvm/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/llvm/tools/llvm-pdbdump/PrettyFunctionDumper.cpp b/llvm/tools/llvm-pdbdump/PrettyFunctionDumper.cpp index 0e0da02..b0be33c 100644 --- a/llvm/tools/llvm-pdbdump/PrettyFunctionDumper.cpp +++ b/llvm/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/llvm/tools/llvm-pdbdump/PrettyTypeDumper.cpp b/llvm/tools/llvm-pdbdump/PrettyTypeDumper.cpp index 12a47d2..2857b07 100644 --- a/llvm/tools/llvm-pdbdump/PrettyTypeDumper.cpp +++ b/llvm/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/llvm/tools/llvm-pdbdump/PrettyTypedefDumper.cpp b/llvm/tools/llvm-pdbdump/PrettyTypedefDumper.cpp index 861f7e2..2d8e915 100644 --- a/llvm/tools/llvm-pdbdump/PrettyTypedefDumper.cpp +++ b/llvm/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/llvm/tools/llvm-pdbdump/PrettyVariableDumper.cpp b/llvm/tools/llvm-pdbdump/PrettyVariableDumper.cpp index 65f0139..ef9a9b5 100644 --- a/llvm/tools/llvm-pdbdump/PrettyVariableDumper.cpp +++ b/llvm/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/llvm/tools/llvm-pdbdump/PrettyVariableDumper.h b/llvm/tools/llvm-pdbdump/PrettyVariableDumper.h index eec389b..ba9fdb1 100644 --- a/llvm/tools/llvm-pdbdump/PrettyVariableDumper.h +++ b/llvm/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/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp b/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp index 8a749ba..a486c8a 100644 --- a/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp +++ b/llvm/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/llvm/tools/llvm-pdbdump/llvm-pdbdump.h b/llvm/tools/llvm-pdbdump/llvm-pdbdump.h index a335d30..c572176 100644 --- a/llvm/tools/llvm-pdbdump/llvm-pdbdump.h +++ b/llvm/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/llvm/unittests/DebugInfo/PDB/PDBApiTest.cpp b/llvm/unittests/DebugInfo/PDB/PDBApiTest.cpp index ba09a8e..6afe83c 100644 --- a/llvm/unittests/DebugInfo/PDB/PDBApiTest.cpp +++ b/llvm/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.7.4