1 #include "UdtRecordCompleter.h"
3 #include "PdbAstBuilder.h"
8 #include "Plugins/ExpressionParser/Clang/ClangASTImporter.h"
9 #include "Plugins/ExpressionParser/Clang/ClangASTMetadata.h"
10 #include "Plugins/ExpressionParser/Clang/ClangUtil.h"
11 #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
12 #include "SymbolFileNativePDB.h"
13 #include "lldb/Core/Address.h"
14 #include "lldb/Symbol/Type.h"
15 #include "lldb/Utility/LLDBAssert.h"
16 #include "lldb/Utility/LLDBLog.h"
17 #include "lldb/lldb-enumerations.h"
18 #include "lldb/lldb-forward.h"
20 #include "llvm/ADT/STLExtras.h"
21 #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
22 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
23 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
24 #include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
25 #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
26 #include "llvm/DebugInfo/PDB/PDBTypes.h"
29 using namespace llvm::codeview
;
30 using namespace llvm::pdb
;
32 using namespace lldb_private
;
33 using namespace lldb_private::npdb
;
35 using Error
= llvm::Error
;
37 UdtRecordCompleter::UdtRecordCompleter(
38 PdbTypeSymId id
, CompilerType
&derived_ct
, clang::TagDecl
&tag_decl
,
39 PdbAstBuilder
&ast_builder
, PdbIndex
&index
,
40 llvm::DenseMap
<clang::Decl
*, DeclStatus
> &decl_to_status
,
41 llvm::DenseMap
<lldb::opaque_compiler_type_t
,
42 llvm::SmallSet
<std::pair
<llvm::StringRef
, CompilerType
>, 8>>
44 : m_id(id
), m_derived_ct(derived_ct
), m_tag_decl(tag_decl
),
45 m_ast_builder(ast_builder
), m_index(index
),
46 m_decl_to_status(decl_to_status
), m_cxx_record_map(cxx_record_map
) {
47 CVType cvt
= m_index
.tpi().getType(m_id
.index
);
50 llvm::cantFail(TypeDeserializer::deserializeAs
<EnumRecord
>(cvt
, m_cvr
.er
));
53 llvm::cantFail(TypeDeserializer::deserializeAs
<UnionRecord
>(cvt
, m_cvr
.ur
));
54 m_layout
.bit_size
= m_cvr
.ur
.getSize() * 8;
55 m_record
.record
.kind
= Member::Union
;
59 llvm::cantFail(TypeDeserializer::deserializeAs
<ClassRecord
>(cvt
, m_cvr
.cr
));
60 m_layout
.bit_size
= m_cvr
.cr
.getSize() * 8;
61 m_record
.record
.kind
= Member::Struct
;
64 llvm_unreachable("unreachable!");
68 clang::QualType
UdtRecordCompleter::AddBaseClassForTypeIndex(
69 llvm::codeview::TypeIndex ti
, llvm::codeview::MemberAccess access
,
70 std::optional
<uint64_t> vtable_idx
) {
71 PdbTypeSymId
type_id(ti
);
72 clang::QualType qt
= m_ast_builder
.GetOrCreateType(type_id
);
74 CVType udt_cvt
= m_index
.tpi().getType(ti
);
76 std::unique_ptr
<clang::CXXBaseSpecifier
> base_spec
=
77 m_ast_builder
.clang().CreateBaseClassSpecifier(
78 qt
.getAsOpaquePtr(), TranslateMemberAccess(access
),
79 vtable_idx
.has_value(), udt_cvt
.kind() == LF_CLASS
);
84 std::make_pair(vtable_idx
.value_or(0), std::move(base_spec
)));
89 void UdtRecordCompleter::AddMethod(llvm::StringRef name
, TypeIndex type_idx
,
90 MemberAccess access
, MethodOptions options
,
91 MemberAttributes attrs
) {
92 clang::QualType method_qt
=
93 m_ast_builder
.GetOrCreateType(PdbTypeSymId(type_idx
));
94 if (method_qt
.isNull())
96 CompilerType method_ct
= m_ast_builder
.ToCompilerType(method_qt
);
97 TypeSystemClang::RequireCompleteType(method_ct
);
98 lldb::opaque_compiler_type_t derived_opaque_ty
=
99 m_derived_ct
.GetOpaqueQualType();
100 auto iter
= m_cxx_record_map
.find(derived_opaque_ty
);
101 if (iter
!= m_cxx_record_map
.end()) {
102 if (iter
->getSecond().contains({name
, method_ct
})) {
107 lldb::AccessType access_type
= TranslateMemberAccess(access
);
108 bool is_artificial
= (options
& MethodOptions::CompilerGenerated
) ==
109 MethodOptions::CompilerGenerated
;
110 m_ast_builder
.clang().AddMethodToCXXRecordType(
111 derived_opaque_ty
, name
.data(), nullptr, method_ct
,
112 access_type
, attrs
.isVirtual(), attrs
.isStatic(), false, false, false,
115 m_cxx_record_map
[derived_opaque_ty
].insert({name
, method_ct
});
118 Error
UdtRecordCompleter::visitKnownMember(CVMemberRecord
&cvr
,
119 BaseClassRecord
&base
) {
120 clang::QualType base_qt
=
121 AddBaseClassForTypeIndex(base
.Type
, base
.getAccess());
123 if (base_qt
.isNull())
124 return llvm::Error::success();
126 m_ast_builder
.clang().GetAsCXXRecordDecl(base_qt
.getAsOpaquePtr());
129 auto offset
= clang::CharUnits::fromQuantity(base
.getBaseOffset());
130 m_layout
.base_offsets
.insert(std::make_pair(decl
, offset
));
132 return llvm::Error::success();
135 Error
UdtRecordCompleter::visitKnownMember(CVMemberRecord
&cvr
,
136 VirtualBaseClassRecord
&base
) {
137 AddBaseClassForTypeIndex(base
.BaseType
, base
.getAccess(), base
.VTableIndex
);
139 return Error::success();
142 Error
UdtRecordCompleter::visitKnownMember(CVMemberRecord
&cvr
,
143 ListContinuationRecord
&cont
) {
144 return Error::success();
147 Error
UdtRecordCompleter::visitKnownMember(CVMemberRecord
&cvr
,
148 VFPtrRecord
&vfptr
) {
149 return Error::success();
152 Error
UdtRecordCompleter::visitKnownMember(
153 CVMemberRecord
&cvr
, StaticDataMemberRecord
&static_data_member
) {
154 clang::QualType member_type
=
155 m_ast_builder
.GetOrCreateType(PdbTypeSymId(static_data_member
.Type
));
156 if (member_type
.isNull())
157 return llvm::Error::success();
159 CompilerType member_ct
= m_ast_builder
.ToCompilerType(member_type
);
161 lldb::AccessType access
=
162 TranslateMemberAccess(static_data_member
.getAccess());
163 auto decl
= TypeSystemClang::AddVariableToRecordType(
164 m_derived_ct
, static_data_member
.Name
, member_ct
, access
);
166 // Static constant members may be a const[expr] declaration.
167 // Query the symbol's value as the variable initializer if valid.
168 if (member_ct
.IsConst() && member_ct
.IsCompleteType()) {
169 std::string qual_name
= decl
->getQualifiedNameAsString();
172 m_index
.globals().findRecordsByName(qual_name
, m_index
.symrecords());
174 for (const auto &result
: results
) {
175 if (result
.second
.kind() == SymbolKind::S_CONSTANT
) {
176 ConstantSym
constant(SymbolRecordKind::ConstantSym
);
177 cantFail(SymbolDeserializer::deserializeAs
<ConstantSym
>(result
.second
,
180 clang::QualType qual_type
= decl
->getType();
181 unsigned type_width
= decl
->getASTContext().getIntWidth(qual_type
);
182 unsigned constant_width
= constant
.Value
.getBitWidth();
184 if (qual_type
->isIntegralOrEnumerationType()) {
185 if (type_width
>= constant_width
) {
186 TypeSystemClang::SetIntegerInitializerForVariable(
187 decl
, constant
.Value
.extOrTrunc(type_width
));
189 LLDB_LOG(GetLog(LLDBLog::AST
),
190 "Class '{0}' has a member '{1}' of type '{2}' ({3} bits) "
191 "which resolves to a wider constant value ({4} bits). "
192 "Ignoring constant.",
193 m_derived_ct
.GetTypeName(), static_data_member
.Name
,
194 member_ct
.GetTypeName(), type_width
, constant_width
);
197 lldb::BasicType basic_type_enum
= member_ct
.GetBasicTypeEnumeration();
198 switch (basic_type_enum
) {
199 case lldb::eBasicTypeFloat
:
200 case lldb::eBasicTypeDouble
:
201 case lldb::eBasicTypeLongDouble
:
202 if (type_width
== constant_width
) {
203 TypeSystemClang::SetFloatingInitializerForVariable(
204 decl
, basic_type_enum
== lldb::eBasicTypeFloat
205 ? llvm::APFloat(constant
.Value
.bitsToFloat())
206 : llvm::APFloat(constant
.Value
.bitsToDouble()));
207 decl
->setConstexpr(true);
210 GetLog(LLDBLog::AST
),
211 "Class '{0}' has a member '{1}' of type '{2}' ({3} bits) "
212 "which resolves to a constant value of mismatched width "
213 "({4} bits). Ignoring constant.",
214 m_derived_ct
.GetTypeName(), static_data_member
.Name
,
215 member_ct
.GetTypeName(), type_width
, constant_width
);
227 // FIXME: Add a PdbSymUid namespace for field list members and update
228 // the m_uid_to_decl map with this decl.
229 return Error::success();
232 Error
UdtRecordCompleter::visitKnownMember(CVMemberRecord
&cvr
,
233 NestedTypeRecord
&nested
) {
234 return Error::success();
237 Error
UdtRecordCompleter::visitKnownMember(CVMemberRecord
&cvr
,
238 DataMemberRecord
&data_member
) {
240 uint64_t offset
= data_member
.FieldOffset
* 8;
241 uint32_t bitfield_width
= 0;
243 TypeIndex
ti(data_member
.Type
);
244 if (!ti
.isSimple()) {
245 CVType cvt
= m_index
.tpi().getType(ti
);
246 if (cvt
.kind() == LF_BITFIELD
) {
248 llvm::cantFail(TypeDeserializer::deserializeAs
<BitFieldRecord
>(cvt
, bfr
));
249 offset
+= bfr
.BitOffset
;
250 bitfield_width
= bfr
.BitSize
;
255 clang::QualType member_qt
= m_ast_builder
.GetOrCreateType(PdbTypeSymId(ti
));
256 if (member_qt
.isNull())
257 return Error::success();
258 TypeSystemClang::RequireCompleteType(m_ast_builder
.ToCompilerType(member_qt
));
259 lldb::AccessType access
= TranslateMemberAccess(data_member
.getAccess());
261 bitfield_width
? bitfield_width
: GetSizeOfType(ti
, m_index
.tpi()) * 8;
263 return Error::success();
264 m_record
.CollectMember(data_member
.Name
, offset
, field_size
, member_qt
, access
,
266 return Error::success();
269 Error
UdtRecordCompleter::visitKnownMember(CVMemberRecord
&cvr
,
270 OneMethodRecord
&one_method
) {
271 AddMethod(one_method
.Name
, one_method
.Type
, one_method
.getAccess(),
272 one_method
.getOptions(), one_method
.Attrs
);
274 return Error::success();
277 Error
UdtRecordCompleter::visitKnownMember(CVMemberRecord
&cvr
,
278 OverloadedMethodRecord
&overloaded
) {
279 TypeIndex method_list_idx
= overloaded
.MethodList
;
281 CVType method_list_type
= m_index
.tpi().getType(method_list_idx
);
282 assert(method_list_type
.kind() == LF_METHODLIST
);
284 MethodOverloadListRecord method_list
;
285 llvm::cantFail(TypeDeserializer::deserializeAs
<MethodOverloadListRecord
>(
286 method_list_type
, method_list
));
288 for (const OneMethodRecord
&method
: method_list
.Methods
)
289 AddMethod(overloaded
.Name
, method
.Type
, method
.getAccess(),
290 method
.getOptions(), method
.Attrs
);
292 return Error::success();
295 Error
UdtRecordCompleter::visitKnownMember(CVMemberRecord
&cvr
,
296 EnumeratorRecord
&enumerator
) {
298 llvm::StringRef name
= DropNameScope(enumerator
.getName());
300 m_ast_builder
.clang().AddEnumerationValueToEnumerationType(
301 m_derived_ct
, decl
, name
.str().c_str(), enumerator
.Value
);
302 return Error::success();
305 void UdtRecordCompleter::complete() {
306 // Ensure the correct order for virtual bases.
307 llvm::stable_sort(m_bases
, llvm::less_first());
309 std::vector
<std::unique_ptr
<clang::CXXBaseSpecifier
>> bases
;
310 bases
.reserve(m_bases
.size());
311 for (auto &ib
: m_bases
)
312 bases
.push_back(std::move(ib
.second
));
314 TypeSystemClang
&clang
= m_ast_builder
.clang();
315 // Make sure all base classes refer to complete types and not forward
316 // declarations. If we don't do this, clang will crash with an
317 // assertion in the call to clang_type.TransferBaseClasses()
318 for (const auto &base_class
: bases
) {
319 clang::TypeSourceInfo
*type_source_info
=
320 base_class
->getTypeSourceInfo();
321 if (type_source_info
) {
322 TypeSystemClang::RequireCompleteType(
323 clang
.GetType(type_source_info
->getType()));
327 clang
.TransferBaseClasses(m_derived_ct
.GetOpaqueQualType(), std::move(bases
));
329 clang
.AddMethodOverridesForCXXRecordType(m_derived_ct
.GetOpaqueQualType());
331 TypeSystemClang::BuildIndirectFields(m_derived_ct
);
332 TypeSystemClang::CompleteTagDeclarationDefinition(m_derived_ct
);
334 if (auto *record_decl
= llvm::dyn_cast
<clang::CXXRecordDecl
>(&m_tag_decl
)) {
335 m_ast_builder
.GetClangASTImporter().SetRecordLayout(record_decl
, m_layout
);
340 UdtRecordCompleter::AddMember(TypeSystemClang
&clang
, Member
*field
,
341 uint64_t bit_offset
, CompilerType parent_ct
,
342 ClangASTImporter::LayoutInfo
&parent_layout
,
343 clang::DeclContext
*parent_decl_ctx
) {
344 SymbolFileNativePDB
*pdb
= static_cast<SymbolFileNativePDB
*>(
345 clang
.GetSymbolFile()->GetBackingSymbolFile());
346 clang::FieldDecl
*field_decl
= nullptr;
347 uint64_t bit_size
= 0;
348 switch (field
->kind
) {
349 case Member::Field
: {
350 field_decl
= TypeSystemClang::AddFieldToRecordType(
351 parent_ct
, field
->name
, m_ast_builder
.ToCompilerType(field
->qt
),
352 field
->access
, field
->bitfield_width
);
353 bit_size
= field
->bit_size
;
357 case Member::Union
: {
358 clang::TagTypeKind kind
= field
->kind
== Member::Struct
359 ? clang::TagTypeKind::TTK_Struct
360 : clang::TagTypeKind::TTK_Union
;
361 ClangASTMetadata metadata
;
362 metadata
.SetUserID(pdb
->anonymous_id
);
363 metadata
.SetIsDynamicCXXType(false);
364 CompilerType record_ct
= clang
.CreateRecordType(
365 parent_decl_ctx
, OptionalClangModuleID(), lldb::eAccessPublic
, "", kind
,
366 lldb::eLanguageTypeC_plus_plus
, &metadata
);
367 TypeSystemClang::StartTagDeclarationDefinition(record_ct
);
368 ClangASTImporter::LayoutInfo layout
;
369 clang::DeclContext
*decl_ctx
= clang
.GetDeclContextForType(record_ct
);
370 for (const auto &member
: field
->fields
) {
371 uint64_t member_offset
= field
->kind
== Member::Struct
372 ? member
->bit_offset
- field
->base_offset
374 uint64_t member_bit_size
= AddMember(clang
, member
.get(), member_offset
,
375 record_ct
, layout
, decl_ctx
);
376 if (field
->kind
== Member::Struct
)
377 bit_size
= std::max(bit_size
, member_offset
+ member_bit_size
);
379 bit_size
= std::max(bit_size
, member_bit_size
);
381 layout
.bit_size
= bit_size
;
382 TypeSystemClang::CompleteTagDeclarationDefinition(record_ct
);
383 clang::RecordDecl
*record_decl
= clang
.GetAsRecordDecl(record_ct
);
384 m_ast_builder
.GetClangASTImporter().SetRecordLayout(record_decl
, layout
);
385 field_decl
= TypeSystemClang::AddFieldToRecordType(
386 parent_ct
, "", record_ct
, lldb::eAccessPublic
, 0);
387 // Mark this record decl as completed.
389 status
.resolved
= true;
390 status
.uid
= pdb
->anonymous_id
--;
391 m_decl_to_status
.insert({record_decl
, status
});
395 // FIXME: Add a PdbSymUid namespace for field list members and update
396 // the m_uid_to_decl map with this decl.
397 parent_layout
.field_offsets
.insert({field_decl
, bit_offset
});
401 void UdtRecordCompleter::FinishRecord() {
402 TypeSystemClang
&clang
= m_ast_builder
.clang();
403 clang::DeclContext
*decl_ctx
=
404 m_ast_builder
.GetOrCreateDeclContextForUid(m_id
);
405 m_record
.ConstructRecord();
406 // Maybe we should check the construsted record size with the size in pdb. If
407 // they mismatch, it might be pdb has fields info missing.
408 for (const auto &field
: m_record
.record
.fields
) {
409 AddMember(clang
, field
.get(), field
->bit_offset
, m_derived_ct
, m_layout
,
414 void UdtRecordCompleter::Record::CollectMember(
415 llvm::StringRef name
, uint64_t offset
, uint64_t field_size
,
416 clang::QualType qt
, lldb::AccessType access
, uint64_t bitfield_width
) {
417 fields_map
[offset
].push_back(std::make_unique
<Member
>(
418 name
, offset
, field_size
, qt
, access
, bitfield_width
));
419 if (start_offset
> offset
)
420 start_offset
= offset
;
423 void UdtRecordCompleter::Record::ConstructRecord() {
424 // For anonymous unions in a struct, msvc generated pdb doesn't have the
425 // entity for that union. So, we need to construct anonymous union and struct
426 // based on field offsets. The final AST is likely not matching the exact
427 // original AST, but the memory layout is preseved.
428 // After we collecting all fields in visitKnownMember, we have all fields in
429 // increasing offset order in m_fields. Since we are iterating in increase
430 // offset order, if the current offset is equal to m_start_offset, we insert
431 // it as direct field of top level record. If the current offset is greater
432 // than m_start_offset, we should be able to find a field in end_offset_map
433 // whose end offset is less than or equal to current offset. (if not, it might
434 // be missing field info. We will ignore the field in this case. e.g. Field A
435 // starts at 0 with size 4 bytes, and Field B starts at 2 with size 4 bytes.
436 // Normally, there must be something which ends at/before 2.) Then we will
437 // append current field to the end of parent record. If parent is struct, we
438 // can just grow it. If parent is a field, it's a field inside an union. We
439 // convert it into an anonymous struct containing old field and new field.
441 // The end offset to a vector of field/struct that ends at the offset.
442 std::map
<uint64_t, std::vector
<Member
*>> end_offset_map
;
443 for (auto &pair
: fields_map
) {
444 uint64_t offset
= pair
.first
;
445 auto &fields
= pair
.second
;
446 lldbassert(offset
>= start_offset
);
447 Member
*parent
= &record
;
448 if (offset
> start_offset
) {
449 // Find the field with largest end offset that is <= offset. If it's less
450 // than offset, it indicates there are padding bytes between end offset
452 lldbassert(!end_offset_map
.empty());
453 auto iter
= end_offset_map
.lower_bound(offset
);
454 if (iter
== end_offset_map
.end())
456 else if (iter
->first
> offset
) {
457 if (iter
== end_offset_map
.begin())
461 if (iter
->second
.empty())
463 parent
= iter
->second
.back();
464 iter
->second
.pop_back();
466 // If it's a field, then the field is inside a union, so we can safely
467 // increase its size by converting it to a struct to hold multiple fields.
468 if (parent
->kind
== Member::Field
)
469 parent
->ConvertToStruct();
471 if (fields
.size() == 1) {
472 uint64_t end_offset
= offset
+ fields
.back()->bit_size
;
473 parent
->fields
.push_back(std::move(fields
.back()));
474 if (parent
->kind
== Member::Struct
) {
475 end_offset_map
[end_offset
].push_back(parent
);
477 lldbassert(parent
== &record
&&
478 "If parent is union, it must be the top level record.");
479 end_offset_map
[end_offset
].push_back(parent
->fields
.back().get());
482 if (parent
->kind
== Member::Struct
) {
483 parent
->fields
.push_back(std::make_unique
<Member
>(Member::Union
));
484 parent
= parent
->fields
.back().get();
485 parent
->bit_offset
= offset
;
487 lldbassert(parent
== &record
&&
488 "If parent is union, it must be the top level record.");
490 for (auto &field
: fields
) {
491 int64_t bit_size
= field
->bit_size
;
492 parent
->fields
.push_back(std::move(field
));
493 end_offset_map
[offset
+ bit_size
].push_back(
494 parent
->fields
.back().get());