[Lldb-commits] [lldb] [lldb] Expose block equality with SBBlock. (PR #184222)
John Harrison via lldb-commits
lldb-commits at lists.llvm.org
Tue Mar 3 14:03:06 PST 2026
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/184222
>From 0e4436f7ef573e456a9eda568eb9515ab348317e Mon Sep 17 00:00:00 2001
From: John Harrison <harjohn at google.com>
Date: Mon, 2 Mar 2026 11:57:20 -0800
Subject: [PATCH 1/5] [lldb] Expose block id in SBBlock.
Exposing the block id in SBBlock. You can indirectly access this with 'GetDescription' but this should be more consistent.
Additionally adding the `operator==` and `operator!=` for SBBlock. This should allow us to uniquely identify blocks in a SBFunction/SBFrame for a refactor to lldb-dap scope handling.
---
lldb/include/lldb/API/SBBlock.h | 7 +++++++
lldb/source/API/SBBlock.cpp | 29 ++++++++++++++++++++++++-----
2 files changed, 31 insertions(+), 5 deletions(-)
diff --git a/lldb/include/lldb/API/SBBlock.h b/lldb/include/lldb/API/SBBlock.h
index de4bb22be2692..ab9918c9eb6fa 100644
--- a/lldb/include/lldb/API/SBBlock.h
+++ b/lldb/include/lldb/API/SBBlock.h
@@ -15,6 +15,7 @@
#include "lldb/API/SBFrame.h"
#include "lldb/API/SBTarget.h"
#include "lldb/API/SBValueList.h"
+#include "lldb/lldb-types.h"
namespace lldb {
@@ -32,8 +33,14 @@ class LLDB_API SBBlock {
explicit operator bool() const;
+ bool operator==(const lldb::SBBlock &rhs) const;
+
+ bool operator!=(const lldb::SBBlock &rhs) const;
+
bool IsValid() const;
+ lldb::user_id_t GetID() const;
+
const char *GetInlinedName() const;
lldb::SBFileSpec GetInlinedCallSiteFile() const;
diff --git a/lldb/source/API/SBBlock.cpp b/lldb/source/API/SBBlock.cpp
index 2ef4cc7227cf9..881ce961ec4f6 100644
--- a/lldb/source/API/SBBlock.cpp
+++ b/lldb/source/API/SBBlock.cpp
@@ -1,4 +1,4 @@
-//===-- SBBlock.cpp -------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -18,10 +18,9 @@
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/VariableList.h"
-#include "lldb/Target/StackFrame.h"
-#include "lldb/Target/Target.h"
#include "lldb/Utility/Instrumentation.h"
#include "lldb/ValueObject/ValueObjectVariable.h"
+#include "lldb/lldb-types.h"
using namespace lldb;
using namespace lldb_private;
@@ -54,6 +53,25 @@ SBBlock::operator bool() const {
return m_opaque_ptr != nullptr;
}
+bool SBBlock::operator==(const SBBlock &rhs) const {
+ LLDB_INSTRUMENT_VA(this, rhs);
+
+ return *m_opaque_ptr == *rhs.m_opaque_ptr;
+}
+
+bool SBBlock::operator!=(const SBBlock &rhs) const {
+ LLDB_INSTRUMENT_VA(this, rhs);
+
+ return *m_opaque_ptr != *rhs.m_opaque_ptr;
+}
+
+user_id_t SBBlock::GetID() const {
+ LLDB_INSTRUMENT_VA(this);
+ if (m_opaque_ptr)
+ return m_opaque_ptr->GetID();
+ return LLDB_INVALID_UID;
+}
+
bool SBBlock::IsInlined() const {
LLDB_INSTRUMENT_VA(this);
@@ -116,8 +134,9 @@ void SBBlock::AppendVariables(bool can_create, bool get_parent_variables,
lldb_private::VariableList *var_list) {
if (IsValid()) {
bool show_inline = true;
- m_opaque_ptr->AppendVariables(can_create, get_parent_variables, show_inline,
- [](Variable *) { return true; }, var_list);
+ m_opaque_ptr->AppendVariables(
+ can_create, get_parent_variables, show_inline,
+ [](Variable *) { return true; }, var_list);
}
}
>From e276475b443d13a3a92ba16026a21e2bab2a5b02 Mon Sep 17 00:00:00 2001
From: John Harrison <harjohn at google.com>
Date: Tue, 3 Mar 2026 10:44:24 -0800
Subject: [PATCH 2/5] Creating unit tests and addressing a null ptr exception.
---
lldb/source/API/SBBlock.cpp | 5 +-
lldb/test/API/python_api/block/Makefile | 3 +
lldb/test/API/python_api/block/TestBlocks.py | 68 ++++++++++++++++++++
lldb/test/API/python_api/block/main.c | 18 ++++++
4 files changed, 92 insertions(+), 2 deletions(-)
create mode 100644 lldb/test/API/python_api/block/Makefile
create mode 100644 lldb/test/API/python_api/block/TestBlocks.py
create mode 100644 lldb/test/API/python_api/block/main.c
diff --git a/lldb/source/API/SBBlock.cpp b/lldb/source/API/SBBlock.cpp
index 881ce961ec4f6..759725b87e8cd 100644
--- a/lldb/source/API/SBBlock.cpp
+++ b/lldb/source/API/SBBlock.cpp
@@ -56,13 +56,14 @@ SBBlock::operator bool() const {
bool SBBlock::operator==(const SBBlock &rhs) const {
LLDB_INSTRUMENT_VA(this, rhs);
- return *m_opaque_ptr == *rhs.m_opaque_ptr;
+ return m_opaque_ptr != nullptr && rhs.m_opaque_ptr != nullptr &&
+ *m_opaque_ptr == *rhs.m_opaque_ptr;
}
bool SBBlock::operator!=(const SBBlock &rhs) const {
LLDB_INSTRUMENT_VA(this, rhs);
- return *m_opaque_ptr != *rhs.m_opaque_ptr;
+ return !(*this == rhs);
}
user_id_t SBBlock::GetID() const {
diff --git a/lldb/test/API/python_api/block/Makefile b/lldb/test/API/python_api/block/Makefile
new file mode 100644
index 0000000000000..10495940055b6
--- /dev/null
+++ b/lldb/test/API/python_api/block/Makefile
@@ -0,0 +1,3 @@
+C_SOURCES := main.c
+
+include Makefile.rules
diff --git a/lldb/test/API/python_api/block/TestBlocks.py b/lldb/test/API/python_api/block/TestBlocks.py
new file mode 100644
index 0000000000000..13ea26a284ea9
--- /dev/null
+++ b/lldb/test/API/python_api/block/TestBlocks.py
@@ -0,0 +1,68 @@
+"""
+Use lldb Python SBBlock API to access specific scopes within a frame.
+"""
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class BlockAPITestCase(TestBase):
+ def test_block_equality(self):
+ """Exercise SBBlock equality checks."""
+ self.build()
+ exe = self.getBuildArtifact("a.out")
+
+ # Create a target by the debugger.
+ target = self.dbg.CreateTarget(exe)
+ self.assertTrue(target, VALID_TARGET)
+
+ source = "main.c"
+ line1 = line_number(source, "// breakpoint 1")
+ line2 = line_number(source, "// breakpoint 2")
+ breakpoint1 = target.BreakpointCreateByLocation(source, line1)
+ breakpoint2 = target.BreakpointCreateByLocation(source, line2)
+ self.assertGreaterEqual(breakpoint1.GetNumLocations(), 1, PROCESS_IS_VALID)
+ self.assertGreaterEqual(breakpoint2.GetNumLocations(), 1, PROCESS_IS_VALID)
+
+ # Now launch the process, and do not stop at the entry point.
+ process = target.LaunchSimple(None, None, self.get_process_working_directory())
+ self.assertState(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED)
+
+ threads = lldbutil.get_threads_stopped_at_breakpoint(process, breakpoint1)
+ self.assertEqual(
+ len(threads), 1, "There should be a thread stopped at breakpoint 1"
+ )
+
+ thread = threads[0]
+ self.assertTrue(thread.IsValid(), "Thread must be valid")
+ frame = thread.GetFrameAtIndex(0)
+ self.assertTrue(frame.IsValid(), "Frame must be valid")
+
+ main_frame_block = frame.GetFrameBlock()
+ self.assertNotEqual(main_frame_block.GetID(), 0, "Invalid block id")
+
+ # Continue to breakpoint 2
+ process.Continue()
+
+ threads = lldbutil.get_threads_stopped_at_breakpoint(process, breakpoint2)
+ self.assertEqual(
+ len(threads), 1, "There should be a thread stopped at breakpoint 2"
+ )
+
+ thread = threads[0]
+ self.assertTrue(thread.IsValid(), "Thread must be valid")
+ frame = thread.GetFrameAtIndex(0)
+ self.assertTrue(frame.IsValid(), "Frame must be valid")
+
+ fn_frame_block = frame.GetFrameBlock()
+ self.assertNotEqual(fn_frame_block.GetID(), 0, "Invalid block id")
+
+ fn_inner_block = frame.GetBlock()
+ self.assertNotEqual(fn_inner_block.GetID(), 0, "Invalid block id")
+
+ # Check __eq__ / __ne__
+ self.assertNotEqual(fn_inner_block, fn_frame_block)
+ self.assertNotEqual(main_frame_block, fn_frame_block)
+ self.assertEqual(fn_inner_block.GetParent(), fn_frame_block)
diff --git a/lldb/test/API/python_api/block/main.c b/lldb/test/API/python_api/block/main.c
new file mode 100644
index 0000000000000..4c7ac493877ec
--- /dev/null
+++ b/lldb/test/API/python_api/block/main.c
@@ -0,0 +1,18 @@
+#include <stdio.h>
+
+int fn(int a, int b) {
+ if (a < b) {
+ int sum = a + b;
+ return sum; // breakpoint 2
+ }
+
+ return a * b;
+}
+
+int main(int argc, char const *argv[]) {
+ int a = 3;
+ int b = 17;
+ int sum = fn(a, b); // breakpoint 1
+ printf("fn(3, 17) returns %d\n", sum);
+ return 0;
+}
>From c144fd86af9154894f5faaa890686777db937c9d Mon Sep 17 00:00:00 2001
From: John Harrison <harjohn at google.com>
Date: Tue, 3 Mar 2026 10:48:24 -0800
Subject: [PATCH 3/5] Apply clang-format.
---
lldb/test/API/python_api/block/main.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/lldb/test/API/python_api/block/main.c b/lldb/test/API/python_api/block/main.c
index 4c7ac493877ec..dca1fef5fb07a 100644
--- a/lldb/test/API/python_api/block/main.c
+++ b/lldb/test/API/python_api/block/main.c
@@ -1,18 +1,18 @@
#include <stdio.h>
int fn(int a, int b) {
- if (a < b) {
- int sum = a + b;
- return sum; // breakpoint 2
- }
+ if (a < b) {
+ int sum = a + b;
+ return sum; // breakpoint 2
+ }
- return a * b;
+ return a * b;
}
int main(int argc, char const *argv[]) {
- int a = 3;
- int b = 17;
- int sum = fn(a, b); // breakpoint 1
- printf("fn(3, 17) returns %d\n", sum);
- return 0;
+ int a = 3;
+ int b = 17;
+ int sum = fn(a, b); // breakpoint 1
+ printf("fn(3, 17) returns %d\n", sum);
+ return 0;
}
>From 1b83018b18a7f318ee1fcc3185fb23de765b726d Mon Sep 17 00:00:00 2001
From: John Harrison <harjohn at google.com>
Date: Tue, 3 Mar 2026 13:44:42 -0800
Subject: [PATCH 4/5] Adjusting the SBBlock API to only expose an equality
check, instead of GetID() since GetID() is not unique enough across object
files.
---
lldb/include/lldb/API/SBBlock.h | 2 --
lldb/source/API/SBBlock.cpp | 10 +++-------
lldb/test/API/python_api/block/Makefile | 2 ++
lldb/test/API/python_api/block/TestBlocks.py | 13 ++++---------
lldb/test/API/python_api/block/fn.c | 8 ++++++++
lldb/test/API/python_api/block/main.c | 9 +--------
6 files changed, 18 insertions(+), 26 deletions(-)
create mode 100644 lldb/test/API/python_api/block/fn.c
diff --git a/lldb/include/lldb/API/SBBlock.h b/lldb/include/lldb/API/SBBlock.h
index ab9918c9eb6fa..153502a6f1122 100644
--- a/lldb/include/lldb/API/SBBlock.h
+++ b/lldb/include/lldb/API/SBBlock.h
@@ -39,8 +39,6 @@ class LLDB_API SBBlock {
bool IsValid() const;
- lldb::user_id_t GetID() const;
-
const char *GetInlinedName() const;
lldb::SBFileSpec GetInlinedCallSiteFile() const;
diff --git a/lldb/source/API/SBBlock.cpp b/lldb/source/API/SBBlock.cpp
index 759725b87e8cd..f8d9ba4f5431b 100644
--- a/lldb/source/API/SBBlock.cpp
+++ b/lldb/source/API/SBBlock.cpp
@@ -57,6 +57,9 @@ bool SBBlock::operator==(const SBBlock &rhs) const {
LLDB_INSTRUMENT_VA(this, rhs);
return m_opaque_ptr != nullptr && rhs.m_opaque_ptr != nullptr &&
+ m_opaque_ptr->GetFunction() == rhs.m_opaque_ptr->GetFunction() &&
+ m_opaque_ptr->GetFunction().GetCompileUnit() ==
+ rhs.m_opaque_ptr->GetFunction().GetCompileUnit() &&
*m_opaque_ptr == *rhs.m_opaque_ptr;
}
@@ -66,13 +69,6 @@ bool SBBlock::operator!=(const SBBlock &rhs) const {
return !(*this == rhs);
}
-user_id_t SBBlock::GetID() const {
- LLDB_INSTRUMENT_VA(this);
- if (m_opaque_ptr)
- return m_opaque_ptr->GetID();
- return LLDB_INVALID_UID;
-}
-
bool SBBlock::IsInlined() const {
LLDB_INSTRUMENT_VA(this);
diff --git a/lldb/test/API/python_api/block/Makefile b/lldb/test/API/python_api/block/Makefile
index 10495940055b6..19331dd4b3c59 100644
--- a/lldb/test/API/python_api/block/Makefile
+++ b/lldb/test/API/python_api/block/Makefile
@@ -1,3 +1,5 @@
C_SOURCES := main.c
+DYLIB_NAME := fn
+DYLIB_C_SOURCES := fn.c
include Makefile.rules
diff --git a/lldb/test/API/python_api/block/TestBlocks.py b/lldb/test/API/python_api/block/TestBlocks.py
index 13ea26a284ea9..07811e30615a2 100644
--- a/lldb/test/API/python_api/block/TestBlocks.py
+++ b/lldb/test/API/python_api/block/TestBlocks.py
@@ -18,11 +18,10 @@ def test_block_equality(self):
target = self.dbg.CreateTarget(exe)
self.assertTrue(target, VALID_TARGET)
- source = "main.c"
- line1 = line_number(source, "// breakpoint 1")
- line2 = line_number(source, "// breakpoint 2")
- breakpoint1 = target.BreakpointCreateByLocation(source, line1)
- breakpoint2 = target.BreakpointCreateByLocation(source, line2)
+ line1 = line_number("main.c", "// breakpoint 1")
+ line2 = line_number("fn.c", "// breakpoint 2")
+ breakpoint1 = target.BreakpointCreateByLocation("main.c", line1)
+ breakpoint2 = target.BreakpointCreateByLocation("fn.c", line2)
self.assertGreaterEqual(breakpoint1.GetNumLocations(), 1, PROCESS_IS_VALID)
self.assertGreaterEqual(breakpoint2.GetNumLocations(), 1, PROCESS_IS_VALID)
@@ -41,7 +40,6 @@ def test_block_equality(self):
self.assertTrue(frame.IsValid(), "Frame must be valid")
main_frame_block = frame.GetFrameBlock()
- self.assertNotEqual(main_frame_block.GetID(), 0, "Invalid block id")
# Continue to breakpoint 2
process.Continue()
@@ -57,10 +55,7 @@ def test_block_equality(self):
self.assertTrue(frame.IsValid(), "Frame must be valid")
fn_frame_block = frame.GetFrameBlock()
- self.assertNotEqual(fn_frame_block.GetID(), 0, "Invalid block id")
-
fn_inner_block = frame.GetBlock()
- self.assertNotEqual(fn_inner_block.GetID(), 0, "Invalid block id")
# Check __eq__ / __ne__
self.assertNotEqual(fn_inner_block, fn_frame_block)
diff --git a/lldb/test/API/python_api/block/fn.c b/lldb/test/API/python_api/block/fn.c
new file mode 100644
index 0000000000000..80ea7e5baa11e
--- /dev/null
+++ b/lldb/test/API/python_api/block/fn.c
@@ -0,0 +1,8 @@
+extern int fn(int a, int b) {
+ if (a < b) {
+ int sum = a + b;
+ return sum; // breakpoint 2
+ }
+
+ return a * b;
+}
diff --git a/lldb/test/API/python_api/block/main.c b/lldb/test/API/python_api/block/main.c
index dca1fef5fb07a..8200ecf5bdf4f 100644
--- a/lldb/test/API/python_api/block/main.c
+++ b/lldb/test/API/python_api/block/main.c
@@ -1,13 +1,6 @@
#include <stdio.h>
-int fn(int a, int b) {
- if (a < b) {
- int sum = a + b;
- return sum; // breakpoint 2
- }
-
- return a * b;
-}
+extern int fn(int a, int b);
int main(int argc, char const *argv[]) {
int a = 3;
>From 9a348ffb39ef323a1ea19275733e12862fe4a8a3 Mon Sep 17 00:00:00 2001
From: John Harrison <harjohn at google.com>
Date: Tue, 3 Mar 2026 14:02:24 -0800
Subject: [PATCH 5/5] Breakpoints should resolve later.
---
lldb/test/API/python_api/block/TestBlocks.py | 2 --
1 file changed, 2 deletions(-)
diff --git a/lldb/test/API/python_api/block/TestBlocks.py b/lldb/test/API/python_api/block/TestBlocks.py
index 07811e30615a2..7d2759abf1578 100644
--- a/lldb/test/API/python_api/block/TestBlocks.py
+++ b/lldb/test/API/python_api/block/TestBlocks.py
@@ -22,8 +22,6 @@ def test_block_equality(self):
line2 = line_number("fn.c", "// breakpoint 2")
breakpoint1 = target.BreakpointCreateByLocation("main.c", line1)
breakpoint2 = target.BreakpointCreateByLocation("fn.c", line2)
- self.assertGreaterEqual(breakpoint1.GetNumLocations(), 1, PROCESS_IS_VALID)
- self.assertGreaterEqual(breakpoint2.GetNumLocations(), 1, PROCESS_IS_VALID)
# Now launch the process, and do not stop at the entry point.
process = target.LaunchSimple(None, None, self.get_process_working_directory())
More information about the lldb-commits
mailing list