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