blob: fe69ea9f7dcd23c831ce6d196f90c916a50db013 [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
Daniel Malea93a64302012-12-05 00:20:57 +000010#include "lldb/lldb-python.h"
11
Greg Claytond314e812011-03-23 00:09:55 +000012// C Includes
Greg Claytonb43767a2011-03-22 01:34:44 +000013#include <errno.h>
14#include <getopt.h>
15#include <signal.h>
16#include <stdint.h>
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20
Greg Claytond314e812011-03-23 00:09:55 +000021// C++ Includes
22
23// Other libraries and framework includes
Greg Claytonfbb76342013-11-20 21:07:01 +000024#include "lldb/lldb-private-log.h"
Greg Claytond314e812011-03-23 00:09:55 +000025#include "lldb/Core/Error.h"
26#include "lldb/Core/ConnectionFileDescriptor.h"
Greg Clayton9b1e1cd2011-04-04 18:18:57 +000027#include "lldb/Core/ConnectionMachPort.h"
Greg Clayton1cb64962011-03-24 04:28:38 +000028#include "lldb/Core/Debugger.h"
29#include "lldb/Core/StreamFile.h"
Greg Clayton59b4fa12012-03-29 17:46:11 +000030#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h"
Greg Clayton1cb64962011-03-24 04:28:38 +000031#include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h"
Greg Claytond314e812011-03-23 00:09:55 +000032using namespace lldb;
33using namespace lldb_private;
34
Greg Claytonb43767a2011-03-22 01:34:44 +000035//----------------------------------------------------------------------
Greg Claytonb7ad58a2013-04-04 20:35:24 +000036// option descriptors for getopt_long_only()
Greg Claytonb43767a2011-03-22 01:34:44 +000037//----------------------------------------------------------------------
38
39int g_debug = 0;
40int g_verbose = 0;
Daniel Maleae0f8f572013-08-26 23:57:52 +000041int g_stay_alive = 0;
Greg Claytonb43767a2011-03-22 01:34:44 +000042
43static struct option g_long_options[] =
44{
45 { "debug", no_argument, &g_debug, 1 },
46 { "verbose", no_argument, &g_verbose, 1 },
Daniel Maleae0f8f572013-08-26 23:57:52 +000047 { "stay-alive", no_argument, &g_stay_alive, 1 },
Greg Claytonb43767a2011-03-22 01:34:44 +000048 { "log-file", required_argument, NULL, 'l' },
49 { "log-flags", required_argument, NULL, 'f' },
Greg Claytond314e812011-03-23 00:09:55 +000050 { "listen", required_argument, NULL, 'L' },
Greg Claytond4724cf2013-11-22 18:55:04 +000051 { "port-offset", required_argument, NULL, 'p' },
52 { "gdbserver-port", required_argument, NULL, 'P' },
Greg Clayton29b8fc42013-11-21 01:44:58 +000053 { "min-gdbserver-port", required_argument, NULL, 'm' },
54 { "max-gdbserver-port", required_argument, NULL, 'M' },
Greg Claytonb43767a2011-03-22 01:34:44 +000055 { NULL, 0, NULL, 0 }
56};
57
Greg Clayton29b8fc42013-11-21 01:44:58 +000058#if defined (__APPLE__)
59#define LOW_PORT (IPPORT_RESERVED)
60#define HIGH_PORT (IPPORT_HIFIRSTAUTO)
61#else
62#define LOW_PORT (1024u)
63#define HIGH_PORT (49151u)
64#endif
65
66
Greg Claytonb43767a2011-03-22 01:34:44 +000067//----------------------------------------------------------------------
68// Watch for signals
69//----------------------------------------------------------------------
70int g_sigpipe_received = 0;
71void
72signal_handler(int signo)
73{
74 switch (signo)
75 {
76 case SIGPIPE:
77 g_sigpipe_received = 1;
78 break;
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.
83 Host::SystemLog(Host::eSystemLogWarning, "SIGHUP received, exiting lldb-platform...\n");
84 abort();
85 break;
Greg Claytonb43767a2011-03-22 01:34:44 +000086 }
87}
88
Daniel Maleae0f8f572013-08-26 23:57:52 +000089static void
90display_usage (const char *progname)
91{
92 fprintf(stderr, "Usage:\n %s [--log-file log-file-path] [--log-flags flags] --listen port\n", progname);
93 exit(0);
94}
95
Greg Claytonb43767a2011-03-22 01:34:44 +000096//----------------------------------------------------------------------
97// main
98//----------------------------------------------------------------------
99int
100main (int argc, char *argv[])
101{
Daniel Maleae0f8f572013-08-26 23:57:52 +0000102 const char *progname = argv[0];
Greg Claytonb43767a2011-03-22 01:34:44 +0000103 signal (SIGPIPE, signal_handler);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000104 signal (SIGHUP, signal_handler);
Greg Claytonb43767a2011-03-22 01:34:44 +0000105 int long_option_index = 0;
Greg Clayton1cb64962011-03-24 04:28:38 +0000106 StreamSP log_stream_sp;
107 Args log_args;
Greg Clayton9b1e1cd2011-04-04 18:18:57 +0000108 Error error;
Greg Clayton73bf5db2011-06-17 01:22:15 +0000109 std::string listen_host_port;
Greg Clayton9d3d6882011-10-31 23:51:19 +0000110 int ch;
Greg Clayton1cb64962011-03-24 04:28:38 +0000111 Debugger::Initialize();
112
Greg Clayton29b8fc42013-11-21 01:44:58 +0000113 GDBRemoteCommunicationServer::PortMap gdbserver_portmap;
114 int min_gdbserver_port = 0;
115 int max_gdbserver_port = 0;
Greg Claytond4724cf2013-11-22 18:55:04 +0000116 uint16_t port_offset = 0;
Greg Clayton29b8fc42013-11-21 01:44:58 +0000117
118 bool show_usage = false;
119 int option_error = 0;
Greg Claytond4724cf2013-11-22 18:55:04 +0000120 // Enable LLDB log channels...
121 StreamSP stream_sp (new StreamFile(stdout, false));
122 const char *log_channels[] = { "platform", "host", "process", NULL };
123 EnableLog (stream_sp, 0, log_channels, NULL);
Greg Clayton9b1e1cd2011-04-04 18:18:57 +0000124
Greg Claytond4724cf2013-11-22 18:55:04 +0000125#if __GLIBC__
126 optind = 0;
127#else
128 optreset = 1;
129 optind = 1;
130#endif
131
Greg Clayton29b8fc42013-11-21 01:44:58 +0000132 while ((ch = getopt_long_only(argc, argv, "l:f:L:p:m:M:", g_long_options, &long_option_index)) != -1)
Greg Claytonb43767a2011-03-22 01:34:44 +0000133 {
134// DNBLogDebug("option: ch == %c (0x%2.2x) --%s%c%s\n",
135// ch, (uint8_t)ch,
136// g_long_options[long_option_index].name,
137// g_long_options[long_option_index].has_arg ? '=' : ' ',
138// optarg ? optarg : "");
139 switch (ch)
140 {
141 case 0: // Any optional that auto set themselves will return 0
142 break;
143
144 case 'l': // Set Log File
145 if (optarg && optarg[0])
146 {
Greg Clayton1cb64962011-03-24 04:28:38 +0000147 if ((strcasecmp(optarg, "stdout") == 0) || (strcmp(optarg, "/dev/stdout") == 0))
148 {
149 log_stream_sp.reset (new StreamFile (stdout, false));
150 }
151 else if ((strcasecmp(optarg, "stderr") == 0) || (strcmp(optarg, "/dev/stderr") == 0))
152 {
153 log_stream_sp.reset (new StreamFile (stderr, false));
154 }
Greg Claytonb43767a2011-03-22 01:34:44 +0000155 else
156 {
Greg Clayton1cb64962011-03-24 04:28:38 +0000157 FILE *log_file = fopen(optarg, "w");
158 if (log_file)
159 {
Greg Claytonb43767a2011-03-22 01:34:44 +0000160 setlinebuf(log_file);
Greg Clayton1cb64962011-03-24 04:28:38 +0000161 log_stream_sp.reset (new StreamFile (log_file, true));
162 }
163 else
164 {
165 const char *errno_str = strerror(errno);
166 fprintf (stderr, "Failed to open log file '%s' for writing: errno = %i (%s)", optarg, errno, errno_str ? errno_str : "unknown error");
167 }
168
Greg Claytonb43767a2011-03-22 01:34:44 +0000169 }
170
Greg Claytonb43767a2011-03-22 01:34:44 +0000171 }
172 break;
173
174 case 'f': // Log Flags
175 if (optarg && optarg[0])
Greg Clayton1cb64962011-03-24 04:28:38 +0000176 log_args.AppendArgument(optarg);
Greg Claytonb43767a2011-03-22 01:34:44 +0000177 break;
Greg Claytond314e812011-03-23 00:09:55 +0000178
179 case 'L':
Greg Clayton73bf5db2011-06-17 01:22:15 +0000180 listen_host_port.append (optarg);
Greg Claytond314e812011-03-23 00:09:55 +0000181 break;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000182
Greg Clayton29b8fc42013-11-21 01:44:58 +0000183 case 'p':
Greg Claytond4724cf2013-11-22 18:55:04 +0000184 {
185 char *end = NULL;
186 long tmp_port_offset = strtoul(optarg, &end, 0);
187 if (end && *end == '\0')
188 {
189 if (LOW_PORT <= tmp_port_offset && tmp_port_offset <= HIGH_PORT)
190 {
191 port_offset = (uint16_t)tmp_port_offset;
192 }
193 else
194 {
195 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);
196 option_error = 5;
197 }
198 }
199 else
200 {
201 fprintf (stderr, "error: invalid port offset string %s\n", optarg);
202 option_error = 4;
203 }
204 }
205 break;
206
207 case 'P':
Greg Clayton29b8fc42013-11-21 01:44:58 +0000208 case 'm':
209 case 'M':
210 {
211 char *end = NULL;
212 long portnum = strtoul(optarg, &end, 0);
213 if (end && *end == '\0')
214 {
215 if (LOW_PORT <= portnum && portnum <= HIGH_PORT)
216 {
Greg Claytond4724cf2013-11-22 18:55:04 +0000217 if (ch == 'P')
Greg Clayton29b8fc42013-11-21 01:44:58 +0000218 gdbserver_portmap[(uint16_t)portnum] = LLDB_INVALID_PROCESS_ID;
219 else if (ch == 'm')
220 min_gdbserver_port = portnum;
221 else
222 max_gdbserver_port = portnum;
223 }
224 else
225 {
226 fprintf (stderr, "error: port number %li is not in the valid user port range of %u - %u\n", portnum, LOW_PORT, HIGH_PORT);
227 option_error = 1;
228 }
229 }
230 else
231 {
232 fprintf (stderr, "error: invalid port number string %s\n", optarg);
233 option_error = 2;
234 }
235 }
236 break;
237
Daniel Maleae0f8f572013-08-26 23:57:52 +0000238 case 'h': /* fall-through is intentional */
239 case '?':
Greg Clayton29b8fc42013-11-21 01:44:58 +0000240 show_usage = true;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000241 break;
Greg Claytonb43767a2011-03-22 01:34:44 +0000242 }
243 }
Greg Clayton29b8fc42013-11-21 01:44:58 +0000244
245 // Make a port map for a port range that was specified.
246 if (min_gdbserver_port < max_gdbserver_port)
247 {
248 for (uint16_t port = min_gdbserver_port; port < max_gdbserver_port; ++port)
249 gdbserver_portmap[port] = LLDB_INVALID_PROCESS_ID;
250 }
251 else if (min_gdbserver_port != max_gdbserver_port)
252 {
253 fprintf (stderr, "error: --min-gdbserver-port (%u) is greater than --max-gdbserver-port (%u)\n", min_gdbserver_port, max_gdbserver_port);
254 option_error = 3;
255
256 }
257
Daniel Maleae0f8f572013-08-26 23:57:52 +0000258 // Print usage and exit if no listening port is specified.
259 if (listen_host_port.empty())
Greg Clayton29b8fc42013-11-21 01:44:58 +0000260 show_usage = true;
261
262 if (show_usage || option_error)
263 {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000264 display_usage(progname);
Greg Clayton29b8fc42013-11-21 01:44:58 +0000265 exit(option_error);
266 }
Greg Claytonb43767a2011-03-22 01:34:44 +0000267
Greg Clayton1cb64962011-03-24 04:28:38 +0000268 if (log_stream_sp)
269 {
270 if (log_args.GetArgumentCount() == 0)
271 log_args.AppendArgument("default");
Jim Ingham228063c2012-02-21 02:23:08 +0000272 ProcessGDBRemoteLog::EnableLog (log_stream_sp, 0,log_args.GetConstArgumentVector(), log_stream_sp.get());
Greg Clayton1cb64962011-03-24 04:28:38 +0000273 }
274
Greg Claytonb7ad58a2013-04-04 20:35:24 +0000275 // Skip any options we consumed with getopt_long_only
Greg Claytonb43767a2011-03-22 01:34:44 +0000276 argc -= optind;
277 argv += optind;
278
279
Daniel Maleae0f8f572013-08-26 23:57:52 +0000280 do {
281 GDBRemoteCommunicationServer gdb_server (true);
Greg Clayton29b8fc42013-11-21 01:44:58 +0000282
Greg Claytond4724cf2013-11-22 18:55:04 +0000283 if (port_offset > 0)
284 gdb_server.SetPortOffset(port_offset);
285
Greg Clayton29b8fc42013-11-21 01:44:58 +0000286 if (!gdbserver_portmap.empty())
287 {
288 gdb_server.SetPortMap(std::move(gdbserver_portmap));
289 }
290
Daniel Maleae0f8f572013-08-26 23:57:52 +0000291 if (!listen_host_port.empty())
Greg Claytond314e812011-03-23 00:09:55 +0000292 {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000293 std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor());
294 if (conn_ap.get())
Greg Claytond314e812011-03-23 00:09:55 +0000295 {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000296 for (int j = 0; j < listen_host_port.size(); j++)
297 {
298 char c = listen_host_port[j];
299 if (c > '9' || c < '0')
300 printf("WARNING: passing anything but a number as argument to --listen will most probably make connecting impossible.\n");
301 }
302 std::auto_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor());
303 if (conn_ap.get())
304 {
305 std::string connect_url ("listen://");
306 connect_url.append(listen_host_port.c_str());
307
308 printf ("Listening for a connection on %s...\n", listen_host_port.c_str());
309 if (conn_ap->Connect(connect_url.c_str(), &error) == eConnectionStatusSuccess)
310 {
311 printf ("Connection established.\n");
312 gdb_server.SetConnection (conn_ap.release());
313 }
314 }
315 }
316
317 if (gdb_server.IsConnected())
318 {
319 // After we connected, we need to get an initial ack from...
320 if (gdb_server.HandshakeWithClient(&error))
321 {
322 bool interrupt = false;
323 bool done = false;
324 while (!interrupt && !done)
325 {
326 if (!gdb_server.GetPacketAndSendResponse (UINT32_MAX, error, interrupt, done))
327 break;
328 }
329
330 if (error.Fail())
331 {
332 fprintf(stderr, "error: %s\n", error.AsCString());
333 }
334 }
335 else
336 {
337 fprintf(stderr, "error: handshake with client failed\n");
338 }
Greg Claytond314e812011-03-23 00:09:55 +0000339 }
340 }
Daniel Maleae0f8f572013-08-26 23:57:52 +0000341 } while (g_stay_alive);
Greg Claytonb43767a2011-03-22 01:34:44 +0000342
Greg Clayton1cb64962011-03-24 04:28:38 +0000343 Debugger::Terminate();
344
Daniel Maleae0f8f572013-08-26 23:57:52 +0000345 fprintf(stderr, "lldb-platform exiting...\n");
346
Greg Claytonb43767a2011-03-22 01:34:44 +0000347 return 0;
348}