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 }