blob: aa8b8830a75708e3ad79dc7b3ee40112b498485c [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 Claytonfb909312013-11-23 01:58:15 +000030#include "lldb/Host/OptionParser.h"
Greg Clayton59b4fa12012-03-29 17:46:11 +000031#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h"
Greg Clayton1cb64962011-03-24 04:28:38 +000032#include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h"
Greg Claytond314e812011-03-23 00:09:55 +000033using namespace lldb;
34using namespace lldb_private;
35
Greg Claytonb43767a2011-03-22 01:34:44 +000036//----------------------------------------------------------------------
Greg Claytonb7ad58a2013-04-04 20:35:24 +000037// option descriptors for getopt_long_only()
Greg Claytonb43767a2011-03-22 01:34:44 +000038//----------------------------------------------------------------------
39
40int g_debug = 0;
41int g_verbose = 0;
Daniel Maleae0f8f572013-08-26 23:57:52 +000042int g_stay_alive = 0;
Greg Claytonb43767a2011-03-22 01:34:44 +000043
44static struct option g_long_options[] =
45{
46 { "debug", no_argument, &g_debug, 1 },
47 { "verbose", no_argument, &g_verbose, 1 },
Daniel Maleae0f8f572013-08-26 23:57:52 +000048 { "stay-alive", no_argument, &g_stay_alive, 1 },
Greg Claytonb43767a2011-03-22 01:34:44 +000049 { "log-file", required_argument, NULL, 'l' },
50 { "log-flags", required_argument, NULL, 'f' },
Greg Claytond314e812011-03-23 00:09:55 +000051 { "listen", required_argument, NULL, 'L' },
Greg Claytond4724cf2013-11-22 18:55:04 +000052 { "port-offset", required_argument, NULL, 'p' },
53 { "gdbserver-port", required_argument, NULL, 'P' },
Greg Clayton29b8fc42013-11-21 01:44:58 +000054 { "min-gdbserver-port", required_argument, NULL, 'm' },
55 { "max-gdbserver-port", required_argument, NULL, 'M' },
Greg Claytonb43767a2011-03-22 01:34:44 +000056 { NULL, 0, NULL, 0 }
57};
58
Greg Clayton29b8fc42013-11-21 01:44:58 +000059#if defined (__APPLE__)
60#define LOW_PORT (IPPORT_RESERVED)
61#define HIGH_PORT (IPPORT_HIFIRSTAUTO)
62#else
63#define LOW_PORT (1024u)
64#define HIGH_PORT (49151u)
65#endif
66
67
Greg Claytonb43767a2011-03-22 01:34:44 +000068//----------------------------------------------------------------------
69// Watch for signals
70//----------------------------------------------------------------------
Greg Claytonb43767a2011-03-22 01:34:44 +000071void
72signal_handler(int signo)
73{
74 switch (signo)
75 {
Daniel Maleae0f8f572013-08-26 23:57:52 +000076 case SIGHUP:
77 // Use SIGINT first, if that does not work, use SIGHUP as a last resort.
78 // And we should not call exit() here because it results in the global destructors
79 // to be invoked and wreaking havoc on the threads still running.
80 Host::SystemLog(Host::eSystemLogWarning, "SIGHUP received, exiting lldb-platform...\n");
81 abort();
82 break;
Greg Claytonb43767a2011-03-22 01:34:44 +000083 }
84}
85
Daniel Maleae0f8f572013-08-26 23:57:52 +000086static void
87display_usage (const char *progname)
88{
89 fprintf(stderr, "Usage:\n %s [--log-file log-file-path] [--log-flags flags] --listen port\n", progname);
90 exit(0);
91}
92
Greg Claytonb43767a2011-03-22 01:34:44 +000093//----------------------------------------------------------------------
94// main
95//----------------------------------------------------------------------
96int
97main (int argc, char *argv[])
98{
Daniel Maleae0f8f572013-08-26 23:57:52 +000099 const char *progname = argv[0];
Greg Claytonfb909312013-11-23 01:58:15 +0000100 signal (SIGPIPE, SIG_IGN);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000101 signal (SIGHUP, signal_handler);
Greg Claytonb43767a2011-03-22 01:34:44 +0000102 int long_option_index = 0;
Greg Clayton1cb64962011-03-24 04:28:38 +0000103 StreamSP log_stream_sp;
104 Args log_args;
Greg Clayton9b1e1cd2011-04-04 18:18:57 +0000105 Error error;
Greg Clayton73bf5db2011-06-17 01:22:15 +0000106 std::string listen_host_port;
Greg Clayton9d3d6882011-10-31 23:51:19 +0000107 int ch;
Greg Clayton1cb64962011-03-24 04:28:38 +0000108 Debugger::Initialize();
109
Greg Clayton29b8fc42013-11-21 01:44:58 +0000110 GDBRemoteCommunicationServer::PortMap gdbserver_portmap;
111 int min_gdbserver_port = 0;
112 int max_gdbserver_port = 0;
Greg Claytond4724cf2013-11-22 18:55:04 +0000113 uint16_t port_offset = 0;
Greg Clayton29b8fc42013-11-21 01:44:58 +0000114
115 bool show_usage = false;
116 int option_error = 0;
Greg Claytond4724cf2013-11-22 18:55:04 +0000117 // Enable LLDB log channels...
118 StreamSP stream_sp (new StreamFile(stdout, false));
119 const char *log_channels[] = { "platform", "host", "process", NULL };
120 EnableLog (stream_sp, 0, log_channels, NULL);
Greg Clayton9b1e1cd2011-04-04 18:18:57 +0000121
Greg Claytonfb909312013-11-23 01:58:15 +0000122 std::string short_options(OptionParser::GetShortOptionString(g_long_options));
123
Greg Claytond4724cf2013-11-22 18:55:04 +0000124#if __GLIBC__
125 optind = 0;
126#else
127 optreset = 1;
128 optind = 1;
129#endif
130
Greg Claytonfb909312013-11-23 01:58:15 +0000131 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 +0000132 {
133// DNBLogDebug("option: ch == %c (0x%2.2x) --%s%c%s\n",
134// ch, (uint8_t)ch,
135// g_long_options[long_option_index].name,
136// g_long_options[long_option_index].has_arg ? '=' : ' ',
137// optarg ? optarg : "");
138 switch (ch)
139 {
140 case 0: // Any optional that auto set themselves will return 0
141 break;
142
143 case 'l': // Set Log File
144 if (optarg && optarg[0])
145 {
Greg Clayton1cb64962011-03-24 04:28:38 +0000146 if ((strcasecmp(optarg, "stdout") == 0) || (strcmp(optarg, "/dev/stdout") == 0))
147 {
148 log_stream_sp.reset (new StreamFile (stdout, false));
149 }
150 else if ((strcasecmp(optarg, "stderr") == 0) || (strcmp(optarg, "/dev/stderr") == 0))
151 {
152 log_stream_sp.reset (new StreamFile (stderr, false));
153 }
Greg Claytonb43767a2011-03-22 01:34:44 +0000154 else
155 {
Greg Clayton1cb64962011-03-24 04:28:38 +0000156 FILE *log_file = fopen(optarg, "w");
157 if (log_file)
158 {
Greg Claytonb43767a2011-03-22 01:34:44 +0000159 setlinebuf(log_file);
Greg Clayton1cb64962011-03-24 04:28:38 +0000160 log_stream_sp.reset (new StreamFile (log_file, true));
161 }
162 else
163 {
164 const char *errno_str = strerror(errno);
165 fprintf (stderr, "Failed to open log file '%s' for writing: errno = %i (%s)", optarg, errno, errno_str ? errno_str : "unknown error");
166 }
167
Greg Claytonb43767a2011-03-22 01:34:44 +0000168 }
169
Greg Claytonb43767a2011-03-22 01:34:44 +0000170 }
171 break;
172
173 case 'f': // Log Flags
174 if (optarg && optarg[0])
Greg Clayton1cb64962011-03-24 04:28:38 +0000175 log_args.AppendArgument(optarg);
Greg Claytonb43767a2011-03-22 01:34:44 +0000176 break;
Greg Claytond314e812011-03-23 00:09:55 +0000177
178 case 'L':
Greg Clayton73bf5db2011-06-17 01:22:15 +0000179 listen_host_port.append (optarg);
Greg Claytond314e812011-03-23 00:09:55 +0000180 break;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000181
Greg Clayton29b8fc42013-11-21 01:44:58 +0000182 case 'p':
Greg Claytond4724cf2013-11-22 18:55:04 +0000183 {
184 char *end = NULL;
185 long tmp_port_offset = strtoul(optarg, &end, 0);
186 if (end && *end == '\0')
187 {
188 if (LOW_PORT <= tmp_port_offset && tmp_port_offset <= HIGH_PORT)
189 {
190 port_offset = (uint16_t)tmp_port_offset;
191 }
192 else
193 {
194 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);
195 option_error = 5;
196 }
197 }
198 else
199 {
200 fprintf (stderr, "error: invalid port offset string %s\n", optarg);
201 option_error = 4;
202 }
203 }
204 break;
205
206 case 'P':
Greg Clayton29b8fc42013-11-21 01:44:58 +0000207 case 'm':
208 case 'M':
209 {
210 char *end = NULL;
211 long portnum = strtoul(optarg, &end, 0);
212 if (end && *end == '\0')
213 {
214 if (LOW_PORT <= portnum && portnum <= HIGH_PORT)
215 {
Greg Claytond4724cf2013-11-22 18:55:04 +0000216 if (ch == 'P')
Greg Clayton29b8fc42013-11-21 01:44:58 +0000217 gdbserver_portmap[(uint16_t)portnum] = LLDB_INVALID_PROCESS_ID;
218 else if (ch == 'm')
219 min_gdbserver_port = portnum;
220 else
221 max_gdbserver_port = portnum;
222 }
223 else
224 {
225 fprintf (stderr, "error: port number %li is not in the valid user port range of %u - %u\n", portnum, LOW_PORT, HIGH_PORT);
226 option_error = 1;
227 }
228 }
229 else
230 {
231 fprintf (stderr, "error: invalid port number string %s\n", optarg);
232 option_error = 2;
233 }
234 }
235 break;
236
Daniel Maleae0f8f572013-08-26 23:57:52 +0000237 case 'h': /* fall-through is intentional */
238 case '?':
Greg Clayton29b8fc42013-11-21 01:44:58 +0000239 show_usage = true;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000240 break;
Greg Claytonb43767a2011-03-22 01:34:44 +0000241 }
242 }
Greg Clayton29b8fc42013-11-21 01:44:58 +0000243
244 // Make a port map for a port range that was specified.
245 if (min_gdbserver_port < max_gdbserver_port)
246 {
247 for (uint16_t port = min_gdbserver_port; port < max_gdbserver_port; ++port)
248 gdbserver_portmap[port] = LLDB_INVALID_PROCESS_ID;
249 }
250 else if (min_gdbserver_port != max_gdbserver_port)
251 {
252 fprintf (stderr, "error: --min-gdbserver-port (%u) is greater than --max-gdbserver-port (%u)\n", min_gdbserver_port, max_gdbserver_port);
253 option_error = 3;
254
255 }
256
Daniel Maleae0f8f572013-08-26 23:57:52 +0000257 // Print usage and exit if no listening port is specified.
258 if (listen_host_port.empty())
Greg Clayton29b8fc42013-11-21 01:44:58 +0000259 show_usage = true;
260
261 if (show_usage || option_error)
262 {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000263 display_usage(progname);
Greg Clayton29b8fc42013-11-21 01:44:58 +0000264 exit(option_error);
265 }
Greg Claytonb43767a2011-03-22 01:34:44 +0000266
Greg Clayton1cb64962011-03-24 04:28:38 +0000267 if (log_stream_sp)
268 {
269 if (log_args.GetArgumentCount() == 0)
270 log_args.AppendArgument("default");
Jim Ingham228063c2012-02-21 02:23:08 +0000271 ProcessGDBRemoteLog::EnableLog (log_stream_sp, 0,log_args.GetConstArgumentVector(), log_stream_sp.get());
Greg Clayton1cb64962011-03-24 04:28:38 +0000272 }
273
Greg Claytonb7ad58a2013-04-04 20:35:24 +0000274 // Skip any options we consumed with getopt_long_only
Greg Claytonb43767a2011-03-22 01:34:44 +0000275 argc -= optind;
276 argv += optind;
277
278
Daniel Maleae0f8f572013-08-26 23:57:52 +0000279 do {
280 GDBRemoteCommunicationServer gdb_server (true);
Greg Clayton29b8fc42013-11-21 01:44:58 +0000281
Greg Claytond4724cf2013-11-22 18:55:04 +0000282 if (port_offset > 0)
283 gdb_server.SetPortOffset(port_offset);
284
Greg Clayton29b8fc42013-11-21 01:44:58 +0000285 if (!gdbserver_portmap.empty())
286 {
287 gdb_server.SetPortMap(std::move(gdbserver_portmap));
288 }
289
Daniel Maleae0f8f572013-08-26 23:57:52 +0000290 if (!listen_host_port.empty())
Greg Claytond314e812011-03-23 00:09:55 +0000291 {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000292 std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor());
293 if (conn_ap.get())
Greg Claytond314e812011-03-23 00:09:55 +0000294 {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000295 for (int j = 0; j < listen_host_port.size(); j++)
296 {
297 char c = listen_host_port[j];
298 if (c > '9' || c < '0')
299 printf("WARNING: passing anything but a number as argument to --listen will most probably make connecting impossible.\n");
300 }
301 std::auto_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor());
302 if (conn_ap.get())
303 {
304 std::string connect_url ("listen://");
305 connect_url.append(listen_host_port.c_str());
306
307 printf ("Listening for a connection on %s...\n", listen_host_port.c_str());
308 if (conn_ap->Connect(connect_url.c_str(), &error) == eConnectionStatusSuccess)
309 {
310 printf ("Connection established.\n");
311 gdb_server.SetConnection (conn_ap.release());
312 }
313 }
314 }
315
316 if (gdb_server.IsConnected())
317 {
318 // After we connected, we need to get an initial ack from...
319 if (gdb_server.HandshakeWithClient(&error))
320 {
321 bool interrupt = false;
322 bool done = false;
323 while (!interrupt && !done)
324 {
325 if (!gdb_server.GetPacketAndSendResponse (UINT32_MAX, error, interrupt, done))
326 break;
327 }
328
329 if (error.Fail())
330 {
331 fprintf(stderr, "error: %s\n", error.AsCString());
332 }
333 }
334 else
335 {
336 fprintf(stderr, "error: handshake with client failed\n");
337 }
Greg Claytond314e812011-03-23 00:09:55 +0000338 }
339 }
Daniel Maleae0f8f572013-08-26 23:57:52 +0000340 } while (g_stay_alive);
Greg Claytonb43767a2011-03-22 01:34:44 +0000341
Greg Clayton1cb64962011-03-24 04:28:38 +0000342 Debugger::Terminate();
343
Daniel Maleae0f8f572013-08-26 23:57:52 +0000344 fprintf(stderr, "lldb-platform exiting...\n");
345
Greg Claytonb43767a2011-03-22 01:34:44 +0000346 return 0;
347}