blob: 525913c18656e92d5566cb42524b1aa6a5cebc30 [file] [log] [blame]
Zachary Turnerc883a8c2017-04-12 23:18:21 +00001//===- 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/DebugInfo/PDB/IPDBSession.h"
13#include "llvm/DebugInfo/PDB/PDBSymbol.h"
14#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
15#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
16#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
17#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h"
18#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
19#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
20#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h"
21
22#include <utility>
23
24using namespace llvm;
25using namespace llvm::pdb;
26
27static std::unique_ptr<PDBSymbol> getSymbolType(const PDBSymbol &Symbol) {
28 const IPDBSession &Session = Symbol.getSession();
29 const IPDBRawSymbol &RawSymbol = Symbol.getRawSymbol();
30 uint32_t TypeId = RawSymbol.getTypeId();
31 return Session.getSymbolById(TypeId);
32}
33
34static uint32_t getTypeLength(const PDBSymbol &Symbol) {
35 auto SymbolType = getSymbolType(Symbol);
36 const IPDBRawSymbol &RawType = SymbolType->getRawSymbol();
37
38 return RawType.getLength();
39}
40
41StorageItemBase::StorageItemBase(const UDTLayoutBase &Parent,
42 const PDBSymbol &Symbol,
43 const std::string &Name,
44 uint32_t OffsetInParent, uint32_t Size)
45 : Parent(Parent), Symbol(Symbol), Name(Name), SizeOf(Size),
46 OffsetInParent(OffsetInParent) {
47 UsedBytes.resize(SizeOf, true);
48}
49
50uint32_t StorageItemBase::deepPaddingSize() const {
51 // sizeof(Field) - sizeof(typeof(Field)) is trailing padding.
52 return SizeOf - getTypeLength(Symbol);
53}
54
55DataMemberLayoutItem::DataMemberLayoutItem(
56 const UDTLayoutBase &Parent, std::unique_ptr<PDBSymbolData> DataMember)
57 : StorageItemBase(Parent, *DataMember, DataMember->getName(),
58 DataMember->getOffset(), getTypeLength(*DataMember)),
59 DataMember(std::move(DataMember)) {
60 auto Type = this->DataMember->getType();
61 if (auto UDT = unique_dyn_cast<PDBSymbolTypeUDT>(Type)) {
62 // UDT data members might have padding in between fields, but otherwise
63 // a member should occupy its entire storage.
64 UsedBytes.resize(SizeOf, false);
65 UdtLayout = llvm::make_unique<ClassLayout>(std::move(UDT));
66 }
67}
68
69const PDBSymbolData &DataMemberLayoutItem::getDataMember() {
70 return *dyn_cast<PDBSymbolData>(&Symbol);
71}
72
73uint32_t DataMemberLayoutItem::deepPaddingSize() const {
74 uint32_t Result = StorageItemBase::deepPaddingSize();
75 if (UdtLayout)
76 Result += UdtLayout->deepPaddingSize();
77 return Result;
78}
79
80VTableLayoutItem::VTableLayoutItem(const UDTLayoutBase &Parent,
81 std::unique_ptr<PDBSymbolTypeVTable> VTable)
82 : StorageItemBase(Parent, *VTable, "<vtbl>", 0, getTypeLength(*VTable)),
83 VTable(std::move(VTable)) {
84 // initialize vtbl methods.
85 auto VTableType = cast<PDBSymbolTypePointer>(this->VTable->getType());
86 uint32_t PointerSize = VTableType->getLength();
87
88 if (auto Shape = unique_dyn_cast<PDBSymbolTypeVTableShape>(
89 VTableType->getPointeeType())) {
90 VTableFuncs.resize(Shape->getCount());
91
Zachary Turner9e7dda32017-04-12 23:18:51 +000092 auto ParentFunctions =
93 Parent.getSymbolBase().findAllChildren<PDBSymbolFunc>();
Zachary Turnerc883a8c2017-04-12 23:18:21 +000094 while (auto Func = ParentFunctions->getNext()) {
95 if (Func->isVirtual()) {
96 uint32_t Index = Func->getVirtualBaseOffset();
97 assert(Index % PointerSize == 0);
98 Index /= PointerSize;
99
100 // Don't allow a compiler generated function to overwrite a user
101 // function in the VTable. Not sure why this happens, but a function
102 // named __vecDelDtor sometimes shows up on top of the destructor.
103 if (Func->isCompilerGenerated() && VTableFuncs[Index])
104 continue;
105 VTableFuncs[Index] = std::move(Func);
106 }
107 }
108 }
109}
110
111UDTLayoutBase::UDTLayoutBase(const PDBSymbol &Symbol, const std::string &Name,
112 uint32_t Size)
Zachary Turner9e7dda32017-04-12 23:18:51 +0000113 : SymbolBase(Symbol), Name(Name), SizeOf(Size) {
Zachary Turnerc883a8c2017-04-12 23:18:21 +0000114 UsedBytes.resize(Size);
115 ChildrenPerByte.resize(Size);
116 initializeChildren(Symbol);
117}
118
Zachary Turner9e7dda32017-04-12 23:18:51 +0000119ClassLayout::ClassLayout(const PDBSymbolTypeUDT &UDT)
120 : UDTLayoutBase(UDT, UDT.getName(), UDT.getLength()), UDT(UDT) {}
121
Zachary Turnerc883a8c2017-04-12 23:18:21 +0000122ClassLayout::ClassLayout(std::unique_ptr<PDBSymbolTypeUDT> UDT)
Zachary Turner9e7dda32017-04-12 23:18:51 +0000123 : ClassLayout(*UDT) {
124 OwnedStorage = std::move(UDT);
125}
Zachary Turnerc883a8c2017-04-12 23:18:21 +0000126
127BaseClassLayout::BaseClassLayout(const UDTLayoutBase &Parent,
128 std::unique_ptr<PDBSymbolTypeBaseClass> Base)
129 : UDTLayoutBase(*Base, Base->getName(), Base->getLength()),
130 StorageItemBase(Parent, *Base, Base->getName(), Base->getOffset(),
131 Base->getLength()),
132 Base(std::move(Base)) {
133 IsVirtualBase = this->Base->isVirtualBaseClass();
134}
135
136uint32_t UDTLayoutBase::shallowPaddingSize() const {
137 return UsedBytes.size() - UsedBytes.count();
138}
139
140uint32_t UDTLayoutBase::deepPaddingSize() const {
141 uint32_t Result = shallowPaddingSize();
142 for (auto &Child : ChildStorage)
143 Result += Child->deepPaddingSize();
144 return Result;
145}
146
147void UDTLayoutBase::initializeChildren(const PDBSymbol &Sym) {
148 auto Children = Sym.findAllChildren();
149 while (auto Child = Children->getNext()) {
150 if (auto Data = unique_dyn_cast<PDBSymbolData>(Child)) {
151 if (Data->getDataKind() == PDB_DataKind::Member) {
152 auto DM =
153 llvm::make_unique<DataMemberLayoutItem>(*this, std::move(Data));
154
155 addChildToLayout(std::move(DM));
156 } else {
157 NonStorageItems.push_back(std::move(Data));
158 }
159 continue;
160 }
161
162 if (auto Base = unique_dyn_cast<PDBSymbolTypeBaseClass>(Child)) {
163 auto BL = llvm::make_unique<BaseClassLayout>(*this, std::move(Base));
164 BaseClasses.push_back(BL.get());
165
166 addChildToLayout(std::move(BL));
167 continue;
168 }
169
170 if (auto VT = unique_dyn_cast<PDBSymbolTypeVTable>(Child)) {
171 auto VTLayout = llvm::make_unique<VTableLayoutItem>(*this, std::move(VT));
172
173 VTable = VTLayout.get();
174
175 addChildToLayout(std::move(VTLayout));
176 continue;
177 }
178
179 NonStorageItems.push_back(std::move(Child));
180 }
181}
182
183void UDTLayoutBase::addChildToLayout(std::unique_ptr<StorageItemBase> Child) {
184 uint32_t Begin = Child->getOffsetInParent();
185 uint32_t End = Begin + Child->getSize();
186 UsedBytes.set(Begin, End);
187 while (Begin != End) {
188 ChildrenPerByte[Begin].push_back(Child.get());
189 ++Begin;
190 }
191
192 auto Loc = std::upper_bound(
193 ChildStorage.begin(), ChildStorage.end(), Begin,
194 [](uint32_t Off, const std::unique_ptr<StorageItemBase> &Item) {
195 return Off < Item->getOffsetInParent();
196 });
197
198 ChildStorage.insert(Loc, std::move(Child));
199}