diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h @@ -68,7 +68,7 @@ /// \return /// An Status object indicating the success or failure of the /// attach operation. - Status AttachWaitProcess(llvm::StringRef process_name); + Status AttachWaitProcess(llvm::StringRef process_name, bool include_existing); // NativeProcessProtocol::NativeDelegate overrides void InitializeDelegate(NativeProcessProtocol *process) override; @@ -183,6 +183,10 @@ PacketResult Handle_vAttachWait(StringExtractorGDBRemote &packet); + PacketResult Handle_qVAttachOrWaitSupported(StringExtractorGDBRemote &packet); + + PacketResult Handle_vAttachOrWait(StringExtractorGDBRemote &packet); + PacketResult Handle_D(StringExtractorGDBRemote &packet); PacketResult Handle_qThreadStopInfo(StringExtractorGDBRemote &packet); diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -162,6 +162,12 @@ RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_vAttachWait, &GDBRemoteCommunicationServerLLGS::Handle_vAttachWait); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_qVAttachOrWaitSupported, + &GDBRemoteCommunicationServerLLGS::Handle_qVAttachOrWaitSupported); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_vAttachOrWait, + &GDBRemoteCommunicationServerLLGS::Handle_vAttachOrWait); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_vCont, &GDBRemoteCommunicationServerLLGS::Handle_vCont); @@ -338,7 +344,7 @@ } Status GDBRemoteCommunicationServerLLGS::AttachWaitProcess( - llvm::StringRef process_name) { + llvm::StringRef process_name, bool include_existing) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); std::chrono::milliseconds polling_interval = std::chrono::milliseconds(1); @@ -347,31 +353,43 @@ ProcessInstanceInfoList exclusion_list; ProcessInstanceInfoMatch match_info; match_info.GetProcessInfo().GetExecutableFile().SetFile( - process_name, llvm::sys::path::Style::posix); + process_name, llvm::sys::path::Style::native); match_info.SetNameMatchType(NameMatch::EndsWith); - // Create the excluded process list before polling begins. - Host::FindProcesses(match_info, exclusion_list); - LLDB_LOG(log, "placed '{0}' processes in the exclusion list.", - exclusion_list.size()); + if (!include_existing) { + // Create the excluded process list before polling begins. + Host::FindProcesses(match_info, exclusion_list); + LLDB_LOG(log, "placed '{0}' processes in the exclusion list.", + exclusion_list.size()); + } else { + LLDB_LOG(log, "including existing processes in search"); + } LLDB_LOG(log, "waiting for '{0}' to appear", process_name); - auto is_in_exclusion_list = - [&exclusion_list](const ProcessInstanceInfo &info) { - for (auto &excluded : exclusion_list) { - if (excluded.GetProcessID() == info.GetProcessID()) - return true; - } - return false; - }; + StreamString name_with_slash_stream; + name_with_slash_stream.Format("/{0}", process_name); + auto name_with_slash = name_with_slash_stream.GetString(); + + // Exclude a process if it's in the exclusion list, OR if the process info's + // name doesn't exactly match the desired name, nor ends with a slash followed + // by the desired name. + auto should_exclude_process = [&exclusion_list, &process_name, + &name_with_slash]( + const ProcessInstanceInfo &info) { + for (auto &excluded : exclusion_list) { + if (excluded.GetProcessID() == info.GetProcessID()) + return true; + } + auto info_name = info.GetNameAsStringRef(); + return info_name != process_name && !info_name.endswith(name_with_slash); + }; ProcessInstanceInfoList loop_process_list; while (true) { loop_process_list.clear(); if (Host::FindProcesses(match_info, loop_process_list)) { - // Remove all the elements that are in the exclusion list. - llvm::erase_if(loop_process_list, is_in_exclusion_list); + llvm::erase_if(loop_process_list, should_exclude_process); // One match! We found the desired process. if (loop_process_list.size() == 1) { @@ -3275,7 +3293,43 @@ LLDB_LOG(log, "attempting to attach to process named '{0}'", process_name); - Status error = AttachWaitProcess(process_name); + Status error = AttachWaitProcess(process_name, false); + if (error.Fail()) { + LLDB_LOG(log, "failed to attach to process named '{0}': {1}", process_name, + error); + return SendErrorResponse(error); + } + + // Notify we attached by sending a stop packet. + return SendStopReasonForState(m_debugged_process_up->GetState()); +} + +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerLLGS::Handle_qVAttachOrWaitSupported( + StringExtractorGDBRemote &packet) { + return SendOKResponse(); +} + +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerLLGS::Handle_vAttachOrWait( + StringExtractorGDBRemote &packet) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); + + // Consume the ';' after the identifier. + packet.SetFilePos(strlen("vAttachOrWait")); + + if (!packet.GetBytesLeft() || packet.GetChar() != ';') + return SendIllFormedResponse(packet, "vAttachOrWait missing expected ';'"); + + // Allocate the buffer for the process name from vAttachWait. + std::string process_name; + if (!packet.GetHexByteString(process_name)) + return SendIllFormedResponse(packet, + "vAttachOrWait failed to parse process name"); + + LLDB_LOG(log, "attempting to attach to process named '{0}'", process_name); + + Status error = AttachWaitProcess(process_name, true); if (error.Fail()) { LLDB_LOG(log, "failed to attach to process named '{0}': {1}", process_name, error);