diff options
Diffstat (limited to 'lldb/source/Plugins/SymbolFile')
5 files changed, 197 insertions, 66 deletions
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index f1e73d73a733..82e9d867c3ac 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -3126,43 +3126,6 @@ void DWARFASTParserClang::ParseSingleMember( if (!member_clang_type.IsCompleteType()) member_clang_type.GetCompleteType(); - { - // Older versions of clang emit the same DWARF for array[0] and array[1]. If - // the current field is at the end of the structure, then there is - // definitely no room for extra elements and we override the type to - // array[0]. This was fixed by f454dfb6b5af. - CompilerType member_array_element_type; - uint64_t member_array_size; - bool member_array_is_incomplete; - - if (member_clang_type.IsArrayType(&member_array_element_type, - &member_array_size, - &member_array_is_incomplete) && - !member_array_is_incomplete) { - uint64_t parent_byte_size = - parent_die.GetAttributeValueAsUnsigned(DW_AT_byte_size, UINT64_MAX); - - // If the attrs.member_byte_offset is still set to UINT32_MAX this means - // that the DW_TAG_member didn't have a DW_AT_data_member_location, so - // don't emit an error if this is the case. - if (attrs.member_byte_offset != UINT32_MAX && - attrs.member_byte_offset >= parent_byte_size) { - if (member_array_size != 1 && - (member_array_size != 0 || - attrs.member_byte_offset > parent_byte_size)) { - module_sp->ReportError( - "{0:x8}: DW_TAG_member '{1}' refers to type {2:x16}" - " which extends beyond the bounds of {3:x8}", - die.GetID(), attrs.name, - attrs.encoding_form.Reference().GetOffset(), parent_die.GetID()); - } - - member_clang_type = - m_ast.CreateArrayType(member_array_element_type, 0, false); - } - } - } - TypeSystemClang::RequireCompleteType(member_clang_type); clang::FieldDecl *field_decl = TypeSystemClang::AddFieldToRecordType( diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp index 51bdcc92b05a..e7fddf08967f 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp @@ -38,16 +38,18 @@ struct CreateMethodDecl : public TypeVisitorCallbacks { TypeIndex func_type_index, clang::FunctionDecl *&function_decl, lldb::opaque_compiler_type_t parent_ty, - llvm::StringRef proc_name, CompilerType func_ct) + llvm::StringRef proc_name, ConstString mangled_name, + CompilerType func_ct) : m_index(m_index), m_clang(m_clang), func_type_index(func_type_index), function_decl(function_decl), parent_ty(parent_ty), - proc_name(proc_name), func_ct(func_ct) {} + proc_name(proc_name), mangled_name(mangled_name), func_ct(func_ct) {} PdbIndex &m_index; TypeSystemClang &m_clang; TypeIndex func_type_index; clang::FunctionDecl *&function_decl; lldb::opaque_compiler_type_t parent_ty; llvm::StringRef proc_name; + ConstString mangled_name; CompilerType func_ct; llvm::Error visitKnownMember(CVMemberRecord &cvr, @@ -87,8 +89,7 @@ struct CreateMethodDecl : public TypeVisitorCallbacks { bool is_artificial = (options & MethodOptions::CompilerGenerated) == MethodOptions::CompilerGenerated; function_decl = m_clang.AddMethodToCXXRecordType( - parent_ty, proc_name, - /*asm_label=*/{}, func_ct, /*access=*/access_type, + parent_ty, proc_name, mangled_name, func_ct, /*access=*/access_type, /*is_virtual=*/is_virtual, /*is_static=*/is_static, /*is_inline=*/false, /*is_explicit=*/false, /*is_attr_used=*/false, /*is_artificial=*/is_artificial); @@ -892,6 +893,10 @@ PdbAstBuilder::CreateFunctionDecl(PdbCompilandSymId func_id, tag_record = CVTagRecord::create(index.tpi().getType(*eti)).asTag(); } } + + ConstString mangled_name( + pdb->FindMangledFunctionName(func_id).value_or(llvm::StringRef())); + if (!tag_record.FieldList.isSimple()) { CVType field_list_cvt = index.tpi().getType(tag_record.FieldList); FieldListRecord field_list; @@ -899,15 +904,15 @@ PdbAstBuilder::CreateFunctionDecl(PdbCompilandSymId func_id, field_list_cvt, field_list)) llvm::consumeError(std::move(error)); CreateMethodDecl process(index, m_clang, func_ti, function_decl, - parent_opaque_ty, func_name, func_ct); + parent_opaque_ty, func_name, mangled_name, + func_ct); if (llvm::Error err = visitMemberRecordStream(field_list.Data, process)) llvm::consumeError(std::move(err)); } if (!function_decl) { function_decl = m_clang.AddMethodToCXXRecordType( - parent_opaque_ty, func_name, - /*asm_label=*/{}, func_ct, + parent_opaque_ty, func_name, mangled_name, func_ct, /*access=*/lldb::AccessType::eAccessPublic, /*is_virtual=*/false, /*is_static=*/false, /*is_inline=*/false, /*is_explicit=*/false, diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp index 888bd89a7262..6c66d86d3e64 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp @@ -946,17 +946,21 @@ lldb_private::npdb::GetCompilerTypeForSimpleKind(SimpleTypeKind kind) { case SimpleTypeKind::Complex64: return lldb::eBasicTypeDoubleComplex; case SimpleTypeKind::Complex32: + case SimpleTypeKind::Complex32PartialPrecision: return lldb::eBasicTypeFloatComplex; - case SimpleTypeKind::Float128: case SimpleTypeKind::Float80: return lldb::eBasicTypeLongDouble; + case SimpleTypeKind::Float128: + return lldb::eBasicTypeFloat128; case SimpleTypeKind::Float64: return lldb::eBasicTypeDouble; case SimpleTypeKind::Float32: + case SimpleTypeKind::Float32PartialPrecision: return lldb::eBasicTypeFloat; case SimpleTypeKind::Float16: return lldb::eBasicTypeHalf; case SimpleTypeKind::Int128: + case SimpleTypeKind::Int128Oct: return lldb::eBasicTypeInt128; case SimpleTypeKind::Int64: case SimpleTypeKind::Int64Quad: @@ -967,6 +971,7 @@ lldb_private::npdb::GetCompilerTypeForSimpleKind(SimpleTypeKind kind) { case SimpleTypeKind::Int16Short: return lldb::eBasicTypeShort; case SimpleTypeKind::UInt128: + case SimpleTypeKind::UInt128Oct: return lldb::eBasicTypeUnsignedInt128; case SimpleTypeKind::UInt64: case SimpleTypeKind::UInt64Quad: @@ -985,16 +990,27 @@ lldb_private::npdb::GetCompilerTypeForSimpleKind(SimpleTypeKind kind) { return lldb::eBasicTypeVoid; case SimpleTypeKind::WideCharacter: return lldb::eBasicTypeWChar; - default: + + // Not supported. + case SimpleTypeKind::Float48: + case SimpleTypeKind::Complex16: + case SimpleTypeKind::Complex48: + case SimpleTypeKind::Complex128: + case SimpleTypeKind::NotTranslated: + case SimpleTypeKind::None: return lldb::eBasicTypeInvalid; } + return lldb::eBasicTypeInvalid; } size_t lldb_private::npdb::GetTypeSizeForSimpleKind(SimpleTypeKind kind) { switch (kind) { case SimpleTypeKind::Boolean128: + case SimpleTypeKind::Complex128: case SimpleTypeKind::Int128: + case SimpleTypeKind::Int128Oct: case SimpleTypeKind::UInt128: + case SimpleTypeKind::UInt128Oct: case SimpleTypeKind::Float128: return 16; case SimpleTypeKind::Complex80: @@ -1008,10 +1024,15 @@ size_t lldb_private::npdb::GetTypeSizeForSimpleKind(SimpleTypeKind kind) { case SimpleTypeKind::Int64: case SimpleTypeKind::Int64Quad: return 8; + case SimpleTypeKind::Complex48: + case SimpleTypeKind::Float48: + return 6; case SimpleTypeKind::Boolean32: case SimpleTypeKind::Character32: case SimpleTypeKind::Complex32: + case SimpleTypeKind::Complex32PartialPrecision: case SimpleTypeKind::Float32: + case SimpleTypeKind::Float32PartialPrecision: case SimpleTypeKind::Int32: case SimpleTypeKind::Int32Long: case SimpleTypeKind::UInt32Long: @@ -1020,6 +1041,7 @@ size_t lldb_private::npdb::GetTypeSizeForSimpleKind(SimpleTypeKind kind) { return 4; case SimpleTypeKind::Boolean16: case SimpleTypeKind::Character16: + case SimpleTypeKind::Complex16: case SimpleTypeKind::Float16: case SimpleTypeKind::Int16: case SimpleTypeKind::Int16Short: @@ -1035,10 +1057,13 @@ size_t lldb_private::npdb::GetTypeSizeForSimpleKind(SimpleTypeKind kind) { case SimpleTypeKind::SByte: case SimpleTypeKind::Character8: return 1; + case SimpleTypeKind::Void: - default: + case SimpleTypeKind::None: + case SimpleTypeKind::NotTranslated: return 0; } + return 0; } PdbTypeSymId lldb_private::npdb::GetBestPossibleDecl(PdbTypeSymId id, diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp index 8b3d775afc16..ecd3188b3d56 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -152,14 +152,24 @@ static bool IsFunctionEpilogue(const CompilandIndexItem &cci, return false; } +// See llvm::codeview::TypeIndex::simpleTypeName as well as strForPrimitiveTi +// from the original pdbdump: +// https://github.com/microsoft/microsoft-pdb/blob/805655a28bd8198004be2ac27e6e0290121a5e89/pdbdump/pdbdump.cpp#L1896-L1974 +// +// For 64bit integers we use "long long" like DIA instead of "__int64". static llvm::StringRef GetSimpleTypeName(SimpleTypeKind kind) { switch (kind) { case SimpleTypeKind::Boolean128: - case SimpleTypeKind::Boolean16: - case SimpleTypeKind::Boolean32: + return "__bool128"; case SimpleTypeKind::Boolean64: + return "__bool64"; + case SimpleTypeKind::Boolean32: + return "__bool32"; + case SimpleTypeKind::Boolean16: + return "__bool16"; case SimpleTypeKind::Boolean8: return "bool"; + case SimpleTypeKind::Byte: case SimpleTypeKind::UnsignedCharacter: return "unsigned char"; @@ -168,57 +178,81 @@ static llvm::StringRef GetSimpleTypeName(SimpleTypeKind kind) { case SimpleTypeKind::SignedCharacter: case SimpleTypeKind::SByte: return "signed char"; - case SimpleTypeKind::Character16: - return "char16_t"; case SimpleTypeKind::Character32: return "char32_t"; + case SimpleTypeKind::Character16: + return "char16_t"; case SimpleTypeKind::Character8: return "char8_t"; + + case SimpleTypeKind::Complex128: + return "_Complex __float128"; case SimpleTypeKind::Complex80: + return "_Complex long double"; case SimpleTypeKind::Complex64: + return "_Complex double"; + case SimpleTypeKind::Complex48: + return "_Complex __float48"; case SimpleTypeKind::Complex32: - return "complex"; + case SimpleTypeKind::Complex32PartialPrecision: + return "_Complex float"; + case SimpleTypeKind::Complex16: + return "_Complex _Float16"; + case SimpleTypeKind::Float128: + return "__float128"; case SimpleTypeKind::Float80: return "long double"; case SimpleTypeKind::Float64: return "double"; + case SimpleTypeKind::Float48: + return "__float48"; case SimpleTypeKind::Float32: + case SimpleTypeKind::Float32PartialPrecision: return "float"; case SimpleTypeKind::Float16: - return "single"; + return "_Float16"; + + case SimpleTypeKind::Int128Oct: case SimpleTypeKind::Int128: return "__int128"; case SimpleTypeKind::Int64: case SimpleTypeKind::Int64Quad: - return "int64_t"; + return "long long"; + case SimpleTypeKind::Int32Long: + return "long"; case SimpleTypeKind::Int32: return "int"; case SimpleTypeKind::Int16: + case SimpleTypeKind::Int16Short: return "short"; + + case SimpleTypeKind::UInt128Oct: case SimpleTypeKind::UInt128: return "unsigned __int128"; case SimpleTypeKind::UInt64: case SimpleTypeKind::UInt64Quad: - return "uint64_t"; - case SimpleTypeKind::HResult: - return "HRESULT"; + return "unsigned long long"; case SimpleTypeKind::UInt32: return "unsigned"; case SimpleTypeKind::UInt16: case SimpleTypeKind::UInt16Short: return "unsigned short"; - case SimpleTypeKind::Int32Long: - return "long"; case SimpleTypeKind::UInt32Long: return "unsigned long"; + + case SimpleTypeKind::HResult: + return "HRESULT"; case SimpleTypeKind::Void: return "void"; case SimpleTypeKind::WideCharacter: return "wchar_t"; - default: + + case SimpleTypeKind::None: + case SimpleTypeKind::NotTranslated: return ""; } + return ""; } static bool IsClassRecord(TypeLeafKind kind) { @@ -501,7 +535,11 @@ lldb::FunctionSP SymbolFileNativePDB::CreateFunction(PdbCompilandSymId func_id, return nullptr; PdbTypeSymId sig_id(proc.FunctionType, false); - Mangled mangled(proc.Name); + + std::optional<llvm::StringRef> mangled_opt = FindMangledSymbol( + SegmentOffset(proc.Segment, proc.CodeOffset), proc.FunctionType); + Mangled mangled(mangled_opt.value_or(proc.Name)); + FunctionSP func_sp = std::make_shared<Function>( &comp_unit, toOpaqueUid(func_id), toOpaqueUid(sig_id), mangled, func_type.get(), func_addr, @@ -594,8 +632,8 @@ lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti, uint64_t uid = toOpaqueUid(PdbTypeSymId(ti, false)); if (ti == TypeIndex::NullptrT()) { Declaration decl; - return MakeType(uid, ConstString("std::nullptr_t"), 0, nullptr, - LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct, + return MakeType(uid, ConstString("decltype(nullptr)"), std::nullopt, + nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct, Type::ResolveState::Full); } @@ -2137,14 +2175,17 @@ TypeSP SymbolFileNativePDB::CreateTypedef(PdbGlobalSymId id) { if (!ts) return nullptr; - ts->GetNativePDBParser()->GetOrCreateTypedefDecl(id); + auto *typedef_decl = ts->GetNativePDBParser()->GetOrCreateTypedefDecl(id); + + CompilerType ct = target_type->GetForwardCompilerType(); + if (auto *clang = llvm::dyn_cast_or_null<TypeSystemClang>(ts.get())) + ct = clang->GetType(clang->getASTContext().getTypeDeclType(typedef_decl)); Declaration decl; return MakeType(toOpaqueUid(id), ConstString(udt.Name), llvm::expectedToOptional(target_type->GetByteSize(nullptr)), nullptr, target_type->GetID(), - lldb_private::Type::eEncodingIsTypedefUID, decl, - target_type->GetForwardCompilerType(), + lldb_private::Type::eEncodingIsTypedefUID, decl, ct, lldb_private::Type::ResolveState::Forward); } @@ -2662,6 +2703,83 @@ SymbolFileNativePDB::GetContextForType(TypeIndex ti) { return ctx; } +std::optional<llvm::StringRef> +SymbolFileNativePDB::FindMangledFunctionName(PdbCompilandSymId func_id) { + const CompilandIndexItem *cci = + m_index->compilands().GetCompiland(func_id.modi); + if (!cci) + return std::nullopt; + + CVSymbol sym_record = cci->m_debug_stream.readSymbolAtOffset(func_id.offset); + if (sym_record.kind() != S_LPROC32 && sym_record.kind() != S_GPROC32) + return std::nullopt; + + ProcSym proc(static_cast<SymbolRecordKind>(sym_record.kind())); + cantFail(SymbolDeserializer::deserializeAs<ProcSym>(sym_record, proc)); + + return FindMangledSymbol(SegmentOffset(proc.Segment, proc.CodeOffset), + proc.FunctionType); +} + +std::optional<llvm::StringRef> +SymbolFileNativePDB::FindMangledSymbol(SegmentOffset so, + TypeIndex function_type) { + auto symbol = m_index->publics().findByAddress(m_index->symrecords(), + so.segment, so.offset); + if (!symbol) + return std::nullopt; + + llvm::StringRef name = symbol->first.Name; + // For functions, we might need to strip the mangled name. See + // StripMangledFunctionName for more info. + if (!function_type.isNoneType() && + (symbol->first.Flags & PublicSymFlags::Function) != PublicSymFlags::None) + name = StripMangledFunctionName(name, function_type); + + return name; +} + +llvm::StringRef +SymbolFileNativePDB::StripMangledFunctionName(const llvm::StringRef mangled, + PdbTypeSymId func_ty) { + // "In non-64 bit environments" (on x86 in pactice), __cdecl functions get + // prefixed with an underscore. For compilers using LLVM, this happens in LLVM + // (as opposed to the compiler frontend). Because of this, DWARF doesn't + // contain the "full" mangled name in DW_AT_linkage_name for these functions. + // We strip the mangling here for compatibility with DWARF. See + // llvm.org/pr161676 and + // https://learn.microsoft.com/en-us/cpp/build/reference/decorated-names#FormatC + + if (!mangled.starts_with('_') || + m_index->dbi().getMachineType() != PDB_Machine::x86) + return mangled; + + CVType cvt = m_index->tpi().getType(func_ty.index); + PDB_CallingConv cc = PDB_CallingConv::NearC; + if (cvt.kind() == LF_PROCEDURE) { + ProcedureRecord proc; + if (llvm::Error error = + TypeDeserializer::deserializeAs<ProcedureRecord>(cvt, proc)) + llvm::consumeError(std::move(error)); + cc = proc.CallConv; + } else if (cvt.kind() == LF_MFUNCTION) { + MemberFunctionRecord mfunc; + if (llvm::Error error = + TypeDeserializer::deserializeAs<MemberFunctionRecord>(cvt, mfunc)) + llvm::consumeError(std::move(error)); + cc = mfunc.CallConv; + } else { + LLDB_LOG(GetLog(LLDBLog::Symbols), "Unexpected function type, got {0}", + cvt.kind()); + return mangled; + } + + if (cc == PDB_CallingConv::NearC || cc == PDB_CallingConv::FarC) + return mangled.drop_front(); + + return mangled; +} + void SymbolFileNativePDB::CacheUdtDeclarations() { for (CVType cvt : m_index->ipi().typeArray()) { switch (cvt.kind()) { diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h index 2405f8b29933..a5fef354af65 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h @@ -140,6 +140,12 @@ public: std::optional<PdbCompilandSymId> FindSymbolScope(PdbCompilandSymId id); + /// Find the mangled name for a function + /// + /// \param id A symbol ID of a S_LPROC32/S_GPROC32 record + /// \returns The mangled name of the function (if available) + std::optional<llvm::StringRef> FindMangledFunctionName(PdbCompilandSymId id); + void FindTypes(const lldb_private::TypeQuery &match, lldb_private::TypeResults &results) override; @@ -269,6 +275,20 @@ private: void CacheUdtDeclarations(); llvm::Expected<Declaration> ResolveUdtDeclaration(PdbTypeSymId type_id); + /// Find a symbol name at a specific address (`so`). + /// + /// \param[in] so The segment and offset where the symbol is located. + /// \param[in] function_type If the symbol is expected to be a function, this + /// has to be the type of the function. It's used to strip the name of + /// __cdecl functions on x86. + /// \returns The mangled symbol name if found, otherwise `std::nullopt`. + std::optional<llvm::StringRef> FindMangledSymbol( + SegmentOffset so, + llvm::codeview::TypeIndex function_type = llvm::codeview::TypeIndex()); + + llvm::StringRef StripMangledFunctionName(llvm::StringRef mangled, + PdbTypeSymId func_ty); + llvm::BumpPtrAllocator m_allocator; lldb::addr_t m_obj_load_address = 0; |
