diff options
Diffstat (limited to 'lldb/source/Plugins/Process/gdb-remote')
-rw-r--r-- | lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp | 163 | ||||
-rw-r--r-- | lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h | 29 |
2 files changed, 161 insertions, 31 deletions
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp index bed8852b7a0..568997f2ead 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp @@ -143,6 +143,10 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec, packet_result = Handle_qKillSpawnedProcess (packet); break; + case StringExtractorGDBRemote::eServerPacketType_k: + packet_result = Handle_k (packet); + break; + case StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess: packet_result = Handle_qLaunchSuccess (packet); break; @@ -271,6 +275,38 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec, return packet_result == PacketResult::Success; } +lldb_private::Error +GDBRemoteCommunicationServer::LaunchProcess (const char *const args[], int argc, unsigned int launch_flags) +{ + if ((argc < 1) || !args || !args[0] || !args[0][0]) + lldb_private::Error ("%s: no process command line specified to launch", __FUNCTION__); + + // Launch the program specified in args + m_process_launch_info.Clear (); + m_process_launch_info.SetArguments (const_cast<const char**> (args), true); + m_process_launch_info.GetFlags ().Set (launch_flags); + + lldb_private::Error error = Host::LaunchProcess (m_process_launch_info); + if (!error.Success ()) + { + fprintf (stderr, "%s: failed to launch executable %s", __FUNCTION__, args[0]); + return error; + } + + printf ("Launched '%s' as process %" PRIu64 "...\n", args[0], m_process_launch_info.GetProcessID()); + + // add to list of spawned processes. On an lldb-gdbserver, we + // would expect there to be only one. + lldb::pid_t pid; + if ( (pid = m_process_launch_info.GetProcessID()) != LLDB_INVALID_PROCESS_ID ) + { + Mutex::Locker locker (m_spawned_pids_mutex); + m_spawned_pids.insert(pid); + } + + return error; +} + GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServer::SendUnimplementedResponse (const char *) { @@ -897,57 +933,122 @@ GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote #endif } -GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServer::Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet) +bool +GDBRemoteCommunicationServer::KillSpawnedProcess (lldb::pid_t pid) { - // Spawn a local debugserver as a platform so we can then attach or launch - // a process... - - if (m_is_platform) + // make sure we know about this process { - packet.SetFilePos(::strlen ("qKillSpawnedProcess:")); + Mutex::Locker locker (m_spawned_pids_mutex); + if (m_spawned_pids.find(pid) == m_spawned_pids.end()) + return false; + } - lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID); + // first try a SIGTERM (standard kill) + Host::Kill (pid, SIGTERM); - // Scope for locker + // check if that worked + for (size_t i=0; i<10; ++i) + { { Mutex::Locker locker (m_spawned_pids_mutex); if (m_spawned_pids.find(pid) == m_spawned_pids.end()) - return SendErrorResponse (10); + { + // it is now killed + return true; + } } - Host::Kill (pid, SIGTERM); + usleep (10000); + } - for (size_t i=0; i<10; ++i) + // check one more time after the final usleep + { + Mutex::Locker locker (m_spawned_pids_mutex); + if (m_spawned_pids.find(pid) == m_spawned_pids.end()) + return true; + } + + // the launched process still lives. Now try killling it again, + // this time with an unblockable signal. + Host::Kill (pid, SIGKILL); + + for (size_t i=0; i<10; ++i) + { { - // Scope for locker + Mutex::Locker locker (m_spawned_pids_mutex); + if (m_spawned_pids.find(pid) == m_spawned_pids.end()) { - Mutex::Locker locker (m_spawned_pids_mutex); - if (m_spawned_pids.find(pid) == m_spawned_pids.end()) - return SendOKResponse(); + // it is now killed + return true; } - usleep (10000); } + usleep (10000); + } - // Scope for locker + // check one more time after the final usleep + // Scope for locker + { + Mutex::Locker locker (m_spawned_pids_mutex); + if (m_spawned_pids.find(pid) == m_spawned_pids.end()) + return true; + } + + // no luck - the process still lives + return false; +} + +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServer::Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet) +{ + packet.SetFilePos(::strlen ("qKillSpawnedProcess:")); + + lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID); + + // verify that we know anything about this pid. + // Scope for locker + { + Mutex::Locker locker (m_spawned_pids_mutex); + if (m_spawned_pids.find(pid) == m_spawned_pids.end()) { - Mutex::Locker locker (m_spawned_pids_mutex); - if (m_spawned_pids.find(pid) == m_spawned_pids.end()) - return SendOKResponse(); + // not a pid we know about + return SendErrorResponse (10); } - Host::Kill (pid, SIGKILL); + } + + // go ahead and attempt to kill the spawned process + if (KillSpawnedProcess (pid)) + return SendOKResponse (); + else + return SendErrorResponse (11); +} - for (size_t i=0; i<10; ++i) +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServer::Handle_k (StringExtractorGDBRemote &packet) +{ + // ignore for now if we're lldb_platform + if (m_is_platform) + return SendUnimplementedResponse (packet.GetStringRef().c_str()); + + // shutdown all spawned processes + std::set<lldb::pid_t> spawned_pids_copy; + + // copy pids + { + Mutex::Locker locker (m_spawned_pids_mutex); + spawned_pids_copy.insert (m_spawned_pids.begin (), m_spawned_pids.end ()); + } + + // nuke the spawned processes + for (auto it = spawned_pids_copy.begin (); it != spawned_pids_copy.end (); ++it) + { + lldb::pid_t spawned_pid = *it; + if (!KillSpawnedProcess (spawned_pid)) { - // Scope for locker - { - Mutex::Locker locker (m_spawned_pids_mutex); - if (m_spawned_pids.find(pid) == m_spawned_pids.end()) - return SendOKResponse(); - } - usleep (10000); + fprintf (stderr, "%s: failed to kill spawned pid %" PRIu64 ", ignoring.\n", __FUNCTION__, spawned_pid); } } - return SendErrorResponse (11); + + // TODO figure out how to shut down gracefully at this point + return SendOKResponse (); } GDBRemoteCommunication::PacketResult diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h index 3b70ab97327..c1223ad0a34 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h @@ -138,6 +138,29 @@ public: m_port_offset = port_offset; } + //------------------------------------------------------------------ + /// Launch a process. + /// + /// This method supports running an lldb-gdbserver or similar + /// server in a situation where the startup code has been provided + /// with all the information for a child process to be launched. + /// + /// @param[in] args + /// The command line to launch. + /// + /// @param[in] argc + /// The number of elements in the args array of cstring pointers. + /// + /// @param[in] launch_flags + /// The launch flags to use when launching this process. + /// + /// @return + /// An Error object indicating the success or failure of the + /// launch. + //------------------------------------------------------------------ + lldb_private::Error + LaunchProcess (const char *const args[], int argc, unsigned int launch_flags); + protected: lldb::thread_t m_async_thread; lldb_private::ProcessLaunchInfo m_process_launch_info; @@ -175,6 +198,9 @@ protected: Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet); PacketResult + Handle_k (StringExtractorGDBRemote &packet); + + PacketResult Handle_qPlatform_mkdir (StringExtractorGDBRemote &packet); PacketResult @@ -275,6 +301,9 @@ private: int signal, int status); + bool + KillSpawnedProcess (lldb::pid_t pid); + //------------------------------------------------------------------ // For GDBRemoteCommunicationServer only //------------------------------------------------------------------ |