UDTLayout.cpp 11 KB

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