[llvm-branch-commits] [lldb] release/23.x: [lldb] Avoid returning a stale AddressOf (#212915) (PR #213377)
Douglas Yung via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Aug 20 16:49:08 PDT 2026
https://github.com/dyung updated https://github.com/llvm/llvm-project/pull/213377
>From fa4a3a18db4ce07f2d5c561c419b14c769b90df2 Mon Sep 17 00:00:00 2001
From: Igor Kudrin <ikudrin at accesssoftek.com>
Date: Fri, 31 Jul 2026 14:19:53 -0700
Subject: [PATCH] [lldb] Avoid returning a stale AddressOf (#212915)
The 'ValueObject::AddressOf()' method assumes that the address of a
value object cannot change, so when it is calculated once, it does not
need to be updated afterwards. However, this is not the case if the
'ValueObject' is a dependent object obtained by calling 'Dereference()'
of another 'ValueObject'. If the latter object is changed, the dependent
value object should return a new address from the 'AddressOf()' method
to reflect the change.
(cherry picked from commit 320164daab4148e3372f6756caaa67882e24a91f)
---
lldb/source/ValueObject/ValueObject.cpp | 7 +-
.../API/python_api/value/change_ptr/Makefile | 3 +
.../value/change_ptr/TestChangePtr.py | 65 +++++++++++++++++++
.../API/python_api/value/change_ptr/main.c | 31 +++++++++
4 files changed, 103 insertions(+), 3 deletions(-)
create mode 100644 lldb/test/API/python_api/value/change_ptr/Makefile
create mode 100644 lldb/test/API/python_api/value/change_ptr/TestChangePtr.py
create mode 100644 lldb/test/API/python_api/value/change_ptr/main.c
diff --git a/lldb/source/ValueObject/ValueObject.cpp b/lldb/source/ValueObject/ValueObject.cpp
index cac4933c64325..49fd513c7f578 100644
--- a/lldb/source/ValueObject/ValueObject.cpp
+++ b/lldb/source/ValueObject/ValueObject.cpp
@@ -2902,9 +2902,6 @@ ValueObjectSP ValueObject::Dereference(Status &error) {
}
ValueObjectSP ValueObject::AddressOf(Status &error) {
- if (m_addr_of_valobj_sp)
- return m_addr_of_valobj_sp;
-
auto [addr, address_type] = GetAddressOf(/*scalar_is_load_address=*/false);
error.Clear();
if (addr != LLDB_INVALID_ADDRESS && address_type != eAddressTypeHost) {
@@ -2918,6 +2915,10 @@ ValueObjectSP ValueObject::AddressOf(Status &error) {
case eAddressTypeFile:
case eAddressTypeLoad: {
+ if (m_addr_of_valobj_sp &&
+ m_addr_of_valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS) == addr)
+ return m_addr_of_valobj_sp;
+ m_addr_of_valobj_sp.reset();
CompilerType compiler_type = GetCompilerType();
if (compiler_type) {
std::string name(1, '&');
diff --git a/lldb/test/API/python_api/value/change_ptr/Makefile b/lldb/test/API/python_api/value/change_ptr/Makefile
new file mode 100644
index 0000000000000..10495940055b6
--- /dev/null
+++ b/lldb/test/API/python_api/value/change_ptr/Makefile
@@ -0,0 +1,3 @@
+C_SOURCES := main.c
+
+include Makefile.rules
diff --git a/lldb/test/API/python_api/value/change_ptr/TestChangePtr.py b/lldb/test/API/python_api/value/change_ptr/TestChangePtr.py
new file mode 100644
index 0000000000000..f68eeb8404d70
--- /dev/null
+++ b/lldb/test/API/python_api/value/change_ptr/TestChangePtr.py
@@ -0,0 +1,65 @@
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class ChangePtrTest(TestBase):
+ def test(self):
+ self.build()
+
+ src_file = lldb.SBFileSpec("main.c")
+ _, process, thread, _ = lldbutil.run_to_source_breakpoint(
+ self, "// break here 1", src_file
+ )
+
+ ## Test 1: The AddressOf of a dereferenced value should change when
+ ## the pointer value is updated.
+
+ frame = thread.GetFrameAtIndex(0)
+ p = frame.FindVariable("p")
+ deref = p.Dereference()
+ self.assertEqual(deref.GetValueAsUnsigned(), 5)
+ self.assertEqual(deref.AddressOf().GetValueAsUnsigned(), p.GetValueAsUnsigned())
+ thread.StepOver()
+ self.assertEqual(deref.GetValueAsUnsigned(), 7)
+ self.assertEqual(deref.AddressOf().GetValueAsUnsigned(), p.GetValueAsUnsigned())
+
+ ## Test 2: The AddressOf of a child value of a dereferenced value should
+ ## change when the base pointer updates.
+
+ lldbutil.continue_to_source_breakpoint(
+ self, process, "// break here 2", src_file
+ )
+ frame = thread.GetFrameAtIndex(0)
+ p = frame.FindVariable("p")
+ deref_child = p.Dereference().GetChildMemberWithName("b")
+ self.assertEqual(deref_child.GetValue(), "'b'")
+ self.assertEqual(
+ deref_child.AddressOf().GetValueAsUnsigned(), p.GetValueAsUnsigned() + 1
+ )
+ thread.StepOver()
+ self.assertEqual(deref_child.GetValue(), "'d'")
+ self.assertEqual(
+ deref_child.AddressOf().GetValueAsUnsigned(), p.GetValueAsUnsigned() + 1
+ )
+
+ ## Test 3: Verify AddressOf updates correctly with persistent expression results.
+ lldbutil.continue_to_source_breakpoint(
+ self, process, "// break here 3", src_file
+ )
+ frame = thread.GetFrameAtIndex(0)
+ frame.EvaluateExpression("int *$ptr = &a")
+ ptr = frame.FindValue("$ptr", lldb.eValueTypeConstResult)
+ deref = ptr.Dereference()
+ self.assertEqual(deref.GetValueAsUnsigned(), 5)
+ self.assertEqual(
+ deref.AddressOf().GetValueAsUnsigned(),
+ frame.FindVariable("a").AddressOf().GetValueAsUnsigned(),
+ )
+ frame.EvaluateExpression("$ptr = &b")
+ self.assertEqual(deref.GetValueAsUnsigned(), 7)
+ self.assertEqual(
+ deref.AddressOf().GetValueAsUnsigned(),
+ frame.FindVariable("b").AddressOf().GetValueAsUnsigned(),
+ )
diff --git a/lldb/test/API/python_api/value/change_ptr/main.c b/lldb/test/API/python_api/value/change_ptr/main.c
new file mode 100644
index 0000000000000..4cce83e61476c
--- /dev/null
+++ b/lldb/test/API/python_api/value/change_ptr/main.c
@@ -0,0 +1,31 @@
+int test1() {
+ int a = 5;
+ int b = 7;
+ int *p = &a;
+ p = &b; // break here 1
+ return *p;
+}
+
+char test2() {
+ struct S {
+ char a;
+ char b;
+ };
+ struct S arr[2] = {{'a', 'b'}, {'c', 'd'}};
+ struct S *p = arr;
+ ++p; // break here 2
+ return p->b;
+}
+
+int test3() {
+ int a = 5;
+ int b = 7;
+ return a + b; // break here 3
+}
+
+int main() {
+ test1();
+ test2();
+ test3();
+ return 0;
+}
More information about the llvm-branch-commits
mailing list