Line data Source code
1 : //===- UDTLayout.cpp ------------------------------------------------------===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 :
10 : #include "llvm/DebugInfo/PDB/UDTLayout.h"
11 : #include "llvm/ADT/ArrayRef.h"
12 : #include "llvm/ADT/BitVector.h"
13 : #include "llvm/ADT/STLExtras.h"
14 : #include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"
15 : #include "llvm/DebugInfo/PDB/IPDBSession.h"
16 : #include "llvm/DebugInfo/PDB/PDBSymbol.h"
17 : #include "llvm/DebugInfo/PDB/PDBSymbolData.h"
18 : #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
19 : #include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h"
20 : #include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
21 : #include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
22 : #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
23 : #include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h"
24 : #include "llvm/DebugInfo/PDB/PDBTypes.h"
25 : #include "llvm/Support/Casting.h"
26 : #include <algorithm>
27 : #include <cassert>
28 : #include <cstdint>
29 : #include <memory>
30 :
31 : using namespace llvm;
32 : using namespace llvm::pdb;
33 :
34 : static std::unique_ptr<PDBSymbol> getSymbolType(const PDBSymbol &Symbol) {
35 0 : const IPDBSession &Session = Symbol.getSession();
36 0 : const IPDBRawSymbol &RawSymbol = Symbol.getRawSymbol();
37 0 : uint32_t TypeId = RawSymbol.getTypeId();
38 0 : return Session.getSymbolById(TypeId);
39 : }
40 :
41 0 : static uint32_t getTypeLength(const PDBSymbol &Symbol) {
42 : auto SymbolType = getSymbolType(Symbol);
43 0 : const IPDBRawSymbol &RawType = SymbolType->getRawSymbol();
44 :
45 0 : return RawType.getLength();
46 : }
47 :
48 18 : LayoutItemBase::LayoutItemBase(const UDTLayoutBase *Parent,
49 : const PDBSymbol *Symbol, const std::string &Name,
50 : uint32_t OffsetInParent, uint32_t Size,
51 18 : bool IsElided)
52 : : Symbol(Symbol), Parent(Parent), Name(Name),
53 : OffsetInParent(OffsetInParent), SizeOf(Size), LayoutSize(Size),
54 36 : IsElided(IsElided) {
55 18 : UsedBytes.resize(SizeOf, true);
56 18 : }
57 :
58 72 : uint32_t LayoutItemBase::deepPaddingSize() const {
59 72 : return UsedBytes.size() - UsedBytes.count();
60 : }
61 :
62 18 : uint32_t LayoutItemBase::tailPadding() const {
63 18 : int Last = UsedBytes.find_last();
64 :
65 18 : return UsedBytes.size() - (Last + 1);
66 : }
67 :
68 0 : DataMemberLayoutItem::DataMemberLayoutItem(
69 0 : const UDTLayoutBase &Parent, std::unique_ptr<PDBSymbolData> Member)
70 0 : : LayoutItemBase(&Parent, Member.get(), Member->getName(),
71 0 : Member->getOffset(), getTypeLength(*Member), false),
72 0 : DataMember(std::move(Member)) {
73 0 : auto Type = DataMember->getType();
74 0 : if (auto UDT = unique_dyn_cast<PDBSymbolTypeUDT>(Type)) {
75 0 : UdtLayout = llvm::make_unique<ClassLayout>(std::move(UDT));
76 0 : UsedBytes = UdtLayout->usedBytes();
77 : }
78 0 : }
79 :
80 0 : VBPtrLayoutItem::VBPtrLayoutItem(const UDTLayoutBase &Parent,
81 : std::unique_ptr<PDBSymbolTypeBuiltin> Sym,
82 0 : uint32_t Offset, uint32_t Size)
83 : : LayoutItemBase(&Parent, Sym.get(), "<vbptr>", Offset, Size, false),
84 0 : Type(std::move(Sym)) {
85 0 : }
86 :
87 0 : const PDBSymbolData &DataMemberLayoutItem::getDataMember() {
88 0 : return *dyn_cast<PDBSymbolData>(Symbol);
89 : }
90 :
91 0 : bool DataMemberLayoutItem::hasUDTLayout() const { return UdtLayout != nullptr; }
92 :
93 0 : const ClassLayout &DataMemberLayoutItem::getUDTLayout() const {
94 0 : return *UdtLayout;
95 : }
96 :
97 0 : VTableLayoutItem::VTableLayoutItem(const UDTLayoutBase &Parent,
98 0 : std::unique_ptr<PDBSymbolTypeVTable> VT)
99 : : LayoutItemBase(&Parent, VT.get(), "<vtbl>", 0, getTypeLength(*VT), false),
100 0 : VTable(std::move(VT)) {
101 0 : auto VTableType = cast<PDBSymbolTypePointer>(VTable->getType());
102 0 : ElementSize = VTableType->getLength();
103 0 : }
104 :
105 18 : UDTLayoutBase::UDTLayoutBase(const UDTLayoutBase *Parent, const PDBSymbol &Sym,
106 : const std::string &Name, uint32_t OffsetInParent,
107 18 : uint32_t Size, bool IsElided)
108 18 : : LayoutItemBase(Parent, &Sym, Name, OffsetInParent, Size, IsElided) {
109 : // UDT storage comes from a union of all the children's storage, so start out
110 : // uninitialized.
111 18 : UsedBytes.reset(0, Size);
112 :
113 18 : initializeChildren(Sym);
114 18 : if (LayoutSize < Size)
115 0 : UsedBytes.resize(LayoutSize);
116 18 : }
117 :
118 18 : uint32_t UDTLayoutBase::tailPadding() const {
119 18 : uint32_t Abs = LayoutItemBase::tailPadding();
120 18 : if (!LayoutItems.empty()) {
121 0 : const LayoutItemBase *Back = LayoutItems.back();
122 0 : uint32_t ChildPadding = Back->LayoutItemBase::tailPadding();
123 0 : if (Abs < ChildPadding)
124 : Abs = 0;
125 : else
126 0 : Abs -= ChildPadding;
127 : }
128 18 : return Abs;
129 : }
130 :
131 18 : ClassLayout::ClassLayout(const PDBSymbolTypeUDT &UDT)
132 54 : : UDTLayoutBase(nullptr, UDT, UDT.getName(), 0, UDT.getLength(), false),
133 36 : UDT(UDT) {
134 18 : ImmediateUsedBytes.resize(SizeOf, false);
135 18 : for (auto &LI : LayoutItems) {
136 0 : uint32_t Begin = LI->getOffsetInParent();
137 0 : uint32_t End = Begin + LI->getLayoutSize();
138 0 : End = std::min(SizeOf, End);
139 0 : ImmediateUsedBytes.set(Begin, End);
140 : }
141 18 : }
142 :
143 18 : ClassLayout::ClassLayout(std::unique_ptr<PDBSymbolTypeUDT> UDT)
144 18 : : ClassLayout(*UDT) {
145 : OwnedStorage = std::move(UDT);
146 18 : }
147 :
148 36 : uint32_t ClassLayout::immediatePadding() const {
149 36 : return SizeOf - ImmediateUsedBytes.count();
150 : }
151 :
152 0 : BaseClassLayout::BaseClassLayout(const UDTLayoutBase &Parent,
153 : uint32_t OffsetInParent, bool Elide,
154 0 : std::unique_ptr<PDBSymbolTypeBaseClass> B)
155 0 : : UDTLayoutBase(&Parent, *B, B->getName(), OffsetInParent, B->getLength(),
156 : Elide),
157 0 : Base(std::move(B)) {
158 0 : if (isEmptyBase()) {
159 : // Special case an empty base so that it doesn't get treated as padding.
160 0 : UsedBytes.resize(1);
161 : UsedBytes.set(0);
162 : }
163 0 : IsVirtualBase = Base->isVirtualBaseClass();
164 0 : }
165 :
166 18 : void UDTLayoutBase::initializeChildren(const PDBSymbol &Sym) {
167 : // Handled bases first, followed by VTables, followed by data members,
168 : // followed by functions, followed by other. This ordering is necessary
169 : // so that bases and vtables get initialized before any functions which
170 : // may override them.
171 18 : UniquePtrVector<PDBSymbolTypeBaseClass> Bases;
172 18 : UniquePtrVector<PDBSymbolTypeVTable> VTables;
173 18 : UniquePtrVector<PDBSymbolData> Members;
174 18 : UniquePtrVector<PDBSymbolTypeBaseClass> VirtualBaseSyms;
175 :
176 18 : auto Children = Sym.findAllChildren();
177 18 : while (auto Child = Children->getNext()) {
178 0 : if (auto Base = unique_dyn_cast<PDBSymbolTypeBaseClass>(Child)) {
179 0 : if (Base->isVirtualBaseClass())
180 : VirtualBaseSyms.push_back(std::move(Base));
181 : else
182 : Bases.push_back(std::move(Base));
183 : }
184 0 : else if (auto Data = unique_dyn_cast<PDBSymbolData>(Child)) {
185 0 : if (Data->getDataKind() == PDB_DataKind::Member)
186 : Members.push_back(std::move(Data));
187 : else
188 0 : Other.push_back(std::move(Data));
189 0 : } else if (auto VT = unique_dyn_cast<PDBSymbolTypeVTable>(Child))
190 : VTables.push_back(std::move(VT));
191 0 : else if (auto Func = unique_dyn_cast<PDBSymbolFunc>(Child))
192 0 : Funcs.push_back(std::move(Func));
193 : else {
194 0 : Other.push_back(std::move(Child));
195 : }
196 : }
197 :
198 : // We don't want to have any re-allocations in the list of bases, so make
199 : // sure to reserve enough space so that our ArrayRefs don't get invalidated.
200 54 : AllBases.reserve(Bases.size() + VirtualBaseSyms.size());
201 :
202 : // Only add non-virtual bases to the class first. Only at the end of the
203 : // class, after all non-virtual bases and data members have been added do we
204 : // add virtual bases. This way the offsets are correctly aligned when we go
205 : // to lay out virtual bases.
206 18 : for (auto &Base : Bases) {
207 0 : uint32_t Offset = Base->getOffset();
208 : // Non-virtual bases never get elided.
209 0 : auto BL = llvm::make_unique<BaseClassLayout>(*this, Offset, false,
210 0 : std::move(Base));
211 :
212 0 : AllBases.push_back(BL.get());
213 0 : addChildToLayout(std::move(BL));
214 : }
215 18 : NonVirtualBases = AllBases;
216 :
217 : assert(VTables.size() <= 1);
218 18 : if (!VTables.empty()) {
219 : auto VTLayout =
220 0 : llvm::make_unique<VTableLayoutItem>(*this, std::move(VTables[0]));
221 :
222 0 : VTable = VTLayout.get();
223 :
224 0 : addChildToLayout(std::move(VTLayout));
225 : }
226 :
227 18 : for (auto &Data : Members) {
228 0 : auto DM = llvm::make_unique<DataMemberLayoutItem>(*this, std::move(Data));
229 :
230 0 : addChildToLayout(std::move(DM));
231 : }
232 :
233 : // Make sure add virtual bases before adding functions, since functions may be
234 : // overrides of virtual functions declared in a virtual base, so the VTables
235 : // and virtual intros need to be correctly initialized.
236 18 : for (auto &VB : VirtualBaseSyms) {
237 0 : int VBPO = VB->getVirtualBasePointerOffset();
238 0 : if (!hasVBPtrAtOffset(VBPO)) {
239 0 : if (auto VBP = VB->getRawSymbol().getVirtualBaseTableType()) {
240 : auto VBPL = llvm::make_unique<VBPtrLayoutItem>(*this, std::move(VBP),
241 0 : VBPO, VBP->getLength());
242 0 : VBPtr = VBPL.get();
243 0 : addChildToLayout(std::move(VBPL));
244 : }
245 : }
246 :
247 : // Virtual bases always go at the end. So just look for the last place we
248 : // ended when writing something, and put our virtual base there.
249 : // Note that virtual bases get elided unless this is a top-most derived
250 : // class.
251 0 : uint32_t Offset = UsedBytes.find_last() + 1;
252 0 : bool Elide = (Parent != nullptr);
253 : auto BL =
254 0 : llvm::make_unique<BaseClassLayout>(*this, Offset, Elide, std::move(VB));
255 0 : AllBases.push_back(BL.get());
256 :
257 : // Only lay this virtual base out directly inside of *this* class if this
258 : // is a top-most derived class. Keep track of it regardless, but only
259 : // physically lay it out if it's a topmost derived class.
260 0 : addChildToLayout(std::move(BL));
261 : }
262 18 : VirtualBases = makeArrayRef(AllBases).drop_front(NonVirtualBases.size());
263 :
264 18 : if (Parent != nullptr)
265 0 : LayoutSize = UsedBytes.find_last() + 1;
266 18 : }
267 :
268 0 : bool UDTLayoutBase::hasVBPtrAtOffset(uint32_t Off) const {
269 0 : if (VBPtr && VBPtr->getOffsetInParent() == Off)
270 : return true;
271 0 : for (BaseClassLayout *BL : AllBases) {
272 0 : if (BL->hasVBPtrAtOffset(Off - BL->getOffsetInParent()))
273 : return true;
274 : }
275 : return false;
276 : }
277 :
278 0 : void UDTLayoutBase::addChildToLayout(std::unique_ptr<LayoutItemBase> Child) {
279 0 : uint32_t Begin = Child->getOffsetInParent();
280 :
281 0 : if (!Child->isElided()) {
282 0 : BitVector ChildBytes = Child->usedBytes();
283 :
284 : // Suppose the child occupies 4 bytes starting at offset 12 in a 32 byte
285 : // class. When we call ChildBytes.resize(32), the Child's storage will
286 : // still begin at offset 0, so we need to shift it left by offset bytes
287 : // to get it into the right position.
288 0 : ChildBytes.resize(UsedBytes.size());
289 0 : ChildBytes <<= Child->getOffsetInParent();
290 0 : UsedBytes |= ChildBytes;
291 :
292 0 : if (ChildBytes.count() > 0) {
293 : auto Loc = std::upper_bound(LayoutItems.begin(), LayoutItems.end(), Begin,
294 : [](uint32_t Off, const LayoutItemBase *Item) {
295 0 : return (Off < Item->getOffsetInParent());
296 : });
297 :
298 0 : LayoutItems.insert(Loc, Child.get());
299 : }
300 : }
301 :
302 0 : ChildStorage.push_back(std::move(Child));
303 0 : }
|