blob: 21063f9a0f7bf0e721de451625f0879d06d1cc41 [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 Claytonb43767a2011-03-22 01:34:44 +000051 { NULL, 0, NULL, 0 }
52};
53
54//----------------------------------------------------------------------
55// Watch for signals
56//----------------------------------------------------------------------
57int g_sigpipe_received = 0;
58void
59signal_handler(int signo)
60{
61 switch (signo)
62 {
63 case SIGPIPE:
64 g_sigpipe_received = 1;
65 break;
Daniel Maleae0f8f572013-08-26 23:57:52 +000066 case SIGHUP:
67 // Use SIGINT first, if that does not work, use SIGHUP as a last resort.
68 // And we should not call exit() here because it results in the global destructors
69 // to be invoked and wreaking havoc on the threads still running.
70 Host::SystemLog(Host::eSystemLogWarning, "SIGHUP received, exiting lldb-platform...\n");
71 abort();
72 break;
Greg Claytonb43767a2011-03-22 01:34:44 +000073 }
74}
75
Daniel Maleae0f8f572013-08-26 23:57:52 +000076static void
77display_usage (const char *progname)
78{
79 fprintf(stderr, "Usage:\n %s [--log-file log-file-path] [--log-flags flags] --listen port\n", progname);
80 exit(0);
81}
82
Greg Claytonb43767a2011-03-22 01:34:44 +000083//----------------------------------------------------------------------
84// main
85//----------------------------------------------------------------------
86int
87main (int argc, char *argv[])
88{
Daniel Maleae0f8f572013-08-26 23:57:52 +000089 const char *progname = argv[0];
Greg Claytonb43767a2011-03-22 01:34:44 +000090 signal (SIGPIPE, signal_handler);
Daniel Maleae0f8f572013-08-26 23:57:52 +000091 signal (SIGHUP, signal_handler);
Greg Claytonb43767a2011-03-22 01:34:44 +000092 int long_option_index = 0;
Greg Clayton1cb64962011-03-24 04:28:38 +000093 StreamSP log_stream_sp;
94 Args log_args;
Greg Clayton9b1e1cd2011-04-04 18:18:57 +000095 Error error;
Greg Clayton73bf5db2011-06-17 01:22:15 +000096 std::string listen_host_port;
Greg Clayton9d3d6882011-10-31 23:51:19 +000097 int ch;
Greg Clayton1cb64962011-03-24 04:28:38 +000098 Debugger::Initialize();
99
Greg Claytonfbb76342013-11-20 21:07:01 +0000100// StreamSP stream_sp (new StreamFile(stdout, false));
101// const char *log_channels[] = { "host", "process", NULL };
102// EnableLog (stream_sp, 0, log_channels, NULL);
Greg Clayton9b1e1cd2011-04-04 18:18:57 +0000103
Greg Claytonb7ad58a2013-04-04 20:35:24 +0000104 while ((ch = getopt_long_only(argc, argv, "l:f:L:", g_long_options, &long_option_index)) != -1)
Greg Claytonb43767a2011-03-22 01:34:44 +0000105 {
106// DNBLogDebug("option: ch == %c (0x%2.2x) --%s%c%s\n",
107// ch, (uint8_t)ch,
108// g_long_options[long_option_index].name,
109// g_long_options[long_option_index].has_arg ? '=' : ' ',
110// optarg ? optarg : "");
111 switch (ch)
112 {
113 case 0: // Any optional that auto set themselves will return 0
114 break;
115
116 case 'l': // Set Log File
117 if (optarg && optarg[0])
118 {
Greg Clayton1cb64962011-03-24 04:28:38 +0000119 if ((strcasecmp(optarg, "stdout") == 0) || (strcmp(optarg, "/dev/stdout") == 0))
120 {
121 log_stream_sp.reset (new StreamFile (stdout, false));
122 }
123 else if ((strcasecmp(optarg, "stderr") == 0) || (strcmp(optarg, "/dev/stderr") == 0))
124 {
125 log_stream_sp.reset (new StreamFile (stderr, false));
126 }
Greg Claytonb43767a2011-03-22 01:34:44 +0000127 else
128 {
Greg Clayton1cb64962011-03-24 04:28:38 +0000129 FILE *log_file = fopen(optarg, "w");
130 if (log_file)
131 {
Greg Claytonb43767a2011-03-22 01:34:44 +0000132 setlinebuf(log_file);
Greg Clayton1cb64962011-03-24 04:28:38 +0000133 log_stream_sp.reset (new StreamFile (log_file, true));
134 }
135 else
136 {
137 const char *errno_str = strerror(errno);
138 fprintf (stderr, "Failed to open log file '%s' for writing: errno = %i (%s)", optarg, errno, errno_str ? errno_str : "unknown error");
139 }
140
Greg Claytonb43767a2011-03-22 01:34:44 +0000141 }
142
Greg Claytonb43767a2011-03-22 01:34:44 +0000143 }
144 break;
145
146 case 'f': // Log Flags
147 if (optarg && optarg[0])
Greg Clayton1cb64962011-03-24 04:28:38 +0000148 log_args.AppendArgument(optarg);
Greg Claytonb43767a2011-03-22 01:34:44 +0000149 break;
Greg Claytond314e812011-03-23 00:09:55 +0000150
151 case 'L':
Greg Clayton73bf5db2011-06-17 01:22:15 +0000152 listen_host_port.append (optarg);
Greg Claytond314e812011-03-23 00:09:55 +0000153 break;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000154
155 case 'h': /* fall-through is intentional */
156 case '?':
157 display_usage(progname);
158 break;
Greg Claytonb43767a2011-03-22 01:34:44 +0000159 }
160 }
Daniel Maleae0f8f572013-08-26 23:57:52 +0000161 // Print usage and exit if no listening port is specified.
162 if (listen_host_port.empty())
163 display_usage(progname);
Greg Claytonb43767a2011-03-22 01:34:44 +0000164
Greg Clayton1cb64962011-03-24 04:28:38 +0000165 if (log_stream_sp)
166 {
167 if (log_args.GetArgumentCount() == 0)
168 log_args.AppendArgument("default");
Jim Ingham228063c2012-02-21 02:23:08 +0000169 ProcessGDBRemoteLog::EnableLog (log_stream_sp, 0,log_args.GetConstArgumentVector(), log_stream_sp.get());
Greg Clayton1cb64962011-03-24 04:28:38 +0000170 }
171
Greg Claytonb7ad58a2013-04-04 20:35:24 +0000172 // Skip any options we consumed with getopt_long_only
Greg Claytonb43767a2011-03-22 01:34:44 +0000173 argc -= optind;
174 argv += optind;
175
176
Daniel Maleae0f8f572013-08-26 23:57:52 +0000177 do {
178 GDBRemoteCommunicationServer gdb_server (true);
179 if (!listen_host_port.empty())
Greg Claytond314e812011-03-23 00:09:55 +0000180 {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000181 std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor());
182 if (conn_ap.get())
Greg Claytond314e812011-03-23 00:09:55 +0000183 {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000184 for (int j = 0; j < listen_host_port.size(); j++)
185 {
186 char c = listen_host_port[j];
187 if (c > '9' || c < '0')
188 printf("WARNING: passing anything but a number as argument to --listen will most probably make connecting impossible.\n");
189 }
190 std::auto_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor());
191 if (conn_ap.get())
192 {
193 std::string connect_url ("listen://");
194 connect_url.append(listen_host_port.c_str());
195
196 printf ("Listening for a connection on %s...\n", listen_host_port.c_str());
197 if (conn_ap->Connect(connect_url.c_str(), &error) == eConnectionStatusSuccess)
198 {
199 printf ("Connection established.\n");
200 gdb_server.SetConnection (conn_ap.release());
201 }
202 }
203 }
204
205 if (gdb_server.IsConnected())
206 {
207 // After we connected, we need to get an initial ack from...
208 if (gdb_server.HandshakeWithClient(&error))
209 {
210 bool interrupt = false;
211 bool done = false;
212 while (!interrupt && !done)
213 {
214 if (!gdb_server.GetPacketAndSendResponse (UINT32_MAX, error, interrupt, done))
215 break;
216 }
217
218 if (error.Fail())
219 {
220 fprintf(stderr, "error: %s\n", error.AsCString());
221 }
222 }
223 else
224 {
225 fprintf(stderr, "error: handshake with client failed\n");
226 }
Greg Claytond314e812011-03-23 00:09:55 +0000227 }
228 }
Daniel Maleae0f8f572013-08-26 23:57:52 +0000229 } while (g_stay_alive);
Greg Claytonb43767a2011-03-22 01:34:44 +0000230
Greg Clayton1cb64962011-03-24 04:28:38 +0000231 Debugger::Terminate();
232
Daniel Maleae0f8f572013-08-26 23:57:52 +0000233 fprintf(stderr, "lldb-platform exiting...\n");
234
Greg Claytonb43767a2011-03-22 01:34:44 +0000235 return 0;
236}