Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h =================================================================== --- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h +++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h @@ -71,6 +71,17 @@ Status AttachToProcess(lldb::pid_t pid); //------------------------------------------------------------------ + /// Wait to attach to a process with a given name. + /// + /// This method supports waiting for the next instance of a process + /// by the name and attaching llgs to that via the configured Platform. + /// + /// @return + /// An + Status AttachWaitProcess(std::string waitfor_process_name, + std::chrono::milliseconds waitfor_interval = std::chrono::milliseconds(1000)); + + //------------------------------------------------------------------ // NativeProcessProtocol::NativeDelegate overrides //------------------------------------------------------------------ void InitializeDelegate(NativeProcessProtocol *process) override; @@ -179,6 +190,8 @@ PacketResult Handle_vAttach(StringExtractorGDBRemote &packet); + PacketResult Handle_vAttachWait(StringExtractorGDBRemote &packet); + PacketResult Handle_D(StringExtractorGDBRemote &packet); PacketResult Handle_qThreadStopInfo(StringExtractorGDBRemote &packet); Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp =================================================================== --- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -164,6 +164,9 @@ StringExtractorGDBRemote::eServerPacketType_vAttach, &GDBRemoteCommunicationServerLLGS::Handle_vAttach); RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_vAttachWait, + &GDBRemoteCommunicationServerLLGS::Handle_vAttachWait); + RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_vCont, &GDBRemoteCommunicationServerLLGS::Handle_vCont); RegisterMemberFunctionHandler( @@ -326,6 +329,62 @@ return Status(); } +Status GDBRemoteCommunicationServerLLGS::AttachWaitProcess( + std::string waitfor_process_name, + std::chrono::milliseconds waitfor_interval) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); + + // Create the matcher used to search the process list + ProcessInstanceInfoList exclusion_list; + ProcessInstanceInfoMatch match_info; + match_info.GetProcessInfo().GetExecutableFile() + .SetFile(waitfor_process_name, false); + match_info.SetNameMatchType(NameMatch::EndsWith); + + // Create the excluded process list before polling begins + Host::FindProcesses(match_info, exclusion_list); + + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s waiting for '%s' " + "to appear", __FUNCTION__, waitfor_process_name.c_str()); + + lldb::pid_t waitfor_pid = LLDB_INVALID_PROCESS_ID; + ProcessInstanceInfoList loop_process_list; + + while (waitfor_pid == LLDB_INVALID_PROCESS_ID) { + loop_process_list.Clear(); + if (Host::FindProcesses(match_info, loop_process_list)) { + // The for loop is to checking for the first matching process that was + // not in the excluded process list. + for(size_t i = 0; i < loop_process_list.GetSize(); i++) { + waitfor_pid = loop_process_list.GetProcessIDAtIndex(i); + for(size_t j = 0; j < exclusion_list.GetSize(); j++) { + if (exclusion_list.GetProcessIDAtIndex(j) == waitfor_pid) { + waitfor_pid = LLDB_INVALID_PROCESS_ID; + } + } + + // If waitfor_pid is not in our exclusion list then use it + if (waitfor_pid != LLDB_INVALID_PROCESS_ID) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s found pid " + "%" PRIu64, __FUNCTION__, waitfor_pid); + break; + } + } + } + // If we have not found the new process sleep until next poll. + if (waitfor_pid == LLDB_INVALID_PROCESS_ID) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s sleep " + "%" PRIu64, __FUNCTION__, waitfor_interval); + std::this_thread::sleep_for(waitfor_interval); + } + } + + return AttachToProcess(waitfor_pid); +} + void GDBRemoteCommunicationServerLLGS::InitializeDelegate( NativeProcessProtocol *process) { assert(process && "process cannot be NULL"); @@ -2932,6 +2991,39 @@ } GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerLLGS::Handle_vAttachWait( + StringExtractorGDBRemote &packet) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); + + // Consume the ';' after vAttach. + packet.SetFilePos(strlen("vAttachWait")); + if (!packet.GetBytesLeft() || packet.GetChar() != ';') + return SendIllFormedResponse(packet, "vAttachWait missing expected ';'"); + + // Allocate the buffer for the process name from vAttachWait + std::string process_name; + if (!packet.GetHexByteString(process_name)) + return SendIllFormedResponse(packet, + "vAttachWait failed to parse process name"); + + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s attempting to attach to " + "process named %s", __FUNCTION__, process_name.c_str()); + + Status error = AttachWaitProcess(process_name); + + if (error.Fail()) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to attach to " + "process named %s: %s\n", __FUNCTION__, process_name.c_str(), + error.AsCString()); + } + + // Notify we attached by sending a stop packet. + return SendStopReasonForState(m_debugged_process_up->GetState()); +} + +GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_D(StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));