@@ -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,68 @@ 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+ if constexpr (std::is_same_v<T, BreakpointOK>)
3152+ reply_array.push_back (" OK" );
3153+ else if constexpr (std::is_same_v<T, BreakpointError>)
3154+ reply_array.push_back (
3155+ llvm::formatv (" E{0:X-2}" , arg.error_code ).str ());
3156+ else if constexpr (std::is_same_v<T, BreakpointIllFormed>)
3157+ reply_array.push_back (" E03" );
3158+ else
3159+ static_assert (false , " non-exhaustive visitor!" );
3160+ },
3161+ result);
3162+ }
3163+
3164+ llvm::json::Object dict;
3165+ dict.try_emplace (" results" , std::move (reply_array));
3166+
3167+ StreamString stream;
3168+ stream.AsRawOstream () << llvm::json::Value (std::move (dict));
3169+ StringRef response_str = stream.GetString ();
3170+ StreamGDBRemote response;
3171+ response.PutEscapedBytes (response_str.data (), response_str.size ());
3172+ return SendPacketNoLock (response.GetString ());
3173+ }
3174+
31103175GDBRemoteCommunication::PacketResult
31113176GDBRemoteCommunicationServerLLGS::Handle_s (StringExtractorGDBRemote &packet) {
31123177 Log *log = GetLog (LLDBLog::Process | LLDBLog::Thread);
@@ -4322,6 +4387,7 @@ std::vector<std::string> GDBRemoteCommunicationServerLLGS::HandleFeatures(
43224387 " QListThreadsInStopReply+" ,
43234388 " qXfer:features:read+" ,
43244389 " QNonStop+" ,
4390+ " jMultiBreakpoint+" ,
43254391 });
43264392
43274393 // report server-only features
0 commit comments