diff options
Diffstat (limited to 'lldb/source/Plugins/SymbolFile')
3 files changed, 114 insertions, 8 deletions
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp index 51bdcc9..e7fddf0 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/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp index 8b3d775..75a8189 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -501,7 +501,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, @@ -2662,6 +2666,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 2405f8b..a5fef35 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; |