| //===-- GDBRemoteCommunicationServer.h --------------------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef liblldb_GDBRemoteCommunicationServer_h_ |
| #define liblldb_GDBRemoteCommunicationServer_h_ |
| |
| // C Includes |
| // C++ Includes |
| #include <vector> |
| #include <set> |
| #include <unordered_map> |
| // Other libraries and framework includes |
| // Project includes |
| #include "lldb/lldb-private-forward.h" |
| #include "lldb/Core/Communication.h" |
| #include "lldb/Host/Mutex.h" |
| #include "lldb/Target/Process.h" |
| #include "GDBRemoteCommunication.h" |
| |
| #include "../../../Host/common/NativeProcessProtocol.h" |
| |
| class ProcessGDBRemote; |
| class StringExtractorGDBRemote; |
| |
| class GDBRemoteCommunicationServer : |
| public GDBRemoteCommunication, |
| public lldb_private::NativeProcessProtocol::NativeDelegate |
| { |
| public: |
| typedef std::map<uint16_t, lldb::pid_t> PortMap; |
| |
| enum |
| { |
| eBroadcastBitRunPacketSent = kLoUserBroadcastBit |
| }; |
| //------------------------------------------------------------------ |
| // Constructors and Destructors |
| //------------------------------------------------------------------ |
| GDBRemoteCommunicationServer(bool is_platform); |
| |
| GDBRemoteCommunicationServer(bool is_platform, |
| const lldb::PlatformSP& platform_sp, |
| lldb::DebuggerSP& debugger_sp); |
| |
| virtual |
| ~GDBRemoteCommunicationServer(); |
| |
| PacketResult |
| GetPacketAndSendResponse (uint32_t timeout_usec, |
| lldb_private::Error &error, |
| bool &interrupt, |
| bool &quit); |
| |
| virtual bool |
| GetThreadSuffixSupported () |
| { |
| return true; |
| } |
| |
| // After connecting, do a little handshake with the client to make sure |
| // we are at least communicating |
| bool |
| HandshakeWithClient (lldb_private::Error *error_ptr); |
| |
| // Set both ports to zero to let the platform automatically bind to |
| // a port chosen by the OS. |
| void |
| SetPortMap (PortMap &&port_map) |
| { |
| m_port_map = port_map; |
| } |
| |
| //---------------------------------------------------------------------- |
| // If we are using a port map where we can only use certain ports, |
| // get the next available port. |
| // |
| // If we are using a port map and we are out of ports, return UINT16_MAX |
| // |
| // If we aren't using a port map, return 0 to indicate we should bind to |
| // port 0 and then figure out which port we used. |
| //---------------------------------------------------------------------- |
| uint16_t |
| GetNextAvailablePort () |
| { |
| if (m_port_map.empty()) |
| return 0; // Bind to port zero and get a port, we didn't have any limitations |
| |
| for (auto &pair : m_port_map) |
| { |
| if (pair.second == LLDB_INVALID_PROCESS_ID) |
| { |
| pair.second = ~(lldb::pid_t)LLDB_INVALID_PROCESS_ID; |
| return pair.first; |
| } |
| } |
| return UINT16_MAX; |
| } |
| |
| bool |
| AssociatePortWithProcess (uint16_t port, lldb::pid_t pid) |
| { |
| PortMap::iterator pos = m_port_map.find(port); |
| if (pos != m_port_map.end()) |
| { |
| pos->second = pid; |
| return true; |
| } |
| return false; |
| } |
| |
| bool |
| FreePort (uint16_t port) |
| { |
| PortMap::iterator pos = m_port_map.find(port); |
| if (pos != m_port_map.end()) |
| { |
| pos->second = LLDB_INVALID_PROCESS_ID; |
| return true; |
| } |
| return false; |
| } |
| |
| bool |
| FreePortForProcess (lldb::pid_t pid) |
| { |
| if (!m_port_map.empty()) |
| { |
| for (auto &pair : m_port_map) |
| { |
| if (pair.second == pid) |
| { |
| pair.second = LLDB_INVALID_PROCESS_ID; |
| return true; |
| } |
| } |
| } |
| return false; |
| } |
| |
| void |
| SetPortOffset (uint16_t port_offset) |
| { |
| m_port_offset = port_offset; |
| } |
| |
| //------------------------------------------------------------------ |
| /// Specify the program to launch and its arguments. |
| /// |
| /// The LaunchProcess () command can be executed to do the lauching. |
| /// |
| /// @param[in] args |
| /// The command line to launch. |
| /// |
| /// @param[in] argc |
| /// The number of elements in the args array of cstring pointers. |
| /// |
| /// @return |
| /// An Error object indicating the success or failure of making |
| /// the setting. |
| //------------------------------------------------------------------ |
| lldb_private::Error |
| SetLaunchArguments (const char *const args[], int argc); |
| |
| //------------------------------------------------------------------ |
| /// Specify the launch flags for the process. |
| /// |
| /// The LaunchProcess () command can be executed to do the lauching. |
| /// |
| /// @param[in] launch_flags |
| /// The launch flags to use when launching this process. |
| /// |
| /// @return |
| /// An Error object indicating the success or failure of making |
| /// the setting. |
| //------------------------------------------------------------------ |
| lldb_private::Error |
| SetLaunchFlags (unsigned int launch_flags); |
| |
| //------------------------------------------------------------------ |
| /// Launch a process with the current launch settings. |
| /// |
| /// 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. |
| /// |
| /// @return |
| /// An Error object indicating the success or failure of the |
| /// launch. |
| //------------------------------------------------------------------ |
| lldb_private::Error |
| LaunchProcess (); |
| |
| //------------------------------------------------------------------ |
| /// Attach to a process. |
| /// |
| /// This method supports attaching llgs to a process accessible via the |
| /// configured Platform. |
| /// |
| /// @return |
| /// An Error object indicating the success or failure of the |
| /// attach operation. |
| //------------------------------------------------------------------ |
| lldb_private::Error |
| AttachToProcess (lldb::pid_t pid); |
| |
| //------------------------------------------------------------------ |
| // NativeProcessProtocol::NativeDelegate overrides |
| //------------------------------------------------------------------ |
| void |
| InitializeDelegate (lldb_private::NativeProcessProtocol *process) override; |
| |
| void |
| ProcessStateChanged (lldb_private::NativeProcessProtocol *process, lldb::StateType state) override; |
| |
| protected: |
| lldb::PlatformSP m_platform_sp; |
| lldb::thread_t m_async_thread; |
| lldb_private::ProcessLaunchInfo m_process_launch_info; |
| lldb_private::Error m_process_launch_error; |
| std::set<lldb::pid_t> m_spawned_pids; |
| lldb_private::Mutex m_spawned_pids_mutex; |
| lldb_private::ProcessInstanceInfoList m_proc_infos; |
| uint32_t m_proc_infos_index; |
| PortMap m_port_map; |
| uint16_t m_port_offset; |
| lldb::tid_t m_current_tid; |
| lldb::tid_t m_continue_tid; |
| lldb_private::Mutex m_debugged_process_mutex; |
| lldb_private::NativeProcessProtocolSP m_debugged_process_sp; |
| lldb::DebuggerSP m_debugger_sp; |
| Communication m_stdio_communication; |
| bool m_exit_now; // use in asynchronous handling to indicate process should exit. |
| lldb::StateType m_inferior_prev_state; |
| bool m_thread_suffix_supported; |
| bool m_list_threads_in_stop_reply; |
| lldb::DataBufferSP m_active_auxv_buffer_sp; |
| lldb_private::Mutex m_saved_registers_mutex; |
| std::unordered_map<uint32_t, lldb::DataBufferSP> m_saved_registers_map; |
| uint32_t m_next_saved_registers_id; |
| |
| PacketResult |
| SendUnimplementedResponse (const char *packet); |
| |
| PacketResult |
| SendErrorResponse (uint8_t error); |
| |
| PacketResult |
| SendIllFormedResponse (const StringExtractorGDBRemote &packet, const char *error_message); |
| |
| PacketResult |
| SendOKResponse (); |
| |
| PacketResult |
| SendONotification (const char *buffer, uint32_t len); |
| |
| PacketResult |
| SendWResponse (lldb_private::NativeProcessProtocol *process); |
| |
| PacketResult |
| SendStopReplyPacketForThread (lldb::tid_t tid); |
| |
| PacketResult |
| SendStopReasonForState (lldb::StateType process_state, bool flush_on_exit); |
| |
| PacketResult |
| Handle_A (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_qLaunchSuccess (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_qHostInfo (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_k (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_qPlatform_mkdir (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_qPlatform_chmod (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_qProcessInfo (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_qProcessInfoPID (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_qfProcessInfo (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_qsProcessInfo (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_qC (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_qUserName (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_qGroupName (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_qSpeedTest (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_QEnvironment (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_QLaunchArch (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_QSetDisableASLR (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_QSetDetachOnError (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_QSetWorkingDir (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_qGetWorkingDir (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_QStartNoAckMode (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_QSetSTDIN (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_QSetSTDOUT (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_QSetSTDERR (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_C (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_c (StringExtractorGDBRemote &packet, bool skip_file_pos_adjustment = false); |
| |
| PacketResult |
| Handle_vCont (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_vCont_actions (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_stop_reason (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_vFile_Open (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_vFile_Close (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_vFile_pRead (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_vFile_pWrite (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_vFile_Size (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_vFile_Mode (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_vFile_Exists (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_vFile_symlink (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_vFile_unlink (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_vFile_Stat (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_vFile_MD5 (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_qPlatform_shell (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_qRegisterInfo (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_qfThreadInfo (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_qsThreadInfo (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_p (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_P (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_H (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_interrupt (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_m (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_M (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_qMemoryRegionInfoSupported (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_qMemoryRegionInfo (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_Z (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_z (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_s (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_qSupported (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_QThreadSuffixSupported (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_QListThreadsInStopReply (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_qXfer_auxv_read (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_QSaveRegisterState (StringExtractorGDBRemote &packet); |
| |
| PacketResult |
| Handle_QRestoreRegisterState (StringExtractorGDBRemote &packet); |
| |
| void |
| SetCurrentThreadID (lldb::tid_t tid); |
| |
| lldb::tid_t |
| GetCurrentThreadID () const; |
| |
| void |
| SetContinueThreadID (lldb::tid_t tid); |
| |
| lldb::tid_t |
| GetContinueThreadID () const { return m_continue_tid; } |
| |
| lldb_private::Error |
| SetSTDIOFileDescriptor (int fd); |
| |
| static void |
| STDIOReadThreadBytesReceived (void *baton, const void *src, size_t src_len); |
| |
| private: |
| bool |
| DebugserverProcessReaped (lldb::pid_t pid); |
| |
| static bool |
| ReapDebugserverProcess (void *callback_baton, |
| lldb::pid_t pid, |
| bool exited, |
| int signal, |
| int status); |
| |
| bool |
| DebuggedProcessReaped (lldb::pid_t pid); |
| |
| static bool |
| ReapDebuggedProcess (void *callback_baton, |
| lldb::pid_t pid, |
| bool exited, |
| int signal, |
| int status); |
| |
| bool |
| KillSpawnedProcess (lldb::pid_t pid); |
| |
| bool |
| IsGdbServer () |
| { |
| return !m_is_platform; |
| } |
| |
| /// Launch a process from lldb-gdbserver |
| lldb_private::Error |
| LaunchDebugServerProcess (); |
| |
| /// Launch a process from lldb-platform |
| lldb_private::Error |
| LaunchPlatformProcess (); |
| |
| void |
| HandleInferiorState_Exited (lldb_private::NativeProcessProtocol *process); |
| |
| void |
| HandleInferiorState_Stopped (lldb_private::NativeProcessProtocol *process); |
| |
| void |
| FlushInferiorOutput (); |
| |
| lldb_private::NativeThreadProtocolSP |
| GetThreadFromSuffix (StringExtractorGDBRemote &packet); |
| |
| uint32_t |
| GetNextSavedRegistersID (); |
| |
| void |
| MaybeCloseInferiorTerminalConnection (); |
| |
| //------------------------------------------------------------------ |
| // For GDBRemoteCommunicationServer only |
| //------------------------------------------------------------------ |
| DISALLOW_COPY_AND_ASSIGN (GDBRemoteCommunicationServer); |
| }; |
| |
| #endif // liblldb_GDBRemoteCommunicationServer_h_ |