diff options
| author | Zachary Turner <zturner@google.com> | 2017-04-12 23:18:21 +0000 |
|---|---|---|
| committer | Zachary Turner <zturner@google.com> | 2017-04-12 23:18:21 +0000 |
| commit | c883a8c6dce207a494c6c3a54de1492635acb664 (patch) | |
| tree | fb2ff9010b62853109fd592e006e560fc2cb4ed7 /llvm/lib/DebugInfo/PDB | |
| parent | 1b395144442f4bf872fb772c87d8b6e3bf78cfd7 (diff) | |
| download | bcm5719-llvm-c883a8c6dce207a494c6c3a54de1492635acb664.tar.gz bcm5719-llvm-c883a8c6dce207a494c6c3a54de1492635acb664.zip | |
[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
Diffstat (limited to 'llvm/lib/DebugInfo/PDB')
| -rw-r--r-- | llvm/lib/DebugInfo/PDB/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp | 15 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp | 2 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp | 7 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp | 5 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/PDB/PDBSymbol.cpp | 9 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/PDB/PDBSymbolExe.cpp | 11 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp | 8 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/PDB/UDTLayout.cpp | 194 |
9 files changed, 243 insertions, 9 deletions
diff --git a/llvm/lib/DebugInfo/PDB/CMakeLists.txt b/llvm/lib/DebugInfo/PDB/CMakeLists.txt index 1295d2a19ce..f87a0b0a72e 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 6182dab213c..5e8c0bdc171 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<PDBSymbolTypeVTable> +DIARawSymbol::getVirtualBaseTableType() const { + CComPtr<IDiaSymbol> TableType; + if (FAILED(Symbol->get_virtualBaseTableType(&TableType)) || !TableType) + return nullptr; + + auto RawVT = llvm::make_unique<DIARawSymbol>(Session, TableType); + auto Pointer = + llvm::make_unique<PDBSymbolTypePointer>(Session, std::move(RawVT)); + return unique_dyn_cast<PDBSymbolTypeVTable>(Pointer->getPointeeType()); +} + PDB_DataKind DIARawSymbol::getDataKind() const { return PrivateGetDIAValue<DWORD, PDB_DataKind>(Symbol, &IDiaSymbol::get_dataKind); diff --git a/llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp b/llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp index 7077bda4a53..6ecf335812b 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<PDBSymbolExe> DIASession::getGlobalScope() { +std::unique_ptr<PDBSymbolExe> DIASession::getGlobalScope() const { CComPtr<IDiaSymbol> 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 4841ded7410..3aba35adb53 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<PDBSymbolTypeVTable> +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 3a83a326cfe..7e6843bceb7 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<PDBSymbolExe> NativeSession::getGlobalScope() { - auto RawSymbol = llvm::make_unique<NativeExeSymbol>(*this); +std::unique_ptr<PDBSymbolExe> NativeSession::getGlobalScope() const { + auto RawSymbol = + llvm::make_unique<NativeExeSymbol>(const_cast<NativeSession &>(*this)); auto PdbSymbol(PDBSymbol::create(*this, std::move(RawSymbol))); std::unique_ptr<PDBSymbolExe> ExeSymbol( static_cast<PDBSymbolExe *>(PdbSymbol.release())); diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp index 2c8438f9c23..14eb6ba8ad8 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<IPDBRawSymbol> 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<Type>()) \ - 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 b9fcac78c36..7417167b61a 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 <utility> @@ -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<PDBSymbolTypePointer>(); + 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 4a9a9ed5fda..15dc1535216 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 <utility> diff --git a/llvm/lib/DebugInfo/PDB/UDTLayout.cpp b/llvm/lib/DebugInfo/PDB/UDTLayout.cpp new file mode 100644 index 00000000000..71443fe7587 --- /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 <utility> + +using namespace llvm; +using namespace llvm::pdb; + +static std::unique_ptr<PDBSymbol> 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<PDBSymbolData> 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<PDBSymbolTypeUDT>(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<ClassLayout>(std::move(UDT)); + } +} + +const PDBSymbolData &DataMemberLayoutItem::getDataMember() { + return *dyn_cast<PDBSymbolData>(&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<PDBSymbolTypeVTable> VTable) + : StorageItemBase(Parent, *VTable, "<vtbl>", 0, getTypeLength(*VTable)), + VTable(std::move(VTable)) { + // initialize vtbl methods. + auto VTableType = cast<PDBSymbolTypePointer>(this->VTable->getType()); + uint32_t PointerSize = VTableType->getLength(); + + if (auto Shape = unique_dyn_cast<PDBSymbolTypeVTableShape>( + VTableType->getPointeeType())) { + VTableFuncs.resize(Shape->getCount()); + + auto ParentFunctions = Parent.getSymbol().findAllChildren<PDBSymbolFunc>(); + 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<PDBSymbolTypeUDT> UDT) + : UDTLayoutBase(*UDT, UDT->getName(), UDT->getLength()), + Type(std::move(UDT)) {} + +BaseClassLayout::BaseClassLayout(const UDTLayoutBase &Parent, + std::unique_ptr<PDBSymbolTypeBaseClass> 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<PDBSymbolData>(Child)) { + if (Data->getDataKind() == PDB_DataKind::Member) { + auto DM = + llvm::make_unique<DataMemberLayoutItem>(*this, std::move(Data)); + + addChildToLayout(std::move(DM)); + } else { + NonStorageItems.push_back(std::move(Data)); + } + continue; + } + + if (auto Base = unique_dyn_cast<PDBSymbolTypeBaseClass>(Child)) { + auto BL = llvm::make_unique<BaseClassLayout>(*this, std::move(Base)); + BaseClasses.push_back(BL.get()); + + addChildToLayout(std::move(BL)); + continue; + } + + if (auto VT = unique_dyn_cast<PDBSymbolTypeVTable>(Child)) { + auto VTLayout = llvm::make_unique<VTableLayoutItem>(*this, std::move(VT)); + + VTable = VTLayout.get(); + + addChildToLayout(std::move(VTLayout)); + continue; + } + + NonStorageItems.push_back(std::move(Child)); + } +} + +void UDTLayoutBase::addChildToLayout(std::unique_ptr<StorageItemBase> 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<StorageItemBase> &Item) { + return Off < Item->getOffsetInParent(); + }); + + ChildStorage.insert(Loc, std::move(Child)); +}
\ No newline at end of file |

