1 #include "UdtRecordCompleter.h" 2 3 #include "PdbIndex.h" 4 #include "PdbSymUid.h" 5 #include "PdbUtil.h" 6 #include "SymbolFileNativePDB.h" 7 8 #include "lldb/Symbol/ClangASTContext.h" 9 #include "lldb/Symbol/Type.h" 10 #include "lldb/Utility/LLDBAssert.h" 11 #include "lldb/lldb-enumerations.h" 12 #include "lldb/lldb-forward.h" 13 14 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" 15 #include "llvm/DebugInfo/CodeView/TypeIndex.h" 16 #include "llvm/DebugInfo/PDB/Native/TpiStream.h" 17 #include "llvm/DebugInfo/PDB/PDBTypes.h" 18 19 using namespace llvm::codeview; 20 using namespace llvm::pdb; 21 using namespace lldb; 22 using namespace lldb_private; 23 using namespace lldb_private::npdb; 24 25 using Error = llvm::Error; 26 27 UdtRecordCompleter::UdtRecordCompleter(PdbSymUid uid, CompilerType &derived_ct, 28 clang::TagDecl &tag_decl, 29 SymbolFileNativePDB &symbol_file) 30 : m_uid(uid), m_derived_ct(derived_ct), m_tag_decl(tag_decl), 31 m_symbol_file(symbol_file) { 32 TpiStream &tpi = symbol_file.m_index->tpi(); 33 TypeIndex ti(uid.asTypeSym().index); 34 CVType cvt = tpi.getType(ti); 35 switch (cvt.kind()) { 36 case LF_ENUM: 37 lldbassert(uid.tag() == PDB_SymType::Enum); 38 llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, m_cvr.er)); 39 break; 40 case LF_UNION: 41 lldbassert(uid.tag() == PDB_SymType::UDT); 42 llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, m_cvr.ur)); 43 break; 44 case LF_CLASS: 45 case LF_STRUCTURE: 46 lldbassert(uid.tag() == PDB_SymType::UDT); 47 llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, m_cvr.cr)); 48 break; 49 default: 50 llvm_unreachable("unreachable!"); 51 } 52 } 53 54 lldb::opaque_compiler_type_t UdtRecordCompleter::AddBaseClassForTypeIndex( 55 llvm::codeview::TypeIndex ti, llvm::codeview::MemberAccess access) { 56 TypeSP base_type = m_symbol_file.GetOrCreateType(ti); 57 CompilerType base_ct = base_type->GetFullCompilerType(); 58 59 CVType udt_cvt = m_symbol_file.m_index->tpi().getType(ti); 60 61 lldb::opaque_compiler_type_t base_qt = base_ct.GetOpaqueQualType(); 62 std::unique_ptr<clang::CXXBaseSpecifier> base_spec = 63 m_symbol_file.GetASTContext().CreateBaseClassSpecifier( 64 base_qt, TranslateMemberAccess(access), false, 65 udt_cvt.kind() == LF_CLASS); 66 lldbassert(base_spec); 67 m_bases.push_back(std::move(base_spec)); 68 return base_qt; 69 } 70 71 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, 72 BaseClassRecord &base) { 73 lldb::opaque_compiler_type_t base_qt = 74 AddBaseClassForTypeIndex(base.Type, base.getAccess()); 75 76 auto decl = m_symbol_file.GetASTContext().GetAsCXXRecordDecl(base_qt); 77 lldbassert(decl); 78 79 auto offset = clang::CharUnits::fromQuantity(base.getBaseOffset()); 80 m_layout.base_offsets.insert(std::make_pair(decl, offset)); 81 82 return llvm::Error::success(); 83 } 84 85 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, 86 VirtualBaseClassRecord &base) { 87 AddBaseClassForTypeIndex(base.BaseType, base.getAccess()); 88 89 // FIXME: Handle virtual base offsets. 90 return Error::success(); 91 } 92 93 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, 94 ListContinuationRecord &cont) { 95 return Error::success(); 96 } 97 98 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, 99 VFPtrRecord &vfptr) { 100 return Error::success(); 101 } 102 103 Error UdtRecordCompleter::visitKnownMember( 104 CVMemberRecord &cvr, StaticDataMemberRecord &static_data_member) { 105 TypeSP member_type = m_symbol_file.GetOrCreateType(static_data_member.Type); 106 CompilerType complete_member_type = member_type->GetFullCompilerType(); 107 108 lldb::AccessType access = 109 TranslateMemberAccess(static_data_member.getAccess()); 110 ClangASTContext::AddVariableToRecordType( 111 m_derived_ct, static_data_member.Name, complete_member_type, access); 112 113 // FIXME: Add a PdbSymUid namespace for field list members and update 114 // the m_uid_to_decl map with this decl. 115 return Error::success(); 116 } 117 118 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, 119 NestedTypeRecord &nested) { 120 return Error::success(); 121 } 122 123 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, 124 DataMemberRecord &data_member) { 125 126 uint64_t offset = data_member.FieldOffset * 8; 127 uint32_t bitfield_width = 0; 128 129 TypeSP member_type; 130 TpiStream &tpi = m_symbol_file.m_index->tpi(); 131 TypeIndex ti(data_member.Type); 132 if (!ti.isSimple()) { 133 CVType cvt = tpi.getType(ti); 134 if (cvt.kind() == LF_BITFIELD) { 135 BitFieldRecord bfr; 136 llvm::cantFail(TypeDeserializer::deserializeAs<BitFieldRecord>(cvt, bfr)); 137 offset += bfr.BitOffset; 138 bitfield_width = bfr.BitSize; 139 ti = bfr.Type; 140 } 141 } 142 143 member_type = m_symbol_file.GetOrCreateType(ti); 144 CompilerType complete_member_type = member_type->GetFullCompilerType(); 145 lldb::AccessType access = TranslateMemberAccess(data_member.getAccess()); 146 147 clang::FieldDecl *decl = ClangASTContext::AddFieldToRecordType( 148 m_derived_ct, data_member.Name, complete_member_type, access, 149 bitfield_width); 150 // FIXME: Add a PdbSymUid namespace for field list members and update 151 // the m_uid_to_decl map with this decl. 152 153 m_layout.field_offsets.insert(std::make_pair(decl, offset)); 154 155 return Error::success(); 156 } 157 158 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, 159 OneMethodRecord &one_method) { 160 return Error::success(); 161 } 162 163 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, 164 OverloadedMethodRecord &overloaded) { 165 return Error::success(); 166 } 167 168 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, 169 EnumeratorRecord &enumerator) { 170 ClangASTContext &clang = m_symbol_file.GetASTContext(); 171 172 Declaration decl; 173 llvm::StringRef name = DropNameScope(enumerator.getName()); 174 lldbassert(m_uid.tag() == PDB_SymType::Enum); 175 TypeSP underlying_type = 176 m_symbol_file.GetOrCreateType(m_cvr.er.getUnderlyingType()); 177 178 uint64_t byte_size = underlying_type->GetByteSize(); 179 clang.AddEnumerationValueToEnumerationType( 180 m_derived_ct, decl, name.str().c_str(), enumerator.Value.getSExtValue(), 181 byte_size * 8); 182 return Error::success(); 183 } 184 185 void UdtRecordCompleter::complete() { 186 ClangASTContext &clang = m_symbol_file.GetASTContext(); 187 clang.TransferBaseClasses(m_derived_ct.GetOpaqueQualType(), 188 std::move(m_bases)); 189 190 clang.AddMethodOverridesForCXXRecordType(m_derived_ct.GetOpaqueQualType()); 191 ClangASTContext::BuildIndirectFields(m_derived_ct); 192 ClangASTContext::CompleteTagDeclarationDefinition(m_derived_ct); 193 194 if (auto *record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(&m_tag_decl)) { 195 m_symbol_file.GetASTImporter().InsertRecordDecl(record_decl, m_layout); 196 } 197 } 198