blob: 6f5dfbcbbb7ac725176d9542b5eda7aa027e4337 [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>
Robert Flacka0e70cd2015-03-25 12:51:31 +000022#include <sys/wait.h>
Greg Claytonb43767a2011-03-22 01:34:44 +000023
Greg Claytond314e812011-03-23 00:09:55 +000024// C++ Includes
25
26// Other libraries and framework includes
27#include "lldb/Core/Error.h"
Greg Clayton9b1e1cd2011-04-04 18:18:57 +000028#include "lldb/Core/ConnectionMachPort.h"
Greg Clayton1cb64962011-03-24 04:28:38 +000029#include "lldb/Core/Debugger.h"
30#include "lldb/Core/StreamFile.h"
Zachary Turner93a66fc2014-10-06 21:22:36 +000031#include "lldb/Host/ConnectionFileDescriptor.h"
Zachary Turner98688922014-08-06 18:16:26 +000032#include "lldb/Host/HostGetOpt.h"
Greg Claytonfb909312013-11-23 01:58:15 +000033#include "lldb/Host/OptionParser.h"
Robert Flacka0e70cd2015-03-25 12:51:31 +000034#include "lldb/Host/Socket.h"
Greg Clayton5fb8f792013-12-02 19:35:49 +000035#include "lldb/Interpreter/CommandInterpreter.h"
36#include "lldb/Interpreter/CommandReturnObject.h"
Tamas Berghammere13c2732015-02-11 10:29:30 +000037#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h"
Greg Clayton1cb64962011-03-24 04:28:38 +000038#include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h"
Tamas Berghammere13c2732015-02-11 10:29:30 +000039
Greg Claytond314e812011-03-23 00:09:55 +000040using namespace lldb;
41using namespace lldb_private;
Tamas Berghammerdb264a62015-03-31 09:52:22 +000042using namespace lldb_private::process_gdb_remote;
Greg Claytond314e812011-03-23 00:09:55 +000043
Greg Claytonb43767a2011-03-22 01:34:44 +000044//----------------------------------------------------------------------
Greg Claytonb7ad58a2013-04-04 20:35:24 +000045// option descriptors for getopt_long_only()
Greg Claytonb43767a2011-03-22 01:34:44 +000046//----------------------------------------------------------------------
47
Tamas Berghammerc2c3d712015-02-18 15:39:41 +000048static int g_debug = 0;
49static int g_verbose = 0;
Robert Flacka0e70cd2015-03-25 12:51:31 +000050static int g_server = 0;
Greg Claytonb43767a2011-03-22 01:34:44 +000051
52static struct option g_long_options[] =
53{
54 { "debug", no_argument, &g_debug, 1 },
55 { "verbose", no_argument, &g_verbose, 1 },
Greg Claytond314e812011-03-23 00:09:55 +000056 { "listen", required_argument, NULL, 'L' },
Greg Claytond4724cf2013-11-22 18:55:04 +000057 { "port-offset", required_argument, NULL, 'p' },
58 { "gdbserver-port", required_argument, NULL, 'P' },
Greg Clayton29b8fc42013-11-21 01:44:58 +000059 { "min-gdbserver-port", required_argument, NULL, 'm' },
60 { "max-gdbserver-port", required_argument, NULL, 'M' },
Greg Clayton5fb8f792013-12-02 19:35:49 +000061 { "lldb-command", required_argument, NULL, 'c' },
Robert Flacka0e70cd2015-03-25 12:51:31 +000062 { "server", no_argument, &g_server, 1 },
Greg Claytonb43767a2011-03-22 01:34:44 +000063 { NULL, 0, NULL, 0 }
64};
65
Greg Clayton29b8fc42013-11-21 01:44:58 +000066#if defined (__APPLE__)
67#define LOW_PORT (IPPORT_RESERVED)
68#define HIGH_PORT (IPPORT_HIFIRSTAUTO)
69#else
70#define LOW_PORT (1024u)
71#define HIGH_PORT (49151u)
72#endif
73
74
Greg Claytonb43767a2011-03-22 01:34:44 +000075//----------------------------------------------------------------------
76// Watch for signals
77//----------------------------------------------------------------------
Tamas Berghammerc2c3d712015-02-18 15:39:41 +000078static void
Greg Claytonb43767a2011-03-22 01:34:44 +000079signal_handler(int signo)
80{
81 switch (signo)
82 {
Daniel Maleae0f8f572013-08-26 23:57:52 +000083 case SIGHUP:
84 // Use SIGINT first, if that does not work, use SIGHUP as a last resort.
85 // And we should not call exit() here because it results in the global destructors
86 // to be invoked and wreaking havoc on the threads still running.
Robert Flack8cc4cf12015-03-06 14:36:33 +000087 Host::SystemLog(Host::eSystemLogWarning, "SIGHUP received, exiting lldb-server...\n");
Daniel Maleae0f8f572013-08-26 23:57:52 +000088 abort();
89 break;
Greg Claytonb43767a2011-03-22 01:34:44 +000090 }
91}
92
Daniel Maleae0f8f572013-08-26 23:57:52 +000093static void
Tamas Berghammerc2c3d712015-02-18 15:39:41 +000094display_usage (const char *progname, const char *subcommand)
Daniel Maleae0f8f572013-08-26 23:57:52 +000095{
Chaoren Lin9afad0e2015-05-21 22:43:43 +000096 fprintf(stderr, "Usage:\n %s %s [--server] --listen port\n",
97 progname, subcommand);
Daniel Maleae0f8f572013-08-26 23:57:52 +000098 exit(0);
99}
100
Greg Claytonb43767a2011-03-22 01:34:44 +0000101//----------------------------------------------------------------------
102// main
103//----------------------------------------------------------------------
104int
Tamas Berghammerc2c3d712015-02-18 15:39:41 +0000105main_platform (int argc, char *argv[])
Greg Claytonb43767a2011-03-22 01:34:44 +0000106{
Daniel Maleae0f8f572013-08-26 23:57:52 +0000107 const char *progname = argv[0];
Tamas Berghammerc2c3d712015-02-18 15:39:41 +0000108 const char *subcommand = argv[1];
109 argc--;
110 argv++;
Greg Claytonfb909312013-11-23 01:58:15 +0000111 signal (SIGPIPE, SIG_IGN);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000112 signal (SIGHUP, signal_handler);
Greg Claytonb43767a2011-03-22 01:34:44 +0000113 int long_option_index = 0;
Greg Clayton9b1e1cd2011-04-04 18:18:57 +0000114 Error error;
Greg Clayton73bf5db2011-06-17 01:22:15 +0000115 std::string listen_host_port;
Greg Clayton9d3d6882011-10-31 23:51:19 +0000116 int ch;
Greg Clayton5fb8f792013-12-02 19:35:49 +0000117
118 lldb::DebuggerSP debugger_sp = Debugger::CreateInstance ();
119
120 debugger_sp->SetInputFileHandle(stdin, false);
121 debugger_sp->SetOutputFileHandle(stdout, false);
122 debugger_sp->SetErrorFileHandle(stderr, false);
Greg Clayton1cb64962011-03-24 04:28:38 +0000123
Tamas Berghammere13c2732015-02-11 10:29:30 +0000124 GDBRemoteCommunicationServerPlatform::PortMap gdbserver_portmap;
Greg Clayton29b8fc42013-11-21 01:44:58 +0000125 int min_gdbserver_port = 0;
126 int max_gdbserver_port = 0;
Greg Claytond4724cf2013-11-22 18:55:04 +0000127 uint16_t port_offset = 0;
Greg Clayton29b8fc42013-11-21 01:44:58 +0000128
Greg Clayton5fb8f792013-12-02 19:35:49 +0000129 std::vector<std::string> lldb_commands;
Greg Clayton29b8fc42013-11-21 01:44:58 +0000130 bool show_usage = false;
131 int option_error = 0;
Robert Flacka0e70cd2015-03-25 12:51:31 +0000132 int socket_error = -1;
Greg Clayton9b1e1cd2011-04-04 18:18:57 +0000133
Greg Claytonfb909312013-11-23 01:58:15 +0000134 std::string short_options(OptionParser::GetShortOptionString(g_long_options));
135
Greg Claytond4724cf2013-11-22 18:55:04 +0000136#if __GLIBC__
137 optind = 0;
138#else
139 optreset = 1;
140 optind = 1;
141#endif
142
Greg Claytonfb909312013-11-23 01:58:15 +0000143 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 +0000144 {
Greg Claytonb43767a2011-03-22 01:34:44 +0000145 switch (ch)
146 {
147 case 0: // Any optional that auto set themselves will return 0
148 break;
149
Greg Claytond314e812011-03-23 00:09:55 +0000150 case 'L':
Greg Clayton73bf5db2011-06-17 01:22:15 +0000151 listen_host_port.append (optarg);
Greg Claytond314e812011-03-23 00:09:55 +0000152 break;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000153
Greg Clayton29b8fc42013-11-21 01:44:58 +0000154 case 'p':
Greg Claytond4724cf2013-11-22 18:55:04 +0000155 {
156 char *end = NULL;
157 long tmp_port_offset = strtoul(optarg, &end, 0);
158 if (end && *end == '\0')
159 {
160 if (LOW_PORT <= tmp_port_offset && tmp_port_offset <= HIGH_PORT)
161 {
162 port_offset = (uint16_t)tmp_port_offset;
163 }
164 else
165 {
166 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);
167 option_error = 5;
168 }
169 }
170 else
171 {
172 fprintf (stderr, "error: invalid port offset string %s\n", optarg);
173 option_error = 4;
174 }
175 }
176 break;
177
178 case 'P':
Greg Clayton29b8fc42013-11-21 01:44:58 +0000179 case 'm':
180 case 'M':
181 {
182 char *end = NULL;
183 long portnum = strtoul(optarg, &end, 0);
184 if (end && *end == '\0')
185 {
186 if (LOW_PORT <= portnum && portnum <= HIGH_PORT)
187 {
Greg Claytond4724cf2013-11-22 18:55:04 +0000188 if (ch == 'P')
Greg Clayton29b8fc42013-11-21 01:44:58 +0000189 gdbserver_portmap[(uint16_t)portnum] = LLDB_INVALID_PROCESS_ID;
190 else if (ch == 'm')
191 min_gdbserver_port = portnum;
192 else
193 max_gdbserver_port = portnum;
194 }
195 else
196 {
197 fprintf (stderr, "error: port number %li is not in the valid user port range of %u - %u\n", portnum, LOW_PORT, HIGH_PORT);
198 option_error = 1;
199 }
200 }
201 else
202 {
203 fprintf (stderr, "error: invalid port number string %s\n", optarg);
204 option_error = 2;
205 }
206 }
207 break;
208
Greg Clayton5fb8f792013-12-02 19:35:49 +0000209 case 'c':
210 lldb_commands.push_back(optarg);
211 break;
212
Daniel Maleae0f8f572013-08-26 23:57:52 +0000213 case 'h': /* fall-through is intentional */
214 case '?':
Greg Clayton29b8fc42013-11-21 01:44:58 +0000215 show_usage = true;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000216 break;
Greg Claytonb43767a2011-03-22 01:34:44 +0000217 }
218 }
Greg Clayton5fb8f792013-12-02 19:35:49 +0000219
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;
230
231 }
232
Daniel Maleae0f8f572013-08-26 23:57:52 +0000233 // Print usage and exit if no listening port is specified.
234 if (listen_host_port.empty())
Greg Clayton29b8fc42013-11-21 01:44:58 +0000235 show_usage = true;
236
237 if (show_usage || option_error)
238 {
Tamas Berghammerc2c3d712015-02-18 15:39:41 +0000239 display_usage(progname, subcommand);
Greg Clayton29b8fc42013-11-21 01:44:58 +0000240 exit(option_error);
241 }
Greg Claytonb43767a2011-03-22 01:34:44 +0000242
Greg Clayton5fb8f792013-12-02 19:35:49 +0000243 // Execute any LLDB commands that we were asked to evaluate.
244 for (const auto &lldb_command : lldb_commands)
245 {
246 lldb_private::CommandReturnObject result;
247 printf("(lldb) %s\n", lldb_command.c_str());
248 debugger_sp->GetCommandInterpreter().HandleCommand(lldb_command.c_str(), eLazyBoolNo, result);
249 const char *output = result.GetOutputData();
250 if (output && output[0])
251 puts(output);
252 }
253
Robert Flacka0e70cd2015-03-25 12:51:31 +0000254 std::unique_ptr<Socket> listening_socket_up;
255 Socket *socket = nullptr;
Robert Flacka0e70cd2015-03-25 12:51:31 +0000256 const bool children_inherit_listen_socket = false;
Vince Harron33aea902015-03-31 00:27:10 +0000257
258 // the test suite makes many connections in parallel, let's not miss any.
259 // The highest this should get reasonably is a function of the number
260 // of target CPUs. For now, let's just use 100
261 const int backlog = 100;
262 error = Socket::TcpListen(listen_host_port.c_str(), children_inherit_listen_socket, socket, NULL, backlog);
Robert Flacka0e70cd2015-03-25 12:51:31 +0000263 if (error.Fail())
264 {
265 printf("error: %s\n", error.AsCString());
266 exit(socket_error);
267 }
268 listening_socket_up.reset(socket);
Vince Harron218353d2015-05-26 03:08:05 +0000269 printf ("Listening for a connection from %u...\n", listening_socket_up->GetLocalPortNumber());
Greg Claytonb43767a2011-03-22 01:34:44 +0000270
Daniel Maleae0f8f572013-08-26 23:57:52 +0000271 do {
Tamas Berghammere13c2732015-02-11 10:29:30 +0000272 GDBRemoteCommunicationServerPlatform platform;
Greg Clayton29b8fc42013-11-21 01:44:58 +0000273
Greg Claytond4724cf2013-11-22 18:55:04 +0000274 if (port_offset > 0)
Tamas Berghammere13c2732015-02-11 10:29:30 +0000275 platform.SetPortOffset(port_offset);
Greg Claytond4724cf2013-11-22 18:55:04 +0000276
Greg Clayton29b8fc42013-11-21 01:44:58 +0000277 if (!gdbserver_portmap.empty())
278 {
Tamas Berghammere13c2732015-02-11 10:29:30 +0000279 platform.SetPortMap(std::move(gdbserver_portmap));
Greg Clayton29b8fc42013-11-21 01:44:58 +0000280 }
281
Robert Flacka0e70cd2015-03-25 12:51:31 +0000282 const bool children_inherit_accept_socket = true;
283 socket = nullptr;
284 error = listening_socket_up->BlockingAccept(listen_host_port.c_str(), children_inherit_accept_socket, socket);
285 if (error.Fail())
Greg Claytond314e812011-03-23 00:09:55 +0000286 {
Robert Flacka0e70cd2015-03-25 12:51:31 +0000287 printf ("error: %s\n", error.AsCString());
288 exit(socket_error);
289 }
290 printf ("Connection established.\n");
291 if (g_server)
292 {
293 // Collect child zombie processes.
294 while (waitpid(-1, nullptr, WNOHANG) > 0);
295 if (fork())
Greg Claytond314e812011-03-23 00:09:55 +0000296 {
Vince Harronf1e69992015-03-31 00:24:51 +0000297 // Parent doesn't need a connection to the lldb client
298 delete socket;
299 socket = nullptr;
300
Robert Flacka0e70cd2015-03-25 12:51:31 +0000301 // Parent will continue to listen for new connections.
302 continue;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000303 }
Robert Flacka0e70cd2015-03-25 12:51:31 +0000304 else
Daniel Maleae0f8f572013-08-26 23:57:52 +0000305 {
Robert Flacka0e70cd2015-03-25 12:51:31 +0000306 // Child process will handle the connection and exit.
307 g_server = 0;
308 // Listening socket is owned by parent process.
309 listening_socket_up.release();
Greg Claytond314e812011-03-23 00:09:55 +0000310 }
311 }
Robert Flacka0e70cd2015-03-25 12:51:31 +0000312 else
313 {
314 // If not running as a server, this process will not accept
315 // connections while a connection is active.
316 listening_socket_up.reset();
317 }
318 platform.SetConnection (new ConnectionFileDescriptor(socket));
319
320 if (platform.IsConnected())
321 {
322 // After we connected, we need to get an initial ack from...
323 if (platform.HandshakeWithClient(&error))
324 {
325 bool interrupt = false;
326 bool done = false;
327 while (!interrupt && !done)
328 {
329 if (platform.GetPacketAndSendResponse (UINT32_MAX, error, interrupt, done) != GDBRemoteCommunication::PacketResult::Success)
330 break;
331 }
332
333 if (error.Fail())
334 {
335 fprintf(stderr, "error: %s\n", error.AsCString());
336 }
337 }
338 else
339 {
340 fprintf(stderr, "error: handshake with client failed\n");
341 }
342 }
343 } while (g_server);
Greg Claytonb43767a2011-03-22 01:34:44 +0000344
Robert Flack8cc4cf12015-03-06 14:36:33 +0000345 fprintf(stderr, "lldb-server exiting...\n");
Daniel Maleae0f8f572013-08-26 23:57:52 +0000346
Greg Claytonb43767a2011-03-22 01:34:44 +0000347 return 0;
348}