diff options
Diffstat (limited to 'lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp')
-rw-r--r-- | lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp | 83 |
1 files changed, 82 insertions, 1 deletions
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()) { |