diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2023-02-11 12:38:04 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2023-02-11 12:38:11 +0000 |
| commit | e3b557809604d036af6e00c60f012c2025b59a5e (patch) | |
| tree | 8a11ba2269a3b669601e2fd41145b174008f4da8 /lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp | |
| parent | 08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (diff) | |
Diffstat (limited to 'lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp')
| -rw-r--r-- | lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp | 588 |
1 files changed, 471 insertions, 117 deletions
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp index 7e10e315be20..82d3707acfa4 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -8,12 +8,6 @@ #include "SymbolFileNativePDB.h" -#include "clang/AST/Attr.h" -#include "clang/AST/CharUnits.h" -#include "clang/AST/Decl.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/Type.h" - #include "Plugins/ExpressionParser/Clang/ClangUtil.h" #include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h" #include "Plugins/ObjectFile/PDB/ObjectFilePDB.h" @@ -59,10 +53,10 @@ #include "llvm/Support/MemoryBuffer.h" #include "DWARFLocationExpression.h" -#include "PdbAstBuilder.h" #include "PdbSymUid.h" #include "PdbUtil.h" #include "UdtRecordCompleter.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -120,7 +114,7 @@ loadMatchingPDBFile(std::string exe_path, llvm::BumpPtrAllocator &allocator) { if (!FileSystem::Instance().Exists(pdb_file)) { const auto exe_dir = FileSpec(exe_path).CopyByRemovingLastPathComponent(); const auto pdb_name = FileSpec(pdb_file).GetFilename().GetCString(); - pdb_file = exe_dir.CopyByAppendingPathComponent(pdb_name).GetCString(); + pdb_file = exe_dir.CopyByAppendingPathComponent(pdb_name).GetPathAsConstString().GetStringRef(); } // If the file is not a PDB or if it doesn't have a matching GUID, fail. @@ -233,6 +227,57 @@ static bool IsClassRecord(TypeLeafKind kind) { } } +static std::optional<CVTagRecord> +GetNestedTagDefinition(const NestedTypeRecord &Record, + const CVTagRecord &parent, TpiStream &tpi) { + // An LF_NESTTYPE is essentially a nested typedef / using declaration, but it + // is also used to indicate the primary definition of a nested class. That is + // to say, if you have: + // struct A { + // struct B {}; + // using C = B; + // }; + // Then in the debug info, this will appear as: + // LF_STRUCTURE `A::B` [type index = N] + // LF_STRUCTURE `A` + // LF_NESTTYPE [name = `B`, index = N] + // LF_NESTTYPE [name = `C`, index = N] + // In order to accurately reconstruct the decl context hierarchy, we need to + // know which ones are actual definitions and which ones are just aliases. + + // If it's a simple type, then this is something like `using foo = int`. + if (Record.Type.isSimple()) + return std::nullopt; + + CVType cvt = tpi.getType(Record.Type); + + if (!IsTagRecord(cvt)) + return std::nullopt; + + // If it's an inner definition, then treat whatever name we have here as a + // single component of a mangled name. So we can inject it into the parent's + // mangled name to see if it matches. + CVTagRecord child = CVTagRecord::create(cvt); + std::string qname = std::string(parent.asTag().getUniqueName()); + if (qname.size() < 4 || child.asTag().getUniqueName().size() < 4) + return std::nullopt; + + // qname[3] is the tag type identifier (struct, class, union, etc). Since the + // inner tag type is not necessarily the same as the outer tag type, re-write + // it to match the inner tag type. + qname[3] = child.asTag().getUniqueName()[3]; + std::string piece; + if (qname[3] == 'W') + piece = "4"; + piece += Record.Name; + piece.push_back('@'); + qname.insert(4, std::move(piece)); + if (qname != child.asTag().UniqueName) + return std::nullopt; + + return std::move(child); +} + void SymbolFileNativePDB::Initialize() { PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance, @@ -310,10 +355,9 @@ void SymbolFileNativePDB::InitializeObject() { LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err), "Failed to initialize"); } else { - ts_or_err->SetSymbolFile(this); - auto *clang = llvm::cast_or_null<TypeSystemClang>(&ts_or_err.get()); - lldbassert(clang); - m_ast = std::make_unique<PdbAstBuilder>(*m_objfile_sp, *m_index, *clang); + if (auto ts = *ts_or_err) + ts->SetSymbolFile(this); + BuildParentMap(); } } @@ -338,6 +382,13 @@ Block &SymbolFileNativePDB::CreateBlock(PdbCompilandSymId block_id) { CompUnitSP comp_unit = GetOrCreateCompileUnit(*cii); lldb::user_id_t opaque_block_uid = toOpaqueUid(block_id); BlockSP child_block = std::make_shared<Block>(opaque_block_uid); + auto ts_or_err = GetTypeSystemForLanguage(comp_unit->GetLanguage()); + if (auto err = ts_or_err.takeError()) + return *child_block; + auto ts = *ts_or_err; + if (!ts) + return *child_block; + PdbAstBuilder* ast_builder = ts->GetNativePDBParser(); switch (sym.kind()) { case S_GPROC32: @@ -345,10 +396,13 @@ Block &SymbolFileNativePDB::CreateBlock(PdbCompilandSymId block_id) { // This is a function. It must be global. Creating the Function entry // for it automatically creates a block for it. FunctionSP func = GetOrCreateFunction(block_id, *comp_unit); - Block &block = func->GetBlock(false); - if (block.GetNumRanges() == 0) - block.AddRange(Block::Range(0, func->GetAddressRange().GetByteSize())); - return block; + if (func) { + Block &block = func->GetBlock(false); + if (block.GetNumRanges() == 0) + block.AddRange(Block::Range(0, func->GetAddressRange().GetByteSize())); + return block; + } + break; } case S_BLOCK32: { // This is a block. Its parent is either a function or another block. In @@ -360,8 +414,26 @@ Block &SymbolFileNativePDB::CreateBlock(PdbCompilandSymId block_id) { lldbassert(block.Parent != 0); PdbCompilandSymId parent_id(block_id.modi, block.Parent); Block &parent_block = GetOrCreateBlock(parent_id); + Function *func = parent_block.CalculateSymbolContextFunction(); + lldbassert(func); + lldb::addr_t block_base = + m_index->MakeVirtualAddress(block.Segment, block.CodeOffset); + lldb::addr_t func_base = + func->GetAddressRange().GetBaseAddress().GetFileAddress(); + if (block_base >= func_base) + child_block->AddRange(Block::Range(block_base - func_base, block.CodeSize)); + else { + GetObjectFile()->GetModule()->ReportError( + "S_BLOCK32 at modi: {0:d} offset: {1:d}: adding range " + "[{2:x16}-{3:x16}) which has a base that is less than the " + "function's " + "low PC 0x%" PRIx64 ". Please file a bug and attach the file at the " + "start of this error message", + block_id.modi, block_id.offset, block_base, + block_base + block.CodeSize, func_base); + } parent_block.AddChild(child_block); - m_ast->GetOrCreateBlockDecl(block_id); + ast_builder->GetOrCreateBlockDecl(block_id); m_blocks.insert({opaque_block_uid, child_block}); break; } @@ -372,7 +444,7 @@ Block &SymbolFileNativePDB::CreateBlock(PdbCompilandSymId block_id) { std::shared_ptr<InlineSite> inline_site = m_inline_sites[opaque_block_uid]; Block &parent_block = GetOrCreateBlock(inline_site->parent_id); parent_block.AddChild(child_block); - m_ast->GetOrCreateInlinedFunctionDecl(block_id); + ast_builder->GetOrCreateInlinedFunctionDecl(block_id); // Copy ranges from InlineSite to Block. for (size_t i = 0; i < inline_site->ranges.GetSize(); ++i) { auto *entry = inline_site->ranges.GetEntryAtIndex(i); @@ -433,7 +505,13 @@ lldb::FunctionSP SymbolFileNativePDB::CreateFunction(PdbCompilandSymId func_id, comp_unit.AddFunction(func_sp); - m_ast->GetOrCreateFunctionDecl(func_id); + auto ts_or_err = GetTypeSystemForLanguage(comp_unit.GetLanguage()); + if (auto err = ts_or_err.takeError()) + return func_sp; + auto ts = *ts_or_err; + if (!ts) + return func_sp; + ts->GetNativePDBParser()->GetOrCreateFunctionDecl(func_id); return func_sp; } @@ -474,10 +552,10 @@ lldb::TypeSP SymbolFileNativePDB::CreateModifierType(PdbTypeSymId type_id, Declaration decl; lldb::TypeSP modified_type = GetOrCreateType(mr.ModifiedType); - return std::make_shared<Type>(toOpaqueUid(type_id), this, ConstString(name), - modified_type->GetByteSize(nullptr), nullptr, - LLDB_INVALID_UID, Type::eEncodingIsUID, decl, - ct, Type::ResolveState::Full); + return MakeType(toOpaqueUid(type_id), ConstString(name), + modified_type->GetByteSize(nullptr), nullptr, + LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct, + Type::ResolveState::Full); } lldb::TypeSP @@ -494,10 +572,9 @@ SymbolFileNativePDB::CreatePointerType(PdbTypeSymId type_id, } Declaration decl; - return std::make_shared<Type>(toOpaqueUid(type_id), this, ConstString(), - pr.getSize(), nullptr, LLDB_INVALID_UID, - Type::eEncodingIsUID, decl, ct, - Type::ResolveState::Full); + return MakeType(toOpaqueUid(type_id), ConstString(), pr.getSize(), nullptr, + LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct, + Type::ResolveState::Full); } lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti, @@ -505,9 +582,9 @@ lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti, uint64_t uid = toOpaqueUid(PdbTypeSymId(ti, false)); if (ti == TypeIndex::NullptrT()) { Declaration decl; - return std::make_shared<Type>( - uid, this, ConstString("std::nullptr_t"), 0, nullptr, LLDB_INVALID_UID, - Type::eEncodingIsUID, decl, ct, Type::ResolveState::Full); + return MakeType(uid, ConstString("std::nullptr_t"), 0, nullptr, + LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct, + Type::ResolveState::Full); } if (ti.getSimpleMode() != SimpleTypeMode::Direct) { @@ -526,9 +603,8 @@ lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti, return nullptr; } Declaration decl; - return std::make_shared<Type>( - uid, this, ConstString(), pointer_size, nullptr, LLDB_INVALID_UID, - Type::eEncodingIsUID, decl, ct, Type::ResolveState::Full); + return MakeType(uid, ConstString(), pointer_size, nullptr, LLDB_INVALID_UID, + Type::eEncodingIsUID, decl, ct, Type::ResolveState::Full); } if (ti.getSimpleKind() == SimpleTypeKind::NotTranslated) @@ -538,9 +614,8 @@ lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti, llvm::StringRef type_name = GetSimpleTypeName(ti.getSimpleKind()); Declaration decl; - return std::make_shared<Type>(uid, this, ConstString(type_name), size, - nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, - decl, ct, Type::ResolveState::Full); + return MakeType(uid, ConstString(type_name), size, nullptr, LLDB_INVALID_UID, + Type::eEncodingIsUID, decl, ct, Type::ResolveState::Full); } static std::string GetUnqualifiedTypeName(const TagRecord &record) { @@ -571,10 +646,9 @@ SymbolFileNativePDB::CreateClassStructUnion(PdbTypeSymId type_id, // FIXME: Search IPI stream for LF_UDT_MOD_SRC_LINE. Declaration decl; - return std::make_shared<Type>(toOpaqueUid(type_id), this, ConstString(uname), - size, nullptr, LLDB_INVALID_UID, - Type::eEncodingIsUID, decl, ct, - Type::ResolveState::Forward); + return MakeType(toOpaqueUid(type_id), ConstString(uname), size, nullptr, + LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct, + Type::ResolveState::Forward); } lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id, @@ -597,11 +671,10 @@ lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id, Declaration decl; TypeSP underlying_type = GetOrCreateType(er.UnderlyingType); - return std::make_shared<lldb_private::Type>( - toOpaqueUid(type_id), this, ConstString(uname), - underlying_type->GetByteSize(nullptr), nullptr, LLDB_INVALID_UID, - lldb_private::Type::eEncodingIsUID, decl, ct, - lldb_private::Type::ResolveState::Forward); + return MakeType(toOpaqueUid(type_id), ConstString(uname), + underlying_type->GetByteSize(nullptr), nullptr, + LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, + ct, lldb_private::Type::ResolveState::Forward); } TypeSP SymbolFileNativePDB::CreateArrayType(PdbTypeSymId type_id, @@ -610,33 +683,30 @@ TypeSP SymbolFileNativePDB::CreateArrayType(PdbTypeSymId type_id, TypeSP element_type = GetOrCreateType(ar.ElementType); Declaration decl; - TypeSP array_sp = std::make_shared<lldb_private::Type>( - toOpaqueUid(type_id), this, ConstString(), ar.Size, nullptr, - LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, ct, - lldb_private::Type::ResolveState::Full); + TypeSP array_sp = + MakeType(toOpaqueUid(type_id), ConstString(), ar.Size, nullptr, + LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, ct, + lldb_private::Type::ResolveState::Full); array_sp->SetEncodingType(element_type.get()); return array_sp; } - TypeSP SymbolFileNativePDB::CreateFunctionType(PdbTypeSymId type_id, const MemberFunctionRecord &mfr, CompilerType ct) { Declaration decl; - return std::make_shared<lldb_private::Type>( - toOpaqueUid(type_id), this, ConstString(), 0, nullptr, LLDB_INVALID_UID, - lldb_private::Type::eEncodingIsUID, decl, ct, - lldb_private::Type::ResolveState::Full); + return MakeType(toOpaqueUid(type_id), ConstString(), 0, nullptr, + LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, + ct, lldb_private::Type::ResolveState::Full); } TypeSP SymbolFileNativePDB::CreateProcedureType(PdbTypeSymId type_id, const ProcedureRecord &pr, CompilerType ct) { Declaration decl; - return std::make_shared<lldb_private::Type>( - toOpaqueUid(type_id), this, ConstString(), 0, nullptr, LLDB_INVALID_UID, - lldb_private::Type::eEncodingIsUID, decl, ct, - lldb_private::Type::ResolveState::Full); + return MakeType(toOpaqueUid(type_id), ConstString(), 0, nullptr, + LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, + ct, lldb_private::Type::ResolveState::Full); } TypeSP SymbolFileNativePDB::CreateType(PdbTypeSymId type_id, CompilerType ct) { @@ -701,7 +771,7 @@ TypeSP SymbolFileNativePDB::CreateType(PdbTypeSymId type_id, CompilerType ct) { TypeSP SymbolFileNativePDB::CreateAndCacheType(PdbTypeSymId type_id) { // If they search for a UDT which is a forward ref, try and resolve the full // decl and just map the forward ref uid to the full decl record. - llvm::Optional<PdbTypeSymId> full_decl_uid; + std::optional<PdbTypeSymId> full_decl_uid; if (IsForwardRefUdt(type_id, m_index->tpi())) { auto expected_full_ti = m_index->tpi().findFullDeclForForwardRef(type_id.index); @@ -726,12 +796,19 @@ TypeSP SymbolFileNativePDB::CreateAndCacheType(PdbTypeSymId type_id) { } PdbTypeSymId best_decl_id = full_decl_uid ? *full_decl_uid : type_id; + auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); + if (auto err = ts_or_err.takeError()) + return nullptr; + auto ts = *ts_or_err; + if (!ts) + return nullptr; - clang::QualType qt = m_ast->GetOrCreateType(best_decl_id); + PdbAstBuilder* ast_builder = ts->GetNativePDBParser(); + clang::QualType qt = ast_builder->GetOrCreateType(best_decl_id); if (qt.isNull()) return nullptr; - TypeSP result = CreateType(best_decl_id, m_ast->ToCompilerType(qt)); + TypeSP result = CreateType(best_decl_id, ast_builder->ToCompilerType(qt)); if (!result) return nullptr; @@ -774,7 +851,7 @@ VariableSP SymbolFileNativePDB::CreateGlobalVariable(PdbGlobalSymId var_id) { switch (sym.kind()) { case S_GDATA32: is_external = true; - LLVM_FALLTHROUGH; + [[fallthrough]]; case S_LDATA32: { DataSym ds(sym.kind()); llvm::cantFail(SymbolDeserializer::deserializeAs<DataSym>(sym, ds)); @@ -789,7 +866,7 @@ VariableSP SymbolFileNativePDB::CreateGlobalVariable(PdbGlobalSymId var_id) { } case S_GTHREAD32: is_external = true; - LLVM_FALLTHROUGH; + [[fallthrough]]; case S_LTHREAD32: { ThreadLocalDataSym tlds(sym.kind()); llvm::cantFail( @@ -807,7 +884,7 @@ VariableSP SymbolFileNativePDB::CreateGlobalVariable(PdbGlobalSymId var_id) { } CompUnitSP comp_unit; - llvm::Optional<uint16_t> modi = m_index->GetModuleIndexForVa(addr); + std::optional<uint16_t> modi = m_index->GetModuleIndexForVa(addr); if (!modi) { return nullptr; } @@ -820,8 +897,14 @@ VariableSP SymbolFileNativePDB::CreateGlobalVariable(PdbGlobalSymId var_id) { SymbolFileTypeSP type_sp = std::make_shared<SymbolFileType>(*this, toOpaqueUid(tid)); Variable::RangeList ranges; + auto ts_or_err = GetTypeSystemForLanguage(comp_unit->GetLanguage()); + if (auto err = ts_or_err.takeError()) + return nullptr; + auto ts = *ts_or_err; + if (!ts) + return nullptr; - m_ast->GetOrCreateVariableDecl(var_id); + ts->GetNativePDBParser()->GetOrCreateVariableDecl(var_id); ModuleSP module_sp = GetObjectFile()->GetModule(); DWARFExpressionList location( @@ -921,10 +1004,14 @@ Block &SymbolFileNativePDB::GetOrCreateBlock(PdbCompilandSymId block_id) { void SymbolFileNativePDB::ParseDeclsForContext( lldb_private::CompilerDeclContext decl_ctx) { - clang::DeclContext *context = m_ast->FromCompilerDeclContext(decl_ctx); + TypeSystem* ts_or_err = decl_ctx.GetTypeSystem(); + if (!ts_or_err) + return; + PdbAstBuilder* ast_builder = ts_or_err->GetNativePDBParser(); + clang::DeclContext *context = ast_builder->FromCompilerDeclContext(decl_ctx); if (!context) return; - m_ast->ParseDeclsForContext(*context); + ast_builder->ParseDeclsForContext(*context); } lldb::CompUnitSP SymbolFileNativePDB::ParseCompileUnitAtIndex(uint32_t index) { @@ -995,7 +1082,7 @@ uint32_t SymbolFileNativePDB::ResolveSymbolContext( lldb::addr_t file_addr = addr.GetFileAddress(); if (NeedsResolvedCompileUnit(resolve_scope)) { - llvm::Optional<uint16_t> modi = m_index->GetModuleIndexForVa(file_addr); + std::optional<uint16_t> modi = m_index->GetModuleIndexForVa(file_addr); if (!modi) return 0; CompUnitSP cu_sp = GetCompileUnitAtIndex(*modi); @@ -1024,16 +1111,25 @@ uint32_t SymbolFileNativePDB::ResolveSymbolContext( continue; if (type == PDB_SymType::Function) { sc.function = GetOrCreateFunction(csid, *sc.comp_unit).get(); - Block &block = sc.function->GetBlock(true); - addr_t func_base = - sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); - addr_t offset = file_addr - func_base; - sc.block = block.FindInnermostBlockByOffset(offset); + if (sc.function) { + Block &block = sc.function->GetBlock(true); + addr_t func_base = + sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); + addr_t offset = file_addr - func_base; + sc.block = block.FindInnermostBlockByOffset(offset); + } } if (type == PDB_SymType::Block) { - sc.block = &GetOrCreateBlock(csid); - sc.function = sc.block->CalculateSymbolContextFunction(); + Block &block = GetOrCreateBlock(csid); + sc.function = block.CalculateSymbolContextFunction(); + if (sc.function) { + sc.function->GetBlock(true); + addr_t func_base = + sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); + addr_t offset = file_addr - func_base; + sc.block = block.FindInnermostBlockByOffset(offset); + } } if (sc.function) resolved_flags |= eSymbolContextFunction; @@ -1329,11 +1425,11 @@ void SymbolFileNativePDB::ParseInlineSite(PdbCompilandSymId id, // Parse range and line info. uint32_t code_offset = 0; int32_t line_offset = 0; - llvm::Optional<uint32_t> code_offset_base; - llvm::Optional<uint32_t> code_offset_end; - llvm::Optional<int32_t> cur_line_offset; - llvm::Optional<int32_t> next_line_offset; - llvm::Optional<uint32_t> next_file_offset; + std::optional<uint32_t> code_offset_base; + std::optional<uint32_t> code_offset_end; + std::optional<int32_t> cur_line_offset; + std::optional<int32_t> next_line_offset; + std::optional<uint32_t> next_file_offset; bool is_terminal_entry = false; bool is_start_of_statement = true; @@ -1406,10 +1502,10 @@ void SymbolFileNativePDB::ParseInlineSite(PdbCompilandSymId id, file_offset = *next_file_offset; if (next_line_offset) { cur_line_offset = next_line_offset; - next_line_offset = llvm::None; + next_line_offset = std::nullopt; } - code_offset_base = is_terminal_entry ? llvm::None : code_offset_end; - code_offset_end = next_file_offset = llvm::None; + code_offset_base = is_terminal_entry ? std::nullopt : code_offset_end; + code_offset_end = next_file_offset = std::nullopt; } if (code_offset_base && cur_line_offset) { if (is_terminal_entry) { @@ -1534,7 +1630,16 @@ size_t SymbolFileNativePDB::ParseSymbolArrayInScope( return count; } -void SymbolFileNativePDB::DumpClangAST(Stream &s) { m_ast->Dump(s); } +void SymbolFileNativePDB::DumpClangAST(Stream &s) { + auto ts_or_err = GetTypeSystemForLanguage(eLanguageTypeC_plus_plus); + if (!ts_or_err) + return; + auto ts = *ts_or_err; + TypeSystemClang *clang = llvm::dyn_cast_or_null<TypeSystemClang>(ts.get()); + if (!clang) + return; + clang->GetNativePDBParser()->Dump(s); +} void SymbolFileNativePDB::FindGlobalVariables( ConstString name, const CompilerDeclContext &parent_decl_ctx, @@ -1563,10 +1668,15 @@ void SymbolFileNativePDB::FindGlobalVariables( } void SymbolFileNativePDB::FindFunctions( - ConstString name, const CompilerDeclContext &parent_decl_ctx, - FunctionNameType name_type_mask, bool include_inlines, + const Module::LookupInfo &lookup_info, + const CompilerDeclContext &parent_decl_ctx, bool include_inlines, SymbolContextList &sc_list) { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); + ConstString name = lookup_info.GetLookupName(); + FunctionNameType name_type_mask = lookup_info.GetNameTypeMask(); + if (name_type_mask & eFunctionNameTypeFull) + name = lookup_info.GetName(); + // For now we only support lookup by method name or full name. if (!(name_type_mask & eFunctionNameTypeFull || name_type_mask & eFunctionNameTypeMethod)) @@ -1702,12 +1812,20 @@ VariableSP SymbolFileNativePDB::CreateLocalVariable(PdbCompilandSymId scope_id, func_block->GetStartAddress(addr); VariableInfo var_info = GetVariableLocationInfo(*m_index, var_id, *func_block, module); - if (!var_info.location || !var_info.ranges) + Function *func = func_block->CalculateSymbolContextFunction(); + if (!func) return nullptr; - + // Use empty dwarf expr if optimized away so that it won't be filtered out + // when lookuping local variables in this scope. + if (!var_info.location.IsValid()) + var_info.location = DWARFExpressionList(module, DWARFExpression(), nullptr); + var_info.location.SetFuncFileAddress( + func->GetAddressRange().GetBaseAddress().GetFileAddress()); CompilandIndexItem *cii = m_index->compilands().GetCompiland(var_id.modi); CompUnitSP comp_unit_sp = GetOrCreateCompileUnit(*cii); TypeSP type_sp = GetOrCreateType(var_info.type); + if (!type_sp) + return nullptr; std::string name = var_info.name.str(); Declaration decl; SymbolFileTypeSP sftype = @@ -1720,15 +1838,21 @@ VariableSP SymbolFileNativePDB::CreateLocalVariable(PdbCompilandSymId scope_id, bool artificial = false; bool location_is_constant_data = false; bool static_member = false; - DWARFExpressionList locaiton_list = DWARFExpressionList( - module, *var_info.location, nullptr); + Variable::RangeList scope_ranges; VariableSP var_sp = std::make_shared<Variable>( toOpaqueUid(var_id), name.c_str(), name.c_str(), sftype, var_scope, - &block, *var_info.ranges, &decl, locaiton_list, external, artificial, + &block, scope_ranges, &decl, var_info.location, external, artificial, location_is_constant_data, static_member); - if (!is_param) - m_ast->GetOrCreateVariableDecl(scope_id, var_id); + if (!is_param) { + auto ts_or_err = GetTypeSystemForLanguage(comp_unit_sp->GetLanguage()); + if (auto err = ts_or_err.takeError()) + return nullptr; + auto ts = *ts_or_err; + if (!ts) + return nullptr; + ts->GetNativePDBParser()->GetOrCreateVariableDecl(scope_id, var_id); + } m_local_variables[toOpaqueUid(var_id)] = var_sp; return var_sp; } @@ -1750,14 +1874,20 @@ TypeSP SymbolFileNativePDB::CreateTypedef(PdbGlobalSymId id) { TypeSP target_type = GetOrCreateType(udt.Type); - (void)m_ast->GetOrCreateTypedefDecl(id); + auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); + if (auto err = ts_or_err.takeError()) + return nullptr; + auto ts = *ts_or_err; + if (!ts) + return nullptr; + + ts->GetNativePDBParser()->GetOrCreateTypedefDecl(id); Declaration decl; - return std::make_shared<lldb_private::Type>( - toOpaqueUid(id), this, ConstString(udt.Name), - target_type->GetByteSize(nullptr), nullptr, target_type->GetID(), - lldb_private::Type::eEncodingIsTypedefUID, decl, - target_type->GetForwardCompilerType(), + return MakeType( + toOpaqueUid(id), ConstString(udt.Name), target_type->GetByteSize(nullptr), + nullptr, target_type->GetID(), lldb_private::Type::eEncodingIsTypedefUID, + decl, target_type->GetForwardCompilerType(), lldb_private::Type::ResolveState::Forward); } @@ -1783,9 +1913,24 @@ size_t SymbolFileNativePDB::ParseVariablesForBlock(PdbCompilandSymId block_id) { ProcSym proc(static_cast<SymbolRecordKind>(sym.kind())); cantFail(SymbolDeserializer::deserializeAs<ProcSym>(sym, proc)); CVType signature = m_index->tpi().getType(proc.FunctionType); - ProcedureRecord sig; - cantFail(TypeDeserializer::deserializeAs<ProcedureRecord>(signature, sig)); - params_remaining = sig.getParameterCount(); + if (signature.kind() == LF_PROCEDURE) { + ProcedureRecord sig; + if (llvm::Error e = TypeDeserializer::deserializeAs<ProcedureRecord>( + signature, sig)) { + llvm::consumeError(std::move(e)); + return 0; + } + params_remaining = sig.getParameterCount(); + } else if (signature.kind() == LF_MFUNCTION) { + MemberFunctionRecord sig; + if (llvm::Error e = TypeDeserializer::deserializeAs<MemberFunctionRecord>( + signature, sig)) { + llvm::consumeError(std::move(e)); + return 0; + } + params_remaining = sig.getParameterCount(); + } else + return 0; break; } case S_BLOCK32: @@ -1884,26 +2029,50 @@ size_t SymbolFileNativePDB::ParseVariablesForContext(const SymbolContext &sc) { } CompilerDecl SymbolFileNativePDB::GetDeclForUID(lldb::user_id_t uid) { - if (auto decl = m_ast->GetOrCreateDeclForUid(uid)) - return *decl; - else + auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); + if (auto err = ts_or_err.takeError()) return CompilerDecl(); + auto ts = *ts_or_err; + if (!ts) + return {}; + + if (auto decl = ts->GetNativePDBParser()->GetOrCreateDeclForUid(uid)) + return *decl; + return CompilerDecl(); } CompilerDeclContext SymbolFileNativePDB::GetDeclContextForUID(lldb::user_id_t uid) { + auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); + if (auto err = ts_or_err.takeError()) + return {}; + auto ts = *ts_or_err; + if (!ts) + return {}; + + PdbAstBuilder *ast_builder = ts->GetNativePDBParser(); clang::DeclContext *context = - m_ast->GetOrCreateDeclContextForUid(PdbSymUid(uid)); + ast_builder->GetOrCreateDeclContextForUid(PdbSymUid(uid)); if (!context) return {}; - return m_ast->ToCompilerDeclContext(*context); + return ast_builder->ToCompilerDeclContext(*context); } CompilerDeclContext SymbolFileNativePDB::GetDeclContextContainingUID(lldb::user_id_t uid) { - clang::DeclContext *context = m_ast->GetParentDeclContext(PdbSymUid(uid)); - return m_ast->ToCompilerDeclContext(*context); + auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); + if (auto err = ts_or_err.takeError()) + return CompilerDeclContext(); + auto ts = *ts_or_err; + if (!ts) + return {}; + + PdbAstBuilder *ast_builder = ts->GetNativePDBParser(); + clang::DeclContext *context = ast_builder->GetParentDeclContext(PdbSymUid(uid)); + if (!context) + return CompilerDeclContext(); + return ast_builder->ToCompilerDeclContext(*context); } Type *SymbolFileNativePDB::ResolveTypeUID(lldb::user_id_t type_uid) { @@ -1924,21 +2093,33 @@ Type *SymbolFileNativePDB::ResolveTypeUID(lldb::user_id_t type_uid) { return nullptr; TypeSP type_sp = CreateAndCacheType(type_id); + if (!type_sp) + return nullptr; return &*type_sp; } -llvm::Optional<SymbolFile::ArrayInfo> +std::optional<SymbolFile::ArrayInfo> SymbolFileNativePDB::GetDynamicArrayInfoForUID( lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) { - return llvm::None; + return std::nullopt; } - bool SymbolFileNativePDB::CompleteType(CompilerType &compiler_type) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); + auto ts = compiler_type.GetTypeSystem(); + auto clang_type_system = ts.dyn_cast_or_null<TypeSystemClang>(); + if (!clang_type_system) + return false; + + PdbAstBuilder *ast_builder = + static_cast<PdbAstBuilder *>(clang_type_system->GetNativePDBParser()); + if (ast_builder && + ast_builder->GetClangASTImporter().CanImport(compiler_type)) + return ast_builder->GetClangASTImporter().CompleteType(compiler_type); clang::QualType qt = clang::QualType::getFromOpaquePtr(compiler_type.GetOpaqueQualType()); - return m_ast->CompleteType(qt); + return ast_builder->CompleteType(qt); } void SymbolFileNativePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope, @@ -1951,13 +2132,13 @@ SymbolFileNativePDB::FindNamespace(ConstString name, return {}; } -llvm::Expected<TypeSystem &> +llvm::Expected<lldb::TypeSystemSP> SymbolFileNativePDB::GetTypeSystemForLanguage(lldb::LanguageType language) { auto type_system_or_err = m_objfile_sp->GetModule()->GetTypeSystemForLanguage(language); - if (type_system_or_err) { - type_system_or_err->SetSymbolFile(this); - } + if (type_system_or_err) + if (auto ts = *type_system_or_err) + ts->SetSymbolFile(this); return type_system_or_err; } @@ -1965,3 +2146,176 @@ uint64_t SymbolFileNativePDB::GetDebugInfoSize() { // PDB files are a separate file that contains all debug info. return m_index->pdb().getFileSize(); } + +void SymbolFileNativePDB::BuildParentMap() { + LazyRandomTypeCollection &types = m_index->tpi().typeCollection(); + + llvm::DenseMap<TypeIndex, TypeIndex> forward_to_full; + llvm::DenseMap<TypeIndex, TypeIndex> full_to_forward; + + struct RecordIndices { + TypeIndex forward; + TypeIndex full; + }; + + llvm::StringMap<RecordIndices> record_indices; + + for (auto ti = types.getFirst(); ti; ti = types.getNext(*ti)) { + CVType type = types.getType(*ti); + if (!IsTagRecord(type)) + continue; + + CVTagRecord tag = CVTagRecord::create(type); + + RecordIndices &indices = record_indices[tag.asTag().getUniqueName()]; + if (tag.asTag().isForwardRef()) + indices.forward = *ti; + else + indices.full = *ti; + + if (indices.full != TypeIndex::None() && + indices.forward != TypeIndex::None()) { + forward_to_full[indices.forward] = indices.full; + full_to_forward[indices.full] = indices.forward; + } + + // We're looking for LF_NESTTYPE records in the field list, so ignore + // forward references (no field list), and anything without a nested class + // (since there won't be any LF_NESTTYPE records). + if (tag.asTag().isForwardRef() || !tag.asTag().containsNestedClass()) + continue; + + struct ProcessTpiStream : public TypeVisitorCallbacks { + ProcessTpiStream(PdbIndex &index, TypeIndex parent, + const CVTagRecord &parent_cvt, + llvm::DenseMap<TypeIndex, TypeIndex> &parents) + : index(index), parents(parents), parent(parent), + parent_cvt(parent_cvt) {} + + PdbIndex &index; + llvm::DenseMap<TypeIndex, TypeIndex> &parents; + + unsigned unnamed_type_index = 1; + TypeIndex parent; + const CVTagRecord &parent_cvt; + + llvm::Error visitKnownMember(CVMemberRecord &CVR, + NestedTypeRecord &Record) override { + std::string unnamed_type_name; + if (Record.Name.empty()) { + unnamed_type_name = + llvm::formatv("<unnamed-type-$S{0}>", unnamed_type_index).str(); + Record.Name = unnamed_type_name; + ++unnamed_type_index; + } + std::optional<CVTagRecord> tag = + GetNestedTagDefinition(Record, parent_cvt, index.tpi()); + if (!tag) + return llvm::ErrorSuccess(); + + parents[Record.Type] = parent; + return llvm::ErrorSuccess(); + } + }; + + CVType field_list_cvt = m_index->tpi().getType(tag.asTag().FieldList); + ProcessTpiStream process(*m_index, *ti, tag, m_parent_types); + FieldListRecord field_list; + if (llvm::Error error = TypeDeserializer::deserializeAs<FieldListRecord>( + field_list_cvt, field_list)) + llvm::consumeError(std::move(error)); + if (llvm::Error error = visitMemberRecordStream(field_list.Data, process)) + llvm::consumeError(std::move(error)); + } + + // Now that we know the forward -> full mapping of all type indices, we can + // re-write all the indices. At the end of this process, we want a mapping + // consisting of fwd -> full and full -> full for all child -> parent indices. + // We can re-write the values in place, but for the keys, we must save them + // off so that we don't modify the map in place while also iterating it. + std::vector<TypeIndex> full_keys; + std::vector<TypeIndex> fwd_keys; + for (auto &entry : m_parent_types) { + TypeIndex key = entry.first; + TypeIndex value = entry.second; + + auto iter = forward_to_full.find(value); + if (iter != forward_to_full.end()) + entry.second = iter->second; + + iter = forward_to_full.find(key); + if (iter != forward_to_full.end()) + fwd_keys.push_back(key); + else + full_keys.push_back(key); + } + for (TypeIndex fwd : fwd_keys) { + TypeIndex full = forward_to_full[fwd]; + m_parent_types[full] = m_parent_types[fwd]; + } + for (TypeIndex full : full_keys) { + TypeIndex fwd = full_to_forward[full]; + m_parent_types[fwd] = m_parent_types[full]; + } +} + +std::optional<PdbCompilandSymId> +SymbolFileNativePDB::FindSymbolScope(PdbCompilandSymId id) { + CVSymbol sym = m_index->ReadSymbolRecord(id); + if (symbolOpensScope(sym.kind())) { + // If this exact symbol opens a scope, we can just directly access its + // parent. + id.offset = getScopeParentOffset(sym); + // Global symbols have parent offset of 0. Return std::nullopt to indicate + // this. + if (id.offset == 0) + return std::nullopt; + return id; + } + + // Otherwise we need to start at the beginning and iterate forward until we + // reach (or pass) this particular symbol + CompilandIndexItem &cii = m_index->compilands().GetOrCreateCompiland(id.modi); + const CVSymbolArray &syms = cii.m_debug_stream.getSymbolArray(); + + auto begin = syms.begin(); + auto end = syms.at(id.offset); + std::vector<PdbCompilandSymId> scope_stack; + + while (begin != end) { + if (begin.offset() > id.offset) { + // We passed it. We couldn't even find this symbol record. + lldbassert(false && "Invalid compiland symbol id!"); + return std::nullopt; + } + + // We haven't found the symbol yet. Check if we need to open or close the + // scope stack. + if (symbolOpensScope(begin->kind())) { + // We can use the end offset of the scope to determine whether or not + // we can just outright skip this entire scope. + uint32_t scope_end = getScopeEndOffset(*begin); + if (scope_end < id.offset) { + begin = syms.at(scope_end); + } else { + // The symbol we're looking for is somewhere in this scope. + scope_stack.emplace_back(id.modi, begin.offset()); + } + } else if (symbolEndsScope(begin->kind())) { + scope_stack.pop_back(); + } + ++begin; + } + if (scope_stack.empty()) + return std::nullopt; + // We have a match! Return the top of the stack + return scope_stack.back(); +} + +std::optional<llvm::codeview::TypeIndex> +SymbolFileNativePDB::GetParentType(llvm::codeview::TypeIndex ti) { + auto parent_iter = m_parent_types.find(ti); + if (parent_iter == m_parent_types.end()) + return std::nullopt; + return parent_iter->second; +} |
