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