I'm attaching the first cut of the patch that I think is worth sharing for 
feedback. There is more work to do with regard to documentation and tests. Any 
feedback is appreciated.

I am going to do my best and follow the steps listed in the "LLVM Developer 
Policy" as this continues forward.

Greg, Pavel, and Jim thank you very much for the help you have provided thus 
far. This would have been insurmountable without the guidance.
From 765f424beb312e8bf88037efbe35d72b921444bd Mon Sep 17 00:00:00 2001
From: Ryan Lovelett <r...@lovelett.me>
Date: Wed, 6 Jun 2018 23:07:14 -0400
Subject: [PATCH] First working attempt

Signed-off-by: Ryan Lovelett <r...@lovelett.me>
---
 .../GDBRemoteCommunicationServerLLGS.cpp      | 92 +++++++++++++++++++
 .../GDBRemoteCommunicationServerLLGS.h        | 13 +++
 2 files changed, 105 insertions(+)

diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
index 32741c240..8c5b7ea73 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -163,6 +163,9 @@ void GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() {
   RegisterMemberFunctionHandler(
       StringExtractorGDBRemote::eServerPacketType_vAttach,
       &GDBRemoteCommunicationServerLLGS::Handle_vAttach);
+  RegisterMemberFunctionHandler(
+      StringExtractorGDBRemote::eServerPacketType_vAttachWait,
+      &GDBRemoteCommunicationServerLLGS::Handle_vAttachWait);
   RegisterMemberFunctionHandler(
       StringExtractorGDBRemote::eServerPacketType_vCont,
       &GDBRemoteCommunicationServerLLGS::Handle_vCont);
@@ -327,6 +330,62 @@ Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) {
   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");
@@ -2942,6 +3001,39 @@ GDBRemoteCommunicationServerLLGS::Handle_vAttach(
   return SendStopReasonForState(m_debugged_process_up->GetState());
 }
 
+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));
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
index 5a74d1aca..03786a49e 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
@@ -70,6 +70,17 @@ public:
   //------------------------------------------------------------------
   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
   //------------------------------------------------------------------
@@ -179,6 +190,8 @@ protected:
 
   PacketResult Handle_vAttach(StringExtractorGDBRemote &packet);
 
+  PacketResult Handle_vAttachWait(StringExtractorGDBRemote &packet);
+
   PacketResult Handle_D(StringExtractorGDBRemote &packet);
 
   PacketResult Handle_qThreadStopInfo(StringExtractorGDBRemote &packet);
-- 
2.17.1

_______________________________________________
lldb-dev mailing list
lldb-dev@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev

Reply via email to