blob: 96aa0fb63a4f1da1f26217e3123bf78978c7c4c0 [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>
Deepak Panickal914b8d92014-01-31 18:48:46 +000014#include "lldb/Host/HostGetOpt.h"
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>
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 Clayton5fb8f792013-12-02 19:35:49 +000031#include "lldb/Interpreter/CommandInterpreter.h"
32#include "lldb/Interpreter/CommandReturnObject.h"
Greg Clayton59b4fa12012-03-29 17:46:11 +000033#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h"
Greg Clayton1cb64962011-03-24 04:28:38 +000034#include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h"
Greg Claytond314e812011-03-23 00:09:55 +000035using namespace lldb;
36using namespace lldb_private;
37
Greg Claytonb43767a2011-03-22 01:34:44 +000038//----------------------------------------------------------------------
Greg Claytonb7ad58a2013-04-04 20:35:24 +000039// option descriptors for getopt_long_only()
Greg Claytonb43767a2011-03-22 01:34:44 +000040//----------------------------------------------------------------------
41
42int g_debug = 0;
43int g_verbose = 0;
Daniel Maleae0f8f572013-08-26 23:57:52 +000044int g_stay_alive = 0;
Greg Claytonb43767a2011-03-22 01:34:44 +000045
46static struct option g_long_options[] =
47{
48 { "debug", no_argument, &g_debug, 1 },
49 { "verbose", no_argument, &g_verbose, 1 },
Daniel Maleae0f8f572013-08-26 23:57:52 +000050 { "stay-alive", no_argument, &g_stay_alive, 1 },
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 Clayton5fb8f792013-12-02 19:35:49 +000056 { "lldb-command", required_argument, NULL, 'c' },
Greg Claytonb43767a2011-03-22 01:34:44 +000057 { NULL, 0, NULL, 0 }
58};
59
Greg Clayton29b8fc42013-11-21 01:44:58 +000060#if defined (__APPLE__)
61#define LOW_PORT (IPPORT_RESERVED)
62#define HIGH_PORT (IPPORT_HIFIRSTAUTO)
63#else
64#define LOW_PORT (1024u)
65#define HIGH_PORT (49151u)
66#endif
67
68
Greg Claytonb43767a2011-03-22 01:34:44 +000069//----------------------------------------------------------------------
70// Watch for signals
71//----------------------------------------------------------------------
Greg Claytonb43767a2011-03-22 01:34:44 +000072void
73signal_handler(int signo)
74{
75 switch (signo)
76 {
Daniel Maleae0f8f572013-08-26 23:57:52 +000077 case SIGHUP:
78 // Use SIGINT first, if that does not work, use SIGHUP as a last resort.
79 // And we should not call exit() here because it results in the global destructors
80 // to be invoked and wreaking havoc on the threads still running.
81 Host::SystemLog(Host::eSystemLogWarning, "SIGHUP received, exiting lldb-platform...\n");
82 abort();
83 break;
Greg Claytonb43767a2011-03-22 01:34:44 +000084 }
85}
86
Daniel Maleae0f8f572013-08-26 23:57:52 +000087static void
88display_usage (const char *progname)
89{
90 fprintf(stderr, "Usage:\n %s [--log-file log-file-path] [--log-flags flags] --listen port\n", progname);
91 exit(0);
92}
93
Greg Claytonb43767a2011-03-22 01:34:44 +000094//----------------------------------------------------------------------
95// main
96//----------------------------------------------------------------------
97int
98main (int argc, char *argv[])
99{
Daniel Maleae0f8f572013-08-26 23:57:52 +0000100 const char *progname = argv[0];
Greg Claytonfb909312013-11-23 01:58:15 +0000101 signal (SIGPIPE, SIG_IGN);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000102 signal (SIGHUP, signal_handler);
Greg Claytonb43767a2011-03-22 01:34:44 +0000103 int long_option_index = 0;
Greg Clayton9b1e1cd2011-04-04 18:18:57 +0000104 Error error;
Greg Clayton73bf5db2011-06-17 01:22:15 +0000105 std::string listen_host_port;
Greg Clayton9d3d6882011-10-31 23:51:19 +0000106 int ch;
Greg Clayton5fb8f792013-12-02 19:35:49 +0000107 Debugger::Initialize(NULL);
108
109 lldb::DebuggerSP debugger_sp = Debugger::CreateInstance ();
110
111 debugger_sp->SetInputFileHandle(stdin, false);
112 debugger_sp->SetOutputFileHandle(stdout, false);
113 debugger_sp->SetErrorFileHandle(stderr, false);
Greg Clayton1cb64962011-03-24 04:28:38 +0000114
Greg Clayton29b8fc42013-11-21 01:44:58 +0000115 GDBRemoteCommunicationServer::PortMap gdbserver_portmap;
116 int min_gdbserver_port = 0;
117 int max_gdbserver_port = 0;
Greg Claytond4724cf2013-11-22 18:55:04 +0000118 uint16_t port_offset = 0;
Greg Clayton29b8fc42013-11-21 01:44:58 +0000119
Greg Clayton5fb8f792013-12-02 19:35:49 +0000120 std::vector<std::string> lldb_commands;
Greg Clayton29b8fc42013-11-21 01:44:58 +0000121 bool show_usage = false;
122 int option_error = 0;
Greg Clayton9b1e1cd2011-04-04 18:18:57 +0000123
Greg Claytonfb909312013-11-23 01:58:15 +0000124 std::string short_options(OptionParser::GetShortOptionString(g_long_options));
125
Greg Claytond4724cf2013-11-22 18:55:04 +0000126#if __GLIBC__
127 optind = 0;
128#else
129 optreset = 1;
130 optind = 1;
131#endif
132
Greg Claytonfb909312013-11-23 01:58:15 +0000133 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 +0000134 {
Greg Claytonb43767a2011-03-22 01:34:44 +0000135 switch (ch)
136 {
137 case 0: // Any optional that auto set themselves will return 0
138 break;
139
Greg Claytond314e812011-03-23 00:09:55 +0000140 case 'L':
Greg Clayton73bf5db2011-06-17 01:22:15 +0000141 listen_host_port.append (optarg);
Greg Claytond314e812011-03-23 00:09:55 +0000142 break;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000143
Greg Clayton29b8fc42013-11-21 01:44:58 +0000144 case 'p':
Greg Claytond4724cf2013-11-22 18:55:04 +0000145 {
146 char *end = NULL;
147 long tmp_port_offset = strtoul(optarg, &end, 0);
148 if (end && *end == '\0')
149 {
150 if (LOW_PORT <= tmp_port_offset && tmp_port_offset <= HIGH_PORT)
151 {
152 port_offset = (uint16_t)tmp_port_offset;
153 }
154 else
155 {
156 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);
157 option_error = 5;
158 }
159 }
160 else
161 {
162 fprintf (stderr, "error: invalid port offset string %s\n", optarg);
163 option_error = 4;
164 }
165 }
166 break;
167
168 case 'P':
Greg Clayton29b8fc42013-11-21 01:44:58 +0000169 case 'm':
170 case 'M':
171 {
172 char *end = NULL;
173 long portnum = strtoul(optarg, &end, 0);
174 if (end && *end == '\0')
175 {
176 if (LOW_PORT <= portnum && portnum <= HIGH_PORT)
177 {
Greg Claytond4724cf2013-11-22 18:55:04 +0000178 if (ch == 'P')
Greg Clayton29b8fc42013-11-21 01:44:58 +0000179 gdbserver_portmap[(uint16_t)portnum] = LLDB_INVALID_PROCESS_ID;
180 else if (ch == 'm')
181 min_gdbserver_port = portnum;
182 else
183 max_gdbserver_port = portnum;
184 }
185 else
186 {
187 fprintf (stderr, "error: port number %li is not in the valid user port range of %u - %u\n", portnum, LOW_PORT, HIGH_PORT);
188 option_error = 1;
189 }
190 }
191 else
192 {
193 fprintf (stderr, "error: invalid port number string %s\n", optarg);
194 option_error = 2;
195 }
196 }
197 break;
198
Greg Clayton5fb8f792013-12-02 19:35:49 +0000199 case 'c':
200 lldb_commands.push_back(optarg);
201 break;
202
Daniel Maleae0f8f572013-08-26 23:57:52 +0000203 case 'h': /* fall-through is intentional */
204 case '?':
Greg Clayton29b8fc42013-11-21 01:44:58 +0000205 show_usage = true;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000206 break;
Greg Claytonb43767a2011-03-22 01:34:44 +0000207 }
208 }
Greg Clayton5fb8f792013-12-02 19:35:49 +0000209
Greg Clayton29b8fc42013-11-21 01:44:58 +0000210 // Make a port map for a port range that was specified.
211 if (min_gdbserver_port < max_gdbserver_port)
212 {
213 for (uint16_t port = min_gdbserver_port; port < max_gdbserver_port; ++port)
214 gdbserver_portmap[port] = LLDB_INVALID_PROCESS_ID;
215 }
216 else if (min_gdbserver_port != max_gdbserver_port)
217 {
218 fprintf (stderr, "error: --min-gdbserver-port (%u) is greater than --max-gdbserver-port (%u)\n", min_gdbserver_port, max_gdbserver_port);
219 option_error = 3;
220
221 }
222
Daniel Maleae0f8f572013-08-26 23:57:52 +0000223 // Print usage and exit if no listening port is specified.
224 if (listen_host_port.empty())
Greg Clayton29b8fc42013-11-21 01:44:58 +0000225 show_usage = true;
226
227 if (show_usage || option_error)
228 {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000229 display_usage(progname);
Greg Clayton29b8fc42013-11-21 01:44:58 +0000230 exit(option_error);
231 }
Greg Claytonb43767a2011-03-22 01:34:44 +0000232
Greg Claytonb7ad58a2013-04-04 20:35:24 +0000233 // Skip any options we consumed with getopt_long_only
Greg Claytonb43767a2011-03-22 01:34:44 +0000234 argc -= optind;
235 argv += optind;
236
Greg Clayton5fb8f792013-12-02 19:35:49 +0000237 // Execute any LLDB commands that we were asked to evaluate.
238 for (const auto &lldb_command : lldb_commands)
239 {
240 lldb_private::CommandReturnObject result;
241 printf("(lldb) %s\n", lldb_command.c_str());
242 debugger_sp->GetCommandInterpreter().HandleCommand(lldb_command.c_str(), eLazyBoolNo, result);
243 const char *output = result.GetOutputData();
244 if (output && output[0])
245 puts(output);
246 }
247
Greg Claytonb43767a2011-03-22 01:34:44 +0000248
Daniel Maleae0f8f572013-08-26 23:57:52 +0000249 do {
250 GDBRemoteCommunicationServer gdb_server (true);
Greg Clayton29b8fc42013-11-21 01:44:58 +0000251
Greg Claytond4724cf2013-11-22 18:55:04 +0000252 if (port_offset > 0)
253 gdb_server.SetPortOffset(port_offset);
254
Greg Clayton29b8fc42013-11-21 01:44:58 +0000255 if (!gdbserver_portmap.empty())
256 {
257 gdb_server.SetPortMap(std::move(gdbserver_portmap));
258 }
259
Daniel Maleae0f8f572013-08-26 23:57:52 +0000260 if (!listen_host_port.empty())
Greg Claytond314e812011-03-23 00:09:55 +0000261 {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000262 std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor());
263 if (conn_ap.get())
Greg Claytond314e812011-03-23 00:09:55 +0000264 {
Greg Clayton00fe87b2013-12-05 22:58:22 +0000265 std::string connect_url ("listen://");
266 connect_url.append(listen_host_port.c_str());
Daniel Maleae0f8f572013-08-26 23:57:52 +0000267
Greg Clayton00fe87b2013-12-05 22:58:22 +0000268 printf ("Listening for a connection from %s...\n", listen_host_port.c_str());
269 if (conn_ap->Connect(connect_url.c_str(), &error) == eConnectionStatusSuccess)
270 {
271 printf ("Connection established.\n");
272 gdb_server.SetConnection (conn_ap.release());
273 }
274 else
275 {
276 printf ("error: %s\n", error.AsCString());
Daniel Maleae0f8f572013-08-26 23:57:52 +0000277 }
278 }
279
280 if (gdb_server.IsConnected())
281 {
282 // After we connected, we need to get an initial ack from...
283 if (gdb_server.HandshakeWithClient(&error))
284 {
285 bool interrupt = false;
286 bool done = false;
287 while (!interrupt && !done)
288 {
Todd Fialaaf245d12014-06-30 21:05:18 +0000289 if (gdb_server.GetPacketAndSendResponse (UINT32_MAX, error, interrupt, done) != GDBRemoteCommunication::PacketResult::Success)
Daniel Maleae0f8f572013-08-26 23:57:52 +0000290 break;
291 }
292
293 if (error.Fail())
294 {
295 fprintf(stderr, "error: %s\n", error.AsCString());
296 }
297 }
298 else
299 {
300 fprintf(stderr, "error: handshake with client failed\n");
301 }
Greg Claytond314e812011-03-23 00:09:55 +0000302 }
303 }
Daniel Maleae0f8f572013-08-26 23:57:52 +0000304 } while (g_stay_alive);
Greg Claytonb43767a2011-03-22 01:34:44 +0000305
Greg Clayton1cb64962011-03-24 04:28:38 +0000306 Debugger::Terminate();
307
Daniel Maleae0f8f572013-08-26 23:57:52 +0000308 fprintf(stderr, "lldb-platform exiting...\n");
309
Greg Claytonb43767a2011-03-22 01:34:44 +0000310 return 0;
311}