blob: a76f821a6a32a016717608273e17184f275d34b3 [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 Turnerb96181c2018-10-22 16:19:07 +000024PDB_SymType lldb_private::npdb::CVSymToPDBSym(SymbolKind kind) {
Zachary Turner307f5ae2018-10-12 19:47:13 +000025 switch (kind) {
26 case S_COMPILE3:
27 case S_OBJNAME:
28 return PDB_SymType::CompilandDetails;
29 case S_ENVBLOCK:
30 return PDB_SymType::CompilandEnv;
31 case S_THUNK32:
32 case S_TRAMPOLINE:
33 return PDB_SymType::Thunk;
34 case S_COFFGROUP:
35 return PDB_SymType::CoffGroup;
36 case S_EXPORT:
37 return PDB_SymType::Export;
38 case S_LPROC32:
39 case S_GPROC32:
40 case S_LPROC32_DPC:
41 return PDB_SymType::Function;
42 case S_PUB32:
43 return PDB_SymType::PublicSymbol;
44 case S_INLINESITE:
45 return PDB_SymType::InlineSite;
46 case S_LOCAL:
47 case S_BPREL32:
48 case S_REGREL32:
49 case S_MANCONSTANT:
50 case S_CONSTANT:
51 case S_LDATA32:
52 case S_GDATA32:
53 case S_LMANDATA:
54 case S_GMANDATA:
55 case S_LTHREAD32:
56 case S_GTHREAD32:
57 return PDB_SymType::Data;
58 case S_BLOCK32:
59 return PDB_SymType::Block;
60 case S_LABEL32:
61 return PDB_SymType::Label;
62 case S_CALLSITEINFO:
63 return PDB_SymType::CallSite;
64 case S_HEAPALLOCSITE:
65 return PDB_SymType::HeapAllocationSite;
66 case S_CALLEES:
67 return PDB_SymType::Callee;
68 case S_CALLERS:
69 return PDB_SymType::Caller;
70 default:
71 lldbassert(false && "Invalid symbol record kind!");
72 }
73 return PDB_SymType::None;
74}
75
Zachary Turnerb96181c2018-10-22 16:19:07 +000076PDB_SymType lldb_private::npdb::CVTypeToPDBType(TypeLeafKind kind) {
77 switch (kind) {
78 case LF_ARRAY:
79 return PDB_SymType::ArrayType;
80 case LF_ARGLIST:
81 return PDB_SymType::FunctionSig;
82 case LF_BCLASS:
83 return PDB_SymType::BaseClass;
84 case LF_BINTERFACE:
85 return PDB_SymType::BaseInterface;
86 case LF_CLASS:
87 case LF_STRUCTURE:
88 case LF_INTERFACE:
89 case LF_UNION:
90 return PDB_SymType::UDT;
91 case LF_POINTER:
92 return PDB_SymType::PointerType;
93 case LF_ENUM:
94 return PDB_SymType::Enum;
95 default:
96 lldbassert(false && "Invalid type record kind!");
97 }
98 return PDB_SymType::None;
99}
100
101bool lldb_private::npdb::SymbolHasAddress(const CVSymbol &sym) {
Zachary Turner307f5ae2018-10-12 19:47:13 +0000102 switch (sym.kind()) {
103 case S_GPROC32:
104 case S_LPROC32:
105 case S_GPROC32_ID:
106 case S_LPROC32_ID:
107 case S_LPROC32_DPC:
108 case S_LPROC32_DPC_ID:
109 case S_THUNK32:
110 case S_TRAMPOLINE:
111 case S_COFFGROUP:
112 case S_BLOCK32:
113 case S_LABEL32:
114 case S_CALLSITEINFO:
115 case S_HEAPALLOCSITE:
116 case S_LDATA32:
117 case S_GDATA32:
118 case S_LMANDATA:
119 case S_GMANDATA:
120 case S_LTHREAD32:
121 case S_GTHREAD32:
122 return true;
123 default:
124 return false;
125 }
126}
127
Zachary Turnerb96181c2018-10-22 16:19:07 +0000128bool lldb_private::npdb::SymbolIsCode(const CVSymbol &sym) {
Zachary Turner307f5ae2018-10-12 19:47:13 +0000129 switch (sym.kind()) {
130 case S_GPROC32:
131 case S_LPROC32:
132 case S_GPROC32_ID:
133 case S_LPROC32_ID:
134 case S_LPROC32_DPC:
135 case S_LPROC32_DPC_ID:
136 case S_THUNK32:
137 case S_TRAMPOLINE:
138 case S_COFFGROUP:
139 case S_BLOCK32:
140 return true;
141 default:
142 return false;
143 }
144}
145
146template <typename RecordT> RecordT createRecord(const CVSymbol &sym) {
147 RecordT record(static_cast<SymbolRecordKind>(sym.kind()));
148 cantFail(SymbolDeserializer::deserializeAs<RecordT>(sym, record));
149 return record;
150}
151
152template <typename RecordT>
153static SegmentOffset GetSegmentAndOffset(const CVSymbol &sym) {
154 RecordT record = createRecord<RecordT>(sym);
155 return {record.Segment, record.CodeOffset};
156}
157
158template <>
159SegmentOffset GetSegmentAndOffset<TrampolineSym>(const CVSymbol &sym) {
160 TrampolineSym record = createRecord<TrampolineSym>(sym);
161 return {record.ThunkSection, record.ThunkOffset};
162}
163
164template <> SegmentOffset GetSegmentAndOffset<Thunk32Sym>(const CVSymbol &sym) {
165 Thunk32Sym record = createRecord<Thunk32Sym>(sym);
166 return {record.Segment, record.Offset};
167}
168
169template <>
170SegmentOffset GetSegmentAndOffset<CoffGroupSym>(const CVSymbol &sym) {
171 CoffGroupSym record = createRecord<CoffGroupSym>(sym);
172 return {record.Segment, record.Offset};
173}
174
175template <> SegmentOffset GetSegmentAndOffset<DataSym>(const CVSymbol &sym) {
176 DataSym record = createRecord<DataSym>(sym);
177 return {record.Segment, record.DataOffset};
178}
179
180template <>
181SegmentOffset GetSegmentAndOffset<ThreadLocalDataSym>(const CVSymbol &sym) {
182 ThreadLocalDataSym record = createRecord<ThreadLocalDataSym>(sym);
183 return {record.Segment, record.DataOffset};
184}
185
Zachary Turnerb96181c2018-10-22 16:19:07 +0000186SegmentOffset lldb_private::npdb::GetSegmentAndOffset(const CVSymbol &sym) {
Zachary Turner307f5ae2018-10-12 19:47:13 +0000187 switch (sym.kind()) {
188 case S_GPROC32:
189 case S_LPROC32:
190 case S_GPROC32_ID:
191 case S_LPROC32_ID:
192 case S_LPROC32_DPC:
193 case S_LPROC32_DPC_ID:
194 return ::GetSegmentAndOffset<ProcSym>(sym);
195 case S_THUNK32:
196 return ::GetSegmentAndOffset<Thunk32Sym>(sym);
197 break;
198 case S_TRAMPOLINE:
199 return ::GetSegmentAndOffset<TrampolineSym>(sym);
200 break;
201 case S_COFFGROUP:
202 return ::GetSegmentAndOffset<CoffGroupSym>(sym);
203 break;
204 case S_BLOCK32:
205 return ::GetSegmentAndOffset<BlockSym>(sym);
206 break;
207 case S_LABEL32:
208 return ::GetSegmentAndOffset<LabelSym>(sym);
209 break;
210 case S_CALLSITEINFO:
211 return ::GetSegmentAndOffset<CallSiteInfoSym>(sym);
212 break;
213 case S_HEAPALLOCSITE:
214 return ::GetSegmentAndOffset<HeapAllocationSiteSym>(sym);
215 break;
216 case S_LDATA32:
217 case S_GDATA32:
218 case S_LMANDATA:
219 case S_GMANDATA:
220 return ::GetSegmentAndOffset<DataSym>(sym);
221 break;
222 case S_LTHREAD32:
223 case S_GTHREAD32:
224 return ::GetSegmentAndOffset<ThreadLocalDataSym>(sym);
225 break;
226 default:
227 lldbassert(false && "Record does not have a segment/offset!");
228 }
229 return {0, 0};
230}
231
232template <typename RecordT>
233SegmentOffsetLength GetSegmentOffsetAndLength(const CVSymbol &sym) {
234 RecordT record = createRecord<RecordT>(sym);
235 return {record.Segment, record.CodeOffset, record.CodeSize};
236}
237
238template <>
239SegmentOffsetLength
240GetSegmentOffsetAndLength<TrampolineSym>(const CVSymbol &sym) {
241 TrampolineSym record = createRecord<TrampolineSym>(sym);
242 return {record.ThunkSection, record.ThunkOffset, record.Size};
243}
244
245template <>
246SegmentOffsetLength GetSegmentOffsetAndLength<Thunk32Sym>(const CVSymbol &sym) {
247 Thunk32Sym record = createRecord<Thunk32Sym>(sym);
248 return SegmentOffsetLength{record.Segment, record.Offset, record.Length};
249}
250
251template <>
252SegmentOffsetLength
253GetSegmentOffsetAndLength<CoffGroupSym>(const CVSymbol &sym) {
254 CoffGroupSym record = createRecord<CoffGroupSym>(sym);
255 return SegmentOffsetLength{record.Segment, record.Offset, record.Size};
256}
257
Zachary Turnerb96181c2018-10-22 16:19:07 +0000258SegmentOffsetLength
259lldb_private::npdb::GetSegmentOffsetAndLength(const CVSymbol &sym) {
Zachary Turner307f5ae2018-10-12 19:47:13 +0000260 switch (sym.kind()) {
261 case S_GPROC32:
262 case S_LPROC32:
263 case S_GPROC32_ID:
264 case S_LPROC32_ID:
265 case S_LPROC32_DPC:
266 case S_LPROC32_DPC_ID:
267 return ::GetSegmentOffsetAndLength<ProcSym>(sym);
268 case S_THUNK32:
269 return ::GetSegmentOffsetAndLength<Thunk32Sym>(sym);
270 break;
271 case S_TRAMPOLINE:
272 return ::GetSegmentOffsetAndLength<TrampolineSym>(sym);
273 break;
274 case S_COFFGROUP:
275 return ::GetSegmentOffsetAndLength<CoffGroupSym>(sym);
276 break;
277 case S_BLOCK32:
278 return ::GetSegmentOffsetAndLength<BlockSym>(sym);
279 break;
280 default:
281 lldbassert(false && "Record does not have a segment/offset/length triple!");
282 }
283 return {0, 0, 0};
284}
Zachary Turnerb96181c2018-10-22 16:19:07 +0000285
286bool lldb_private::npdb::IsForwardRefUdt(CVType cvt) {
287 ClassRecord cr;
288 UnionRecord ur;
289 EnumRecord er;
290 switch (cvt.kind()) {
291 case LF_CLASS:
292 case LF_STRUCTURE:
293 case LF_INTERFACE:
294 llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));
295 return cr.isForwardRef();
296 case LF_UNION:
297 llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));
298 return ur.isForwardRef();
299 case LF_ENUM:
300 llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
301 return er.isForwardRef();
302 default:
303 return false;
304 }
305}
306
307lldb::AccessType
308lldb_private::npdb::TranslateMemberAccess(MemberAccess access) {
309 switch (access) {
310 case MemberAccess::Private:
311 return lldb::eAccessPrivate;
312 case MemberAccess::Protected:
313 return lldb::eAccessProtected;
314 case MemberAccess::Public:
315 return lldb::eAccessPublic;
316 case MemberAccess::None:
317 return lldb::eAccessNone;
318 }
319 llvm_unreachable("unreachable");
320}
321
322TypeIndex lldb_private::npdb::GetFieldListIndex(CVType cvt) {
323 switch (cvt.kind()) {
324 case LF_CLASS:
325 case LF_STRUCTURE:
326 case LF_INTERFACE: {
327 ClassRecord cr;
328 cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));
329 return cr.FieldList;
330 }
331 case LF_UNION: {
332 UnionRecord ur;
333 cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));
334 return ur.FieldList;
335 }
336 case LF_ENUM: {
337 EnumRecord er;
338 cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
339 return er.FieldList;
340 }
341 default:
342 llvm_unreachable("Unreachable!");
343 }
344}
345
Zachary Turner511bff22018-10-30 18:57:08 +0000346TypeIndex lldb_private::npdb::LookThroughModifierRecord(CVType modifier) {
347 lldbassert(modifier.kind() == LF_MODIFIER);
348 ModifierRecord mr;
349 llvm::cantFail(TypeDeserializer::deserializeAs<ModifierRecord>(modifier, mr));
350 return mr.ModifiedType;
351}
352
Zachary Turnerb96181c2018-10-22 16:19:07 +0000353llvm::StringRef lldb_private::npdb::DropNameScope(llvm::StringRef name) {
354 // Not all PDB names can be parsed with CPlusPlusNameParser.
355 // E.g. it fails on names containing `anonymous namespace'.
356 // So we simply drop everything before '::'
357
358 auto offset = name.rfind("::");
359 if (offset == llvm::StringRef::npos)
360 return name;
361 assert(offset + 2 <= name.size());
362
363 return name.substr(offset + 2);
364}