blob: e1ba03f276a5ae03081cb20ab740b5d675cbb9ed [file] [log] [blame]
Zachary Turner307f5ae2018-10-12 19:47:13 +00001//===-- PdbUtil.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 "PdbUtil.h"
11
12#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
Zachary Turnerb96181c2018-10-22 16:19:07 +000013#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
Zachary Turner307f5ae2018-10-12 19:47:13 +000014
15#include "lldb/Utility/LLDBAssert.h"
16
Zachary Turnerb96181c2018-10-22 16:19:07 +000017#include "lldb/lldb-enumerations.h"
18
Zachary Turner307f5ae2018-10-12 19:47:13 +000019using namespace lldb_private;
20using namespace lldb_private::npdb;
21using namespace llvm::codeview;
22using namespace llvm::pdb;
23
Zachary Turner056e4ab2018-11-08 18:50:11 +000024CVTagRecord CVTagRecord::create(CVType type) {
25 assert(IsTagRecord(type) && "type is not a tag record!");
26 switch (type.kind()) {
27 case LF_CLASS:
28 case LF_STRUCTURE:
29 case LF_INTERFACE: {
30 ClassRecord cr;
31 llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(type, cr));
32 return CVTagRecord(std::move(cr));
33 }
34 case LF_UNION: {
35 UnionRecord ur;
36 llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(type, ur));
37 return CVTagRecord(std::move(ur));
38 }
39 case LF_ENUM: {
40 EnumRecord er;
41 llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(type, er));
42 return CVTagRecord(std::move(er));
43 }
44 default:
45 llvm_unreachable("Unreachable!");
46 }
47}
48
49CVTagRecord::CVTagRecord(ClassRecord &&c)
50 : cvclass(std::move(c)),
51 m_kind(cvclass.Kind == TypeRecordKind::Struct ? Struct : Class) {}
52CVTagRecord::CVTagRecord(UnionRecord &&u)
53 : cvunion(std::move(u)), m_kind(Union) {}
54CVTagRecord::CVTagRecord(EnumRecord &&e) : cvenum(std::move(e)), m_kind(Enum) {}
55
Zachary Turnerb96181c2018-10-22 16:19:07 +000056PDB_SymType lldb_private::npdb::CVSymToPDBSym(SymbolKind kind) {
Zachary Turner307f5ae2018-10-12 19:47:13 +000057 switch (kind) {
58 case S_COMPILE3:
59 case S_OBJNAME:
60 return PDB_SymType::CompilandDetails;
61 case S_ENVBLOCK:
62 return PDB_SymType::CompilandEnv;
63 case S_THUNK32:
64 case S_TRAMPOLINE:
65 return PDB_SymType::Thunk;
66 case S_COFFGROUP:
67 return PDB_SymType::CoffGroup;
68 case S_EXPORT:
69 return PDB_SymType::Export;
70 case S_LPROC32:
71 case S_GPROC32:
72 case S_LPROC32_DPC:
73 return PDB_SymType::Function;
74 case S_PUB32:
75 return PDB_SymType::PublicSymbol;
76 case S_INLINESITE:
77 return PDB_SymType::InlineSite;
78 case S_LOCAL:
79 case S_BPREL32:
80 case S_REGREL32:
81 case S_MANCONSTANT:
82 case S_CONSTANT:
83 case S_LDATA32:
84 case S_GDATA32:
85 case S_LMANDATA:
86 case S_GMANDATA:
87 case S_LTHREAD32:
88 case S_GTHREAD32:
89 return PDB_SymType::Data;
90 case S_BLOCK32:
91 return PDB_SymType::Block;
92 case S_LABEL32:
93 return PDB_SymType::Label;
94 case S_CALLSITEINFO:
95 return PDB_SymType::CallSite;
96 case S_HEAPALLOCSITE:
97 return PDB_SymType::HeapAllocationSite;
98 case S_CALLEES:
99 return PDB_SymType::Callee;
100 case S_CALLERS:
101 return PDB_SymType::Caller;
102 default:
103 lldbassert(false && "Invalid symbol record kind!");
104 }
105 return PDB_SymType::None;
106}
107
Zachary Turnerb96181c2018-10-22 16:19:07 +0000108PDB_SymType lldb_private::npdb::CVTypeToPDBType(TypeLeafKind kind) {
109 switch (kind) {
110 case LF_ARRAY:
111 return PDB_SymType::ArrayType;
112 case LF_ARGLIST:
113 return PDB_SymType::FunctionSig;
114 case LF_BCLASS:
115 return PDB_SymType::BaseClass;
116 case LF_BINTERFACE:
117 return PDB_SymType::BaseInterface;
118 case LF_CLASS:
119 case LF_STRUCTURE:
120 case LF_INTERFACE:
121 case LF_UNION:
122 return PDB_SymType::UDT;
123 case LF_POINTER:
124 return PDB_SymType::PointerType;
125 case LF_ENUM:
126 return PDB_SymType::Enum;
Zachary Turner544a66d82018-11-01 16:37:29 +0000127 case LF_PROCEDURE:
128 return PDB_SymType::FunctionSig;
Zachary Turner056e4ab2018-11-08 18:50:11 +0000129 case LF_BITFIELD:
130 return PDB_SymType::BuiltinType;
Zachary Turnerb96181c2018-10-22 16:19:07 +0000131 default:
132 lldbassert(false && "Invalid type record kind!");
133 }
134 return PDB_SymType::None;
135}
136
137bool lldb_private::npdb::SymbolHasAddress(const CVSymbol &sym) {
Zachary Turner307f5ae2018-10-12 19:47:13 +0000138 switch (sym.kind()) {
139 case S_GPROC32:
140 case S_LPROC32:
141 case S_GPROC32_ID:
142 case S_LPROC32_ID:
143 case S_LPROC32_DPC:
144 case S_LPROC32_DPC_ID:
145 case S_THUNK32:
146 case S_TRAMPOLINE:
147 case S_COFFGROUP:
148 case S_BLOCK32:
149 case S_LABEL32:
150 case S_CALLSITEINFO:
151 case S_HEAPALLOCSITE:
152 case S_LDATA32:
153 case S_GDATA32:
154 case S_LMANDATA:
155 case S_GMANDATA:
156 case S_LTHREAD32:
157 case S_GTHREAD32:
158 return true;
159 default:
160 return false;
161 }
162}
163
Zachary Turnerb96181c2018-10-22 16:19:07 +0000164bool lldb_private::npdb::SymbolIsCode(const CVSymbol &sym) {
Zachary Turner307f5ae2018-10-12 19:47:13 +0000165 switch (sym.kind()) {
166 case S_GPROC32:
167 case S_LPROC32:
168 case S_GPROC32_ID:
169 case S_LPROC32_ID:
170 case S_LPROC32_DPC:
171 case S_LPROC32_DPC_ID:
172 case S_THUNK32:
173 case S_TRAMPOLINE:
174 case S_COFFGROUP:
175 case S_BLOCK32:
176 return true;
177 default:
178 return false;
179 }
180}
181
182template <typename RecordT> RecordT createRecord(const CVSymbol &sym) {
183 RecordT record(static_cast<SymbolRecordKind>(sym.kind()));
184 cantFail(SymbolDeserializer::deserializeAs<RecordT>(sym, record));
185 return record;
186}
187
188template <typename RecordT>
189static SegmentOffset GetSegmentAndOffset(const CVSymbol &sym) {
190 RecordT record = createRecord<RecordT>(sym);
191 return {record.Segment, record.CodeOffset};
192}
193
194template <>
195SegmentOffset GetSegmentAndOffset<TrampolineSym>(const CVSymbol &sym) {
196 TrampolineSym record = createRecord<TrampolineSym>(sym);
197 return {record.ThunkSection, record.ThunkOffset};
198}
199
200template <> SegmentOffset GetSegmentAndOffset<Thunk32Sym>(const CVSymbol &sym) {
201 Thunk32Sym record = createRecord<Thunk32Sym>(sym);
202 return {record.Segment, record.Offset};
203}
204
205template <>
206SegmentOffset GetSegmentAndOffset<CoffGroupSym>(const CVSymbol &sym) {
207 CoffGroupSym record = createRecord<CoffGroupSym>(sym);
208 return {record.Segment, record.Offset};
209}
210
211template <> SegmentOffset GetSegmentAndOffset<DataSym>(const CVSymbol &sym) {
212 DataSym record = createRecord<DataSym>(sym);
213 return {record.Segment, record.DataOffset};
214}
215
216template <>
217SegmentOffset GetSegmentAndOffset<ThreadLocalDataSym>(const CVSymbol &sym) {
218 ThreadLocalDataSym record = createRecord<ThreadLocalDataSym>(sym);
219 return {record.Segment, record.DataOffset};
220}
221
Zachary Turnerb96181c2018-10-22 16:19:07 +0000222SegmentOffset lldb_private::npdb::GetSegmentAndOffset(const CVSymbol &sym) {
Zachary Turner307f5ae2018-10-12 19:47:13 +0000223 switch (sym.kind()) {
224 case S_GPROC32:
225 case S_LPROC32:
226 case S_GPROC32_ID:
227 case S_LPROC32_ID:
228 case S_LPROC32_DPC:
229 case S_LPROC32_DPC_ID:
230 return ::GetSegmentAndOffset<ProcSym>(sym);
231 case S_THUNK32:
232 return ::GetSegmentAndOffset<Thunk32Sym>(sym);
233 break;
234 case S_TRAMPOLINE:
235 return ::GetSegmentAndOffset<TrampolineSym>(sym);
236 break;
237 case S_COFFGROUP:
238 return ::GetSegmentAndOffset<CoffGroupSym>(sym);
239 break;
240 case S_BLOCK32:
241 return ::GetSegmentAndOffset<BlockSym>(sym);
242 break;
243 case S_LABEL32:
244 return ::GetSegmentAndOffset<LabelSym>(sym);
245 break;
246 case S_CALLSITEINFO:
247 return ::GetSegmentAndOffset<CallSiteInfoSym>(sym);
248 break;
249 case S_HEAPALLOCSITE:
250 return ::GetSegmentAndOffset<HeapAllocationSiteSym>(sym);
251 break;
252 case S_LDATA32:
253 case S_GDATA32:
254 case S_LMANDATA:
255 case S_GMANDATA:
256 return ::GetSegmentAndOffset<DataSym>(sym);
257 break;
258 case S_LTHREAD32:
259 case S_GTHREAD32:
260 return ::GetSegmentAndOffset<ThreadLocalDataSym>(sym);
261 break;
262 default:
263 lldbassert(false && "Record does not have a segment/offset!");
264 }
265 return {0, 0};
266}
267
268template <typename RecordT>
269SegmentOffsetLength GetSegmentOffsetAndLength(const CVSymbol &sym) {
270 RecordT record = createRecord<RecordT>(sym);
271 return {record.Segment, record.CodeOffset, record.CodeSize};
272}
273
274template <>
275SegmentOffsetLength
276GetSegmentOffsetAndLength<TrampolineSym>(const CVSymbol &sym) {
277 TrampolineSym record = createRecord<TrampolineSym>(sym);
278 return {record.ThunkSection, record.ThunkOffset, record.Size};
279}
280
281template <>
282SegmentOffsetLength GetSegmentOffsetAndLength<Thunk32Sym>(const CVSymbol &sym) {
283 Thunk32Sym record = createRecord<Thunk32Sym>(sym);
284 return SegmentOffsetLength{record.Segment, record.Offset, record.Length};
285}
286
287template <>
288SegmentOffsetLength
289GetSegmentOffsetAndLength<CoffGroupSym>(const CVSymbol &sym) {
290 CoffGroupSym record = createRecord<CoffGroupSym>(sym);
291 return SegmentOffsetLength{record.Segment, record.Offset, record.Size};
292}
293
Zachary Turnerb96181c2018-10-22 16:19:07 +0000294SegmentOffsetLength
295lldb_private::npdb::GetSegmentOffsetAndLength(const CVSymbol &sym) {
Zachary Turner307f5ae2018-10-12 19:47:13 +0000296 switch (sym.kind()) {
297 case S_GPROC32:
298 case S_LPROC32:
299 case S_GPROC32_ID:
300 case S_LPROC32_ID:
301 case S_LPROC32_DPC:
302 case S_LPROC32_DPC_ID:
303 return ::GetSegmentOffsetAndLength<ProcSym>(sym);
304 case S_THUNK32:
305 return ::GetSegmentOffsetAndLength<Thunk32Sym>(sym);
306 break;
307 case S_TRAMPOLINE:
308 return ::GetSegmentOffsetAndLength<TrampolineSym>(sym);
309 break;
310 case S_COFFGROUP:
311 return ::GetSegmentOffsetAndLength<CoffGroupSym>(sym);
312 break;
313 case S_BLOCK32:
314 return ::GetSegmentOffsetAndLength<BlockSym>(sym);
315 break;
316 default:
317 lldbassert(false && "Record does not have a segment/offset/length triple!");
318 }
319 return {0, 0, 0};
320}
Zachary Turnerb96181c2018-10-22 16:19:07 +0000321
322bool lldb_private::npdb::IsForwardRefUdt(CVType cvt) {
323 ClassRecord cr;
324 UnionRecord ur;
325 EnumRecord er;
326 switch (cvt.kind()) {
327 case LF_CLASS:
328 case LF_STRUCTURE:
329 case LF_INTERFACE:
330 llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));
331 return cr.isForwardRef();
332 case LF_UNION:
333 llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));
334 return ur.isForwardRef();
335 case LF_ENUM:
336 llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
337 return er.isForwardRef();
338 default:
339 return false;
340 }
341}
342
Zachary Turner056e4ab2018-11-08 18:50:11 +0000343bool lldb_private::npdb::IsTagRecord(llvm::codeview::CVType cvt) {
344 switch (cvt.kind()) {
345 case LF_CLASS:
346 case LF_STRUCTURE:
347 case LF_UNION:
348 case LF_ENUM:
349 return true;
350 default:
351 return false;
352 }
353}
354
Zachary Turnerb96181c2018-10-22 16:19:07 +0000355lldb::AccessType
356lldb_private::npdb::TranslateMemberAccess(MemberAccess access) {
357 switch (access) {
358 case MemberAccess::Private:
359 return lldb::eAccessPrivate;
360 case MemberAccess::Protected:
361 return lldb::eAccessProtected;
362 case MemberAccess::Public:
363 return lldb::eAccessPublic;
364 case MemberAccess::None:
365 return lldb::eAccessNone;
366 }
367 llvm_unreachable("unreachable");
368}
369
370TypeIndex lldb_private::npdb::GetFieldListIndex(CVType cvt) {
371 switch (cvt.kind()) {
372 case LF_CLASS:
373 case LF_STRUCTURE:
374 case LF_INTERFACE: {
375 ClassRecord cr;
376 cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));
377 return cr.FieldList;
378 }
379 case LF_UNION: {
380 UnionRecord ur;
381 cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));
382 return ur.FieldList;
383 }
384 case LF_ENUM: {
385 EnumRecord er;
386 cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
387 return er.FieldList;
388 }
389 default:
390 llvm_unreachable("Unreachable!");
391 }
392}
393
Zachary Turner511bff22018-10-30 18:57:08 +0000394TypeIndex lldb_private::npdb::LookThroughModifierRecord(CVType modifier) {
395 lldbassert(modifier.kind() == LF_MODIFIER);
396 ModifierRecord mr;
397 llvm::cantFail(TypeDeserializer::deserializeAs<ModifierRecord>(modifier, mr));
398 return mr.ModifiedType;
399}
400
Zachary Turnerb96181c2018-10-22 16:19:07 +0000401llvm::StringRef lldb_private::npdb::DropNameScope(llvm::StringRef name) {
402 // Not all PDB names can be parsed with CPlusPlusNameParser.
403 // E.g. it fails on names containing `anonymous namespace'.
404 // So we simply drop everything before '::'
405
406 auto offset = name.rfind("::");
407 if (offset == llvm::StringRef::npos)
408 return name;
409 assert(offset + 2 <= name.size());
410
411 return name.substr(offset + 2);
Zachary Turner544a66d82018-11-01 16:37:29 +0000412}