1 //===-- GDBRemoteCommunicationServerPlatform.h ------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATIONSERVERPLATFORM_H
10 #define LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATIONSERVERPLATFORM_H
11 
12 #include <map>
13 #include <mutex>
14 #include <optional>
15 #include <set>
16 
17 #include "GDBRemoteCommunicationServerCommon.h"
18 #include "lldb/Host/Socket.h"
19 
20 #include "llvm/Support/Error.h"
21 
22 namespace lldb_private {
23 namespace process_gdb_remote {
24 
25 class GDBRemoteCommunicationServerPlatform
26     : public GDBRemoteCommunicationServerCommon {
27 public:
28   class PortMap {
29   public:
30     // This class is used to restrict the range of ports that
31     // platform created debugserver/gdbserver processes will
32     // communicate on.
33 
34     // Construct an empty map, where empty means any port is allowed.
35     PortMap() = default;
36 
37     // Make a port map with a range of free ports
38     // from min_port to max_port-1.
39     PortMap(uint16_t min_port, uint16_t max_port);
40 
41     // Add a port to the map. If it is already in the map do not modify
42     // its mapping. (used ports remain used, new ports start as free)
43     void AllowPort(uint16_t port);
44 
45     // If we are using a port map where we can only use certain ports,
46     // get the next available port.
47     //
48     // If we are using a port map and we are out of ports, return an error.
49     //
50     // If we aren't using a port map, return 0 to indicate we should bind to
51     // port 0 and then figure out which port we used.
52     llvm::Expected<uint16_t> GetNextAvailablePort();
53 
54     // Tie a port to a process ID. Returns false if the port is not in the port
55     // map. If the port is already in use it will be moved to the given pid.
56     // FIXME: This is and GetNextAvailablePort make create a race condition if
57     // the portmap is shared between processes.
58     bool AssociatePortWithProcess(uint16_t port, lldb::pid_t pid);
59 
60     // Free the given port. Returns false if the port is not in the map.
61     bool FreePort(uint16_t port);
62 
63     // Free the port associated with the given pid. Returns false if there is
64     // no port associated with the pid.
65     bool FreePortForProcess(lldb::pid_t pid);
66 
67     // Returns true if there are no ports in the map, regardless of the state
68     // of those ports. Meaning a map with 1 used port is not empty.
69     bool empty() const;
70 
71   private:
72     std::map<uint16_t, lldb::pid_t> m_port_map;
73   };
74 
75   GDBRemoteCommunicationServerPlatform(
76       const Socket::SocketProtocol socket_protocol, const char *socket_scheme);
77 
78   ~GDBRemoteCommunicationServerPlatform() override;
79 
80   Status LaunchProcess() override;
81 
82   // Set both ports to zero to let the platform automatically bind to
83   // a port chosen by the OS.
84   void SetPortMap(PortMap &&port_map);
85 
86   void SetPortOffset(uint16_t port_offset);
87 
88   void SetInferiorArguments(const lldb_private::Args &args);
89 
90   // Set port if you want to use a specific port number.
91   // Otherwise port will be set to the port that was chosen for you.
92   Status LaunchGDBServer(const lldb_private::Args &args, std::string hostname,
93                          lldb::pid_t &pid, std::optional<uint16_t> &port,
94                          std::string &socket_name);
95 
96   void SetPendingGdbServer(lldb::pid_t pid, uint16_t port,
97                            const std::string &socket_name);
98 
99 protected:
100   const Socket::SocketProtocol m_socket_protocol;
101   const std::string m_socket_scheme;
102   std::recursive_mutex m_spawned_pids_mutex;
103   std::set<lldb::pid_t> m_spawned_pids;
104 
105   PortMap m_port_map;
106   uint16_t m_port_offset;
107   struct {
108     lldb::pid_t pid;
109     uint16_t port;
110     std::string socket_name;
111   } m_pending_gdb_server;
112 
113   PacketResult Handle_qLaunchGDBServer(StringExtractorGDBRemote &packet);
114 
115   PacketResult Handle_qQueryGDBServer(StringExtractorGDBRemote &packet);
116 
117   PacketResult Handle_qKillSpawnedProcess(StringExtractorGDBRemote &packet);
118 
119   PacketResult Handle_qPathComplete(StringExtractorGDBRemote &packet);
120 
121   PacketResult Handle_qProcessInfo(StringExtractorGDBRemote &packet);
122 
123   PacketResult Handle_qGetWorkingDir(StringExtractorGDBRemote &packet);
124 
125   PacketResult Handle_QSetWorkingDir(StringExtractorGDBRemote &packet);
126 
127   PacketResult Handle_qC(StringExtractorGDBRemote &packet);
128 
129   PacketResult Handle_jSignalsInfo(StringExtractorGDBRemote &packet);
130 
131 private:
132   bool KillSpawnedProcess(lldb::pid_t pid);
133 
134   void DebugserverProcessReaped(lldb::pid_t pid);
135 
136   static const FileSpec &GetDomainSocketDir();
137 
138   static FileSpec GetDomainSocketPath(const char *prefix);
139 
140   GDBRemoteCommunicationServerPlatform(
141       const GDBRemoteCommunicationServerPlatform &) = delete;
142   const GDBRemoteCommunicationServerPlatform &
143   operator=(const GDBRemoteCommunicationServerPlatform &) = delete;
144 };
145 
146 } // namespace process_gdb_remote
147 } // namespace lldb_private
148 
149 #endif // LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATIONSERVERPLATFORM_H
150