2017-07-01 01:06:03 +02:00
|
|
|
//===- UDTLayout.cpp ------------------------------------------------------===//
|
[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
2017-04-13 01:18:21 +02:00
|
|
|
//
|
2019-01-19 09:50:56 +01:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
[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
2017-04-13 01:18:21 +02:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "llvm/DebugInfo/PDB/UDTLayout.h"
|
2017-07-01 01:06:03 +02:00
|
|
|
#include "llvm/ADT/ArrayRef.h"
|
|
|
|
#include "llvm/ADT/BitVector.h"
|
2017-04-13 23:11:00 +02:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2017-07-01 01:06:03 +02:00
|
|
|
#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"
|
[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
2017-04-13 01:18:21 +02:00
|
|
|
#include "llvm/DebugInfo/PDB/IPDBSession.h"
|
|
|
|
#include "llvm/DebugInfo/PDB/PDBSymbol.h"
|
|
|
|
#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
|
|
|
|
#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
|
|
|
|
#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h"
|
2017-04-24 19:47:24 +02:00
|
|
|
#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
|
[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
2017-04-13 01:18:21 +02:00
|
|
|
#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
|
|
|
|
#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
|
|
|
|
#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h"
|
2017-07-01 01:06:03 +02:00
|
|
|
#include "llvm/DebugInfo/PDB/PDBTypes.h"
|
|
|
|
#include "llvm/Support/Casting.h"
|
|
|
|
#include <algorithm>
|
|
|
|
#include <cassert>
|
|
|
|
#include <cstdint>
|
|
|
|
#include <memory>
|
[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
2017-04-13 01:18:21 +02:00
|
|
|
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2017-04-24 19:47:24 +02:00
|
|
|
LayoutItemBase::LayoutItemBase(const UDTLayoutBase *Parent,
|
|
|
|
const PDBSymbol *Symbol, const std::string &Name,
|
|
|
|
uint32_t OffsetInParent, uint32_t Size,
|
|
|
|
bool IsElided)
|
|
|
|
: Symbol(Symbol), Parent(Parent), Name(Name),
|
|
|
|
OffsetInParent(OffsetInParent), SizeOf(Size), LayoutSize(Size),
|
|
|
|
IsElided(IsElided) {
|
[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
2017-04-13 01:18:21 +02:00
|
|
|
UsedBytes.resize(SizeOf, true);
|
|
|
|
}
|
|
|
|
|
2017-04-24 19:47:24 +02:00
|
|
|
uint32_t LayoutItemBase::deepPaddingSize() const {
|
|
|
|
return UsedBytes.size() - UsedBytes.count();
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t LayoutItemBase::tailPadding() const {
|
|
|
|
int Last = UsedBytes.find_last();
|
|
|
|
|
|
|
|
return UsedBytes.size() - (Last + 1);
|
[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
2017-04-13 01:18:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
DataMemberLayoutItem::DataMemberLayoutItem(
|
2017-04-24 19:47:24 +02:00
|
|
|
const UDTLayoutBase &Parent, std::unique_ptr<PDBSymbolData> Member)
|
|
|
|
: LayoutItemBase(&Parent, Member.get(), Member->getName(),
|
|
|
|
Member->getOffset(), getTypeLength(*Member), false),
|
|
|
|
DataMember(std::move(Member)) {
|
|
|
|
auto Type = DataMember->getType();
|
[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
2017-04-13 01:18:21 +02:00
|
|
|
if (auto UDT = unique_dyn_cast<PDBSymbolTypeUDT>(Type)) {
|
2019-08-15 17:54:37 +02:00
|
|
|
UdtLayout = std::make_unique<ClassLayout>(std::move(UDT));
|
2017-04-24 19:47:24 +02:00
|
|
|
UsedBytes = UdtLayout->usedBytes();
|
[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
2017-04-13 01:18:21 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-24 19:47:24 +02:00
|
|
|
VBPtrLayoutItem::VBPtrLayoutItem(const UDTLayoutBase &Parent,
|
|
|
|
std::unique_ptr<PDBSymbolTypeBuiltin> Sym,
|
|
|
|
uint32_t Offset, uint32_t Size)
|
|
|
|
: LayoutItemBase(&Parent, Sym.get(), "<vbptr>", Offset, Size, false),
|
|
|
|
Type(std::move(Sym)) {
|
|
|
|
}
|
|
|
|
|
[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
2017-04-13 01:18:21 +02:00
|
|
|
const PDBSymbolData &DataMemberLayoutItem::getDataMember() {
|
2017-04-24 19:47:24 +02:00
|
|
|
return *dyn_cast<PDBSymbolData>(Symbol);
|
[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
2017-04-13 01:18:21 +02:00
|
|
|
}
|
|
|
|
|
2017-04-13 23:11:00 +02:00
|
|
|
bool DataMemberLayoutItem::hasUDTLayout() const { return UdtLayout != nullptr; }
|
|
|
|
|
|
|
|
const ClassLayout &DataMemberLayoutItem::getUDTLayout() const {
|
|
|
|
return *UdtLayout;
|
|
|
|
}
|
|
|
|
|
[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
2017-04-13 01:18:21 +02:00
|
|
|
VTableLayoutItem::VTableLayoutItem(const UDTLayoutBase &Parent,
|
2017-04-24 19:47:24 +02:00
|
|
|
std::unique_ptr<PDBSymbolTypeVTable> VT)
|
|
|
|
: LayoutItemBase(&Parent, VT.get(), "<vtbl>", 0, getTypeLength(*VT), false),
|
|
|
|
VTable(std::move(VT)) {
|
|
|
|
auto VTableType = cast<PDBSymbolTypePointer>(VTable->getType());
|
2017-04-13 23:11:00 +02:00
|
|
|
ElementSize = VTableType->getLength();
|
2017-04-24 19:47:24 +02:00
|
|
|
}
|
[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
2017-04-13 01:18:21 +02:00
|
|
|
|
2017-04-24 19:47:24 +02:00
|
|
|
UDTLayoutBase::UDTLayoutBase(const UDTLayoutBase *Parent, const PDBSymbol &Sym,
|
|
|
|
const std::string &Name, uint32_t OffsetInParent,
|
|
|
|
uint32_t Size, bool IsElided)
|
|
|
|
: LayoutItemBase(Parent, &Sym, Name, OffsetInParent, Size, IsElided) {
|
|
|
|
// UDT storage comes from a union of all the children's storage, so start out
|
|
|
|
// uninitialized.
|
|
|
|
UsedBytes.reset(0, Size);
|
|
|
|
|
|
|
|
initializeChildren(Sym);
|
|
|
|
if (LayoutSize < Size)
|
|
|
|
UsedBytes.resize(LayoutSize);
|
[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
2017-04-13 01:18:21 +02:00
|
|
|
}
|
|
|
|
|
2017-04-24 19:47:24 +02:00
|
|
|
uint32_t UDTLayoutBase::tailPadding() const {
|
|
|
|
uint32_t Abs = LayoutItemBase::tailPadding();
|
|
|
|
if (!LayoutItems.empty()) {
|
|
|
|
const LayoutItemBase *Back = LayoutItems.back();
|
|
|
|
uint32_t ChildPadding = Back->LayoutItemBase::tailPadding();
|
|
|
|
if (Abs < ChildPadding)
|
|
|
|
Abs = 0;
|
|
|
|
else
|
|
|
|
Abs -= ChildPadding;
|
|
|
|
}
|
|
|
|
return Abs;
|
[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
2017-04-13 01:18:21 +02:00
|
|
|
}
|
|
|
|
|
2017-04-13 01:18:51 +02:00
|
|
|
ClassLayout::ClassLayout(const PDBSymbolTypeUDT &UDT)
|
2017-04-24 19:47:24 +02:00
|
|
|
: UDTLayoutBase(nullptr, UDT, UDT.getName(), 0, UDT.getLength(), false),
|
2017-04-25 22:22:29 +02:00
|
|
|
UDT(UDT) {
|
|
|
|
ImmediateUsedBytes.resize(SizeOf, false);
|
|
|
|
for (auto &LI : LayoutItems) {
|
|
|
|
uint32_t Begin = LI->getOffsetInParent();
|
|
|
|
uint32_t End = Begin + LI->getLayoutSize();
|
|
|
|
End = std::min(SizeOf, End);
|
|
|
|
ImmediateUsedBytes.set(Begin, End);
|
|
|
|
}
|
|
|
|
}
|
2017-04-13 01:18:51 +02:00
|
|
|
|
[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
2017-04-13 01:18:21 +02:00
|
|
|
ClassLayout::ClassLayout(std::unique_ptr<PDBSymbolTypeUDT> UDT)
|
2017-04-13 01:18:51 +02:00
|
|
|
: ClassLayout(*UDT) {
|
|
|
|
OwnedStorage = std::move(UDT);
|
|
|
|
}
|
[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
2017-04-13 01:18:21 +02:00
|
|
|
|
2017-04-25 22:22:29 +02:00
|
|
|
uint32_t ClassLayout::immediatePadding() const {
|
|
|
|
return SizeOf - ImmediateUsedBytes.count();
|
|
|
|
}
|
|
|
|
|
[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
2017-04-13 01:18:21 +02:00
|
|
|
BaseClassLayout::BaseClassLayout(const UDTLayoutBase &Parent,
|
2017-04-24 19:47:24 +02:00
|
|
|
uint32_t OffsetInParent, bool Elide,
|
|
|
|
std::unique_ptr<PDBSymbolTypeBaseClass> B)
|
|
|
|
: UDTLayoutBase(&Parent, *B, B->getName(), OffsetInParent, B->getLength(),
|
|
|
|
Elide),
|
|
|
|
Base(std::move(B)) {
|
|
|
|
if (isEmptyBase()) {
|
|
|
|
// Special case an empty base so that it doesn't get treated as padding.
|
|
|
|
UsedBytes.resize(1);
|
|
|
|
UsedBytes.set(0);
|
|
|
|
}
|
|
|
|
IsVirtualBase = Base->isVirtualBaseClass();
|
[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
2017-04-13 01:18:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void UDTLayoutBase::initializeChildren(const PDBSymbol &Sym) {
|
2017-04-13 23:11:00 +02:00
|
|
|
// Handled bases first, followed by VTables, followed by data members,
|
|
|
|
// followed by functions, followed by other. This ordering is necessary
|
|
|
|
// so that bases and vtables get initialized before any functions which
|
|
|
|
// may override them.
|
|
|
|
UniquePtrVector<PDBSymbolTypeBaseClass> Bases;
|
|
|
|
UniquePtrVector<PDBSymbolTypeVTable> VTables;
|
|
|
|
UniquePtrVector<PDBSymbolData> Members;
|
2017-04-24 19:47:24 +02:00
|
|
|
UniquePtrVector<PDBSymbolTypeBaseClass> VirtualBaseSyms;
|
|
|
|
|
[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
2017-04-13 01:18:21 +02:00
|
|
|
auto Children = Sym.findAllChildren();
|
|
|
|
while (auto Child = Children->getNext()) {
|
2017-04-13 23:11:00 +02:00
|
|
|
if (auto Base = unique_dyn_cast<PDBSymbolTypeBaseClass>(Child)) {
|
|
|
|
if (Base->isVirtualBaseClass())
|
2017-04-24 19:47:24 +02:00
|
|
|
VirtualBaseSyms.push_back(std::move(Base));
|
2017-04-13 23:11:00 +02:00
|
|
|
else
|
|
|
|
Bases.push_back(std::move(Base));
|
[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
2017-04-13 01:18:21 +02:00
|
|
|
}
|
2017-04-13 23:11:00 +02:00
|
|
|
else if (auto Data = unique_dyn_cast<PDBSymbolData>(Child)) {
|
|
|
|
if (Data->getDataKind() == PDB_DataKind::Member)
|
|
|
|
Members.push_back(std::move(Data));
|
|
|
|
else
|
2017-06-12 22:46:35 +02:00
|
|
|
Other.push_back(std::move(Data));
|
2017-04-13 23:11:00 +02:00
|
|
|
} else if (auto VT = unique_dyn_cast<PDBSymbolTypeVTable>(Child))
|
|
|
|
VTables.push_back(std::move(VT));
|
|
|
|
else if (auto Func = unique_dyn_cast<PDBSymbolFunc>(Child))
|
|
|
|
Funcs.push_back(std::move(Func));
|
2017-06-12 22:46:35 +02:00
|
|
|
else {
|
2017-04-13 23:11:00 +02:00
|
|
|
Other.push_back(std::move(Child));
|
2017-06-12 22:46:35 +02:00
|
|
|
}
|
2017-04-13 23:11:00 +02:00
|
|
|
}
|
[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
2017-04-13 01:18:21 +02:00
|
|
|
|
2017-04-24 19:47:24 +02:00
|
|
|
// We don't want to have any re-allocations in the list of bases, so make
|
|
|
|
// sure to reserve enough space so that our ArrayRefs don't get invalidated.
|
|
|
|
AllBases.reserve(Bases.size() + VirtualBaseSyms.size());
|
|
|
|
|
|
|
|
// Only add non-virtual bases to the class first. Only at the end of the
|
|
|
|
// class, after all non-virtual bases and data members have been added do we
|
|
|
|
// add virtual bases. This way the offsets are correctly aligned when we go
|
|
|
|
// to lay out virtual bases.
|
2017-04-13 23:11:00 +02:00
|
|
|
for (auto &Base : Bases) {
|
2017-04-24 19:47:24 +02:00
|
|
|
uint32_t Offset = Base->getOffset();
|
|
|
|
// Non-virtual bases never get elided.
|
2019-08-15 17:54:37 +02:00
|
|
|
auto BL = std::make_unique<BaseClassLayout>(*this, Offset, false,
|
2017-04-24 19:47:24 +02:00
|
|
|
std::move(Base));
|
2017-04-13 23:11:00 +02:00
|
|
|
|
2017-04-24 19:47:24 +02:00
|
|
|
AllBases.push_back(BL.get());
|
2017-04-13 23:11:00 +02:00
|
|
|
addChildToLayout(std::move(BL));
|
|
|
|
}
|
2017-04-24 19:47:24 +02:00
|
|
|
NonVirtualBases = AllBases;
|
2017-04-13 23:11:00 +02:00
|
|
|
|
2017-04-24 19:47:24 +02:00
|
|
|
assert(VTables.size() <= 1);
|
|
|
|
if (!VTables.empty()) {
|
|
|
|
auto VTLayout =
|
2019-08-15 17:54:37 +02:00
|
|
|
std::make_unique<VTableLayoutItem>(*this, std::move(VTables[0]));
|
2017-04-13 23:11:00 +02:00
|
|
|
|
|
|
|
VTable = VTLayout.get();
|
|
|
|
|
|
|
|
addChildToLayout(std::move(VTLayout));
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto &Data : Members) {
|
2019-08-15 17:54:37 +02:00
|
|
|
auto DM = std::make_unique<DataMemberLayoutItem>(*this, std::move(Data));
|
2017-04-13 23:11:00 +02:00
|
|
|
|
|
|
|
addChildToLayout(std::move(DM));
|
|
|
|
}
|
|
|
|
|
2017-04-24 19:47:24 +02:00
|
|
|
// Make sure add virtual bases before adding functions, since functions may be
|
|
|
|
// overrides of virtual functions declared in a virtual base, so the VTables
|
|
|
|
// and virtual intros need to be correctly initialized.
|
|
|
|
for (auto &VB : VirtualBaseSyms) {
|
|
|
|
int VBPO = VB->getVirtualBasePointerOffset();
|
|
|
|
if (!hasVBPtrAtOffset(VBPO)) {
|
|
|
|
if (auto VBP = VB->getRawSymbol().getVirtualBaseTableType()) {
|
2019-08-15 17:54:37 +02:00
|
|
|
auto VBPL = std::make_unique<VBPtrLayoutItem>(*this, std::move(VBP),
|
2017-04-24 19:47:24 +02:00
|
|
|
VBPO, VBP->getLength());
|
|
|
|
VBPtr = VBPL.get();
|
|
|
|
addChildToLayout(std::move(VBPL));
|
|
|
|
}
|
|
|
|
}
|
[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
2017-04-13 01:18:21 +02:00
|
|
|
|
2017-04-24 19:47:24 +02:00
|
|
|
// Virtual bases always go at the end. So just look for the last place we
|
|
|
|
// ended when writing something, and put our virtual base there.
|
|
|
|
// Note that virtual bases get elided unless this is a top-most derived
|
|
|
|
// class.
|
|
|
|
uint32_t Offset = UsedBytes.find_last() + 1;
|
|
|
|
bool Elide = (Parent != nullptr);
|
|
|
|
auto BL =
|
2019-08-15 17:54:37 +02:00
|
|
|
std::make_unique<BaseClassLayout>(*this, Offset, Elide, std::move(VB));
|
2017-04-24 19:47:24 +02:00
|
|
|
AllBases.push_back(BL.get());
|
|
|
|
|
|
|
|
// Only lay this virtual base out directly inside of *this* class if this
|
|
|
|
// is a top-most derived class. Keep track of it regardless, but only
|
|
|
|
// physically lay it out if it's a topmost derived class.
|
|
|
|
addChildToLayout(std::move(BL));
|
2017-04-13 23:11:00 +02:00
|
|
|
}
|
2017-04-24 19:47:24 +02:00
|
|
|
VirtualBases = makeArrayRef(AllBases).drop_front(NonVirtualBases.size());
|
|
|
|
|
|
|
|
if (Parent != nullptr)
|
|
|
|
LayoutSize = UsedBytes.find_last() + 1;
|
2017-04-13 23:11:00 +02:00
|
|
|
}
|
|
|
|
|
2017-04-24 19:47:24 +02:00
|
|
|
bool UDTLayoutBase::hasVBPtrAtOffset(uint32_t Off) const {
|
|
|
|
if (VBPtr && VBPtr->getOffsetInParent() == Off)
|
|
|
|
return true;
|
|
|
|
for (BaseClassLayout *BL : AllBases) {
|
|
|
|
if (BL->hasVBPtrAtOffset(Off - BL->getOffsetInParent()))
|
|
|
|
return true;
|
2017-04-13 23:11:00 +02:00
|
|
|
}
|
2017-04-24 19:47:24 +02:00
|
|
|
return false;
|
2017-04-13 23:11:00 +02:00
|
|
|
}
|
[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
2017-04-13 01:18:21 +02:00
|
|
|
|
2017-04-24 19:47:24 +02:00
|
|
|
void UDTLayoutBase::addChildToLayout(std::unique_ptr<LayoutItemBase> Child) {
|
|
|
|
uint32_t Begin = Child->getOffsetInParent();
|
2017-04-13 23:11:00 +02:00
|
|
|
|
2017-04-24 19:47:24 +02:00
|
|
|
if (!Child->isElided()) {
|
|
|
|
BitVector ChildBytes = Child->usedBytes();
|
2017-04-13 23:11:00 +02:00
|
|
|
|
2017-04-24 19:47:24 +02:00
|
|
|
// Suppose the child occupies 4 bytes starting at offset 12 in a 32 byte
|
|
|
|
// class. When we call ChildBytes.resize(32), the Child's storage will
|
|
|
|
// still begin at offset 0, so we need to shift it left by offset bytes
|
|
|
|
// to get it into the right position.
|
|
|
|
ChildBytes.resize(UsedBytes.size());
|
|
|
|
ChildBytes <<= Child->getOffsetInParent();
|
|
|
|
UsedBytes |= ChildBytes;
|
2017-04-13 23:11:00 +02:00
|
|
|
|
2017-04-24 19:47:24 +02:00
|
|
|
if (ChildBytes.count() > 0) {
|
|
|
|
auto Loc = std::upper_bound(LayoutItems.begin(), LayoutItems.end(), Begin,
|
|
|
|
[](uint32_t Off, const LayoutItemBase *Item) {
|
|
|
|
return (Off < Item->getOffsetInParent());
|
|
|
|
});
|
[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
2017-04-13 01:18:21 +02:00
|
|
|
|
2017-04-24 19:47:24 +02:00
|
|
|
LayoutItems.insert(Loc, Child.get());
|
|
|
|
}
|
[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
2017-04-13 01:18:21 +02:00
|
|
|
}
|
|
|
|
|
2017-04-24 19:47:24 +02:00
|
|
|
ChildStorage.push_back(std::move(Child));
|
2017-07-01 01:06:03 +02:00
|
|
|
}
|