blob: 8fdc472257ce7ab433bd66ab897b404c0da98b03 [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
Greg Claytond314e812011-03-23 00:09:55 +000010// C Includes
Greg Claytonb43767a2011-03-22 01:34:44 +000011#include <errno.h>
Zachary Turner98688922014-08-06 18:16:26 +000012#if defined(__APPLE__)
13#include <netinet/in.h>
14#endif
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>
Robert Flacka0e70cd2015-03-25 12:51:31 +000020#include <sys/wait.h>
Greg Claytonb43767a2011-03-22 01:34:44 +000021
Greg Claytond314e812011-03-23 00:09:55 +000022// C++ Includes
Oleksiy Vyalov298be462015-07-06 18:05:19 +000023#include <fstream>
Greg Claytond314e812011-03-23 00:09:55 +000024
25// Other libraries and framework includes
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +000026#include "llvm/Support/FileSystem.h"
27#include "llvm/Support/FileUtilities.h"
28
Greg Claytond314e812011-03-23 00:09:55 +000029#include "lldb/Core/Error.h"
Zachary Turner93a66fc2014-10-06 21:22:36 +000030#include "lldb/Host/ConnectionFileDescriptor.h"
Oleksiy Vyalov298be462015-07-06 18:05:19 +000031#include "lldb/Host/FileSpec.h"
32#include "lldb/Host/FileSystem.h"
Zachary Turner98688922014-08-06 18:16:26 +000033#include "lldb/Host/HostGetOpt.h"
Greg Claytonfb909312013-11-23 01:58:15 +000034#include "lldb/Host/OptionParser.h"
Oleksiy Vyalove98628c2015-10-15 23:54:09 +000035#include "lldb/Host/common/TCPSocket.h"
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +000036#include "Acceptor.h"
Tamas Berghammer9c9ecce2015-05-27 13:34:04 +000037#include "LLDBServerUtilities.h"
Tamas Berghammere13c2732015-02-11 10:29:30 +000038#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h"
Greg Clayton1cb64962011-03-24 04:28:38 +000039#include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h"
Tamas Berghammere13c2732015-02-11 10:29:30 +000040
Greg Claytond314e812011-03-23 00:09:55 +000041using namespace lldb;
42using namespace lldb_private;
Tamas Berghammer9c9ecce2015-05-27 13:34:04 +000043using namespace lldb_private::lldb_server;
Tamas Berghammerdb264a62015-03-31 09:52:22 +000044using namespace lldb_private::process_gdb_remote;
Tamas Berghammer9c9ecce2015-05-27 13:34:04 +000045using namespace llvm;
Greg Claytond314e812011-03-23 00:09:55 +000046
Greg Claytonb43767a2011-03-22 01:34:44 +000047//----------------------------------------------------------------------
Greg Claytonb7ad58a2013-04-04 20:35:24 +000048// option descriptors for getopt_long_only()
Greg Claytonb43767a2011-03-22 01:34:44 +000049//----------------------------------------------------------------------
50
Tamas Berghammerc2c3d712015-02-18 15:39:41 +000051static int g_debug = 0;
52static int g_verbose = 0;
Robert Flacka0e70cd2015-03-25 12:51:31 +000053static int g_server = 0;
Greg Claytonb43767a2011-03-22 01:34:44 +000054
55static struct option g_long_options[] =
56{
57 { "debug", no_argument, &g_debug, 1 },
58 { "verbose", no_argument, &g_verbose, 1 },
Tamas Berghammer9c9ecce2015-05-27 13:34:04 +000059 { "log-file", required_argument, NULL, 'l' },
60 { "log-channels", required_argument, NULL, 'c' },
Greg Claytond314e812011-03-23 00:09:55 +000061 { "listen", required_argument, NULL, 'L' },
Greg Claytond4724cf2013-11-22 18:55:04 +000062 { "port-offset", required_argument, NULL, 'p' },
63 { "gdbserver-port", required_argument, NULL, 'P' },
Greg Clayton29b8fc42013-11-21 01:44:58 +000064 { "min-gdbserver-port", required_argument, NULL, 'm' },
65 { "max-gdbserver-port", required_argument, NULL, 'M' },
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +000066 { "socket-file", required_argument, NULL, 'f' },
Robert Flacka0e70cd2015-03-25 12:51:31 +000067 { "server", no_argument, &g_server, 1 },
Greg Claytonb43767a2011-03-22 01:34:44 +000068 { NULL, 0, NULL, 0 }
69};
70
Greg Clayton29b8fc42013-11-21 01:44:58 +000071#if defined (__APPLE__)
72#define LOW_PORT (IPPORT_RESERVED)
73#define HIGH_PORT (IPPORT_HIFIRSTAUTO)
74#else
75#define LOW_PORT (1024u)
76#define HIGH_PORT (49151u)
77#endif
78
Greg Claytonb43767a2011-03-22 01:34:44 +000079//----------------------------------------------------------------------
80// Watch for signals
81//----------------------------------------------------------------------
Tamas Berghammerc2c3d712015-02-18 15:39:41 +000082static void
Greg Claytonb43767a2011-03-22 01:34:44 +000083signal_handler(int signo)
84{
85 switch (signo)
86 {
Daniel Maleae0f8f572013-08-26 23:57:52 +000087 case SIGHUP:
88 // Use SIGINT first, if that does not work, use SIGHUP as a last resort.
89 // And we should not call exit() here because it results in the global destructors
90 // to be invoked and wreaking havoc on the threads still running.
Robert Flack8cc4cf12015-03-06 14:36:33 +000091 Host::SystemLog(Host::eSystemLogWarning, "SIGHUP received, exiting lldb-server...\n");
Daniel Maleae0f8f572013-08-26 23:57:52 +000092 abort();
93 break;
Greg Claytonb43767a2011-03-22 01:34:44 +000094 }
95}
96
Daniel Maleae0f8f572013-08-26 23:57:52 +000097static void
Tamas Berghammerc2c3d712015-02-18 15:39:41 +000098display_usage (const char *progname, const char *subcommand)
Daniel Maleae0f8f572013-08-26 23:57:52 +000099{
Oleksiy Vyalov298be462015-07-06 18:05:19 +0000100 fprintf(stderr, "Usage:\n %s %s [--log-file log-file-name] [--log-channels log-channel-list] [--port-file port-file-path] --server --listen port\n", progname, subcommand);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000101 exit(0);
102}
103
Oleksiy Vyalov298be462015-07-06 18:05:19 +0000104static Error
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000105save_socket_id_to_file(const std::string &socket_id, const FileSpec &file_spec)
Oleksiy Vyalov298be462015-07-06 18:05:19 +0000106{
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000107 FileSpec temp_file_spec(file_spec.GetDirectory().AsCString(), false);
Oleksiy Vyalovdf62ed32015-07-14 18:54:52 +0000108 auto error = FileSystem::MakeDirectory(temp_file_spec, eFilePermissionsDirectoryDefault);
Oleksiy Vyalov298be462015-07-06 18:05:19 +0000109 if (error.Fail())
Oleksiy Vyalovdf62ed32015-07-14 18:54:52 +0000110 return Error("Failed to create directory %s: %s", temp_file_spec.GetCString(), error.AsCString());
Oleksiy Vyalov298be462015-07-06 18:05:19 +0000111
112 llvm::SmallString<PATH_MAX> temp_file_path;
Oleksiy Vyalovdf62ed32015-07-14 18:54:52 +0000113 temp_file_spec.AppendPathComponent("port-file.%%%%%%");
114 auto err_code = llvm::sys::fs::createUniqueFile(temp_file_spec.GetCString(), temp_file_path);
Oleksiy Vyalov298be462015-07-06 18:05:19 +0000115 if (err_code)
116 return Error("Failed to create temp file: %s", err_code.message().c_str());
117
118 llvm::FileRemover tmp_file_remover(temp_file_path.c_str());
119
120 {
121 std::ofstream temp_file(temp_file_path.c_str(), std::ios::out);
122 if (!temp_file.is_open())
123 return Error("Failed to open temp file %s", temp_file_path.c_str());
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000124 temp_file << socket_id;
Oleksiy Vyalov298be462015-07-06 18:05:19 +0000125 }
126
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000127 err_code = llvm::sys::fs::rename(temp_file_path.c_str(), file_spec.GetPath().c_str());
Oleksiy Vyalov298be462015-07-06 18:05:19 +0000128 if (err_code)
129 return Error("Failed to rename file %s to %s: %s",
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000130 temp_file_path.c_str(), file_spec.GetPath().c_str(), err_code.message().c_str());
Oleksiy Vyalov298be462015-07-06 18:05:19 +0000131
132 tmp_file_remover.releaseFile();
133 return Error();
134}
135
Greg Claytonb43767a2011-03-22 01:34:44 +0000136//----------------------------------------------------------------------
137// main
138//----------------------------------------------------------------------
139int
Tamas Berghammerc2c3d712015-02-18 15:39:41 +0000140main_platform (int argc, char *argv[])
Greg Claytonb43767a2011-03-22 01:34:44 +0000141{
Daniel Maleae0f8f572013-08-26 23:57:52 +0000142 const char *progname = argv[0];
Tamas Berghammerc2c3d712015-02-18 15:39:41 +0000143 const char *subcommand = argv[1];
144 argc--;
145 argv++;
Greg Claytonfb909312013-11-23 01:58:15 +0000146 signal (SIGPIPE, SIG_IGN);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000147 signal (SIGHUP, signal_handler);
Greg Claytonb43767a2011-03-22 01:34:44 +0000148 int long_option_index = 0;
Greg Clayton9b1e1cd2011-04-04 18:18:57 +0000149 Error error;
Greg Clayton73bf5db2011-06-17 01:22:15 +0000150 std::string listen_host_port;
Greg Clayton9d3d6882011-10-31 23:51:19 +0000151 int ch;
Greg Clayton5fb8f792013-12-02 19:35:49 +0000152
Tamas Berghammer9c9ecce2015-05-27 13:34:04 +0000153 std::string log_file;
154 StringRef log_channels; // e.g. "lldb process threads:gdb-remote default:linux all"
Oleksiy Vyalov298be462015-07-06 18:05:19 +0000155
Tamas Berghammere13c2732015-02-11 10:29:30 +0000156 GDBRemoteCommunicationServerPlatform::PortMap gdbserver_portmap;
Greg Clayton29b8fc42013-11-21 01:44:58 +0000157 int min_gdbserver_port = 0;
158 int max_gdbserver_port = 0;
Greg Claytond4724cf2013-11-22 18:55:04 +0000159 uint16_t port_offset = 0;
Oleksiy Vyalov298be462015-07-06 18:05:19 +0000160
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000161 FileSpec socket_file;
Greg Clayton29b8fc42013-11-21 01:44:58 +0000162 bool show_usage = false;
163 int option_error = 0;
Robert Flacka0e70cd2015-03-25 12:51:31 +0000164 int socket_error = -1;
Greg Clayton9b1e1cd2011-04-04 18:18:57 +0000165
Greg Claytonfb909312013-11-23 01:58:15 +0000166 std::string short_options(OptionParser::GetShortOptionString(g_long_options));
167
Greg Claytond4724cf2013-11-22 18:55:04 +0000168#if __GLIBC__
169 optind = 0;
170#else
171 optreset = 1;
172 optind = 1;
173#endif
174
Greg Claytonfb909312013-11-23 01:58:15 +0000175 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 +0000176 {
Greg Claytonb43767a2011-03-22 01:34:44 +0000177 switch (ch)
178 {
179 case 0: // Any optional that auto set themselves will return 0
180 break;
181
Greg Claytond314e812011-03-23 00:09:55 +0000182 case 'L':
Greg Clayton73bf5db2011-06-17 01:22:15 +0000183 listen_host_port.append (optarg);
Greg Claytond314e812011-03-23 00:09:55 +0000184 break;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000185
Tamas Berghammer9c9ecce2015-05-27 13:34:04 +0000186 case 'l': // Set Log File
187 if (optarg && optarg[0])
188 log_file.assign(optarg);
189 break;
190
191 case 'c': // Log Channels
192 if (optarg && optarg[0])
193 log_channels = StringRef(optarg);
194 break;
195
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000196 case 'f': // Socket file
Oleksiy Vyalov298be462015-07-06 18:05:19 +0000197 if (optarg && optarg[0])
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000198 socket_file.SetFile(optarg, false);
Oleksiy Vyalov298be462015-07-06 18:05:19 +0000199 break;
200
Greg Clayton29b8fc42013-11-21 01:44:58 +0000201 case 'p':
Greg Claytond4724cf2013-11-22 18:55:04 +0000202 {
203 char *end = NULL;
204 long tmp_port_offset = strtoul(optarg, &end, 0);
205 if (end && *end == '\0')
206 {
207 if (LOW_PORT <= tmp_port_offset && tmp_port_offset <= HIGH_PORT)
208 {
209 port_offset = (uint16_t)tmp_port_offset;
210 }
211 else
212 {
213 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);
214 option_error = 5;
215 }
216 }
217 else
218 {
219 fprintf (stderr, "error: invalid port offset string %s\n", optarg);
220 option_error = 4;
221 }
222 }
223 break;
224
225 case 'P':
Greg Clayton29b8fc42013-11-21 01:44:58 +0000226 case 'm':
227 case 'M':
228 {
229 char *end = NULL;
230 long portnum = strtoul(optarg, &end, 0);
231 if (end && *end == '\0')
232 {
233 if (LOW_PORT <= portnum && portnum <= HIGH_PORT)
234 {
Greg Claytond4724cf2013-11-22 18:55:04 +0000235 if (ch == 'P')
Greg Clayton29b8fc42013-11-21 01:44:58 +0000236 gdbserver_portmap[(uint16_t)portnum] = LLDB_INVALID_PROCESS_ID;
237 else if (ch == 'm')
238 min_gdbserver_port = portnum;
239 else
240 max_gdbserver_port = portnum;
241 }
242 else
243 {
244 fprintf (stderr, "error: port number %li is not in the valid user port range of %u - %u\n", portnum, LOW_PORT, HIGH_PORT);
245 option_error = 1;
246 }
247 }
248 else
249 {
250 fprintf (stderr, "error: invalid port number string %s\n", optarg);
251 option_error = 2;
252 }
253 }
254 break;
Greg Clayton5fb8f792013-12-02 19:35:49 +0000255
Daniel Maleae0f8f572013-08-26 23:57:52 +0000256 case 'h': /* fall-through is intentional */
257 case '?':
Greg Clayton29b8fc42013-11-21 01:44:58 +0000258 show_usage = true;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000259 break;
Greg Claytonb43767a2011-03-22 01:34:44 +0000260 }
261 }
Greg Clayton5fb8f792013-12-02 19:35:49 +0000262
Tamas Berghammer9c9ecce2015-05-27 13:34:04 +0000263 if (!LLDBServerUtilities::SetupLogging(log_file, log_channels, 0))
264 return -1;
265
Greg Clayton29b8fc42013-11-21 01:44:58 +0000266 // Make a port map for a port range that was specified.
267 if (min_gdbserver_port < max_gdbserver_port)
268 {
269 for (uint16_t port = min_gdbserver_port; port < max_gdbserver_port; ++port)
270 gdbserver_portmap[port] = LLDB_INVALID_PROCESS_ID;
271 }
272 else if (min_gdbserver_port != max_gdbserver_port)
273 {
274 fprintf (stderr, "error: --min-gdbserver-port (%u) is greater than --max-gdbserver-port (%u)\n", min_gdbserver_port, max_gdbserver_port);
275 option_error = 3;
Greg Clayton29b8fc42013-11-21 01:44:58 +0000276 }
277
Daniel Maleae0f8f572013-08-26 23:57:52 +0000278 // Print usage and exit if no listening port is specified.
279 if (listen_host_port.empty())
Greg Clayton29b8fc42013-11-21 01:44:58 +0000280 show_usage = true;
281
282 if (show_usage || option_error)
283 {
Tamas Berghammerc2c3d712015-02-18 15:39:41 +0000284 display_usage(progname, subcommand);
Greg Clayton29b8fc42013-11-21 01:44:58 +0000285 exit(option_error);
286 }
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000287
Robert Flacka0e70cd2015-03-25 12:51:31 +0000288 const bool children_inherit_listen_socket = false;
Vince Harron33aea902015-03-31 00:27:10 +0000289 // the test suite makes many connections in parallel, let's not miss any.
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000290 // The highest this should get reasonably is a function of the number
291 // of target CPUs. For now, let's just use 100.
Vince Harron33aea902015-03-31 00:27:10 +0000292 const int backlog = 100;
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000293
294 std::unique_ptr<Acceptor> acceptor_up(Acceptor::Create(listen_host_port, children_inherit_listen_socket, error));
Oleksiy Vyalove98628c2015-10-15 23:54:09 +0000295 if (error.Fail())
296 {
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000297 fprintf(stderr, "failed to create acceptor: %s", error.AsCString());
Oleksiy Vyalove98628c2015-10-15 23:54:09 +0000298 exit(socket_error);
299 }
300
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000301 error = acceptor_up->Listen(backlog);
Robert Flacka0e70cd2015-03-25 12:51:31 +0000302 if (error.Fail())
303 {
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000304 printf("failed to listen: %s\n", error.AsCString());
Robert Flacka0e70cd2015-03-25 12:51:31 +0000305 exit(socket_error);
306 }
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000307 if (socket_file)
Oleksiy Vyalov298be462015-07-06 18:05:19 +0000308 {
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000309 error = save_socket_id_to_file(acceptor_up->GetLocalSocketId(), socket_file);
Oleksiy Vyalov298be462015-07-06 18:05:19 +0000310 if (error.Fail())
311 {
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000312 fprintf(stderr, "failed to write socket id to %s: %s", socket_file.GetPath().c_str(), error.AsCString());
Oleksiy Vyalov298be462015-07-06 18:05:19 +0000313 return 1;
314 }
315 }
Greg Claytonb43767a2011-03-22 01:34:44 +0000316
Daniel Maleae0f8f572013-08-26 23:57:52 +0000317 do {
Oleksiy Vyalov14857122015-10-28 19:49:50 +0000318 GDBRemoteCommunicationServerPlatform platform(acceptor_up->GetSocketProtocol(),
319 acceptor_up->GetSocketScheme());
Greg Clayton29b8fc42013-11-21 01:44:58 +0000320
Greg Claytond4724cf2013-11-22 18:55:04 +0000321 if (port_offset > 0)
Tamas Berghammere13c2732015-02-11 10:29:30 +0000322 platform.SetPortOffset(port_offset);
Greg Claytond4724cf2013-11-22 18:55:04 +0000323
Greg Clayton29b8fc42013-11-21 01:44:58 +0000324 if (!gdbserver_portmap.empty())
325 {
Tamas Berghammere13c2732015-02-11 10:29:30 +0000326 platform.SetPortMap(std::move(gdbserver_portmap));
Greg Clayton29b8fc42013-11-21 01:44:58 +0000327 }
328
Robert Flacka0e70cd2015-03-25 12:51:31 +0000329 const bool children_inherit_accept_socket = true;
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000330 Connection* conn = nullptr;
331 error = acceptor_up->Accept(children_inherit_accept_socket, conn);
Robert Flacka0e70cd2015-03-25 12:51:31 +0000332 if (error.Fail())
Greg Claytond314e812011-03-23 00:09:55 +0000333 {
Robert Flacka0e70cd2015-03-25 12:51:31 +0000334 printf ("error: %s\n", error.AsCString());
335 exit(socket_error);
336 }
337 printf ("Connection established.\n");
338 if (g_server)
339 {
340 // Collect child zombie processes.
341 while (waitpid(-1, nullptr, WNOHANG) > 0);
342 if (fork())
Greg Claytond314e812011-03-23 00:09:55 +0000343 {
Vince Harronf1e69992015-03-31 00:24:51 +0000344 // Parent doesn't need a connection to the lldb client
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000345 delete conn;
Vince Harronf1e69992015-03-31 00:24:51 +0000346
Robert Flacka0e70cd2015-03-25 12:51:31 +0000347 // Parent will continue to listen for new connections.
348 continue;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000349 }
Robert Flacka0e70cd2015-03-25 12:51:31 +0000350 else
Daniel Maleae0f8f572013-08-26 23:57:52 +0000351 {
Robert Flacka0e70cd2015-03-25 12:51:31 +0000352 // Child process will handle the connection and exit.
353 g_server = 0;
354 // Listening socket is owned by parent process.
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000355 acceptor_up.release();
Greg Claytond314e812011-03-23 00:09:55 +0000356 }
357 }
Robert Flacka0e70cd2015-03-25 12:51:31 +0000358 else
359 {
360 // If not running as a server, this process will not accept
361 // connections while a connection is active.
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000362 acceptor_up.reset();
Robert Flacka0e70cd2015-03-25 12:51:31 +0000363 }
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000364 platform.SetConnection (conn);
Robert Flacka0e70cd2015-03-25 12:51:31 +0000365
366 if (platform.IsConnected())
367 {
368 // After we connected, we need to get an initial ack from...
Pavel Labath77dc9562015-07-13 10:44:55 +0000369 if (platform.HandshakeWithClient())
Robert Flacka0e70cd2015-03-25 12:51:31 +0000370 {
371 bool interrupt = false;
372 bool done = false;
373 while (!interrupt && !done)
374 {
375 if (platform.GetPacketAndSendResponse (UINT32_MAX, error, interrupt, done) != GDBRemoteCommunication::PacketResult::Success)
376 break;
377 }
378
379 if (error.Fail())
380 {
381 fprintf(stderr, "error: %s\n", error.AsCString());
382 }
383 }
384 else
385 {
386 fprintf(stderr, "error: handshake with client failed\n");
387 }
388 }
389 } while (g_server);
Greg Claytonb43767a2011-03-22 01:34:44 +0000390
Robert Flack8cc4cf12015-03-06 14:36:33 +0000391 fprintf(stderr, "lldb-server exiting...\n");
Daniel Maleae0f8f572013-08-26 23:57:52 +0000392
Greg Claytonb43767a2011-03-22 01:34:44 +0000393 return 0;
394}