10b57cec5SDimitry Andric //===-- GDBRemoteCommunicationServerPlatform.h ------------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 95ffd83dbSDimitry Andric #ifndef LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATIONSERVERPLATFORM_H 105ffd83dbSDimitry Andric #define LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATIONSERVERPLATFORM_H 110b57cec5SDimitry Andric 120b57cec5SDimitry Andric #include <map> 130b57cec5SDimitry Andric #include <mutex> 14*bdd1243dSDimitry Andric #include <optional> 150b57cec5SDimitry Andric #include <set> 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric #include "GDBRemoteCommunicationServerCommon.h" 180b57cec5SDimitry Andric #include "lldb/Host/Socket.h" 190b57cec5SDimitry Andric 20e8d8bef9SDimitry Andric #include "llvm/Support/Error.h" 21e8d8bef9SDimitry Andric 220b57cec5SDimitry Andric namespace lldb_private { 230b57cec5SDimitry Andric namespace process_gdb_remote { 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric class GDBRemoteCommunicationServerPlatform 260b57cec5SDimitry Andric : public GDBRemoteCommunicationServerCommon { 270b57cec5SDimitry Andric public: 28e8d8bef9SDimitry Andric class PortMap { 29e8d8bef9SDimitry Andric public: 30e8d8bef9SDimitry Andric // This class is used to restrict the range of ports that 31e8d8bef9SDimitry Andric // platform created debugserver/gdbserver processes will 32e8d8bef9SDimitry Andric // communicate on. 33e8d8bef9SDimitry Andric 34e8d8bef9SDimitry Andric // Construct an empty map, where empty means any port is allowed. 35e8d8bef9SDimitry Andric PortMap() = default; 36e8d8bef9SDimitry Andric 37e8d8bef9SDimitry Andric // Make a port map with a range of free ports 38e8d8bef9SDimitry Andric // from min_port to max_port-1. 39e8d8bef9SDimitry Andric PortMap(uint16_t min_port, uint16_t max_port); 40e8d8bef9SDimitry Andric 41e8d8bef9SDimitry Andric // Add a port to the map. If it is already in the map do not modify 42e8d8bef9SDimitry Andric // its mapping. (used ports remain used, new ports start as free) 43e8d8bef9SDimitry Andric void AllowPort(uint16_t port); 44e8d8bef9SDimitry Andric 45e8d8bef9SDimitry Andric // If we are using a port map where we can only use certain ports, 46e8d8bef9SDimitry Andric // get the next available port. 47e8d8bef9SDimitry Andric // 48e8d8bef9SDimitry Andric // If we are using a port map and we are out of ports, return an error. 49e8d8bef9SDimitry Andric // 50e8d8bef9SDimitry Andric // If we aren't using a port map, return 0 to indicate we should bind to 51e8d8bef9SDimitry Andric // port 0 and then figure out which port we used. 52e8d8bef9SDimitry Andric llvm::Expected<uint16_t> GetNextAvailablePort(); 53e8d8bef9SDimitry Andric 54e8d8bef9SDimitry Andric // Tie a port to a process ID. Returns false if the port is not in the port 55e8d8bef9SDimitry Andric // map. If the port is already in use it will be moved to the given pid. 56e8d8bef9SDimitry Andric // FIXME: This is and GetNextAvailablePort make create a race condition if 57e8d8bef9SDimitry Andric // the portmap is shared between processes. 58e8d8bef9SDimitry Andric bool AssociatePortWithProcess(uint16_t port, lldb::pid_t pid); 59e8d8bef9SDimitry Andric 60e8d8bef9SDimitry Andric // Free the given port. Returns false if the port is not in the map. 61e8d8bef9SDimitry Andric bool FreePort(uint16_t port); 62e8d8bef9SDimitry Andric 63e8d8bef9SDimitry Andric // Free the port associated with the given pid. Returns false if there is 64e8d8bef9SDimitry Andric // no port associated with the pid. 65e8d8bef9SDimitry Andric bool FreePortForProcess(lldb::pid_t pid); 66e8d8bef9SDimitry Andric 67e8d8bef9SDimitry Andric // Returns true if there are no ports in the map, regardless of the state 68e8d8bef9SDimitry Andric // of those ports. Meaning a map with 1 used port is not empty. 69e8d8bef9SDimitry Andric bool empty() const; 70e8d8bef9SDimitry Andric 71e8d8bef9SDimitry Andric private: 72e8d8bef9SDimitry Andric std::map<uint16_t, lldb::pid_t> m_port_map; 73e8d8bef9SDimitry Andric }; 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric GDBRemoteCommunicationServerPlatform( 760b57cec5SDimitry Andric const Socket::SocketProtocol socket_protocol, const char *socket_scheme); 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric ~GDBRemoteCommunicationServerPlatform() override; 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric Status LaunchProcess() override; 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric // Set both ports to zero to let the platform automatically bind to 830b57cec5SDimitry Andric // a port chosen by the OS. 840b57cec5SDimitry Andric void SetPortMap(PortMap &&port_map); 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric void SetPortOffset(uint16_t port_offset); 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric void SetInferiorArguments(const lldb_private::Args &args); 890b57cec5SDimitry Andric 90e8d8bef9SDimitry Andric // Set port if you want to use a specific port number. 91e8d8bef9SDimitry Andric // Otherwise port will be set to the port that was chosen for you. 920b57cec5SDimitry Andric Status LaunchGDBServer(const lldb_private::Args &args, std::string hostname, 93*bdd1243dSDimitry Andric lldb::pid_t &pid, std::optional<uint16_t> &port, 940b57cec5SDimitry Andric std::string &socket_name); 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric void SetPendingGdbServer(lldb::pid_t pid, uint16_t port, 970b57cec5SDimitry Andric const std::string &socket_name); 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric protected: 1000b57cec5SDimitry Andric const Socket::SocketProtocol m_socket_protocol; 1010b57cec5SDimitry Andric const std::string m_socket_scheme; 1020b57cec5SDimitry Andric std::recursive_mutex m_spawned_pids_mutex; 1030b57cec5SDimitry Andric std::set<lldb::pid_t> m_spawned_pids; 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric PortMap m_port_map; 1060b57cec5SDimitry Andric uint16_t m_port_offset; 1070b57cec5SDimitry Andric struct { 1080b57cec5SDimitry Andric lldb::pid_t pid; 1090b57cec5SDimitry Andric uint16_t port; 1100b57cec5SDimitry Andric std::string socket_name; 1110b57cec5SDimitry Andric } m_pending_gdb_server; 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric PacketResult Handle_qLaunchGDBServer(StringExtractorGDBRemote &packet); 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric PacketResult Handle_qQueryGDBServer(StringExtractorGDBRemote &packet); 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric PacketResult Handle_qKillSpawnedProcess(StringExtractorGDBRemote &packet); 1180b57cec5SDimitry Andric 119e8d8bef9SDimitry Andric PacketResult Handle_qPathComplete(StringExtractorGDBRemote &packet); 120e8d8bef9SDimitry Andric 1210b57cec5SDimitry Andric PacketResult Handle_qProcessInfo(StringExtractorGDBRemote &packet); 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric PacketResult Handle_qGetWorkingDir(StringExtractorGDBRemote &packet); 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric PacketResult Handle_QSetWorkingDir(StringExtractorGDBRemote &packet); 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric PacketResult Handle_qC(StringExtractorGDBRemote &packet); 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric PacketResult Handle_jSignalsInfo(StringExtractorGDBRemote &packet); 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric private: 1320b57cec5SDimitry Andric bool KillSpawnedProcess(lldb::pid_t pid); 1330b57cec5SDimitry Andric 13481ad6265SDimitry Andric void DebugserverProcessReaped(lldb::pid_t pid); 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric static const FileSpec &GetDomainSocketDir(); 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric static FileSpec GetDomainSocketPath(const char *prefix); 1390b57cec5SDimitry Andric 1405ffd83dbSDimitry Andric GDBRemoteCommunicationServerPlatform( 1415ffd83dbSDimitry Andric const GDBRemoteCommunicationServerPlatform &) = delete; 1425ffd83dbSDimitry Andric const GDBRemoteCommunicationServerPlatform & 1435ffd83dbSDimitry Andric operator=(const GDBRemoteCommunicationServerPlatform &) = delete; 1440b57cec5SDimitry Andric }; 1450b57cec5SDimitry Andric 1460b57cec5SDimitry Andric } // namespace process_gdb_remote 1470b57cec5SDimitry Andric } // namespace lldb_private 1480b57cec5SDimitry Andric 1495ffd83dbSDimitry Andric #endif // LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATIONSERVERPLATFORM_H 150