blob: e5b70f5e03b3d6d472593856127ba6aa67921103 [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>
Zachary Turner98688922014-08-06 18:16:26 +000014#if defined(__APPLE__)
15#include <netinet/in.h>
16#endif
Greg Claytonb43767a2011-03-22 01:34:44 +000017#include <signal.h>
18#include <stdint.h>
19#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
22
Greg Claytond314e812011-03-23 00:09:55 +000023// C++ Includes
24
25// Other libraries and framework includes
26#include "lldb/Core/Error.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"
Zachary Turner93a66fc2014-10-06 21:22:36 +000030#include "lldb/Host/ConnectionFileDescriptor.h"
Zachary Turner98688922014-08-06 18:16:26 +000031#include "lldb/Host/HostGetOpt.h"
Greg Claytonfb909312013-11-23 01:58:15 +000032#include "lldb/Host/OptionParser.h"
Greg Clayton5fb8f792013-12-02 19:35:49 +000033#include "lldb/Interpreter/CommandInterpreter.h"
34#include "lldb/Interpreter/CommandReturnObject.h"
Tamas Berghammere13c2732015-02-11 10:29:30 +000035#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h"
Greg Clayton1cb64962011-03-24 04:28:38 +000036#include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h"
Tamas Berghammere13c2732015-02-11 10:29:30 +000037
Greg Claytond314e812011-03-23 00:09:55 +000038using namespace lldb;
39using namespace lldb_private;
40
Greg Claytonb43767a2011-03-22 01:34:44 +000041//----------------------------------------------------------------------
Greg Claytonb7ad58a2013-04-04 20:35:24 +000042// option descriptors for getopt_long_only()
Greg Claytonb43767a2011-03-22 01:34:44 +000043//----------------------------------------------------------------------
44
Tamas Berghammerc2c3d712015-02-18 15:39:41 +000045static int g_debug = 0;
46static int g_verbose = 0;
47static int g_stay_alive = 0;
Greg Claytonb43767a2011-03-22 01:34:44 +000048
49static struct option g_long_options[] =
50{
51 { "debug", no_argument, &g_debug, 1 },
52 { "verbose", no_argument, &g_verbose, 1 },
Daniel Maleae0f8f572013-08-26 23:57:52 +000053 { "stay-alive", no_argument, &g_stay_alive, 1 },
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' },
Greg Clayton5fb8f792013-12-02 19:35:49 +000059 { "lldb-command", required_argument, NULL, 'c' },
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
71
Greg Claytonb43767a2011-03-22 01:34:44 +000072//----------------------------------------------------------------------
73// Watch for signals
74//----------------------------------------------------------------------
Tamas Berghammerc2c3d712015-02-18 15:39:41 +000075static void
Greg Claytonb43767a2011-03-22 01:34:44 +000076signal_handler(int signo)
77{
78 switch (signo)
79 {
Daniel Maleae0f8f572013-08-26 23:57:52 +000080 case SIGHUP:
81 // Use SIGINT first, if that does not work, use SIGHUP as a last resort.
82 // And we should not call exit() here because it results in the global destructors
83 // to be invoked and wreaking havoc on the threads still running.
Robert Flack8cc4cf12015-03-06 14:36:33 +000084 Host::SystemLog(Host::eSystemLogWarning, "SIGHUP received, exiting lldb-server...\n");
Daniel Maleae0f8f572013-08-26 23:57:52 +000085 abort();
86 break;
Greg Claytonb43767a2011-03-22 01:34:44 +000087 }
88}
89
Daniel Maleae0f8f572013-08-26 23:57:52 +000090static void
Tamas Berghammerc2c3d712015-02-18 15:39:41 +000091display_usage (const char *progname, const char *subcommand)
Daniel Maleae0f8f572013-08-26 23:57:52 +000092{
Tamas Berghammerc2c3d712015-02-18 15:39:41 +000093 fprintf(stderr, "Usage:\n %s %s [--log-file log-file-path] [--log-flags flags] --listen port\n", progname, subcommand);
Daniel Maleae0f8f572013-08-26 23:57:52 +000094 exit(0);
95}
96
Greg Claytonb43767a2011-03-22 01:34:44 +000097//----------------------------------------------------------------------
98// main
99//----------------------------------------------------------------------
100int
Tamas Berghammerc2c3d712015-02-18 15:39:41 +0000101main_platform (int argc, char *argv[])
Greg Claytonb43767a2011-03-22 01:34:44 +0000102{
Daniel Maleae0f8f572013-08-26 23:57:52 +0000103 const char *progname = argv[0];
Tamas Berghammerc2c3d712015-02-18 15:39:41 +0000104 const char *subcommand = argv[1];
105 argc--;
106 argv++;
Greg Claytonfb909312013-11-23 01:58:15 +0000107 signal (SIGPIPE, SIG_IGN);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000108 signal (SIGHUP, signal_handler);
Greg Claytonb43767a2011-03-22 01:34:44 +0000109 int long_option_index = 0;
Greg Clayton9b1e1cd2011-04-04 18:18:57 +0000110 Error error;
Greg Clayton73bf5db2011-06-17 01:22:15 +0000111 std::string listen_host_port;
Greg Clayton9d3d6882011-10-31 23:51:19 +0000112 int ch;
Greg Clayton5fb8f792013-12-02 19:35:49 +0000113
114 lldb::DebuggerSP debugger_sp = Debugger::CreateInstance ();
115
116 debugger_sp->SetInputFileHandle(stdin, false);
117 debugger_sp->SetOutputFileHandle(stdout, false);
118 debugger_sp->SetErrorFileHandle(stderr, false);
Greg Clayton1cb64962011-03-24 04:28:38 +0000119
Tamas Berghammere13c2732015-02-11 10:29:30 +0000120 GDBRemoteCommunicationServerPlatform::PortMap gdbserver_portmap;
Greg Clayton29b8fc42013-11-21 01:44:58 +0000121 int min_gdbserver_port = 0;
122 int max_gdbserver_port = 0;
Greg Claytond4724cf2013-11-22 18:55:04 +0000123 uint16_t port_offset = 0;
Greg Clayton29b8fc42013-11-21 01:44:58 +0000124
Greg Clayton5fb8f792013-12-02 19:35:49 +0000125 std::vector<std::string> lldb_commands;
Greg Clayton29b8fc42013-11-21 01:44:58 +0000126 bool show_usage = false;
127 int option_error = 0;
Greg Clayton9b1e1cd2011-04-04 18:18:57 +0000128
Greg Claytonfb909312013-11-23 01:58:15 +0000129 std::string short_options(OptionParser::GetShortOptionString(g_long_options));
130
Greg Claytond4724cf2013-11-22 18:55:04 +0000131#if __GLIBC__
132 optind = 0;
133#else
134 optreset = 1;
135 optind = 1;
136#endif
137
Greg Claytonfb909312013-11-23 01:58:15 +0000138 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 +0000139 {
Greg Claytonb43767a2011-03-22 01:34:44 +0000140 switch (ch)
141 {
142 case 0: // Any optional that auto set themselves will return 0
143 break;
144
Greg Claytond314e812011-03-23 00:09:55 +0000145 case 'L':
Greg Clayton73bf5db2011-06-17 01:22:15 +0000146 listen_host_port.append (optarg);
Greg Claytond314e812011-03-23 00:09:55 +0000147 break;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000148
Greg Clayton29b8fc42013-11-21 01:44:58 +0000149 case 'p':
Greg Claytond4724cf2013-11-22 18:55:04 +0000150 {
151 char *end = NULL;
152 long tmp_port_offset = strtoul(optarg, &end, 0);
153 if (end && *end == '\0')
154 {
155 if (LOW_PORT <= tmp_port_offset && tmp_port_offset <= HIGH_PORT)
156 {
157 port_offset = (uint16_t)tmp_port_offset;
158 }
159 else
160 {
161 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);
162 option_error = 5;
163 }
164 }
165 else
166 {
167 fprintf (stderr, "error: invalid port offset string %s\n", optarg);
168 option_error = 4;
169 }
170 }
171 break;
172
173 case 'P':
Greg Clayton29b8fc42013-11-21 01:44:58 +0000174 case 'm':
175 case 'M':
176 {
177 char *end = NULL;
178 long portnum = strtoul(optarg, &end, 0);
179 if (end && *end == '\0')
180 {
181 if (LOW_PORT <= portnum && portnum <= HIGH_PORT)
182 {
Greg Claytond4724cf2013-11-22 18:55:04 +0000183 if (ch == 'P')
Greg Clayton29b8fc42013-11-21 01:44:58 +0000184 gdbserver_portmap[(uint16_t)portnum] = LLDB_INVALID_PROCESS_ID;
185 else if (ch == 'm')
186 min_gdbserver_port = portnum;
187 else
188 max_gdbserver_port = portnum;
189 }
190 else
191 {
192 fprintf (stderr, "error: port number %li is not in the valid user port range of %u - %u\n", portnum, LOW_PORT, HIGH_PORT);
193 option_error = 1;
194 }
195 }
196 else
197 {
198 fprintf (stderr, "error: invalid port number string %s\n", optarg);
199 option_error = 2;
200 }
201 }
202 break;
203
Greg Clayton5fb8f792013-12-02 19:35:49 +0000204 case 'c':
205 lldb_commands.push_back(optarg);
206 break;
207
Daniel Maleae0f8f572013-08-26 23:57:52 +0000208 case 'h': /* fall-through is intentional */
209 case '?':
Greg Clayton29b8fc42013-11-21 01:44:58 +0000210 show_usage = true;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000211 break;
Greg Claytonb43767a2011-03-22 01:34:44 +0000212 }
213 }
Greg Clayton5fb8f792013-12-02 19:35:49 +0000214
Greg Clayton29b8fc42013-11-21 01:44:58 +0000215 // Make a port map for a port range that was specified.
216 if (min_gdbserver_port < max_gdbserver_port)
217 {
218 for (uint16_t port = min_gdbserver_port; port < max_gdbserver_port; ++port)
219 gdbserver_portmap[port] = LLDB_INVALID_PROCESS_ID;
220 }
221 else if (min_gdbserver_port != max_gdbserver_port)
222 {
223 fprintf (stderr, "error: --min-gdbserver-port (%u) is greater than --max-gdbserver-port (%u)\n", min_gdbserver_port, max_gdbserver_port);
224 option_error = 3;
225
226 }
227
Daniel Maleae0f8f572013-08-26 23:57:52 +0000228 // Print usage and exit if no listening port is specified.
229 if (listen_host_port.empty())
Greg Clayton29b8fc42013-11-21 01:44:58 +0000230 show_usage = true;
231
232 if (show_usage || option_error)
233 {
Tamas Berghammerc2c3d712015-02-18 15:39:41 +0000234 display_usage(progname, subcommand);
Greg Clayton29b8fc42013-11-21 01:44:58 +0000235 exit(option_error);
236 }
Greg Claytonb43767a2011-03-22 01:34:44 +0000237
Greg Clayton5fb8f792013-12-02 19:35:49 +0000238 // Execute any LLDB commands that we were asked to evaluate.
239 for (const auto &lldb_command : lldb_commands)
240 {
241 lldb_private::CommandReturnObject result;
242 printf("(lldb) %s\n", lldb_command.c_str());
243 debugger_sp->GetCommandInterpreter().HandleCommand(lldb_command.c_str(), eLazyBoolNo, result);
244 const char *output = result.GetOutputData();
245 if (output && output[0])
246 puts(output);
247 }
248
Greg Claytonb43767a2011-03-22 01:34:44 +0000249
Daniel Maleae0f8f572013-08-26 23:57:52 +0000250 do {
Tamas Berghammere13c2732015-02-11 10:29:30 +0000251 GDBRemoteCommunicationServerPlatform platform;
Greg Clayton29b8fc42013-11-21 01:44:58 +0000252
Greg Claytond4724cf2013-11-22 18:55:04 +0000253 if (port_offset > 0)
Tamas Berghammere13c2732015-02-11 10:29:30 +0000254 platform.SetPortOffset(port_offset);
Greg Claytond4724cf2013-11-22 18:55:04 +0000255
Greg Clayton29b8fc42013-11-21 01:44:58 +0000256 if (!gdbserver_portmap.empty())
257 {
Tamas Berghammere13c2732015-02-11 10:29:30 +0000258 platform.SetPortMap(std::move(gdbserver_portmap));
Greg Clayton29b8fc42013-11-21 01:44:58 +0000259 }
260
Daniel Maleae0f8f572013-08-26 23:57:52 +0000261 if (!listen_host_port.empty())
Greg Claytond314e812011-03-23 00:09:55 +0000262 {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000263 std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor());
264 if (conn_ap.get())
Greg Claytond314e812011-03-23 00:09:55 +0000265 {
Greg Clayton00fe87b2013-12-05 22:58:22 +0000266 std::string connect_url ("listen://");
267 connect_url.append(listen_host_port.c_str());
Daniel Maleae0f8f572013-08-26 23:57:52 +0000268
Greg Clayton00fe87b2013-12-05 22:58:22 +0000269 printf ("Listening for a connection from %s...\n", listen_host_port.c_str());
270 if (conn_ap->Connect(connect_url.c_str(), &error) == eConnectionStatusSuccess)
271 {
272 printf ("Connection established.\n");
Tamas Berghammere13c2732015-02-11 10:29:30 +0000273 platform.SetConnection (conn_ap.release());
Greg Clayton00fe87b2013-12-05 22:58:22 +0000274 }
275 else
276 {
277 printf ("error: %s\n", error.AsCString());
Daniel Maleae0f8f572013-08-26 23:57:52 +0000278 }
279 }
280
Tamas Berghammere13c2732015-02-11 10:29:30 +0000281 if (platform.IsConnected())
Daniel Maleae0f8f572013-08-26 23:57:52 +0000282 {
283 // After we connected, we need to get an initial ack from...
Tamas Berghammere13c2732015-02-11 10:29:30 +0000284 if (platform.HandshakeWithClient(&error))
Daniel Maleae0f8f572013-08-26 23:57:52 +0000285 {
286 bool interrupt = false;
287 bool done = false;
288 while (!interrupt && !done)
289 {
Tamas Berghammere13c2732015-02-11 10:29:30 +0000290 if (platform.GetPacketAndSendResponse (UINT32_MAX, error, interrupt, done) != GDBRemoteCommunication::PacketResult::Success)
Daniel Maleae0f8f572013-08-26 23:57:52 +0000291 break;
292 }
293
294 if (error.Fail())
295 {
296 fprintf(stderr, "error: %s\n", error.AsCString());
297 }
298 }
299 else
300 {
301 fprintf(stderr, "error: handshake with client failed\n");
302 }
Greg Claytond314e812011-03-23 00:09:55 +0000303 }
304 }
Daniel Maleae0f8f572013-08-26 23:57:52 +0000305 } while (g_stay_alive);
Greg Claytonb43767a2011-03-22 01:34:44 +0000306
Robert Flack8cc4cf12015-03-06 14:36:33 +0000307 fprintf(stderr, "lldb-server exiting...\n");
Daniel Maleae0f8f572013-08-26 23:57:52 +0000308
Greg Claytonb43767a2011-03-22 01:34:44 +0000309 return 0;
310}