Skip to content

Commit e6803d4

Browse files
felipepiovezanKHicketts
authored andcommitted
[lldbremote] Implement support for MultiBreakpoint packet (llvm#192919)
This is fairly straightforward, thanks to the helper functions created in the previous commit. The following PRs are related to the MultiBreakpoint feature: * llvm#192910 * llvm#192914 * llvm#192915 * llvm#192919 * llvm#192962 * llvm#192964 * llvm#192971 * llvm#192988
1 parent 4ee9615 commit e6803d4

6 files changed

Lines changed: 74 additions & 1 deletion

File tree

lldb/include/lldb/Utility/StringExtractorGDBRemote.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ class StringExtractorGDBRemote : public StringExtractor {
172172
eServerPacketType_jLLDBTraceStop,
173173
eServerPacketType_jLLDBTraceGetState,
174174
eServerPacketType_jLLDBTraceGetBinaryData,
175+
eServerPacketType_jMultiBreakpoint,
175176

176177
eServerPacketType_qMemTags, // read memory tags
177178
eServerPacketType_QMemTags, // write memory tags

lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -933,6 +933,7 @@ def add_qSupported_packets(self, client_features=[]):
933933
"SupportedWatchpointTypes",
934934
"SupportedCompressions",
935935
"MultiMemRead",
936+
"jMultiBreakpoint",
936937
]
937938

938939
def parse_qSupported_response(self, context):

lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,9 @@ void GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() {
218218
RegisterMemberFunctionHandler(
219219
StringExtractorGDBRemote::eServerPacketType_jLLDBTraceGetBinaryData,
220220
&GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceGetBinaryData);
221+
RegisterMemberFunctionHandler(
222+
StringExtractorGDBRemote::eServerPacketType_jMultiBreakpoint,
223+
&GDBRemoteCommunicationServerLLGS::Handle_jMultiBreakpoint);
221224

222225
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_g,
223226
&GDBRemoteCommunicationServerLLGS::Handle_g);
@@ -3107,6 +3110,70 @@ GDBRemoteCommunicationServerLLGS::Handle_z(StringExtractorGDBRemote &packet) {
31073110
ExecuteRemoveBreakpoint(packet.GetStringRef()));
31083111
}
31093112

3113+
GDBRemoteCommunication::PacketResult
3114+
GDBRemoteCommunicationServerLLGS::Handle_jMultiBreakpoint(
3115+
StringExtractorGDBRemote &packet) {
3116+
llvm::StringRef packet_str = packet.GetStringRef();
3117+
if (!packet_str.consume_front("jMultiBreakpoint:"))
3118+
return SendIllFormedResponse(packet,
3119+
"Invalid jMultiBreakpoint packet prefix");
3120+
3121+
llvm::Expected<llvm::json::Value> parsed = llvm::json::parse(packet_str);
3122+
if (!parsed) {
3123+
llvm::consumeError(parsed.takeError());
3124+
return SendIllFormedResponse(packet,
3125+
"jMultiBreakpoint did not contain valid JSON");
3126+
}
3127+
llvm::json::Object *request_dict = parsed->getAsObject();
3128+
if (!request_dict)
3129+
return SendIllFormedResponse(
3130+
packet, "jMultiBreakpoint did not contain a JSON dictionary");
3131+
3132+
llvm::json::Array *request_array =
3133+
request_dict->getArray("breakpoint_requests");
3134+
if (!request_array)
3135+
return SendIllFormedResponse(
3136+
packet,
3137+
"jMultiBreakpoint did not contain a valid 'breakpoint_requests' field");
3138+
3139+
llvm::json::Array reply_array;
3140+
for (const llvm::json::Value &value : *request_array) {
3141+
std::optional<llvm::StringRef> request = value.getAsString();
3142+
if (!request)
3143+
return SendIllFormedResponse(packet,
3144+
"jMultiBreakpoint had a non-string entry");
3145+
BreakpointResult result = request->starts_with("Z")
3146+
? ExecuteSetBreakpoint(*request)
3147+
: ExecuteRemoveBreakpoint(*request);
3148+
std::visit(
3149+
[&](const auto &arg) {
3150+
using T = std::decay_t<decltype(arg)>;
3151+
static_assert(std::is_same_v<T, BreakpointOK> ||
3152+
std::is_same_v<T, BreakpointError> ||
3153+
std::is_same_v<T, BreakpointIllFormed>,
3154+
"non-exhaustive visitor!");
3155+
if constexpr (std::is_same_v<T, BreakpointOK>)
3156+
reply_array.push_back("OK");
3157+
else if constexpr (std::is_same_v<T, BreakpointError>)
3158+
reply_array.push_back(
3159+
llvm::formatv("E{0:X-2}", arg.error_code).str());
3160+
else
3161+
reply_array.push_back("E03");
3162+
},
3163+
result);
3164+
}
3165+
3166+
llvm::json::Object dict;
3167+
dict.try_emplace("results", std::move(reply_array));
3168+
3169+
StreamString stream;
3170+
stream.AsRawOstream() << llvm::json::Value(std::move(dict));
3171+
StringRef response_str = stream.GetString();
3172+
StreamGDBRemote response;
3173+
response.PutEscapedBytes(response_str.data(), response_str.size());
3174+
return SendPacketNoLock(response.GetString());
3175+
}
3176+
31103177
GDBRemoteCommunication::PacketResult
31113178
GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) {
31123179
Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread);
@@ -4322,6 +4389,7 @@ std::vector<std::string> GDBRemoteCommunicationServerLLGS::HandleFeatures(
43224389
"QListThreadsInStopReply+",
43234390
"qXfer:features:read+",
43244391
"QNonStop+",
4392+
"jMultiBreakpoint+",
43254393
});
43264394

43274395
// report server-only features

lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,8 @@ class GDBRemoteCommunicationServerLLGS
276276

277277
PacketResult Handle_T(StringExtractorGDBRemote &packet);
278278

279+
PacketResult Handle_jMultiBreakpoint(StringExtractorGDBRemote &packet);
280+
279281
void SetCurrentThreadID(lldb::tid_t tid);
280282

281283
lldb::tid_t GetCurrentThreadID() const;

lldb/source/Utility/StringExtractorGDBRemote.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,8 @@ StringExtractorGDBRemote::GetServerPacketType() const {
330330
return eServerPacketType_jLLDBTraceGetState;
331331
if (PACKET_STARTS_WITH("jLLDBTraceGetBinaryData:"))
332332
return eServerPacketType_jLLDBTraceGetBinaryData;
333+
if (PACKET_STARTS_WITH("jMultiBreakpoint:"))
334+
return eServerPacketType_jMultiBreakpoint;
333335
break;
334336

335337
case 'v':

lldb/test/API/functionalities/multi-breakpoint/TestMultiBreakpoint.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
from lldbsuite.test.gdbclientutils import *
1313

1414

15-
@skipUnlessDarwin # Remove once lldbsever support is implemented.
1615
@skipIfOutOfTreeDebugserver
1716
# Runs on systems where we can always predict the software break size
1817
@skipIf(archs=no_match(["x86_64", "arm64", "aarch64"]))

0 commit comments

Comments
 (0)