Skip to content

Commit 1810753

Browse files
committed
[lldb-dap] Add memory event
1 parent acd0899 commit 1810753

File tree

8 files changed

+80
-0
lines changed

8 files changed

+80
-0
lines changed

lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ def __init__(
216216
self.events: List[Event] = []
217217
self.progress_events: List[Event] = []
218218
self.invalidated_event: Optional[Event] = None
219+
self.memory_event: Optional[Event] = None
219220
self.reverse_requests: List[Request] = []
220221
self.module_events: List[Dict] = []
221222
self.sequence: int = 1
@@ -443,6 +444,8 @@ def _handle_event(self, packet: Event) -> None:
443444
self.capabilities.update(body["capabilities"])
444445
elif event == "invalidated":
445446
self.invalidated_event = packet
447+
elif event == "memory":
448+
self.memory_event = packet
446449

447450
def _handle_reverse_request(self, request: Request) -> None:
448451
if request in self.reverse_requests:
@@ -1018,6 +1021,7 @@ def request_initialize(self, sourceInitFile=False):
10181021
"supportsStartDebuggingRequest": True,
10191022
"supportsProgressReporting": True,
10201023
"supportsInvalidatedEvent": True,
1024+
"supportsMemoryEvent": True,
10211025
"$__lldb_sourceInitFile": sourceInitFile,
10221026
},
10231027
}

lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,14 @@ def verify_invalidated_event(self, expected_areas):
248248
areas = event["body"].get("areas", [])
249249
self.assertEqual(set(expected_areas), set(areas))
250250

251+
def verify_memory_event(self, memoryReference):
252+
if memoryReference is None:
253+
self.assertIsNone(self.dap_server.memory_event)
254+
event = self.dap_server.memory_event
255+
self.dap_server.memory_event = None
256+
self.assertIsNotNone(event)
257+
self.assertEqual(memoryReference, event["body"].get("memoryReference"))
258+
251259
def get_dict_value(self, d: dict, key_path: list[str]) -> Any:
252260
"""Verify each key in the key_path array is in contained in each
253261
dictionary within "d". Assert if any key isn't in the
@@ -364,6 +372,7 @@ def set_variable(self, varRef, name, value, id=None):
364372
response = self.dap_server.request_setVariable(varRef, name, str(value), id=id)
365373
if response["success"]:
366374
self.verify_invalidated_event(["variables"])
375+
self.verify_memory_event(response["body"].get("memoryReference"))
367376
return response
368377

369378
def set_local(self, name, value, id=None):

lldb/tools/lldb-dap/EventHelper.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,4 +284,17 @@ void SendInvalidatedEvent(
284284
dap.Send(protocol::Event{"invalidated", std::move(body)});
285285
}
286286

287+
void SendMemoryEvent(DAP &dap, lldb::SBValue variable) {
288+
if (!dap.clientFeatures.contains(protocol::eClientFeatureMemoryEvent))
289+
return;
290+
const lldb::addr_t addr = variable.GetLoadAddress();
291+
if (addr == LLDB_INVALID_ADDRESS)
292+
return;
293+
protocol::MemoryEventBody body;
294+
body.memoryReference = addr;
295+
body.offset = 0;
296+
body.count = variable.GetByteSize();
297+
dap.Send(protocol::Event{"memory", std::move(body)});
298+
}
299+
287300
} // namespace lldb_dap

lldb/tools/lldb-dap/EventHelper.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ void SendProcessExitedEvent(DAP &dap, lldb::SBProcess &process);
3737
void SendInvalidatedEvent(
3838
DAP &dap, llvm::ArrayRef<protocol::InvalidatedEventBody::Area> areas);
3939

40+
void SendMemoryEvent(DAP &dap, lldb::SBValue variable);
41+
4042
} // namespace lldb_dap
4143

4244
#endif

lldb/tools/lldb-dap/Handler/SetVariableRequestHandler.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ SetVariableRequestHandler::Run(const SetVariableArguments &args) const {
8282
// (e.g. references) can be changed.
8383
SendInvalidatedEvent(dap, {InvalidatedEventBody::eAreaVariables});
8484

85+
// Also send memory event to signal client that variable memory was changed.
86+
SendMemoryEvent(dap, variable);
87+
8588
return body;
8689
}
8790

lldb/tools/lldb-dap/Protocol/ProtocolEvents.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "Protocol/ProtocolEvents.h"
10+
#include "JSONUtils.h"
1011
#include "llvm/Support/JSON.h"
1112

1213
using namespace llvm;
@@ -56,4 +57,11 @@ llvm::json::Value toJSON(const InvalidatedEventBody &IEB) {
5657
return Result;
5758
}
5859

60+
llvm::json::Value toJSON(const MemoryEventBody &MEB) {
61+
return json::Object{
62+
{"memoryReference", EncodeMemoryReference(MEB.memoryReference)},
63+
{"offset", MEB.offset},
64+
{"count", MEB.count}};
65+
}
66+
5967
} // namespace lldb_dap::protocol

lldb/tools/lldb-dap/Protocol/ProtocolEvents.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,34 @@ struct InvalidatedEventBody {
8888
llvm::json::Value toJSON(const InvalidatedEventBody::Area &);
8989
llvm::json::Value toJSON(const InvalidatedEventBody &);
9090

91+
/// This event indicates that some memory range has been updated. It should only
92+
/// be sent if the corresponding capability supportsMemoryEvent is true.
93+
///
94+
/// Clients typically react to the event by re-issuing a readMemory request if
95+
/// they show the memory identified by the memoryReference and if the updated
96+
/// memory range overlaps the displayed range. Clients should not make
97+
/// assumptions how individual memory references relate to each other, so they
98+
/// should not assume that they are part of a single continuous address range
99+
/// and might overlap.
100+
///
101+
/// Debug adapters can use this event to indicate that the contents of a memory
102+
/// range has changed due to some other request like setVariable or
103+
/// setExpression. Debug adapters are not expected to emit this event for each
104+
/// and every memory change of a running program, because that information is
105+
/// typically not available from debuggers and it would flood clients with too
106+
/// many events.
107+
struct MemoryEventBody {
108+
/// Memory reference of a memory range that has been updated.
109+
lldb::addr_t memoryReference;
110+
111+
/// Starting offset in bytes where memory has been updated. Can be negative.
112+
int64_t offset;
113+
114+
/// Number of bytes updated.
115+
uint64_t count;
116+
};
117+
llvm::json::Value toJSON(const MemoryEventBody &);
118+
91119
} // end namespace lldb_dap::protocol
92120

93121
#endif

lldb/unittests/DAP/ProtocolTypesTest.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,3 +1088,16 @@ TEST(ProtocolTypesTest, InvalidatedEventBody) {
10881088
})";
10891089
EXPECT_EQ(json, pp(body));
10901090
}
1091+
1092+
TEST(ProtocolTypesTest, MemoryEventBody) {
1093+
MemoryEventBody body;
1094+
body.memoryReference = 12345;
1095+
body.offset = 0;
1096+
body.count = 4;
1097+
StringRef json = R"({
1098+
"count": 4,
1099+
"memoryReference": "0x3039",
1100+
"offset": 0
1101+
})";
1102+
EXPECT_EQ(json, pp(body));
1103+
}

0 commit comments

Comments
 (0)