llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-lldb Author: firmiana (firmiana402) <details> <summary>Changes</summary> `SymbolFileDWARF::CollectCallEdges` only scanned direct children of a concrete subprogram DIE. GCC can place a call made from an inlined function under the corresponding `DW_TAG_inlined_subroutine`, so LLDB did not record the edge. `DW_OP_entry_value` evaluation then failed after skipping the synthetic inline frame and looking up the return address in the concrete parent function. Recursively collect call-site DIEs from the concrete function's child scopes while stopping at nested `DW_TAG_subprogram` entries, whose call sites belong to another function. The existing parsing of each call-site DIE remains unchanged. Add a DWARF YAML unit test covering both a call site nested in an inline instance and the nested-subprogram traversal boundary. Fixes #<!-- -->219198 --- Full diff: https://github.com/llvm/llvm-project/pull/219213.diff 3 Files Affected: - (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (+19-9) - (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h (+2-2) - (modified) lldb/unittests/SymbolFile/DWARF/SymbolFileDWARFTests.cpp (+70) ``````````diff diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 81cd4444161f7..c26b7d2386ac2 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -4194,6 +4194,21 @@ CollectCallSiteParameters(ModuleSP module, DWARFDIE call_site_die) { return parameters; } +static void CollectCallSiteDIEs(DWARFDIE parent, + std::vector<DWARFDIE> &call_site_dies) { + for (DWARFDIE child : parent.children()) { + if (child.Tag() == DW_TAG_call_site || + child.Tag() == DW_TAG_GNU_call_site) { + call_site_dies.push_back(child); + continue; + } + + // A nested subprogram owns its call sites independently of this function. + if (child.Tag() != DW_TAG_subprogram) + CollectCallSiteDIEs(child, call_site_dies); + } +} + /// Collect call graph edges present in a function DIE. std::vector<std::unique_ptr<lldb_private::CallEdge>> SymbolFileDWARF::CollectCallEdges(ModuleSP module, DWARFDIE function_die) { @@ -4209,16 +4224,11 @@ SymbolFileDWARF::CollectCallEdges(ModuleSP module, DWARFDIE function_die) { LLDB_LOG(log, "CollectCallEdges: Found call site info in {0}", function_die.GetPubname()); - // Scan the DIE for TAG_call_site entries. - // TODO: A recursive scan of all blocks in the subprogram is needed in order - // to be DWARF5-compliant. This may need to be done lazily to be performant. - // For now, assume that all entries are nested directly under the subprogram - // (this is the kind of DWARF LLVM produces) and parse them eagerly. - std::vector<std::unique_ptr<CallEdge>> call_edges; - for (DWARFDIE child : function_die.children()) { - if (child.Tag() != DW_TAG_call_site && child.Tag() != DW_TAG_GNU_call_site) - continue; + std::vector<DWARFDIE> call_site_dies; + CollectCallSiteDIEs(function_die, call_site_dies); + std::vector<std::unique_ptr<CallEdge>> call_edges; + for (DWARFDIE child : call_site_dies) { std::optional<DWARFDIE> call_origin; std::optional<DWARFExpressionList> call_target; addr_t return_pc = LLDB_INVALID_ADDRESS; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 9879fc4fe922c..1d8e24d272e86 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -486,8 +486,8 @@ class SymbolFileDWARF : public SymbolFileCommon { bool ClassContainsSelector(const DWARFDIE &class_die, ConstString selector); - /// Parse call site entries (DW_TAG_call_site), including any nested call site - /// parameters (DW_TAG_call_site_parameter). + /// Parse call site entries (DW_TAG_call_site), including entries in nested + /// scopes and their call site parameters (DW_TAG_call_site_parameter). std::vector<std::unique_ptr<CallEdge>> CollectCallEdges(lldb::ModuleSP module, DWARFDIE function_die); diff --git a/lldb/unittests/SymbolFile/DWARF/SymbolFileDWARFTests.cpp b/lldb/unittests/SymbolFile/DWARF/SymbolFileDWARFTests.cpp index 7f477f1913f9c..d26a78d743bbf 100644 --- a/lldb/unittests/SymbolFile/DWARF/SymbolFileDWARFTests.cpp +++ b/lldb/unittests/SymbolFile/DWARF/SymbolFileDWARFTests.cpp @@ -22,6 +22,7 @@ #include "Plugins/SymbolFile/PDB/SymbolFilePDB.h" #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" #include "TestingSupport/SubsystemRAII.h" +#include "TestingSupport/Symbol/YAMLModuleTester.h" #include "TestingSupport/TestUtilities.h" #include "lldb/Core/Address.h" #include "lldb/Core/Module.h" @@ -29,6 +30,7 @@ #include "lldb/Host/FileSystem.h" #include "lldb/Host/HostInfo.h" #include "lldb/Symbol/CompileUnit.h" +#include "lldb/Symbol/Function.h" #include "lldb/Symbol/LineTable.h" #include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/DataEncoder.h" @@ -69,6 +71,74 @@ TEST_F(SymbolFileDWARFTests, TestAbilitiesForDWARF) { EXPECT_EQ(expected_abilities, symfile->CalculateAbilities()); } +TEST(SymbolFileDWARFCallEdgeTests, ParseCallSiteNestedInInline) { + const char *yamldata = R"( +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +DWARF: + debug_abbrev: + - Table: + - Code: 0x1 + Tag: DW_TAG_compile_unit + Children: DW_CHILDREN_yes + - Code: 0x2 + Tag: DW_TAG_subprogram + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_call_all_calls + Form: DW_FORM_flag_present + - Code: 0x3 + Tag: DW_TAG_inlined_subroutine + Children: DW_CHILDREN_yes + - Code: 0x4 + Tag: DW_TAG_call_site + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_call_target + Form: DW_FORM_exprloc + - Attribute: DW_AT_call_return_pc + Form: DW_FORM_addr + debug_info: + - Version: 5 + UnitType: DW_UT_compile + AddrSize: 8 + Entries: + - AbbrCode: 0x1 + - AbbrCode: 0x2 + - AbbrCode: 0x3 + - AbbrCode: 0x4 + Values: + - Value: 0x1 + BlockData: + - 0x50 # DW_OP_reg0 + - Value: 0x1234 + - AbbrCode: 0x0 + - AbbrCode: 0x2 + - AbbrCode: 0x4 + Values: + - Value: 0x1 + BlockData: + - 0x50 # DW_OP_reg0 + - Value: 0x5678 + - AbbrCode: 0x0 + - AbbrCode: 0x0 + - AbbrCode: 0x0 +)"; + + YAMLModuleTester t(yamldata); + auto *symbol_file = + llvm::cast<SymbolFileDWARF>(t.GetModule()->GetSymbolFile()); + DWARFDIE function_die = t.GetDwarfUnit()->DIE().GetFirstChild(); + + auto call_edges = symbol_file->ParseCallEdgesInFunction(function_die.GetID()); + ASSERT_EQ(call_edges.size(), 1u); + EXPECT_EQ(call_edges.front()->GetSortKey().second, 0x1234u); +} + TEST_F(SymbolFileDWARFTests, ParseArangesNonzeroSegmentSize) { // This `.debug_aranges` table header is a valid 32bit big-endian section // according to the DWARFv5 spec:6.2.1, but contains segment selectors which `````````` </details> https://github.com/llvm/llvm-project/pull/219213 _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
