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 m_cvr
.er
.Options
= ClassOptions::None
;
51 llvm::cantFail(TypeDeserializer::deserializeAs
<EnumRecord
>(cvt
, m_cvr
.er
));
54 m_cvr
.ur
.Options
= ClassOptions::None
;
55 llvm::cantFail(TypeDeserializer::deserializeAs
<UnionRecord
>(cvt
, m_cvr
.ur
));
56 m_layout
.bit_size
= m_cvr
.ur
.getSize() * 8;
57 m_record
.record
.kind
= Member::Union
;
61 m_cvr
.cr
.Options
= ClassOptions::None
;
62 llvm::cantFail(TypeDeserializer::deserializeAs
<ClassRecord
>(cvt
, m_cvr
.cr
));
63 m_layout
.bit_size
= m_cvr
.cr
.getSize() * 8;
64 m_record
.record
.kind
= Member::Struct
;
67 llvm_unreachable("unreachable!");
71 clang::QualType
UdtRecordCompleter::AddBaseClassForTypeIndex(
72 llvm::codeview::TypeIndex ti
, llvm::codeview::MemberAccess access
,
73 std::optional
<uint64_t> vtable_idx
) {
74 PdbTypeSymId
type_id(ti
);
75 clang::QualType qt
= m_ast_builder
.GetOrCreateType(type_id
);
77 CVType udt_cvt
= m_index
.tpi().getType(ti
);
79 std::unique_ptr
<clang::CXXBaseSpecifier
> base_spec
=
80 m_ast_builder
.clang().CreateBaseClassSpecifier(
81 qt
.getAsOpaquePtr(), TranslateMemberAccess(access
),
82 vtable_idx
.has_value(), udt_cvt
.kind() == LF_CLASS
);
87 std::make_pair(vtable_idx
.value_or(0), std::move(base_spec
)));
92 void UdtRecordCompleter::AddMethod(llvm::StringRef name
, TypeIndex type_idx
,
93 MemberAccess access
, MethodOptions options
,
94 MemberAttributes attrs
) {
95 clang::QualType method_qt
=
96 m_ast_builder
.GetOrCreateType(PdbTypeSymId(type_idx
));
97 if (method_qt
.isNull())
99 CompilerType method_ct
= m_ast_builder
.ToCompilerType(method_qt
);
100 TypeSystemClang::RequireCompleteType(method_ct
);
101 lldb::opaque_compiler_type_t derived_opaque_ty
=
102 m_derived_ct
.GetOpaqueQualType();
103 auto iter
= m_cxx_record_map
.find(derived_opaque_ty
);
104 if (iter
!= m_cxx_record_map
.end()) {
105 if (iter
->getSecond().contains({name
, method_ct
})) {
110 lldb::AccessType access_type
= TranslateMemberAccess(access
);
111 bool is_artificial
= (options
& MethodOptions::CompilerGenerated
) ==
112 MethodOptions::CompilerGenerated
;
113 m_ast_builder
.clang().AddMethodToCXXRecordType(
114 derived_opaque_ty
, name
.data(), nullptr, method_ct
,
115 access_type
, attrs
.isVirtual(), attrs
.isStatic(), false, false, false,
118 m_cxx_record_map
[derived_opaque_ty
].insert({name
, method_ct
});
121 Error
UdtRecordCompleter::visitKnownMember(CVMemberRecord
&cvr
,
122 BaseClassRecord
&base
) {
123 clang::QualType base_qt
=
124 AddBaseClassForTypeIndex(base
.Type
, base
.getAccess());
126 if (base_qt
.isNull())
127 return llvm::Error::success();
129 m_ast_builder
.clang().GetAsCXXRecordDecl(base_qt
.getAsOpaquePtr());
132 auto offset
= clang::CharUnits::fromQuantity(base
.getBaseOffset());
133 m_layout
.base_offsets
.insert(std::make_pair(decl
, offset
));
135 return llvm::Error::success();
138 Error
UdtRecordCompleter::visitKnownMember(CVMemberRecord
&cvr
,
139 VirtualBaseClassRecord
&base
) {
140 AddBaseClassForTypeIndex(base
.BaseType
, base
.getAccess(), base
.VTableIndex
);
142 return Error::success();
145 Error
UdtRecordCompleter::visitKnownMember(CVMemberRecord
&cvr
,
146 ListContinuationRecord
&cont
) {
147 return Error::success();
150 Error
UdtRecordCompleter::visitKnownMember(CVMemberRecord
&cvr
,
151 VFPtrRecord
&vfptr
) {
152 return Error::success();
155 Error
UdtRecordCompleter::visitKnownMember(
156 CVMemberRecord
&cvr
, StaticDataMemberRecord
&static_data_member
) {
157 clang::QualType member_type
=
158 m_ast_builder
.GetOrCreateType(PdbTypeSymId(static_data_member
.Type
));
159 if (member_type
.isNull())
160 return llvm::Error::success();
162 CompilerType member_ct
= m_ast_builder
.ToCompilerType(member_type
);
164 lldb::AccessType access
=
165 TranslateMemberAccess(static_data_member
.getAccess());
166 auto decl
= TypeSystemClang::AddVariableToRecordType(
167 m_derived_ct
, static_data_member
.Name
, member_ct
, access
);
169 // Static constant members may be a const[expr] declaration.
170 // Query the symbol's value as the variable initializer if valid.
171 if (member_ct
.IsConst() && member_ct
.IsCompleteType()) {
172 std::string qual_name
= decl
->getQualifiedNameAsString();
175 m_index
.globals().findRecordsByName(qual_name
, m_index
.symrecords());
177 for (const auto &result
: results
) {
178 if (result
.second
.kind() == SymbolKind::S_CONSTANT
) {
179 ConstantSym
constant(SymbolRecordKind::ConstantSym
);
180 cantFail(SymbolDeserializer::deserializeAs
<ConstantSym
>(result
.second
,
183 clang::QualType qual_type
= decl
->getType();
184 unsigned type_width
= decl
->getASTContext().getIntWidth(qual_type
);
185 unsigned constant_width
= constant
.Value
.getBitWidth();
187 if (qual_type
->isIntegralOrEnumerationType()) {
188 if (type_width
>= constant_width
) {
189 TypeSystemClang::SetIntegerInitializerForVariable(
190 decl
, constant
.Value
.extOrTrunc(type_width
));
192 LLDB_LOG(GetLog(LLDBLog::AST
),
193 "Class '{0}' has a member '{1}' of type '{2}' ({3} bits) "
194 "which resolves to a wider constant value ({4} bits). "
195 "Ignoring constant.",
196 m_derived_ct
.GetTypeName(), static_data_member
.Name
,
197 member_ct
.GetTypeName(), type_width
, constant_width
);
200 lldb::BasicType basic_type_enum
= member_ct
.GetBasicTypeEnumeration();
201 switch (basic_type_enum
) {
202 case lldb::eBasicTypeFloat
:
203 case lldb::eBasicTypeDouble
:
204 case lldb::eBasicTypeLongDouble
:
205 if (type_width
== constant_width
) {
206 TypeSystemClang::SetFloatingInitializerForVariable(
207 decl
, basic_type_enum
== lldb::eBasicTypeFloat
208 ? llvm::APFloat(constant
.Value
.bitsToFloat())
209 : llvm::APFloat(constant
.Value
.bitsToDouble()));
210 decl
->setConstexpr(true);
213 GetLog(LLDBLog::AST
),
214 "Class '{0}' has a member '{1}' of type '{2}' ({3} bits) "
215 "which resolves to a constant value of mismatched width "
216 "({4} bits). Ignoring constant.",
217 m_derived_ct
.GetTypeName(), static_data_member
.Name
,
218 member_ct
.GetTypeName(), type_width
, constant_width
);
230 // FIXME: Add a PdbSymUid namespace for field list members and update
231 // the m_uid_to_decl map with this decl.
232 return Error::success();
235 Error
UdtRecordCompleter::visitKnownMember(CVMemberRecord
&cvr
,
236 NestedTypeRecord
&nested
) {
237 return Error::success();
240 Error
UdtRecordCompleter::visitKnownMember(CVMemberRecord
&cvr
,
241 DataMemberRecord
&data_member
) {
243 uint64_t offset
= data_member
.FieldOffset
* 8;
244 uint32_t bitfield_width
= 0;
246 TypeIndex
ti(data_member
.Type
);
247 if (!ti
.isSimple()) {
248 CVType cvt
= m_index
.tpi().getType(ti
);
249 if (cvt
.kind() == LF_BITFIELD
) {
251 llvm::cantFail(TypeDeserializer::deserializeAs
<BitFieldRecord
>(cvt
, bfr
));
252 offset
+= bfr
.BitOffset
;
253 bitfield_width
= bfr
.BitSize
;
258 clang::QualType member_qt
= m_ast_builder
.GetOrCreateType(PdbTypeSymId(ti
));
259 if (member_qt
.isNull())
260 return Error::success();
261 TypeSystemClang::RequireCompleteType(m_ast_builder
.ToCompilerType(member_qt
));
262 lldb::AccessType access
= TranslateMemberAccess(data_member
.getAccess());
264 bitfield_width
? bitfield_width
: GetSizeOfType(ti
, m_index
.tpi()) * 8;
266 return Error::success();
267 m_record
.CollectMember(data_member
.Name
, offset
, field_size
, member_qt
, access
,
269 return Error::success();
272 Error
UdtRecordCompleter::visitKnownMember(CVMemberRecord
&cvr
,
273 OneMethodRecord
&one_method
) {
274 AddMethod(one_method
.Name
, one_method
.Type
, one_method
.getAccess(),
275 one_method
.getOptions(), one_method
.Attrs
);
277 return Error::success();
280 Error
UdtRecordCompleter::visitKnownMember(CVMemberRecord
&cvr
,
281 OverloadedMethodRecord
&overloaded
) {
282 TypeIndex method_list_idx
= overloaded
.MethodList
;
284 CVType method_list_type
= m_index
.tpi().getType(method_list_idx
);
285 assert(method_list_type
.kind() == LF_METHODLIST
);
287 MethodOverloadListRecord method_list
;
288 llvm::cantFail(TypeDeserializer::deserializeAs
<MethodOverloadListRecord
>(
289 method_list_type
, method_list
));
291 for (const OneMethodRecord
&method
: method_list
.Methods
)
292 AddMethod(overloaded
.Name
, method
.Type
, method
.getAccess(),
293 method
.getOptions(), method
.Attrs
);
295 return Error::success();
298 Error
UdtRecordCompleter::visitKnownMember(CVMemberRecord
&cvr
,
299 EnumeratorRecord
&enumerator
) {
301 llvm::StringRef name
= DropNameScope(enumerator
.getName());
303 m_ast_builder
.clang().AddEnumerationValueToEnumerationType(
304 m_derived_ct
, decl
, name
.str().c_str(), enumerator
.Value
);
305 return Error::success();
308 void UdtRecordCompleter::complete() {
309 // Ensure the correct order for virtual bases.
310 llvm::stable_sort(m_bases
, llvm::less_first());
312 std::vector
<std::unique_ptr
<clang::CXXBaseSpecifier
>> bases
;
313 bases
.reserve(m_bases
.size());
314 for (auto &ib
: m_bases
)
315 bases
.push_back(std::move(ib
.second
));
317 TypeSystemClang
&clang
= m_ast_builder
.clang();
318 // Make sure all base classes refer to complete types and not forward
319 // declarations. If we don't do this, clang will crash with an
320 // assertion in the call to clang_type.TransferBaseClasses()
321 for (const auto &base_class
: bases
) {
322 clang::TypeSourceInfo
*type_source_info
=
323 base_class
->getTypeSourceInfo();
324 if (type_source_info
) {
325 TypeSystemClang::RequireCompleteType(
326 clang
.GetType(type_source_info
->getType()));
330 clang
.TransferBaseClasses(m_derived_ct
.GetOpaqueQualType(), std::move(bases
));
332 clang
.AddMethodOverridesForCXXRecordType(m_derived_ct
.GetOpaqueQualType());
334 TypeSystemClang::BuildIndirectFields(m_derived_ct
);
335 TypeSystemClang::CompleteTagDeclarationDefinition(m_derived_ct
);
337 if (auto *record_decl
= llvm::dyn_cast
<clang::CXXRecordDecl
>(&m_tag_decl
)) {
338 m_ast_builder
.GetClangASTImporter().SetRecordLayout(record_decl
, m_layout
);
343 UdtRecordCompleter::AddMember(TypeSystemClang
&clang
, Member
*field
,
344 uint64_t bit_offset
, CompilerType parent_ct
,
345 ClangASTImporter::LayoutInfo
&parent_layout
,
346 clang::DeclContext
*parent_decl_ctx
) {
347 SymbolFileNativePDB
*pdb
= static_cast<SymbolFileNativePDB
*>(
348 clang
.GetSymbolFile()->GetBackingSymbolFile());
349 clang::FieldDecl
*field_decl
= nullptr;
350 uint64_t bit_size
= 0;
351 switch (field
->kind
) {
352 case Member::Field
: {
353 field_decl
= TypeSystemClang::AddFieldToRecordType(
354 parent_ct
, field
->name
, m_ast_builder
.ToCompilerType(field
->qt
),
355 field
->access
, field
->bitfield_width
);
356 bit_size
= field
->bit_size
;
360 case Member::Union
: {
361 clang::TagTypeKind kind
= field
->kind
== Member::Struct
362 ? clang::TagTypeKind::Struct
363 : clang::TagTypeKind::Union
;
364 ClangASTMetadata metadata
;
365 metadata
.SetUserID(pdb
->anonymous_id
);
366 metadata
.SetIsDynamicCXXType(false);
367 CompilerType record_ct
= clang
.CreateRecordType(
368 parent_decl_ctx
, OptionalClangModuleID(), lldb::eAccessPublic
, "",
369 llvm::to_underlying(kind
), lldb::eLanguageTypeC_plus_plus
, metadata
);
370 TypeSystemClang::StartTagDeclarationDefinition(record_ct
);
371 ClangASTImporter::LayoutInfo layout
;
372 clang::DeclContext
*decl_ctx
= clang
.GetDeclContextForType(record_ct
);
373 for (const auto &member
: field
->fields
) {
374 uint64_t member_offset
= field
->kind
== Member::Struct
375 ? member
->bit_offset
- field
->base_offset
377 uint64_t member_bit_size
= AddMember(clang
, member
.get(), member_offset
,
378 record_ct
, layout
, decl_ctx
);
379 if (field
->kind
== Member::Struct
)
380 bit_size
= std::max(bit_size
, member_offset
+ member_bit_size
);
382 bit_size
= std::max(bit_size
, member_bit_size
);
384 layout
.bit_size
= bit_size
;
385 TypeSystemClang::CompleteTagDeclarationDefinition(record_ct
);
386 clang::RecordDecl
*record_decl
= clang
.GetAsRecordDecl(record_ct
);
387 m_ast_builder
.GetClangASTImporter().SetRecordLayout(record_decl
, layout
);
388 field_decl
= TypeSystemClang::AddFieldToRecordType(
389 parent_ct
, "", record_ct
, lldb::eAccessPublic
, 0);
390 // Mark this record decl as completed.
392 status
.resolved
= true;
393 status
.uid
= pdb
->anonymous_id
--;
394 m_decl_to_status
.insert({record_decl
, status
});
398 // FIXME: Add a PdbSymUid namespace for field list members and update
399 // the m_uid_to_decl map with this decl.
400 parent_layout
.field_offsets
.insert({field_decl
, bit_offset
});
404 void UdtRecordCompleter::FinishRecord() {
405 TypeSystemClang
&clang
= m_ast_builder
.clang();
406 clang::DeclContext
*decl_ctx
=
407 m_ast_builder
.GetOrCreateDeclContextForUid(m_id
);
408 m_record
.ConstructRecord();
409 // Maybe we should check the construsted record size with the size in pdb. If
410 // they mismatch, it might be pdb has fields info missing.
411 for (const auto &field
: m_record
.record
.fields
) {
412 AddMember(clang
, field
.get(), field
->bit_offset
, m_derived_ct
, m_layout
,
417 void UdtRecordCompleter::Record::CollectMember(
418 llvm::StringRef name
, uint64_t offset
, uint64_t field_size
,
419 clang::QualType qt
, lldb::AccessType access
, uint64_t bitfield_width
) {
420 fields_map
[offset
].push_back(std::make_unique
<Member
>(
421 name
, offset
, field_size
, qt
, access
, bitfield_width
));
422 if (start_offset
> offset
)
423 start_offset
= offset
;
426 void UdtRecordCompleter::Record::ConstructRecord() {
427 // For anonymous unions in a struct, msvc generated pdb doesn't have the
428 // entity for that union. So, we need to construct anonymous union and struct
429 // based on field offsets. The final AST is likely not matching the exact
430 // original AST, but the memory layout is preseved.
431 // After we collecting all fields in visitKnownMember, we have all fields in
432 // increasing offset order in m_fields. Since we are iterating in increase
433 // offset order, if the current offset is equal to m_start_offset, we insert
434 // it as direct field of top level record. If the current offset is greater
435 // than m_start_offset, we should be able to find a field in end_offset_map
436 // whose end offset is less than or equal to current offset. (if not, it might
437 // be missing field info. We will ignore the field in this case. e.g. Field A
438 // starts at 0 with size 4 bytes, and Field B starts at 2 with size 4 bytes.
439 // Normally, there must be something which ends at/before 2.) Then we will
440 // append current field to the end of parent record. If parent is struct, we
441 // can just grow it. If parent is a field, it's a field inside an union. We
442 // convert it into an anonymous struct containing old field and new field.
444 // The end offset to a vector of field/struct that ends at the offset.
445 std::map
<uint64_t, std::vector
<Member
*>> end_offset_map
;
446 for (auto &pair
: fields_map
) {
447 uint64_t offset
= pair
.first
;
448 auto &fields
= pair
.second
;
449 lldbassert(offset
>= start_offset
);
450 Member
*parent
= &record
;
451 if (offset
> start_offset
) {
452 // Find the field with largest end offset that is <= offset. If it's less
453 // than offset, it indicates there are padding bytes between end offset
455 lldbassert(!end_offset_map
.empty());
456 auto iter
= end_offset_map
.lower_bound(offset
);
457 if (iter
== end_offset_map
.end())
459 else if (iter
->first
> offset
) {
460 if (iter
== end_offset_map
.begin())
464 if (iter
->second
.empty())
466 parent
= iter
->second
.back();
467 iter
->second
.pop_back();
469 // If it's a field, then the field is inside a union, so we can safely
470 // increase its size by converting it to a struct to hold multiple fields.
471 if (parent
->kind
== Member::Field
)
472 parent
->ConvertToStruct();
474 if (fields
.size() == 1) {
475 uint64_t end_offset
= offset
+ fields
.back()->bit_size
;
476 parent
->fields
.push_back(std::move(fields
.back()));
477 if (parent
->kind
== Member::Struct
) {
478 end_offset_map
[end_offset
].push_back(parent
);
480 lldbassert(parent
== &record
&&
481 "If parent is union, it must be the top level record.");
482 end_offset_map
[end_offset
].push_back(parent
->fields
.back().get());
485 if (parent
->kind
== Member::Struct
) {
486 parent
->fields
.push_back(std::make_unique
<Member
>(Member::Union
));
487 parent
= parent
->fields
.back().get();
488 parent
->bit_offset
= offset
;
490 lldbassert(parent
== &record
&&
491 "If parent is union, it must be the top level record.");
493 for (auto &field
: fields
) {
494 int64_t bit_size
= field
->bit_size
;
495 parent
->fields
.push_back(std::move(field
));
496 end_offset_map
[offset
+ bit_size
].push_back(
497 parent
->fields
.back().get());