blob: 33ba1ad1ef98191d8d6abefe79b189d2aa840170 [file] [log] [blame]
Greg Claytonb43767a2011-03-22 01:34:44 +00001//===-- 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
Greg Claytond314e812011-03-23 00:09:55 +000010// C Includes
Greg Claytonb43767a2011-03-22 01:34:44 +000011#include <errno.h>
Zachary Turner98688922014-08-06 18:16:26 +000012#if defined(__APPLE__)
13#include <netinet/in.h>
14#endif
Greg Claytonb43767a2011-03-22 01:34:44 +000015#include <signal.h>
16#include <stdint.h>
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
Robert Flacka0e70cd2015-03-25 12:51:31 +000020#include <sys/wait.h>
Greg Claytonb43767a2011-03-22 01:34:44 +000021
Greg Claytond314e812011-03-23 00:09:55 +000022// C++ Includes
23
24// Other libraries and framework includes
25#include "lldb/Core/Error.h"
Zachary Turner93a66fc2014-10-06 21:22:36 +000026#include "lldb/Host/ConnectionFileDescriptor.h"
Zachary Turner98688922014-08-06 18:16:26 +000027#include "lldb/Host/HostGetOpt.h"
Greg Claytonfb909312013-11-23 01:58:15 +000028#include "lldb/Host/OptionParser.h"
Robert Flacka0e70cd2015-03-25 12:51:31 +000029#include "lldb/Host/Socket.h"
Tamas Berghammer9c9ecce2015-05-27 13:34:04 +000030#include "LLDBServerUtilities.h"
Tamas Berghammere13c2732015-02-11 10:29:30 +000031#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h"
Greg Clayton1cb64962011-03-24 04:28:38 +000032#include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h"
Tamas Berghammere13c2732015-02-11 10:29:30 +000033
Greg Claytond314e812011-03-23 00:09:55 +000034using namespace lldb;
35using namespace lldb_private;
Tamas Berghammer9c9ecce2015-05-27 13:34:04 +000036using namespace lldb_private::lldb_server;
Tamas Berghammerdb264a62015-03-31 09:52:22 +000037using namespace lldb_private::process_gdb_remote;
Tamas Berghammer9c9ecce2015-05-27 13:34:04 +000038using namespace llvm;
Greg Claytond314e812011-03-23 00:09:55 +000039
Greg Claytonb43767a2011-03-22 01:34:44 +000040//----------------------------------------------------------------------
Greg Claytonb7ad58a2013-04-04 20:35:24 +000041// option descriptors for getopt_long_only()
Greg Claytonb43767a2011-03-22 01:34:44 +000042//----------------------------------------------------------------------
43
Tamas Berghammerc2c3d712015-02-18 15:39:41 +000044static int g_debug = 0;
45static int g_verbose = 0;
Robert Flacka0e70cd2015-03-25 12:51:31 +000046static int g_server = 0;
Greg Claytonb43767a2011-03-22 01:34:44 +000047
48static struct option g_long_options[] =
49{
50 { "debug", no_argument, &g_debug, 1 },
51 { "verbose", no_argument, &g_verbose, 1 },
Tamas Berghammer9c9ecce2015-05-27 13:34:04 +000052 { "log-file", required_argument, NULL, 'l' },
53 { "log-channels", required_argument, NULL, 'c' },
Greg Claytond314e812011-03-23 00:09:55 +000054 { "listen", required_argument, NULL, 'L' },
Greg Claytond4724cf2013-11-22 18:55:04 +000055 { "port-offset", required_argument, NULL, 'p' },
56 { "gdbserver-port", required_argument, NULL, 'P' },
Greg Clayton29b8fc42013-11-21 01:44:58 +000057 { "min-gdbserver-port", required_argument, NULL, 'm' },
58 { "max-gdbserver-port", required_argument, NULL, 'M' },
Robert Flacka0e70cd2015-03-25 12:51:31 +000059 { "server", no_argument, &g_server, 1 },
Greg Claytonb43767a2011-03-22 01:34:44 +000060 { NULL, 0, NULL, 0 }
61};
62
Greg Clayton29b8fc42013-11-21 01:44:58 +000063#if defined (__APPLE__)
64#define LOW_PORT (IPPORT_RESERVED)
65#define HIGH_PORT (IPPORT_HIFIRSTAUTO)
66#else
67#define LOW_PORT (1024u)
68#define HIGH_PORT (49151u)
69#endif
70
Greg Claytonb43767a2011-03-22 01:34:44 +000071//----------------------------------------------------------------------
72// Watch for signals
73//----------------------------------------------------------------------
Tamas Berghammerc2c3d712015-02-18 15:39:41 +000074static void
Greg Claytonb43767a2011-03-22 01:34:44 +000075signal_handler(int signo)
76{
77 switch (signo)
78 {
Daniel Maleae0f8f572013-08-26 23:57:52 +000079 case SIGHUP:
80 // Use SIGINT first, if that does not work, use SIGHUP as a last resort.
81 // And we should not call exit() here because it results in the global destructors
82 // to be invoked and wreaking havoc on the threads still running.
Robert Flack8cc4cf12015-03-06 14:36:33 +000083 Host::SystemLog(Host::eSystemLogWarning, "SIGHUP received, exiting lldb-server...\n");
Daniel Maleae0f8f572013-08-26 23:57:52 +000084 abort();
85 break;
Greg Claytonb43767a2011-03-22 01:34:44 +000086 }
87}
88
Daniel Maleae0f8f572013-08-26 23:57:52 +000089static void
Tamas Berghammerc2c3d712015-02-18 15:39:41 +000090display_usage (const char *progname, const char *subcommand)
Daniel Maleae0f8f572013-08-26 23:57:52 +000091{
Tamas Berghammer9c9ecce2015-05-27 13:34:04 +000092 fprintf(stderr, "Usage:\n %s %s [--log-file log-file-name] [--log-channels log-channel-list] --server --listen port\n", progname, subcommand);
Daniel Maleae0f8f572013-08-26 23:57:52 +000093 exit(0);
94}
95
Greg Claytonb43767a2011-03-22 01:34:44 +000096//----------------------------------------------------------------------
97// main
98//----------------------------------------------------------------------
99int
Tamas Berghammerc2c3d712015-02-18 15:39:41 +0000100main_platform (int argc, char *argv[])
Greg Claytonb43767a2011-03-22 01:34:44 +0000101{
Daniel Maleae0f8f572013-08-26 23:57:52 +0000102 const char *progname = argv[0];
Tamas Berghammerc2c3d712015-02-18 15:39:41 +0000103 const char *subcommand = argv[1];
104 argc--;
105 argv++;
Greg Claytonfb909312013-11-23 01:58:15 +0000106 signal (SIGPIPE, SIG_IGN);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000107 signal (SIGHUP, signal_handler);
Greg Claytonb43767a2011-03-22 01:34:44 +0000108 int long_option_index = 0;
Greg Clayton9b1e1cd2011-04-04 18:18:57 +0000109 Error error;
Greg Clayton73bf5db2011-06-17 01:22:15 +0000110 std::string listen_host_port;
Greg Clayton9d3d6882011-10-31 23:51:19 +0000111 int ch;
Greg Clayton5fb8f792013-12-02 19:35:49 +0000112
Tamas Berghammer9c9ecce2015-05-27 13:34:04 +0000113 std::string log_file;
114 StringRef log_channels; // e.g. "lldb process threads:gdb-remote default:linux all"
115
Tamas Berghammere13c2732015-02-11 10:29:30 +0000116 GDBRemoteCommunicationServerPlatform::PortMap gdbserver_portmap;
Greg Clayton29b8fc42013-11-21 01:44:58 +0000117 int min_gdbserver_port = 0;
118 int max_gdbserver_port = 0;
Greg Claytond4724cf2013-11-22 18:55:04 +0000119 uint16_t port_offset = 0;
Greg Clayton29b8fc42013-11-21 01:44:58 +0000120
121 bool show_usage = false;
122 int option_error = 0;
Robert Flacka0e70cd2015-03-25 12:51:31 +0000123 int socket_error = -1;
Greg Clayton9b1e1cd2011-04-04 18:18:57 +0000124
Greg Claytonfb909312013-11-23 01:58:15 +0000125 std::string short_options(OptionParser::GetShortOptionString(g_long_options));
126
Greg Claytond4724cf2013-11-22 18:55:04 +0000127#if __GLIBC__
128 optind = 0;
129#else
130 optreset = 1;
131 optind = 1;
132#endif
133
Greg Claytonfb909312013-11-23 01:58:15 +0000134 while ((ch = getopt_long_only(argc, argv, short_options.c_str(), g_long_options, &long_option_index)) != -1)
Greg Claytonb43767a2011-03-22 01:34:44 +0000135 {
Greg Claytonb43767a2011-03-22 01:34:44 +0000136 switch (ch)
137 {
138 case 0: // Any optional that auto set themselves will return 0
139 break;
140
Greg Claytond314e812011-03-23 00:09:55 +0000141 case 'L':
Greg Clayton73bf5db2011-06-17 01:22:15 +0000142 listen_host_port.append (optarg);
Greg Claytond314e812011-03-23 00:09:55 +0000143 break;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000144
Tamas Berghammer9c9ecce2015-05-27 13:34:04 +0000145 case 'l': // Set Log File
146 if (optarg && optarg[0])
147 log_file.assign(optarg);
148 break;
149
150 case 'c': // Log Channels
151 if (optarg && optarg[0])
152 log_channels = StringRef(optarg);
153 break;
154
Greg Clayton29b8fc42013-11-21 01:44:58 +0000155 case 'p':
Greg Claytond4724cf2013-11-22 18:55:04 +0000156 {
157 char *end = NULL;
158 long tmp_port_offset = strtoul(optarg, &end, 0);
159 if (end && *end == '\0')
160 {
161 if (LOW_PORT <= tmp_port_offset && tmp_port_offset <= HIGH_PORT)
162 {
163 port_offset = (uint16_t)tmp_port_offset;
164 }
165 else
166 {
167 fprintf (stderr, "error: port offset %li is not in the valid user port range of %u - %u\n", tmp_port_offset, LOW_PORT, HIGH_PORT);
168 option_error = 5;
169 }
170 }
171 else
172 {
173 fprintf (stderr, "error: invalid port offset string %s\n", optarg);
174 option_error = 4;
175 }
176 }
177 break;
178
179 case 'P':
Greg Clayton29b8fc42013-11-21 01:44:58 +0000180 case 'm':
181 case 'M':
182 {
183 char *end = NULL;
184 long portnum = strtoul(optarg, &end, 0);
185 if (end && *end == '\0')
186 {
187 if (LOW_PORT <= portnum && portnum <= HIGH_PORT)
188 {
Greg Claytond4724cf2013-11-22 18:55:04 +0000189 if (ch == 'P')
Greg Clayton29b8fc42013-11-21 01:44:58 +0000190 gdbserver_portmap[(uint16_t)portnum] = LLDB_INVALID_PROCESS_ID;
191 else if (ch == 'm')
192 min_gdbserver_port = portnum;
193 else
194 max_gdbserver_port = portnum;
195 }
196 else
197 {
198 fprintf (stderr, "error: port number %li is not in the valid user port range of %u - %u\n", portnum, LOW_PORT, HIGH_PORT);
199 option_error = 1;
200 }
201 }
202 else
203 {
204 fprintf (stderr, "error: invalid port number string %s\n", optarg);
205 option_error = 2;
206 }
207 }
208 break;
Greg Clayton5fb8f792013-12-02 19:35:49 +0000209
Daniel Maleae0f8f572013-08-26 23:57:52 +0000210 case 'h': /* fall-through is intentional */
211 case '?':
Greg Clayton29b8fc42013-11-21 01:44:58 +0000212 show_usage = true;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000213 break;
Greg Claytonb43767a2011-03-22 01:34:44 +0000214 }
215 }
Greg Clayton5fb8f792013-12-02 19:35:49 +0000216
Tamas Berghammer9c9ecce2015-05-27 13:34:04 +0000217 if (!LLDBServerUtilities::SetupLogging(log_file, log_channels, 0))
218 return -1;
219
Greg Clayton29b8fc42013-11-21 01:44:58 +0000220 // Make a port map for a port range that was specified.
221 if (min_gdbserver_port < max_gdbserver_port)
222 {
223 for (uint16_t port = min_gdbserver_port; port < max_gdbserver_port; ++port)
224 gdbserver_portmap[port] = LLDB_INVALID_PROCESS_ID;
225 }
226 else if (min_gdbserver_port != max_gdbserver_port)
227 {
228 fprintf (stderr, "error: --min-gdbserver-port (%u) is greater than --max-gdbserver-port (%u)\n", min_gdbserver_port, max_gdbserver_port);
229 option_error = 3;
Greg Clayton29b8fc42013-11-21 01:44:58 +0000230 }
231
Daniel Maleae0f8f572013-08-26 23:57:52 +0000232 // Print usage and exit if no listening port is specified.
233 if (listen_host_port.empty())
Greg Clayton29b8fc42013-11-21 01:44:58 +0000234 show_usage = true;
235
236 if (show_usage || option_error)
237 {
Tamas Berghammerc2c3d712015-02-18 15:39:41 +0000238 display_usage(progname, subcommand);
Greg Clayton29b8fc42013-11-21 01:44:58 +0000239 exit(option_error);
240 }
Greg Claytonb43767a2011-03-22 01:34:44 +0000241
Robert Flacka0e70cd2015-03-25 12:51:31 +0000242 std::unique_ptr<Socket> listening_socket_up;
243 Socket *socket = nullptr;
Robert Flacka0e70cd2015-03-25 12:51:31 +0000244 const bool children_inherit_listen_socket = false;
Vince Harron33aea902015-03-31 00:27:10 +0000245
246 // the test suite makes many connections in parallel, let's not miss any.
247 // The highest this should get reasonably is a function of the number
248 // of target CPUs. For now, let's just use 100
249 const int backlog = 100;
250 error = Socket::TcpListen(listen_host_port.c_str(), children_inherit_listen_socket, socket, NULL, backlog);
Robert Flacka0e70cd2015-03-25 12:51:31 +0000251 if (error.Fail())
252 {
253 printf("error: %s\n", error.AsCString());
254 exit(socket_error);
255 }
256 listening_socket_up.reset(socket);
Vince Harron218353d2015-05-26 03:08:05 +0000257 printf ("Listening for a connection from %u...\n", listening_socket_up->GetLocalPortNumber());
Greg Claytonb43767a2011-03-22 01:34:44 +0000258
Daniel Maleae0f8f572013-08-26 23:57:52 +0000259 do {
Tamas Berghammere13c2732015-02-11 10:29:30 +0000260 GDBRemoteCommunicationServerPlatform platform;
Greg Clayton29b8fc42013-11-21 01:44:58 +0000261
Greg Claytond4724cf2013-11-22 18:55:04 +0000262 if (port_offset > 0)
Tamas Berghammere13c2732015-02-11 10:29:30 +0000263 platform.SetPortOffset(port_offset);
Greg Claytond4724cf2013-11-22 18:55:04 +0000264
Greg Clayton29b8fc42013-11-21 01:44:58 +0000265 if (!gdbserver_portmap.empty())
266 {
Tamas Berghammere13c2732015-02-11 10:29:30 +0000267 platform.SetPortMap(std::move(gdbserver_portmap));
Greg Clayton29b8fc42013-11-21 01:44:58 +0000268 }
269
Robert Flacka0e70cd2015-03-25 12:51:31 +0000270 const bool children_inherit_accept_socket = true;
271 socket = nullptr;
272 error = listening_socket_up->BlockingAccept(listen_host_port.c_str(), children_inherit_accept_socket, socket);
273 if (error.Fail())
Greg Claytond314e812011-03-23 00:09:55 +0000274 {
Robert Flacka0e70cd2015-03-25 12:51:31 +0000275 printf ("error: %s\n", error.AsCString());
276 exit(socket_error);
277 }
278 printf ("Connection established.\n");
279 if (g_server)
280 {
281 // Collect child zombie processes.
282 while (waitpid(-1, nullptr, WNOHANG) > 0);
283 if (fork())
Greg Claytond314e812011-03-23 00:09:55 +0000284 {
Vince Harronf1e69992015-03-31 00:24:51 +0000285 // Parent doesn't need a connection to the lldb client
286 delete socket;
287 socket = nullptr;
288
Robert Flacka0e70cd2015-03-25 12:51:31 +0000289 // Parent will continue to listen for new connections.
290 continue;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000291 }
Robert Flacka0e70cd2015-03-25 12:51:31 +0000292 else
Daniel Maleae0f8f572013-08-26 23:57:52 +0000293 {
Robert Flacka0e70cd2015-03-25 12:51:31 +0000294 // Child process will handle the connection and exit.
295 g_server = 0;
296 // Listening socket is owned by parent process.
297 listening_socket_up.release();
Greg Claytond314e812011-03-23 00:09:55 +0000298 }
299 }
Robert Flacka0e70cd2015-03-25 12:51:31 +0000300 else
301 {
302 // If not running as a server, this process will not accept
303 // connections while a connection is active.
304 listening_socket_up.reset();
305 }
306 platform.SetConnection (new ConnectionFileDescriptor(socket));
307
308 if (platform.IsConnected())
309 {
310 // After we connected, we need to get an initial ack from...
311 if (platform.HandshakeWithClient(&error))
312 {
313 bool interrupt = false;
314 bool done = false;
315 while (!interrupt && !done)
316 {
317 if (platform.GetPacketAndSendResponse (UINT32_MAX, error, interrupt, done) != GDBRemoteCommunication::PacketResult::Success)
318 break;
319 }
320
321 if (error.Fail())
322 {
323 fprintf(stderr, "error: %s\n", error.AsCString());
324 }
325 }
326 else
327 {
328 fprintf(stderr, "error: handshake with client failed\n");
329 }
330 }
331 } while (g_server);
Greg Claytonb43767a2011-03-22 01:34:44 +0000332
Robert Flack8cc4cf12015-03-06 14:36:33 +0000333 fprintf(stderr, "lldb-server exiting...\n");
Daniel Maleae0f8f572013-08-26 23:57:52 +0000334
Greg Claytonb43767a2011-03-22 01:34:44 +0000335 return 0;
336}