blob: 71443fe7587822ba9341ededf8cf0469cb009d65 [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
92 auto ParentFunctions = Parent.getSymbol().findAllChildren<PDBSymbolFunc>();
93 while (auto Func = ParentFunctions->getNext()) {
94 if (Func->isVirtual()) {
95 uint32_t Index = Func->getVirtualBaseOffset();
96 assert(Index % PointerSize == 0);
97 Index /= PointerSize;
98
99 // Don't allow a compiler generated function to overwrite a user
100 // function in the VTable. Not sure why this happens, but a function
101 // named __vecDelDtor sometimes shows up on top of the destructor.
102 if (Func->isCompilerGenerated() && VTableFuncs[Index])
103 continue;
104 VTableFuncs[Index] = std::move(Func);
105 }
106 }
107 }
108}
109
110UDTLayoutBase::UDTLayoutBase(const PDBSymbol &Symbol, const std::string &Name,
111 uint32_t Size)
112 : Symbol(Symbol), Name(Name), SizeOf(Size) {
113 UsedBytes.resize(Size);
114 ChildrenPerByte.resize(Size);
115 initializeChildren(Symbol);
116}
117
118ClassLayout::ClassLayout(std::unique_ptr<PDBSymbolTypeUDT> UDT)
119 : UDTLayoutBase(*UDT, UDT->getName(), UDT->getLength()),
120 Type(std::move(UDT)) {}
121
122BaseClassLayout::BaseClassLayout(const UDTLayoutBase &Parent,
123 std::unique_ptr<PDBSymbolTypeBaseClass> Base)
124 : UDTLayoutBase(*Base, Base->getName(), Base->getLength()),
125 StorageItemBase(Parent, *Base, Base->getName(), Base->getOffset(),
126 Base->getLength()),
127 Base(std::move(Base)) {
128 IsVirtualBase = this->Base->isVirtualBaseClass();
129}
130
131uint32_t UDTLayoutBase::shallowPaddingSize() const {
132 return UsedBytes.size() - UsedBytes.count();
133}
134
135uint32_t UDTLayoutBase::deepPaddingSize() const {
136 uint32_t Result = shallowPaddingSize();
137 for (auto &Child : ChildStorage)
138 Result += Child->deepPaddingSize();
139 return Result;
140}
141
142void UDTLayoutBase::initializeChildren(const PDBSymbol &Sym) {
143 auto Children = Sym.findAllChildren();
144 while (auto Child = Children->getNext()) {
145 if (auto Data = unique_dyn_cast<PDBSymbolData>(Child)) {
146 if (Data->getDataKind() == PDB_DataKind::Member) {
147 auto DM =
148 llvm::make_unique<DataMemberLayoutItem>(*this, std::move(Data));
149
150 addChildToLayout(std::move(DM));
151 } else {
152 NonStorageItems.push_back(std::move(Data));
153 }
154 continue;
155 }
156
157 if (auto Base = unique_dyn_cast<PDBSymbolTypeBaseClass>(Child)) {
158 auto BL = llvm::make_unique<BaseClassLayout>(*this, std::move(Base));
159 BaseClasses.push_back(BL.get());
160
161 addChildToLayout(std::move(BL));
162 continue;
163 }
164
165 if (auto VT = unique_dyn_cast<PDBSymbolTypeVTable>(Child)) {
166 auto VTLayout = llvm::make_unique<VTableLayoutItem>(*this, std::move(VT));
167
168 VTable = VTLayout.get();
169
170 addChildToLayout(std::move(VTLayout));
171 continue;
172 }
173
174 NonStorageItems.push_back(std::move(Child));
175 }
176}
177
178void UDTLayoutBase::addChildToLayout(std::unique_ptr<StorageItemBase> Child) {
179 uint32_t Begin = Child->getOffsetInParent();
180 uint32_t End = Begin + Child->getSize();
181 UsedBytes.set(Begin, End);
182 while (Begin != End) {
183 ChildrenPerByte[Begin].push_back(Child.get());
184 ++Begin;
185 }
186
187 auto Loc = std::upper_bound(
188 ChildStorage.begin(), ChildStorage.end(), Begin,
189 [](uint32_t Off, const std::unique_ptr<StorageItemBase> &Item) {
190 return Off < Item->getOffsetInParent();
191 });
192
193 ChildStorage.insert(Loc, std::move(Child));
194}