Skip to content

Commit 6b23fbf

Browse files
committed
Provide non-dereferenced memory references
1 parent 12f37b6 commit 6b23fbf

File tree

5 files changed

+47
-84
lines changed

5 files changed

+47
-84
lines changed

lldb/test/API/tools/lldb-dap/memory/TestDAP_memory.py

Lines changed: 41 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212

1313

1414
class TestDAP_memory(lldbdap_testcase.DAPTestCaseBase):
15-
def test_readMemory(self):
15+
def test_memory_refs_variables(self):
1616
"""
17-
Tests the 'readMemory' request
17+
Tests memory references for evaluate
1818
"""
1919
program = self.getBuildArtifact("a.out")
2020
self.build_and_launch(program)
@@ -27,33 +27,13 @@ def test_readMemory(self):
2727
self.continue_to_next_stop()
2828

2929
locals = {l["name"]: l for l in self.dap_server.get_local_variables()}
30-
rawptr_ref = locals["rawptr"]["memoryReference"]
31-
32-
# We can read the complete string
33-
mem = self.dap_server.request_readMemory(rawptr_ref, 0, 5)["body"]
34-
self.assertEqual(mem["unreadableBytes"], 0)
35-
self.assertEqual(b64decode(mem["data"]), b"dead\0")
36-
37-
# Use an offset
38-
mem = self.dap_server.request_readMemory(rawptr_ref, 2, 3)["body"]
39-
self.assertEqual(b64decode(mem["data"]), b"ad\0")
40-
41-
# Use a negative offset
42-
mem = self.dap_server.request_readMemory(rawptr_ref, -1, 6)["body"]
43-
self.assertEqual(b64decode(mem["data"])[1:], b"dead\0")
44-
45-
# Reads of size 0 are successful
46-
# VS-Code sends those in order to check if a `memoryReference` can actually be dereferenced.
47-
mem = self.dap_server.request_readMemory(rawptr_ref, 0, 0)
48-
self.assertEqual(mem["success"], True)
49-
self.assertEqual(mem["body"]["data"], "")
5030

51-
# Reads at offset 0x0 fail
52-
mem = self.dap_server.request_readMemory("0x0", 0, 6)
53-
self.assertEqual(mem["success"], False)
54-
self.assertEqual(mem["message"], "Memory region is not readable")
31+
# Pointers should have memory-references
32+
self.assertIn("memoryReference", locals["rawptr"].keys())
33+
# Non-pointers should also have memory-references
34+
self.assertIn("memoryReference", locals["not_a_ptr"].keys())
5535

56-
def test_memory_refs_variables(self):
36+
def test_memory_refs_evaluate(self):
5737
"""
5838
Tests memory references for evaluate
5939
"""
@@ -67,21 +47,14 @@ def test_memory_refs_variables(self):
6747
)
6848
self.continue_to_next_stop()
6949

70-
locals = {l["name"]: l for l in self.dap_server.get_local_variables()}
71-
72-
# Pointers should have memory-references
73-
self.assertIn("memoryReference", locals["rawptr"].keys())
74-
# Smart pointers also have memory-references
7550
self.assertIn(
7651
"memoryReference",
77-
self.dap_server.get_local_variable_child("smartptr", "pointer").keys(),
52+
self.dap_server.request_evaluate("rawptr")["body"].keys(),
7853
)
79-
# Non-pointers should not have memory-references
80-
self.assertNotIn("memoryReference", locals["not_a_ptr"].keys())
8154

82-
def test_memory_refs_evaluate(self):
55+
def test_memory_refs_set_variable(self):
8356
"""
84-
Tests memory references for evaluate
57+
Tests memory references for `setVariable`
8558
"""
8659
program = self.getBuildArtifact("a.out")
8760
self.build_and_launch(program)
@@ -93,21 +66,17 @@ def test_memory_refs_evaluate(self):
9366
)
9467
self.continue_to_next_stop()
9568

96-
# Pointers contain memory references
69+
ptr_value = self.get_local_as_int("rawptr")
9770
self.assertIn(
9871
"memoryReference",
99-
self.dap_server.request_evaluate("rawptr + 1")["body"].keys(),
100-
)
101-
102-
# Non-pointer expressions don't include a memory reference
103-
self.assertNotIn(
104-
"memoryReference",
105-
self.dap_server.request_evaluate("1 + 3")["body"].keys(),
72+
self.dap_server.request_setVariable(1, "rawptr", ptr_value + 2)[
73+
"body"
74+
].keys(),
10675
)
10776

108-
def test_memory_refs_set_variable(self):
77+
def test_readMemory(self):
10978
"""
110-
Tests memory references for `setVariable`
79+
Tests the 'readMemory' request
11180
"""
11281
program = self.getBuildArtifact("a.out")
11382
self.build_and_launch(program)
@@ -119,17 +88,29 @@ def test_memory_refs_set_variable(self):
11988
)
12089
self.continue_to_next_stop()
12190

122-
# Pointers contain memory references
123-
ptr_value = self.get_local_as_int("rawptr")
124-
self.assertIn(
125-
"memoryReference",
126-
self.dap_server.request_setVariable(1, "rawptr", ptr_value + 2)[
127-
"body"
128-
].keys(),
129-
)
91+
ptr_deref = self.dap_server.request_evaluate("*rawptr")["body"]
92+
memref = ptr_deref["memoryReference"]
13093

131-
# Non-pointer expressions don't include a memory reference
132-
self.assertNotIn(
133-
"memoryReference",
134-
self.dap_server.request_setVariable(1, "not_a_ptr", 42)["body"].keys(),
135-
)
94+
# We can read the complete string
95+
mem = self.dap_server.request_readMemory(memref, 0, 5)["body"]
96+
self.assertEqual(mem["unreadableBytes"], 0)
97+
self.assertEqual(b64decode(mem["data"]), b"dead\0")
98+
99+
# Use an offset
100+
mem = self.dap_server.request_readMemory(memref, 2, 3)["body"]
101+
self.assertEqual(b64decode(mem["data"]), b"ad\0")
102+
103+
# Use a negative offset
104+
mem = self.dap_server.request_readMemory(memref, -1, 6)["body"]
105+
self.assertEqual(b64decode(mem["data"])[1:], b"dead\0")
106+
107+
# Reads of size 0 are successful
108+
# VS-Code sends those in order to check if a `memoryReference` can actually be dereferenced.
109+
mem = self.dap_server.request_readMemory(memref, 0, 0)
110+
self.assertEqual(mem["success"], True)
111+
self.assertEqual(mem["body"]["data"], "")
112+
113+
# Reads at offset 0x0 fail
114+
mem = self.dap_server.request_readMemory("0x0", 0, 6)
115+
self.assertEqual(mem["success"], False)
116+
self.assertEqual(mem["message"], "Memory region is not readable")

lldb/test/API/tools/lldb-dap/memory/main.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
int main() {
55
int not_a_ptr = 666;
66
const char *rawptr = "dead";
7-
std::unique_ptr<int> smartptr(new int(42));
87
// Breakpoint
98
return 0;
109
}

lldb/tools/lldb-dap/JSONUtils.cpp

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1195,17 +1195,6 @@ std::string VariableDescription::GetResult(llvm::StringRef context) {
11951195
return description.trim().str();
11961196
}
11971197

1198-
std::optional<lldb::addr_t> GetMemoryReference(lldb::SBValue v) {
1199-
if (!v.GetType().IsPointerType())
1200-
return std::nullopt;
1201-
1202-
lldb::SBValue deref = v.Dereference();
1203-
lldb::addr_t load_addr = deref.GetLoadAddress();
1204-
if (load_addr != LLDB_INVALID_ADDRESS)
1205-
return load_addr;
1206-
return std::nullopt;
1207-
}
1208-
12091198
// "Variable": {
12101199
// "type": "object",
12111200
// "description": "A Variable is a name/value pair. Optionally a variable
@@ -1382,8 +1371,8 @@ llvm::json::Value CreateVariable(lldb::SBValue v, int64_t variablesReference,
13821371
else
13831372
object.try_emplace("variablesReference", (int64_t)0);
13841373

1385-
if (std::optional<lldb::addr_t> addr = GetMemoryReference(v))
1386-
object.try_emplace("memoryReference", EncodeMemoryReference(*addr));
1374+
if (lldb::addr_t addr = v.GetLoadAddress(); addr != LLDB_INVALID_ADDRESS)
1375+
object.try_emplace("memoryReference", EncodeMemoryReference(addr));
13871376

13881377
object.try_emplace("$__lldb_extensions", desc.GetVariableExtensionsJSON());
13891378
return llvm::json::Value(std::move(object));

lldb/tools/lldb-dap/JSONUtils.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -448,12 +448,6 @@ struct VariableDescription {
448448
std::string GetResult(llvm::StringRef context);
449449
};
450450

451-
/// Get the corresponding `memoryReference` for a value.
452-
///
453-
/// According to the DAP documentation, the `memoryReference` should
454-
/// refer to the pointee, not to the address of the pointer itself.
455-
std::optional<lldb::addr_t> GetMemoryReference(lldb::SBValue v);
456-
457451
/// Create a "Variable" object for a LLDB thread object.
458452
///
459453
/// This function will fill in the following keys in the returned

lldb/tools/lldb-dap/lldb-dap.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1617,8 +1617,8 @@ void request_evaluate(const llvm::json::Object &request) {
16171617
} else {
16181618
body.try_emplace("variablesReference", (int64_t)0);
16191619
}
1620-
if (std::optional<lldb::addr_t> addr = GetMemoryReference(value))
1621-
body.try_emplace("memoryReference", EncodeMemoryReference(*addr));
1620+
if (lldb::addr_t addr = value.GetLoadAddress(); addr != LLDB_INVALID_ADDRESS)
1621+
body.try_emplace("memoryReference", EncodeMemoryReference(addr));
16221622
}
16231623
}
16241624
response.try_emplace("body", std::move(body));
@@ -3792,8 +3792,8 @@ void request_setVariable(const llvm::json::Object &request) {
37923792
variable, /*is_permanent=*/false);
37933793
body.try_emplace("variablesReference", newVariablesReference);
37943794

3795-
if (std::optional<lldb::addr_t> addr = GetMemoryReference(variable))
3796-
body.try_emplace("memoryReference", EncodeMemoryReference(*addr));
3795+
if (lldb::addr_t addr = variable.GetLoadAddress(); addr != LLDB_INVALID_ADDRESS)
3796+
body.try_emplace("memoryReference", EncodeMemoryReference(addr));
37973797
} else {
37983798
EmplaceSafeString(body, "message", std::string(error.GetCString()));
37993799
}

0 commit comments

Comments
 (0)