1 //===-- lldb-platform.cpp ---------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include <errno.h>
11 #if defined(__APPLE__)
12 #include <netinet/in.h>
13 #endif
14 #include <signal.h>
15 #include <stdint.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <sys/wait.h>
20 
21 #include <fstream>
22 
23 #include "llvm/Support/FileSystem.h"
24 #include "llvm/Support/FileUtilities.h"
25 
26 #include "Acceptor.h"
27 #include "LLDBServerUtilities.h"
28 #include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h"
29 #include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h"
30 #include "lldb/Host/ConnectionFileDescriptor.h"
31 #include "lldb/Host/HostGetOpt.h"
32 #include "lldb/Host/OptionParser.h"
33 #include "lldb/Host/common/TCPSocket.h"
34 #include "lldb/Utility/FileSpec.h"
35 #include "lldb/Utility/Status.h"
36 
37 using namespace lldb;
38 using namespace lldb_private;
39 using namespace lldb_private::lldb_server;
40 using namespace lldb_private::process_gdb_remote;
41 using namespace llvm;
42 
43 //----------------------------------------------------------------------
44 // option descriptors for getopt_long_only()
45 //----------------------------------------------------------------------
46 
47 static int g_debug = 0;
48 static int g_verbose = 0;
49 static int g_server = 0;
50 
51 static struct option g_long_options[] = {
52     {"debug", no_argument, &g_debug, 1},
53     {"verbose", no_argument, &g_verbose, 1},
54     {"log-file", required_argument, NULL, 'l'},
55     {"log-channels", required_argument, NULL, 'c'},
56     {"listen", required_argument, NULL, 'L'},
57     {"port-offset", required_argument, NULL, 'p'},
58     {"gdbserver-port", required_argument, NULL, 'P'},
59     {"min-gdbserver-port", required_argument, NULL, 'm'},
60     {"max-gdbserver-port", required_argument, NULL, 'M'},
61     {"socket-file", required_argument, NULL, 'f'},
62     {"server", no_argument, &g_server, 1},
63     {NULL, 0, NULL, 0}};
64 
65 #if defined(__APPLE__)
66 #define LOW_PORT (IPPORT_RESERVED)
67 #define HIGH_PORT (IPPORT_HIFIRSTAUTO)
68 #else
69 #define LOW_PORT (1024u)
70 #define HIGH_PORT (49151u)
71 #endif
72 
73 //----------------------------------------------------------------------
74 // Watch for signals
75 //----------------------------------------------------------------------
76 static void signal_handler(int signo) {
77   switch (signo) {
78   case SIGHUP:
79     // Use SIGINT first, if that does not work, use SIGHUP as a last resort.
80     // And we should not call exit() here because it results in the global
81     // destructors
82     // to be invoked and wreaking havoc on the threads still running.
83     Host::SystemLog(Host::eSystemLogWarning,
84                     "SIGHUP received, exiting lldb-server...\n");
85     abort();
86     break;
87   }
88 }
89 
90 static void display_usage(const char *progname, const char *subcommand) {
91   fprintf(stderr, "Usage:\n  %s %s [--log-file log-file-name] [--log-channels "
92                   "log-channel-list] [--port-file port-file-path] --server "
93                   "--listen port\n",
94           progname, subcommand);
95   exit(0);
96 }
97 
98 static Status save_socket_id_to_file(const std::string &socket_id,
99                                      const FileSpec &file_spec) {
100   FileSpec temp_file_spec(file_spec.GetDirectory().AsCString());
101   Status error(llvm::sys::fs::create_directory(temp_file_spec.GetPath()));
102   if (error.Fail())
103     return Status("Failed to create directory %s: %s",
104                   temp_file_spec.GetCString(), error.AsCString());
105 
106   llvm::SmallString<64> temp_file_path;
107   temp_file_spec.AppendPathComponent("port-file.%%%%%%");
108   int FD;
109   auto err_code = llvm::sys::fs::createUniqueFile(temp_file_spec.GetPath(), FD,
110                                                   temp_file_path);
111   if (err_code)
112     return Status("Failed to create temp file: %s", err_code.message().c_str());
113 
114   llvm::FileRemover tmp_file_remover(temp_file_path);
115 
116   {
117     llvm::raw_fd_ostream temp_file(FD, true);
118     temp_file << socket_id;
119     temp_file.close();
120     if (temp_file.has_error())
121       return Status("Failed to write to port file.");
122   }
123 
124   err_code = llvm::sys::fs::rename(temp_file_path, file_spec.GetPath());
125   if (err_code)
126     return Status("Failed to rename file %s to %s: %s", temp_file_path.c_str(),
127                   file_spec.GetPath().c_str(), err_code.message().c_str());
128 
129   tmp_file_remover.releaseFile();
130   return Status();
131 }
132 
133 //----------------------------------------------------------------------
134 // main
135 //----------------------------------------------------------------------
136 int main_platform(int argc, char *argv[]) {
137   const char *progname = argv[0];
138   const char *subcommand = argv[1];
139   argc--;
140   argv++;
141   signal(SIGPIPE, SIG_IGN);
142   signal(SIGHUP, signal_handler);
143   int long_option_index = 0;
144   Status error;
145   std::string listen_host_port;
146   int ch;
147 
148   std::string log_file;
149   StringRef
150       log_channels; // e.g. "lldb process threads:gdb-remote default:linux all"
151 
152   GDBRemoteCommunicationServerPlatform::PortMap gdbserver_portmap;
153   int min_gdbserver_port = 0;
154   int max_gdbserver_port = 0;
155   uint16_t port_offset = 0;
156 
157   FileSpec socket_file;
158   bool show_usage = false;
159   int option_error = 0;
160   int socket_error = -1;
161 
162   std::string short_options(OptionParser::GetShortOptionString(g_long_options));
163 
164 #if __GLIBC__
165   optind = 0;
166 #else
167   optreset = 1;
168   optind = 1;
169 #endif
170 
171   while ((ch = getopt_long_only(argc, argv, short_options.c_str(),
172                                 g_long_options, &long_option_index)) != -1) {
173     switch (ch) {
174     case 0: // Any optional that auto set themselves will return 0
175       break;
176 
177     case 'L':
178       listen_host_port.append(optarg);
179       break;
180 
181     case 'l': // Set Log File
182       if (optarg && optarg[0])
183         log_file.assign(optarg);
184       break;
185 
186     case 'c': // Log Channels
187       if (optarg && optarg[0])
188         log_channels = StringRef(optarg);
189       break;
190 
191     case 'f': // Socket file
192       if (optarg && optarg[0])
193         socket_file.SetFile(optarg, FileSpec::Style::native);
194       break;
195 
196     case 'p': {
197       if (!llvm::to_integer(optarg, port_offset)) {
198         llvm::errs() << "error: invalid port offset string " << optarg << "\n";
199         option_error = 4;
200         break;
201       }
202       if (port_offset < LOW_PORT || port_offset > HIGH_PORT) {
203         llvm::errs() << llvm::formatv("error: port offset {0} is not in the "
204                                       "valid user port range of {1} - {2}\n",
205                                       port_offset, LOW_PORT, HIGH_PORT);
206         option_error = 5;
207       }
208     } break;
209 
210     case 'P':
211     case 'm':
212     case 'M': {
213       uint16_t portnum;
214       if (!llvm::to_integer(optarg, portnum)) {
215         llvm::errs() << "error: invalid port number string " << optarg << "\n";
216         option_error = 2;
217         break;
218       }
219       if (portnum < LOW_PORT || portnum > HIGH_PORT) {
220         llvm::errs() << llvm::formatv("error: port number {0} is not in the "
221                                       "valid user port range of {1} - {2}\n",
222                                       portnum, LOW_PORT, HIGH_PORT);
223         option_error = 1;
224         break;
225       }
226       if (ch == 'P')
227         gdbserver_portmap[portnum] = LLDB_INVALID_PROCESS_ID;
228       else if (ch == 'm')
229         min_gdbserver_port = portnum;
230       else
231         max_gdbserver_port = portnum;
232     } break;
233 
234     case 'h': /* fall-through is intentional */
235     case '?':
236       show_usage = true;
237       break;
238     }
239   }
240 
241   if (!LLDBServerUtilities::SetupLogging(log_file, log_channels, 0))
242     return -1;
243 
244   // Make a port map for a port range that was specified.
245   if (min_gdbserver_port < max_gdbserver_port) {
246     for (uint16_t port = min_gdbserver_port; port < max_gdbserver_port; ++port)
247       gdbserver_portmap[port] = LLDB_INVALID_PROCESS_ID;
248   } else if (min_gdbserver_port != max_gdbserver_port) {
249     fprintf(stderr, "error: --min-gdbserver-port (%u) is greater than "
250                     "--max-gdbserver-port (%u)\n",
251             min_gdbserver_port, max_gdbserver_port);
252     option_error = 3;
253   }
254 
255   // Print usage and exit if no listening port is specified.
256   if (listen_host_port.empty())
257     show_usage = true;
258 
259   if (show_usage || option_error) {
260     display_usage(progname, subcommand);
261     exit(option_error);
262   }
263 
264   // Skip any options we consumed with getopt_long_only.
265   argc -= optind;
266   argv += optind;
267   lldb_private::Args inferior_arguments;
268   inferior_arguments.SetArguments(argc, const_cast<const char **>(argv));
269 
270   const bool children_inherit_listen_socket = false;
271   // the test suite makes many connections in parallel, let's not miss any.
272   // The highest this should get reasonably is a function of the number
273   // of target CPUs. For now, let's just use 100.
274   const int backlog = 100;
275 
276   std::unique_ptr<Acceptor> acceptor_up(Acceptor::Create(
277       listen_host_port, children_inherit_listen_socket, error));
278   if (error.Fail()) {
279     fprintf(stderr, "failed to create acceptor: %s", error.AsCString());
280     exit(socket_error);
281   }
282 
283   error = acceptor_up->Listen(backlog);
284   if (error.Fail()) {
285     printf("failed to listen: %s\n", error.AsCString());
286     exit(socket_error);
287   }
288   if (socket_file) {
289     error =
290         save_socket_id_to_file(acceptor_up->GetLocalSocketId(), socket_file);
291     if (error.Fail()) {
292       fprintf(stderr, "failed to write socket id to %s: %s\n",
293               socket_file.GetPath().c_str(), error.AsCString());
294       return 1;
295     }
296   }
297 
298   do {
299     GDBRemoteCommunicationServerPlatform platform(
300         acceptor_up->GetSocketProtocol(), acceptor_up->GetSocketScheme());
301 
302     if (port_offset > 0)
303       platform.SetPortOffset(port_offset);
304 
305     if (!gdbserver_portmap.empty()) {
306       platform.SetPortMap(std::move(gdbserver_portmap));
307     }
308 
309     const bool children_inherit_accept_socket = true;
310     Connection *conn = nullptr;
311     error = acceptor_up->Accept(children_inherit_accept_socket, conn);
312     if (error.Fail()) {
313       printf("error: %s\n", error.AsCString());
314       exit(socket_error);
315     }
316     printf("Connection established.\n");
317     if (g_server) {
318       // Collect child zombie processes.
319       while (waitpid(-1, nullptr, WNOHANG) > 0)
320         ;
321       if (fork()) {
322         // Parent doesn't need a connection to the lldb client
323         delete conn;
324 
325         // Parent will continue to listen for new connections.
326         continue;
327       } else {
328         // Child process will handle the connection and exit.
329         g_server = 0;
330         // Listening socket is owned by parent process.
331         acceptor_up.release();
332       }
333     } else {
334       // If not running as a server, this process will not accept
335       // connections while a connection is active.
336       acceptor_up.reset();
337     }
338     platform.SetConnection(conn);
339 
340     if (platform.IsConnected()) {
341       if (inferior_arguments.GetArgumentCount() > 0) {
342         lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
343         uint16_t port = 0;
344         std::string socket_name;
345         Status error = platform.LaunchGDBServer(inferior_arguments,
346                                                 "", // hostname
347                                                 pid, port, socket_name);
348         if (error.Success())
349           platform.SetPendingGdbServer(pid, port, socket_name);
350         else
351           fprintf(stderr, "failed to start gdbserver: %s\n", error.AsCString());
352       }
353 
354       // After we connected, we need to get an initial ack from...
355       if (platform.HandshakeWithClient()) {
356         bool interrupt = false;
357         bool done = false;
358         while (!interrupt && !done) {
359           if (platform.GetPacketAndSendResponse(llvm::None, error, interrupt,
360                                                 done) !=
361               GDBRemoteCommunication::PacketResult::Success)
362             break;
363         }
364 
365         if (error.Fail()) {
366           fprintf(stderr, "error: %s\n", error.AsCString());
367         }
368       } else {
369         fprintf(stderr, "error: handshake with client failed\n");
370       }
371     }
372   } while (g_server);
373 
374   fprintf(stderr, "lldb-server exiting...\n");
375 
376   return 0;
377 }
378