[Lldb-commits] [lldb] [lldb] Collect call sites nested in inline instances (PR #219213)

via lldb-commits lldb-commits at lists.llvm.org
Wed Sep 23 07:10:18 PDT 2026


https://github.com/firmiana402 updated https://github.com/llvm/llvm-project/pull/219213

>From 7f752ce4f65e00bcb12ab1f781953573f3b00594 Mon Sep 17 00:00:00 2001
From: firmiana402 <firmiana402 at gmail.com>
Date: Thu, 27 Aug 2026 20:30:45 +0800
Subject: [PATCH 1/2] [lldb] Collect call sites nested in inline instances

---
 .../SymbolFile/DWARF/SymbolFileDWARF.cpp      | 28 +++++---
 .../SymbolFile/DWARF/SymbolFileDWARF.h        |  4 +-
 .../SymbolFile/DWARF/SymbolFileDWARFTests.cpp | 70 +++++++++++++++++++
 3 files changed, 91 insertions(+), 11 deletions(-)

diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 41e3372584d4f4..9b2f24b908f20e 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -4198,6 +4198,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) {
@@ -4213,16 +4228,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 f76bcf16304ec8..42e6d962a80a19 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -488,8 +488,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 7f477f1913f9c4..d26a78d743bbf7 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

>From c48db6994f4ede8a24d8addcf4779a54eb4aac35 Mon Sep 17 00:00:00 2001
From: firmiana402 <firmiana402 at gmail.com>
Date: Wed, 23 Sep 2026 18:50:23 +0800
Subject: [PATCH 2/2] [lldb] Enhance call site collection with depth-limited
 traversal

---
 .../SymbolFile/DWARF/SymbolFileDWARF.cpp      | 38 ++++++++++++++-----
 1 file changed, 28 insertions(+), 10 deletions(-)

diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 9b2f24b908f20e..a0602daaac16a0 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -10,6 +10,7 @@
 #include "clang/Basic/ABI.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
@@ -4198,18 +4199,35 @@ CollectCallSiteParameters(ModuleSP module, DWARFDIE call_site_die) {
   return parameters;
 }
 
-static void CollectCallSiteDIEs(DWARFDIE parent,
+static void CollectCallSiteDIEs(DWARFDIE function_die,
                                 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;
-    }
+  // Bound traversal depth so malformed or unusually deep DWARF cannot cause
+  // unbounded traversal.
+  constexpr unsigned MaxScopeDepth = 8;
+  struct WorkItem {
+    DWARFDIE die;
+    unsigned depth;
+  };
 
-    // A nested subprogram owns its call sites independently of this function.
-    if (child.Tag() != DW_TAG_subprogram)
-      CollectCallSiteDIEs(child, call_site_dies);
+  llvm::SmallVector<WorkItem, 8> worklist;
+  worklist.push_back({function_die, 0});
+
+  while (!worklist.empty()) {
+    WorkItem item = worklist.pop_back_val();
+    for (DWARFDIE child : item.die.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 || item.depth >= MaxScopeDepth)
+        continue;
+
+      worklist.push_back({child, item.depth + 1});
+    }
   }
 }
 



More information about the lldb-commits mailing list