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/PDBSymbolTypePointer.h"
20 #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
21 #include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h"
22 
23 #include <utility>
24 
25 using namespace llvm;
26 using namespace llvm::pdb;
27 
28 static std::unique_ptr<PDBSymbol> getSymbolType(const PDBSymbol &Symbol) {
29   const IPDBSession &Session = Symbol.getSession();
30   const IPDBRawSymbol &RawSymbol = Symbol.getRawSymbol();
31   uint32_t TypeId = RawSymbol.getTypeId();
32   return Session.getSymbolById(TypeId);
33 }
34 
35 static uint32_t getTypeLength(const PDBSymbol &Symbol) {
36   auto SymbolType = getSymbolType(Symbol);
37   const IPDBRawSymbol &RawType = SymbolType->getRawSymbol();
38 
39   return RawType.getLength();
40 }
41 
42 StorageItemBase::StorageItemBase(const UDTLayoutBase &Parent,
43                                  const PDBSymbol &Symbol,
44                                  const std::string &Name,
45                                  uint32_t OffsetInParent, uint32_t Size)
46     : Parent(Parent), Symbol(Symbol), Name(Name),
47       OffsetInParent(OffsetInParent), SizeOf(Size) {
48   UsedBytes.resize(SizeOf, true);
49 }
50 
51 uint32_t StorageItemBase::deepPaddingSize() const {
52   // sizeof(Field) - sizeof(typeof(Field)) is trailing padding.
53   return SizeOf - getTypeLength(Symbol);
54 }
55 
56 DataMemberLayoutItem::DataMemberLayoutItem(
57     const UDTLayoutBase &Parent, std::unique_ptr<PDBSymbolData> DataMember)
58     : StorageItemBase(Parent, *DataMember, DataMember->getName(),
59                       DataMember->getOffset(), getTypeLength(*DataMember)),
60       DataMember(std::move(DataMember)) {
61   auto Type = this->DataMember->getType();
62   if (auto UDT = unique_dyn_cast<PDBSymbolTypeUDT>(Type)) {
63     // UDT data members might have padding in between fields, but otherwise
64     // a member should occupy its entire storage.
65     UsedBytes.resize(SizeOf, false);
66     UdtLayout = llvm::make_unique<ClassLayout>(std::move(UDT));
67   }
68 }
69 
70 const PDBSymbolData &DataMemberLayoutItem::getDataMember() {
71   return *dyn_cast<PDBSymbolData>(&Symbol);
72 }
73 
74 bool DataMemberLayoutItem::hasUDTLayout() const { return UdtLayout != nullptr; }
75 
76 const ClassLayout &DataMemberLayoutItem::getUDTLayout() const {
77   return *UdtLayout;
78 }
79 
80 uint32_t DataMemberLayoutItem::deepPaddingSize() const {
81   uint32_t Result = StorageItemBase::deepPaddingSize();
82   if (UdtLayout)
83     Result += UdtLayout->deepPaddingSize();
84   return Result;
85 }
86 
87 VTableLayoutItem::VTableLayoutItem(const UDTLayoutBase &Parent,
88                                    std::unique_ptr<PDBSymbolTypeVTable> VTable)
89     : StorageItemBase(Parent, *VTable, "<vtbl>", 0, getTypeLength(*VTable)),
90       VTable(std::move(VTable)) {
91   auto VTableType = cast<PDBSymbolTypePointer>(this->VTable->getType());
92   ElementSize = VTableType->getLength();
93 
94   Shape =
95       unique_dyn_cast<PDBSymbolTypeVTableShape>(VTableType->getPointeeType());
96   if (Shape)
97     VTableFuncs.resize(Shape->getCount());
98 }
99 
100 UDTLayoutBase::UDTLayoutBase(const PDBSymbol &Symbol, const std::string &Name,
101                              uint32_t Size)
102     : SymbolBase(Symbol), Name(Name), SizeOf(Size) {
103   UsedBytes.resize(Size);
104   ChildrenPerByte.resize(Size);
105   initializeChildren(Symbol);
106 }
107 
108 ClassLayout::ClassLayout(const PDBSymbolTypeUDT &UDT)
109     : UDTLayoutBase(UDT, UDT.getName(), UDT.getLength()), UDT(UDT) {}
110 
111 ClassLayout::ClassLayout(std::unique_ptr<PDBSymbolTypeUDT> UDT)
112     : ClassLayout(*UDT) {
113   OwnedStorage = std::move(UDT);
114 }
115 
116 BaseClassLayout::BaseClassLayout(const UDTLayoutBase &Parent,
117                                  std::unique_ptr<PDBSymbolTypeBaseClass> Base)
118     : UDTLayoutBase(*Base, Base->getName(), Base->getLength()),
119       StorageItemBase(Parent, *Base, Base->getName(), Base->getOffset(),
120                       Base->getLength()),
121       Base(std::move(Base)) {
122   IsVirtualBase = this->Base->isVirtualBaseClass();
123 }
124 
125 uint32_t UDTLayoutBase::shallowPaddingSize() const {
126   return UsedBytes.size() - UsedBytes.count();
127 }
128 
129 uint32_t UDTLayoutBase::deepPaddingSize() const {
130   uint32_t Result = shallowPaddingSize();
131   for (auto &Child : ChildStorage)
132     Result += Child->deepPaddingSize();
133   return Result;
134 }
135 
136 void UDTLayoutBase::initializeChildren(const PDBSymbol &Sym) {
137   // Handled bases first, followed by VTables, followed by data members,
138   // followed by functions, followed by other.  This ordering is necessary
139   // so that bases and vtables get initialized before any functions which
140   // may override them.
141 
142   UniquePtrVector<PDBSymbolTypeBaseClass> Bases;
143   UniquePtrVector<PDBSymbolTypeVTable> VTables;
144   UniquePtrVector<PDBSymbolData> Members;
145   auto Children = Sym.findAllChildren();
146   while (auto Child = Children->getNext()) {
147     if (auto Base = unique_dyn_cast<PDBSymbolTypeBaseClass>(Child)) {
148       if (Base->isVirtualBaseClass())
149         VirtualBases.push_back(std::move(Base));
150       else
151         Bases.push_back(std::move(Base));
152     }
153 
154     else if (auto Data = unique_dyn_cast<PDBSymbolData>(Child)) {
155       if (Data->getDataKind() == PDB_DataKind::Member)
156         Members.push_back(std::move(Data));
157       else
158         Other.push_back(std::move(Child));
159     } else if (auto VT = unique_dyn_cast<PDBSymbolTypeVTable>(Child))
160       VTables.push_back(std::move(VT));
161     else if (auto Func = unique_dyn_cast<PDBSymbolFunc>(Child))
162       Funcs.push_back(std::move(Func));
163     else
164       Other.push_back(std::move(Child));
165   }
166 
167   for (auto &Base : Bases) {
168     auto BL = llvm::make_unique<BaseClassLayout>(*this, std::move(Base));
169     BaseClasses.push_back(BL.get());
170 
171     addChildToLayout(std::move(BL));
172   }
173 
174   for (auto &VT : VTables) {
175     auto VTLayout = llvm::make_unique<VTableLayoutItem>(*this, std::move(VT));
176 
177     VTable = VTLayout.get();
178 
179     addChildToLayout(std::move(VTLayout));
180     continue;
181   }
182 
183   for (auto &Data : Members) {
184     auto DM = llvm::make_unique<DataMemberLayoutItem>(*this, std::move(Data));
185 
186     addChildToLayout(std::move(DM));
187   }
188 
189   for (auto &Func : Funcs) {
190     if (!Func->isVirtual())
191       continue;
192 
193     if (Func->isIntroVirtualFunction())
194       addVirtualIntro(*Func);
195     else
196       addVirtualOverride(*Func);
197   }
198 }
199 
200 void UDTLayoutBase::addVirtualIntro(PDBSymbolFunc &Func) {
201   // Kind of a hack, but we prefer the more common destructor name that people
202   // are familiar with, e.g. ~ClassName.  It seems there are always both and
203   // the vector deleting destructor overwrites the nice destructor, so just
204   // ignore the vector deleting destructor.
205   if (Func.getName() == "__vecDelDtor")
206     return;
207 
208   if (!VTable) {
209     // FIXME: Handle this.  What's most likely happening is we have an intro
210     // virtual in a derived class where the base also has an intro virtual.
211     // In this case the vtable lives in the base.  What we really need is
212     // for each UDTLayoutBase to contain a list of all its vtables, and
213     // then propagate this list up the hierarchy so that derived classes have
214     // direct access to their bases' vtables.
215     return;
216   }
217 
218   uint32_t Stride = VTable->getElementSize();
219 
220   uint32_t Index = Func.getVirtualBaseOffset();
221   assert(Index % Stride == 0);
222   Index /= Stride;
223 
224   VTable->setFunction(Index, Func);
225 }
226 
227 VTableLayoutItem *UDTLayoutBase::findVTableAtOffset(uint32_t RelativeOffset) {
228   if (VTable && VTable->getOffsetInParent() == RelativeOffset)
229     return VTable;
230   for (auto Base : BaseClasses) {
231     uint32_t Begin = Base->getOffsetInParent();
232     uint32_t End = Begin + Base->getSize();
233     if (RelativeOffset < Begin || RelativeOffset >= End)
234       continue;
235 
236     return Base->findVTableAtOffset(RelativeOffset - Begin);
237   }
238 
239   return nullptr;
240 }
241 
242 void UDTLayoutBase::addVirtualOverride(PDBSymbolFunc &Func) {
243   auto Signature = Func.getSignature();
244   auto ThisAdjust = Signature->getThisAdjust();
245   // ThisAdjust tells us which VTable we're looking for.  Specifically, it's
246   // the offset into the current class of the VTable we're looking for.  So
247   // look through the base hierarchy until we find one such that
248   // AbsoluteOffset(VT) == ThisAdjust
249   VTableLayoutItem *VT = findVTableAtOffset(ThisAdjust);
250   if (!VT) {
251     // FIXME: There really should be a vtable here.  If there's not it probably
252     // means that the vtable is in a virtual base, which we don't yet support.
253     assert(!VirtualBases.empty());
254     return;
255   }
256   int32_t OverrideIndex = -1;
257   // Now we've found the VTable.  Func will not have a virtual base offset set,
258   // so instead we need to compare names and signatures.  We iterate each item
259   // in the VTable.  All items should already have non null entries because they
260   // were initialized by the intro virtual, which was guaranteed to come before.
261   for (auto ItemAndIndex : enumerate(VT->funcs())) {
262     auto Item = ItemAndIndex.value();
263     assert(Item);
264     // If the name doesn't match, this isn't an override.  Note that it's ok
265     // for the return type to not match (e.g. co-variant return).
266     if (Item->getName() != Func.getName()) {
267       if (Item->isDestructor() && Func.isDestructor()) {
268         OverrideIndex = ItemAndIndex.index();
269         break;
270       }
271       continue;
272     }
273     // Now make sure it's the right overload.  Get the signature of the existing
274     // vtable method and make sure it has the same arglist and the same cv-ness.
275     auto ExistingSig = Item->getSignature();
276     if (ExistingSig->isConstType() != Signature->isConstType())
277       continue;
278     if (ExistingSig->isVolatileType() != Signature->isVolatileType())
279       continue;
280 
281     // Now compare arguments.  Using the raw bytes of the PDB this would be
282     // trivial
283     // because there is an ArgListId and they should be identical.  But DIA
284     // doesn't
285     // expose this, so the best we can do is iterate each argument and confirm
286     // that
287     // each one is identical.
288     if (ExistingSig->getCount() != Signature->getCount())
289       continue;
290     bool IsMatch = true;
291     auto ExistingEnumerator = ExistingSig->getArguments();
292     auto NewEnumerator = Signature->getArguments();
293     for (uint32_t I = 0; I < ExistingEnumerator->getChildCount(); ++I) {
294       auto ExistingArg = ExistingEnumerator->getNext();
295       auto NewArg = NewEnumerator->getNext();
296       if (ExistingArg->getSymIndexId() != NewArg->getSymIndexId()) {
297         IsMatch = false;
298         break;
299       }
300     }
301     if (!IsMatch)
302       continue;
303 
304     // It's a match!  Stick the new function into the VTable.
305     OverrideIndex = ItemAndIndex.index();
306     break;
307   }
308   if (OverrideIndex == -1) {
309     // FIXME: This is probably due to one of the other FIXMEs in this file.
310     return;
311   }
312   VT->setFunction(OverrideIndex, Func);
313 }
314 
315 void UDTLayoutBase::addChildToLayout(std::unique_ptr<StorageItemBase> Child) {
316   uint32_t Begin = Child->getOffsetInParent();
317   uint32_t End = Begin + Child->getSize();
318   // Due to the empty base optimization, End might point outside the bounds of
319   // the parent class.  If that happens, just clamp the value.
320   End = std::min(End, getClassSize());
321 
322   UsedBytes.set(Begin, End);
323   while (Begin != End) {
324     ChildrenPerByte[Begin].push_back(Child.get());
325     ++Begin;
326   }
327 
328   auto Loc = std::upper_bound(
329       ChildStorage.begin(), ChildStorage.end(), Begin,
330       [](uint32_t Off, const std::unique_ptr<StorageItemBase> &Item) {
331         return Off < Item->getOffsetInParent();
332       });
333 
334   ChildStorage.insert(Loc, std::move(Child));
335 }