Skip to content

Commit 9149f89

Browse files
committed
[lldb][lldb-dap] Added support for "WriteMemory" request. #131820
Resolved review comments and added additional case in writeMemory test.
1 parent 898327f commit 9149f89

File tree

3 files changed

+39
-19
lines changed

3 files changed

+39
-19
lines changed

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -536,10 +536,14 @@ def writeMemory(self, memoryReference, data=None, offset=None, allowPartial=None
536536
# This function accepts data in decimal and hexadecimal format,
537537
# converts it to a Base64 string, and send it to the DAP,
538538
# which expects Base64 encoded data.
539-
encodedData = "" if data is None else base64.b64encode(
540-
# (bit_length + 7 (rounding up to nearest byte) ) //8 = converts to bytes.
541-
data.to_bytes((data.bit_length() + 7) // 8, "little")
542-
).decode()
539+
encodedData = (
540+
""
541+
if data is None
542+
else base64.b64encode(
543+
# (bit_length + 7 (rounding up to nearest byte) ) //8 = converts to bytes.
544+
data.to_bytes((data.bit_length() + 7) // 8, "little")
545+
).decode()
546+
)
543547
response = self.dap_server.request_writeMemory(
544548
memoryReference, encodedData, offset=offset, allowPartial=allowPartial
545549
)

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

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,8 @@ def test_writeMemory(self):
131131
ptr_deref = self.dap_server.request_evaluate("not_a_ptr")["body"]
132132
memref = ptr_deref["memoryReference"]
133133

134-
# Write the Base64-encoded string "Mg==", which decodes to binary 0x32
135-
# which is decimal 50 and corresponds to the ASCII character '2'.
134+
# Write the decimal value 50 (0x32 in hexadecimal) to memory.
135+
# This corresponds to the ASCII character '2' and encodes to Base64 as "Mg==".
136136
mem_response = self.writeMemory(memref, 50, 0, True)
137137
self.assertEqual(mem_response["success"], True)
138138
self.assertEqual(mem_response["body"]["bytesWritten"], 1)
@@ -143,6 +143,19 @@ def test_writeMemory(self):
143143
self.assertEqual(mem_response["success"], True)
144144
self.assertEqual(mem_response["body"]["data"], "Mg==")
145145

146+
# Write the decimal value 100 (0x64 in hexadecimal) to memory.
147+
# This corresponds to the ASCII character 'd' and encodes to Base64 as "ZA==".
148+
# allowPartial=False
149+
mem_response = self.writeMemory(memref, 100, 0, False)
150+
self.assertEqual(mem_response["success"], True)
151+
self.assertEqual(mem_response["body"]["bytesWritten"], 1)
152+
153+
# Read back the modified memory and verify that the written data matches
154+
# the expected result.
155+
mem_response = self.dap_server.request_readMemory(memref, 0, 1)
156+
self.assertEqual(mem_response["success"], True)
157+
self.assertEqual(mem_response["body"]["data"], "ZA==")
158+
146159
# Memory write failed for 0x0.
147160
mem_response = self.writeMemory("0x0", 50, 0, True)
148161
self.assertEqual(mem_response["success"], False)

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

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,8 @@ void WriteMemoryRequestHandler::operator()(
105105
memoryReference.str());
106106
return;
107107
}
108-
109-
lldb::addr_t address = *addr_opt;
110-
lldb::addr_t address_offset =
111-
address + GetInteger<uint64_t>(arguments, "offset").value_or(0);
108+
lldb::addr_t address =
109+
*addr_opt + GetInteger<uint64_t>(arguments, "offset").value_or(0);
112110

113111
llvm::StringRef data64 = GetString(arguments, "data").value_or("");
114112
if (data64.empty()) {
@@ -133,27 +131,32 @@ void WriteMemoryRequestHandler::operator()(
133131
lldb::SBError write_error;
134132
uint64_t bytes_written = 0;
135133

136-
// Write the memory
134+
// Write the memory.
137135
if (!output.empty()) {
138136
lldb::SBProcess process = dap.target.GetProcess();
139137
// If 'allowPartial' is false or missing, a debug adapter should attempt to
140138
// verify the region is writable before writing, and fail the response if it
141139
// is not.
142-
if (allowPartial == false) {
143-
140+
if (!allowPartial) {
141+
// Compute the end of the write range.
142+
lldb::addr_t end_address = address + output.size();
143+
// Get memory region info for the given address.
144+
// This provides the region's base, end, and permissions
145+
// (read/write/executable).
144146
lldb::SBMemoryRegionInfo region_info;
145-
lldb::SBError error =
146-
process.GetMemoryRegionInfo(address_offset, region_info);
147-
if (!error.Success() || !region_info.IsWritable()) {
148-
dap.SendErrorResponse(response, "Memory 0x" +
149-
llvm::utohexstr(address_offset) +
147+
lldb::SBError error = process.GetMemoryRegionInfo(address, region_info);
148+
// Fail if the region info retrieval fails, is not writable, or the range
149+
// exceeds the region.
150+
if (!error.Success() || !region_info.IsWritable() ||
151+
end_address > region_info.GetRegionEnd()) {
152+
dap.SendErrorResponse(response, "Memory 0x" + llvm::utohexstr(address) +
150153
" region is not writable");
151154
return;
152155
}
153156
}
154157

155158
bytes_written =
156-
process.WriteMemory(address_offset, static_cast<void *>(output.data()),
159+
process.WriteMemory(address, static_cast<void *>(output.data()),
157160
output.size(), write_error);
158161
}
159162

0 commit comments

Comments
 (0)