Skip to content
Merged
Show file tree
Hide file tree
Changes from 129 commits
Commits
Show all changes
156 commits
Select commit Hold shift + click to select a range
960351c
[lldb][test] Add the ability to extract the variable value out of the…
Nov 17, 2023
94c7680
Merge branch 'llvm:main' into main
santhoshe447 Nov 17, 2023
3235090
Merge branch 'llvm:main' into main
santhoshe447 Dec 12, 2023
ff9077f
Merge branch 'llvm:main' into main
santhoshe447 Dec 12, 2023
fa762d2
Merge branch 'llvm:main' into main
santhoshe447 Dec 12, 2023
09ff158
Merge branch 'llvm:main' into main
santhoshe447 May 3, 2024
ab44a69
[lldb-dap] Added "port" property to vscode "attach" command.
May 3, 2024
ef4f016
Merge branch 'llvm:main' into main
santhoshe447 May 3, 2024
35ba7f7
Merge branch 'llvm:main' into main
santhoshe447 May 6, 2024
bd38f88
Merge branch 'llvm:main' into main
santhoshe447 May 7, 2024
f65a580
Merge branch 'llvm:main' into main
santhoshe447 May 7, 2024
5763225
Merge branch 'llvm:main' into main
santhoshe447 May 7, 2024
bb18d6d
Merge branch 'llvm:main' into main
santhoshe447 May 7, 2024
1b1ae2b
Merge branch 'llvm:main' into main
santhoshe447 May 7, 2024
a2e4580
Merge branch 'llvm:main' into main
santhoshe447 May 8, 2024
3795dcd
Merge branch 'llvm:main' into main
santhoshe447 May 8, 2024
628fa40
Merge branch 'llvm:main' into main
santhoshe447 May 8, 2024
4e2e524
[lldb-dap] Added "port" property to vscode "attach" command.
May 8, 2024
4774f58
Merge branch 'llvm:main' into main
santhoshe447 May 9, 2024
175f1d3
[lldb-dap] Added "port" property to vscode "attach" command.
May 9, 2024
a6e9f66
Merge branch 'llvm:main' into main
santhoshe447 May 9, 2024
e5c0aed
Resolved code format issue.
May 9, 2024
c502203
Resolved code format errors.
May 9, 2024
89800a8
Merge branch 'llvm:main' into main
santhoshe447 May 15, 2024
c1bf2bd
[lldb-dap] Added "port" property to vscode "attach" command - Address…
May 15, 2024
5590afc
[lldb-dap] Added "port" property to vscode "attach" command - fix cod…
May 15, 2024
afcce33
Merge branch 'llvm:main' into main
santhoshe447 May 20, 2024
281c281
Merge branch 'llvm:main' into main
santhoshe447 May 24, 2024
624b789
Merge branch 'llvm:main' into main
santhoshe447 May 28, 2024
023b51e
[lldb-dap] Added "port" property to vscode "attach" command - resolve…
May 28, 2024
d19eb88
[lldb-dap] Added "port" property to vscode "attach" command -resolved…
May 28, 2024
16c37cd
Merge branch 'llvm:main' into main
santhoshe447 May 30, 2024
599a5ca
Merge branch 'llvm:main' into main
santhoshe447 May 30, 2024
fe9a4b6
[lldb-dap] Added "port" property to vscode "attach" command. #91570
May 30, 2024
c91b02d
[lldb-dap] Added "port" property to vscode "attach" command.
May 30, 2024
35ad541
Merge branch 'llvm:main' into main
santhoshe447 Jun 4, 2024
8e3f3a5
Merge branch 'llvm:main' into main
santhoshe447 Jun 4, 2024
de29728
[lldb-dap] Added "port" property to vscode "attach" command - address…
Jun 4, 2024
ac84b53
[lldb-dap] Added "port" property to vscode "attach" command - resolve…
Jun 4, 2024
7d1319c
Merge branch 'llvm:main' into main
santhoshe447 Jun 7, 2024
2a0eb9d
Merge branch 'llvm:main' into main
santhoshe447 Jun 10, 2024
08f40aa
[lldb-dap] Added "port" property to vscode "attach" command - fixed …
Jun 10, 2024
2a0bc63
[lldb-dap] Added "port" property to vscode "attach" command - resolve…
Jun 10, 2024
656c34a
[lldb-dap] Added "port" property to vscode "attach" command.
Jun 10, 2024
673ae34
Merge branch 'llvm:main' into main
santhoshe447 Jun 28, 2024
c6e552a
Merge branch 'llvm:main' into main
santhoshe447 Jul 22, 2024
043895d
Merge branch 'llvm:main' into main
santhoshe447 Jul 22, 2024
fe36e25
[lldb-dap] Updated README.md for newly added attach properties.
Jul 22, 2024
2011cb5
Merge branch 'llvm:main' into main
santhoshe447 Jul 23, 2024
03e4c20
Merge branch 'llvm:main' into main
santhoshe447 Jul 24, 2024
10d16b8
[lldb-dap] Updated README.md for newly added attach properties. #99926
Jul 24, 2024
a6c4895
Merge branch 'llvm:main' into main
santhoshe447 Jul 25, 2024
58affe7
[lldb-dap] Bump the version to 0.2.3
Jul 25, 2024
033c6a1
Merge branch 'llvm:main' into main
santhoshe447 Jul 25, 2024
7c96402
Merge branch 'llvm:main' into main
santhoshe447 Jul 26, 2024
17a99a7
Merge branch 'llvm:main' into main
santhoshe447 Aug 5, 2024
1e7d5f0
Merge branch 'llvm:main' into main
santhoshe447 Aug 13, 2024
e6fa6a8
Merge branch 'llvm:main' into main
santhoshe447 Aug 19, 2024
5069297
Merge branch 'llvm:main' into main
santhoshe447 Aug 20, 2024
7e22182
[lldb-dap] Enabling instruction breakpoint support to lldb-dap.
santhoshe447 Aug 20, 2024
ffe8dbc
[lldb-dap] Enabling instruction breakpoint support to lldb-dap.
santhoshe447 Aug 20, 2024
4d87a93
[lldb-dap] Enabling instruction breakpoint support to lldb-dap.
santhoshe447 Aug 20, 2024
18bcb03
[lldb-dap] Enabling instruction breakpoint support to lldb-dap.
santhoshe447 Aug 20, 2024
9893985
[lldb-dap] Enabling instruction breakpoint support to lldb-dap.
santhoshe447 Aug 21, 2024
e0101c1
[lldb-dap] Enabling instruction breakpoint support to lldb-dap.
santhoshe447 Aug 22, 2024
17f8c6d
[lldb-dap] Enabling instruction breakpoint support to lldb-dap.
santhoshe447 Aug 22, 2024
8c19498
[lldb-dap] Enabling instruction breakpoint support to lldb-dap.
santhoshe447 Aug 22, 2024
5031df9
Merge branch 'main' into main
santhoshe447 Aug 22, 2024
27d668f
Merge branch 'llvm:main' into main
santhoshe447 Aug 26, 2024
dbad4c5
[lldb-dap] Enabling instruction breakpoint support to lldb-dap.
santhoshe447 Aug 26, 2024
bac086e
[lldb-dap] Enabling instruction breakpoint support to lldb-dap.
santhoshe447 Aug 26, 2024
5401fbe
[lldb-dap] Enabling instruction breakpoint support to lldb-dap.
santhoshe447 Aug 26, 2024
3523cef
[lldb-dap] Enabling instruction breakpoint support to lldb-dap.
santhoshe447 Aug 26, 2024
ab68b22
[lldb-dap] Enabling instruction breakpoint support to lldb-dap.
santhoshe447 Aug 26, 2024
fc30dd1
Merge branch 'llvm:main' into main
santhoshe447 Aug 26, 2024
724e679
Merge branch 'llvm:main' into main
santhoshe447 Aug 26, 2024
76168c5
Merge branch 'llvm:main' into main
santhoshe447 Aug 27, 2024
e17a0fa
[lldb-dap] XFailed TestDAP_instruction_breakpoint.py for windows.
santhoshe447 Aug 27, 2024
466c75a
Merge branch 'llvm:main' into main
santhoshe447 Sep 24, 2024
a34fe4b
Merge branch 'llvm:main' into main
santhoshe447 Sep 25, 2024
a9dad2e
Merge branch 'llvm:main' into main
santhoshe447 Sep 27, 2024
d096a4e
Merge branch 'llvm:main' into main
santhoshe447 Sep 28, 2024
dbd26f5
Merge branch 'llvm:main' into main
santhoshe447 Oct 1, 2024
be23e48
Merge branch 'llvm:main' into main
santhoshe447 Oct 7, 2024
c22c9e0
Merge branch 'llvm:main' into main
santhoshe447 Oct 23, 2024
4d3c68d
Merge branch 'llvm:main' into main
santhoshe447 Oct 25, 2024
626ecee
Merge branch 'llvm:main' into main
santhoshe447 Oct 28, 2024
90bc8c0
Merge branch 'llvm:main' into main
santhoshe447 Oct 28, 2024
fa0a7c6
Merge branch 'llvm:main' into main
santhoshe447 Oct 29, 2024
684b1e7
Merge branch 'llvm:main' into main
santhoshe447 Oct 29, 2024
8959322
[lldb-dap] Fix for missing 'raw_string_ostream::flush' removal in Pro…
santhoshe447 Oct 29, 2024
698a4b1
Merge branch 'llvm:main' into main
santhoshe447 Nov 27, 2024
5400b68
Merge branch 'llvm:main' into main
santhoshe447 Dec 13, 2024
e5e2908
Merge branch 'llvm:main' into main
santhoshe447 Feb 25, 2025
cd186a8
Merge branch 'llvm:main' into main
santhoshe447 Mar 5, 2025
98db394
Merge branch 'llvm:main' into main
santhoshe447 Mar 12, 2025
8764180
Merge branch 'llvm:main' into main
santhoshe447 Mar 13, 2025
55a67cd
Merge branch 'llvm:main' into main
santhoshe447 Mar 18, 2025
ef23ddc
[lldb][lldb-dap] Added WriteMemory support
santhoshe447 Mar 18, 2025
c55eece
[lldb][lldb-dap] Added WriteMemory support
santhoshe447 Mar 18, 2025
0a8140e
Merge branch 'main' of github.com:santhoshe447/llvm-project into main
santhoshe447 Mar 18, 2025
9a6d643
Merge branch 'llvm:main' into main
santhoshe447 Mar 18, 2025
b428148
[lldb][lldb-dap] Added readMemory and WriteMemory, var type correctio…
santhoshe447 Mar 18, 2025
dcdaa07
Merge branch 'main' of github.com:santhoshe447/llvm-project into main
santhoshe447 Mar 18, 2025
6d0d08f
Merge branch 'main' of github.com:santhoshe447/llvm-project into main
santhoshe447 Mar 18, 2025
895b78e
[lldb][lldb-dap] Added support for "WriteMemory" request. #131820
santhoshe447 Mar 19, 2025
d14ac94
[lldb][lldb-dap] Added support for "WriteMemory" request. #131820
santhoshe447 Mar 19, 2025
9a88226
Merge branch 'main' of github.com:santhoshe447/llvm-project into main
santhoshe447 Mar 19, 2025
6ca125a
Merge branch 'main' into main
santhoshe447 Mar 20, 2025
a1d75c6
Merge branch 'llvm:main' into main
santhoshe447 Mar 21, 2025
27ecce0
Merge branch 'llvm:main' into main
santhoshe447 Mar 21, 2025
7311866
Merge branch 'main' of github.com:santhoshe447/llvm-project into main
santhoshe447 Mar 21, 2025
2122c2e
Merge branch 'llvm:main' into main
santhoshe447 Mar 26, 2025
f7e9af8
[lldb][lldb-dap] Added support for "WriteMemory" request. #131820
santhoshe447 Mar 26, 2025
683d775
Merge branch 'main' of github.com:santhoshe447/llvm-project into main
santhoshe447 Mar 26, 2025
32f4823
Merge branch 'main' of github.com:santhoshe447/llvm-project into main
santhoshe447 Mar 26, 2025
f5b7cf3
Merge branch 'main' of github.com:santhoshe447/llvm-project into main
santhoshe447 Mar 27, 2025
f65902a
[lldb][lldb-dap] Added support for "WriteMemory" request. #131820
santhoshe447 Mar 27, 2025
1f77293
Merge branch 'main' of github.com:santhoshe447/llvm-project into main
santhoshe447 Mar 28, 2025
6f676bb
[lldb][lldb-dap] Added support for "WriteMemory" request. #131820
santhoshe447 Mar 28, 2025
b342a42
Merge branch 'main' of github.com:santhoshe447/llvm-project into main
santhoshe447 Apr 1, 2025
50a2bc2
Merge branch 'main' of github.com:santhoshe447/llvm-project into main
santhoshe447 Apr 1, 2025
898327f
Merge branch 'main' of github.com:santhoshe447/llvm-project into main
santhoshe447 Apr 1, 2025
9149f89
[lldb][lldb-dap] Added support for "WriteMemory" request. #131820
santhoshe447 Apr 1, 2025
1b84b53
Merge branch 'llvm:main' into main
santhoshe447 Apr 2, 2025
cd70ba3
[lldb][lldb-dap] Added support for "WriteMemory" request. #131820
santhoshe447 Apr 2, 2025
4f2163e
Merge branch 'main' into main
santhoshe447 Apr 4, 2025
001dcd7
[lldb][lldb-dap] Added support for "WriteMemory" request. #131820
santhoshe447 Apr 4, 2025
6417816
Merge branch 'llvm:main' into main
santhoshe447 Apr 4, 2025
359a365
Merge branch 'llvm:main' into main
santhoshe447 Apr 7, 2025
285f07d
[lldb][lldb-dap] Added support for "WriteMemory" request. #131820
santhoshe447 Apr 7, 2025
cd7145c
Merge branch 'llvm:main' into main
santhoshe447 Apr 7, 2025
b9bc76b
[lldb][lldb-dap] Added support for "WriteMemory" request. #156761
santhoshe447 Apr 8, 2025
dccb38f
[lldb][lldb-dap] Added support for "WriteMemory" request. #157136
santhoshe447 Apr 8, 2025
e8feef2
[lldb][lldb-dap] Added support for "WriteMemory" request. #131820
santhoshe447 Apr 8, 2025
cb8e204
Merge branch 'main' into main
santhoshe447 Apr 15, 2025
8b358b8
Merge branch 'llvm:main' into main
santhoshe447 Apr 17, 2025
b8a5631
Merge branch 'llvm:main' into main
santhoshe447 Apr 18, 2025
fb9f136
Merge branch 'llvm:main' into main
santhoshe447 Apr 21, 2025
d0f95bd
Merge branch 'llvm:main' into main
santhoshe447 Apr 25, 2025
15fed53
Merge branch 'llvm:main' into main
santhoshe447 Apr 29, 2025
2eebc3d
Merge branch 'llvm:main' into main
santhoshe447 May 2, 2025
a5e0830
Merge branch 'llvm:main' into main
santhoshe447 May 5, 2025
20fc36c
Merge branch 'llvm:main' into main
santhoshe447 May 7, 2025
75c2fe5
Resolved merge conflicts.
santhoshe447 May 28, 2025
fc8fe46
Merge branch 'llvm:main' into main
santhoshe447 May 28, 2025
440987f
Merge branch 'llvm:main' into main
santhoshe447 Jun 13, 2025
652405a
Merge branch 'main' into main
santhoshe447 Jun 19, 2025
150222e
Merge branch 'llvm:main' into main
santhoshe447 Jun 24, 2025
7d25017
Merge branch 'llvm:main' into main
santhoshe447 Jun 27, 2025
cdbecca
Merge branch 'llvm:main' into main
santhoshe447 Jul 3, 2025
d9fccd7
Merge branch 'llvm:main' into main
santhoshe447 Jul 3, 2025
2930a70
[lldb][lldb-dap] Added support for "WriteMemory" request.
santhoshe447 Jul 3, 2025
77ad557
Merge branch 'llvm:main' into main
santhoshe447 Jul 8, 2025
582ab01
Merge branch 'main' into main
santhoshe447 Jul 9, 2025
492f5c0
Update ProtocolRequests.cpp
santhoshe447 Jul 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -732,6 +732,20 @@ def request_readMemory(self, memoryReference, offset, count):
}
return self.send_recv(command_dict)

def request_writeMemory(self, memoryReference, data, offset=0, allowPartial=True):
args_dict = {
"memoryReference": memoryReference,
"offset": offset,
"allowPartial": allowPartial,
"data": data,
}
command_dict = {
"command": "writeMemory",
"type": "request",
"arguments": args_dict,
}
return self.send_recv(command_dict)

def request_evaluate(self, expression, frameIndex=0, threadId=None, context=None):
stackFrame = self.get_stackFrame(frameIndex=frameIndex, threadId=threadId)
if stackFrame is None:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbplatformutil
import lldbgdbserverutils
import base64


class DAPTestCaseBase(TestBase):
Expand Down Expand Up @@ -530,3 +531,20 @@ def getBuiltinDebugServerTool(self):
self.dap_server.request_disconnect(terminateDebuggee=True)
self.assertIsNotNone(server_tool, "debugserver not found.")
return server_tool

def writeMemory(self, memoryReference, data=None, offset=None, allowPartial=None):
# This function accepts data in decimal and hexadecimal format,
# converts it to a Base64 string, and send it to the DAP,
# which expects Base64 encoded data.
encodedData = (
""
if data is None
else base64.b64encode(
# (bit_length + 7 (rounding up to nearest byte) ) //8 = converts to bytes.
data.to_bytes((data.bit_length() + 7) // 8, "little")
).decode()
)
response = self.dap_server.request_writeMemory(
memoryReference, encodedData, offset=offset, allowPartial=allowPartial
)
return response
70 changes: 70 additions & 0 deletions lldb/test/API/tools/lldb-dap/memory/TestDAP_memory.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,73 @@ def test_readMemory(self):
# Reads at offset 0x0 fail
mem = self.dap_server.request_readMemory("0x0", 0, 6)
self.assertEqual(mem["success"], False)

def test_writeMemory(self):
"""
Tests the 'writeMemory' request
"""
program = self.getBuildArtifact("a.out")
self.build_and_launch(program)
source = "main.cpp"
self.source_path = os.path.join(os.getcwd(), source)
self.set_source_breakpoints(
source,
[line_number(source, "// Breakpoint")],
)
self.continue_to_next_stop()

# Get the 'not_a_ptr' writable variable reference address.
ptr_deref = self.dap_server.request_evaluate("not_a_ptr")["body"]
memref = ptr_deref["memoryReference"]

# Write the decimal value 50 (0x32 in hexadecimal) to memory.
# This corresponds to the ASCII character '2' and encodes to Base64 as "Mg==".
mem_response = self.writeMemory(memref, 50, 0, True)
self.assertEqual(mem_response["success"], True)
self.assertEqual(mem_response["body"]["bytesWritten"], 1)

# Read back the modified memory and verify that the written data matches
# the expected result.
mem_response = self.dap_server.request_readMemory(memref, 0, 1)
self.assertEqual(mem_response["success"], True)
self.assertEqual(mem_response["body"]["data"], "Mg==")

# Write the decimal value 100 (0x64 in hexadecimal) to memory.
# This corresponds to the ASCII character 'd' and encodes to Base64 as "ZA==".
# allowPartial=False
mem_response = self.writeMemory(memref, 100, 0, False)
self.assertEqual(mem_response["success"], True)
self.assertEqual(mem_response["body"]["bytesWritten"], 1)

# Read back the modified memory and verify that the written data matches
# the expected result.
mem_response = self.dap_server.request_readMemory(memref, 0, 1)
self.assertEqual(mem_response["success"], True)
self.assertEqual(mem_response["body"]["data"], "ZA==")

# Memory write failed for 0x0.
mem_response = self.writeMemory("0x0", 50, 0, True)
self.assertEqual(mem_response["success"], False)

# Malformed memory reference.
mem_response = self.writeMemory("12345", 50, 0, True)
self.assertEqual(mem_response["success"], False)

ptr_deref = self.dap_server.request_evaluate("nonWritable")["body"]
memref = ptr_deref["memoryReference"]

# Writing to non-writable region should return an appropriate error.
mem_response = self.writeMemory(memref, 50, 0, False)
self.assertEqual(mem_response["success"], False)
self.assertRegex(
mem_response["message"],
r"Memory " + memref + " region is not writable",
)

# Trying to write empty value; data=""
mem_response = self.writeMemory(memref)
self.assertEqual(mem_response["success"], False)
self.assertRegex(
mem_response["message"],
r"Data cannot be empty value. Provide valid data",
)
2 changes: 2 additions & 0 deletions lldb/test/API/tools/lldb-dap/memory/main.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
int main() {
int not_a_ptr = 666;
const char *rawptr = "dead";
// Immutable variable, .rodata region.
static const int nonWritable = 100;
// Breakpoint
return 0;
}
3 changes: 2 additions & 1 deletion lldb/tools/lldb-dap/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ add_lldb_tool(lldb-dap
Handler/TestGetTargetBreakpointsRequestHandler.cpp
Handler/ThreadsRequestHandler.cpp
Handler/VariablesRequestHandler.cpp

Handler/WriteMemoryRequestHandler.cpp

Protocol/ProtocolBase.cpp
Protocol/ProtocolTypes.cpp
Protocol/ProtocolRequests.cpp
Expand Down
7 changes: 7 additions & 0 deletions lldb/tools/lldb-dap/DAP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1186,4 +1186,11 @@ protocol::Capabilities DAP::GetCapabilities() {
return capabilities;
}

void DAP::SendErrorResponse(llvm::json::Object &response,
llvm::StringRef message) {
response["success"] = false;
EmplaceSafeString(response, "message", message);
SendJSON(llvm::json::Value(std::move(response)));
}

} // namespace lldb_dap
8 changes: 8 additions & 0 deletions lldb/tools/lldb-dap/DAP.h
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,14 @@ struct DAP {
InstructionBreakpoint *GetInstructionBPFromStopReason(lldb::SBThread &thread);

lldb::SBMutex GetAPIMutex() const { return target.GetAPIMutex(); }

/// Sends an error response in DAP with success=false and an error message.
///
/// \param[out] response
/// The response object to update.
/// \param[in] message
/// The error message.
void SendErrorResponse(llvm::json::Object &response, llvm::StringRef message);
};

} // namespace lldb_dap
Expand Down
10 changes: 10 additions & 0 deletions lldb/tools/lldb-dap/Handler/RequestHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,16 @@ class TestGetTargetBreakpointsRequestHandler : public LegacyRequestHandler {
void operator()(const llvm::json::Object &request) const override;
};

class WriteMemoryRequestHandler : public LegacyRequestHandler {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer if we would directly use the non-legacy approach here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer if we would directly use the non-legacy approach here

What is non legacy handler approach ?

public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "writeMemory"; }
FeatureSet GetSupportedFeatures() const override {
return {protocol::eAdapterFeatureWriteMemoryRequest};
}
void operator()(const llvm::json::Object &request) const override;
};

} // namespace lldb_dap

#endif
175 changes: 175 additions & 0 deletions lldb/tools/lldb-dap/Handler/WriteMemoryRequestHandler.cpp
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably worth mentioning in the release notes, in llvm/docs/ReleaseNotes.md

Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
//===-- WriteMemoryRequestHandler.cpp -------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "DAP.h"
#include "JSONUtils.h"
#include "RequestHandler.h"
#include "lldb/API/SBMemoryRegionInfo.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Base64.h"

namespace lldb_dap {

// "WriteMemoryRequest": {
// "allOf": [ { "$ref": "#/definitions/Request" }, {
// "type": "object",
// "description": "Writes bytes to memory at the provided location.\n
// Clients should only call this request if the corresponding
// capability `supportsWriteMemoryRequest` is true.",
// "properties": {
// "command": {
// "type": "string",
// "enum": [ "writeMemory" ]
// },
// "arguments": {
// "$ref": "#/definitions/WriteMemoryArguments"
// }
// },
// "required": [ "command", "arguments" ]
// }]
// },
// "WriteMemoryArguments": {
// "type": "object",
// "description": "Arguments for `writeMemory` request.",
// "properties": {
// "memoryReference": {
// "type": "string",
// "description": "Memory reference to the base location to which
// data should be written."
// },
// "offset": {
// "type": "integer",
// "description": "Offset (in bytes) to be applied to the reference
// location before writing data. Can be negative."
// },
// "allowPartial": {
// "type": "boolean",
// "description": "Property to control partial writes. If true, the
// debug adapter should attempt to write memory even if the entire
// memory region is not writable. In such a case the debug adapter
// should stop after hitting the first byte of memory that cannot be
// written and return the number of bytes written in the response
// via the `offset` and `bytesWritten` properties.\nIf false or
// missing, a debug adapter should attempt to verify the region is
// writable before writing, and fail the response if it is not."
// },
// "data": {
// "type": "string",
// "description": "Bytes to write, encoded using base64."
// }
// },
// "required": [ "memoryReference", "data" ]
// },
// "WriteMemoryResponse": {
// "allOf": [ { "$ref": "#/definitions/Response" }, {
// "type": "object",
// "description": "Response to `writeMemory` request.",
// "properties": {
// "body": {
// "type": "object",
// "properties": {
// "offset": {
// "type": "integer",
// "description": "Property that should be returned when
// `allowPartial` is true to indicate the offset of the first
// byte of data successfully written. Can be negative."
// },
// "bytesWritten": {
// "type": "integer",
// "description": "Property that should be returned when
// `allowPartial` is true to indicate the number of bytes
// starting from address that were successfully written."
// }
// }
// }
// }
// }]
// },
void WriteMemoryRequestHandler::operator()(
const llvm::json::Object &request) const {
llvm::json::Object response;
FillResponse(request, response);

auto arguments = request.getObject("arguments");
llvm::StringRef memoryReference =
GetString(arguments, "memoryReference").value_or("");

auto addr_opt = DecodeMemoryReference(memoryReference);
if (!addr_opt.has_value()) {
dap.SendErrorResponse(response, "Malformed memory reference: " +
memoryReference.str());
return;
}
lldb::addr_t address =
*addr_opt + GetInteger<uint64_t>(arguments, "offset").value_or(0);

llvm::StringRef data64 = GetString(arguments, "data").value_or("");
if (data64.empty()) {
dap.SendErrorResponse(response,
"Data cannot be empty value. Provide valid data");
return;
}

// The VSCode IDE or other DAP clients send memory data as a Base64 string.
// This function decodes it into raw binary before writing it to the target
// process memory.
std::vector<char> output;
auto decode_error = llvm::decodeBase64(data64, output);

if (decode_error) {
dap.SendErrorResponse(response,
llvm::toString(std::move(decode_error)).c_str());
return;
}

bool allowPartial = GetBoolean(arguments, "allowPartial").value_or(true);
lldb::SBError write_error;
uint64_t bytes_written = 0;

// Write the memory.
if (!output.empty()) {
lldb::SBProcess process = dap.target.GetProcess();
// If 'allowPartial' is false or missing, a debug adapter should attempt to
// verify the region is writable before writing, and fail the response if it
// is not.
if (!allowPartial) {
// Compute the end of the write range.
lldb::addr_t end_address = address + output.size();
// Get memory region info for the given address.
// This provides the region's base, end, and permissions
// (read/write/executable).
lldb::SBMemoryRegionInfo region_info;
lldb::SBError error = process.GetMemoryRegionInfo(address, region_info);
// Fail if the region info retrieval fails, is not writable, or the range
// exceeds the region.
if (!error.Success() || !region_info.IsWritable() ||
end_address > region_info.GetRegionEnd()) {
dap.SendErrorResponse(response, "Memory 0x" + llvm::utohexstr(address) +
" region is not writable");
return;
}
}

bytes_written =
process.WriteMemory(address, static_cast<void *>(output.data()),
output.size(), write_error);
}

if (bytes_written == 0) {
dap.SendErrorResponse(response, write_error.GetCString());
return;
}

llvm::json::Object body;
body.try_emplace("bytesWritten", std::move(bytes_written));

response.try_emplace("body", std::move(body));
dap.SendJSON(llvm::json::Value(std::move(response)));
}

} // namespace lldb_dap
1 change: 1 addition & 0 deletions lldb/tools/lldb-dap/lldb-dap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ static void RegisterRequestCallbacks(DAP &dap) {
dap.RegisterRequest<StepOutRequestHandler>();
dap.RegisterRequest<ThreadsRequestHandler>();
dap.RegisterRequest<VariablesRequestHandler>();
dap.RegisterRequest<WriteMemoryRequestHandler>();

// Custom requests
dap.RegisterRequest<CompileUnitsRequestHandler>();
Expand Down