blob: 8e4174ec4e4084b90bf36923f7f0426d98b5054e [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>
12#include <getopt.h>
13#include <signal.h>
14#include <stdint.h>
15#include <stdio.h>
16#include <stdlib.h>
17#include <string.h>
18
Greg Claytond314e812011-03-23 00:09:55 +000019// C++ Includes
20
21// Other libraries and framework includes
22#include "lldb/Core/Error.h"
23#include "lldb/Core/ConnectionFileDescriptor.h"
Greg Clayton1cb64962011-03-24 04:28:38 +000024#include "lldb/Core/Debugger.h"
25#include "lldb/Core/StreamFile.h"
Greg Clayton576d8832011-03-22 04:00:09 +000026#include "GDBRemoteCommunicationServer.h"
Greg Clayton1cb64962011-03-24 04:28:38 +000027#include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h"
Greg Claytond314e812011-03-23 00:09:55 +000028using namespace lldb;
29using namespace lldb_private;
30
Greg Claytonb43767a2011-03-22 01:34:44 +000031//----------------------------------------------------------------------
32// option descriptors for getopt_long()
33//----------------------------------------------------------------------
34
35int g_debug = 0;
36int g_verbose = 0;
37
38static struct option g_long_options[] =
39{
40 { "debug", no_argument, &g_debug, 1 },
41 { "verbose", no_argument, &g_verbose, 1 },
42 { "log-file", required_argument, NULL, 'l' },
43 { "log-flags", required_argument, NULL, 'f' },
Greg Claytond314e812011-03-23 00:09:55 +000044 { "listen", required_argument, NULL, 'L' },
Greg Claytonb43767a2011-03-22 01:34:44 +000045 { NULL, 0, NULL, 0 }
46};
47
48//----------------------------------------------------------------------
49// Watch for signals
50//----------------------------------------------------------------------
51int g_sigpipe_received = 0;
52void
53signal_handler(int signo)
54{
55 switch (signo)
56 {
57 case SIGPIPE:
58 g_sigpipe_received = 1;
59 break;
60 }
61}
62
63//----------------------------------------------------------------------
64// main
65//----------------------------------------------------------------------
66int
67main (int argc, char *argv[])
68{
69 signal (SIGPIPE, signal_handler);
70 int long_option_index = 0;
Greg Clayton1cb64962011-03-24 04:28:38 +000071 StreamSP log_stream_sp;
72 Args log_args;
73 std::string listen_host_post;
Greg Claytonb43767a2011-03-22 01:34:44 +000074 char ch;
Greg Clayton1cb64962011-03-24 04:28:38 +000075 Debugger::Initialize();
76
Greg Claytonb43767a2011-03-22 01:34:44 +000077
Greg Clayton1cb64962011-03-24 04:28:38 +000078 while ((ch = getopt_long(argc, argv, "l:f:L:", g_long_options, &long_option_index)) != -1)
Greg Claytonb43767a2011-03-22 01:34:44 +000079 {
80// DNBLogDebug("option: ch == %c (0x%2.2x) --%s%c%s\n",
81// ch, (uint8_t)ch,
82// g_long_options[long_option_index].name,
83// g_long_options[long_option_index].has_arg ? '=' : ' ',
84// optarg ? optarg : "");
85 switch (ch)
86 {
87 case 0: // Any optional that auto set themselves will return 0
88 break;
89
90 case 'l': // Set Log File
91 if (optarg && optarg[0])
92 {
Greg Clayton1cb64962011-03-24 04:28:38 +000093 if ((strcasecmp(optarg, "stdout") == 0) || (strcmp(optarg, "/dev/stdout") == 0))
94 {
95 log_stream_sp.reset (new StreamFile (stdout, false));
96 }
97 else if ((strcasecmp(optarg, "stderr") == 0) || (strcmp(optarg, "/dev/stderr") == 0))
98 {
99 log_stream_sp.reset (new StreamFile (stderr, false));
100 }
Greg Claytonb43767a2011-03-22 01:34:44 +0000101 else
102 {
Greg Clayton1cb64962011-03-24 04:28:38 +0000103 FILE *log_file = fopen(optarg, "w");
104 if (log_file)
105 {
Greg Claytonb43767a2011-03-22 01:34:44 +0000106 setlinebuf(log_file);
Greg Clayton1cb64962011-03-24 04:28:38 +0000107 log_stream_sp.reset (new StreamFile (log_file, true));
108 }
109 else
110 {
111 const char *errno_str = strerror(errno);
112 fprintf (stderr, "Failed to open log file '%s' for writing: errno = %i (%s)", optarg, errno, errno_str ? errno_str : "unknown error");
113 }
114
Greg Claytonb43767a2011-03-22 01:34:44 +0000115 }
116
Greg Claytonb43767a2011-03-22 01:34:44 +0000117 }
118 break;
119
120 case 'f': // Log Flags
121 if (optarg && optarg[0])
Greg Clayton1cb64962011-03-24 04:28:38 +0000122 log_args.AppendArgument(optarg);
Greg Claytonb43767a2011-03-22 01:34:44 +0000123 break;
Greg Claytond314e812011-03-23 00:09:55 +0000124
125 case 'L':
Greg Clayton1cb64962011-03-24 04:28:38 +0000126 listen_host_post.append (optarg);
Greg Claytond314e812011-03-23 00:09:55 +0000127 break;
Greg Claytonb43767a2011-03-22 01:34:44 +0000128 }
129 }
130
Greg Clayton1cb64962011-03-24 04:28:38 +0000131 if (log_stream_sp)
132 {
133 if (log_args.GetArgumentCount() == 0)
134 log_args.AppendArgument("default");
135 ProcessGDBRemoteLog::EnableLog (log_stream_sp, 0,log_args, log_stream_sp.get());
136 }
137
Greg Claytonb43767a2011-03-22 01:34:44 +0000138 // Skip any options we consumed with getopt_long
139 argc -= optind;
140 argv += optind;
141
142
Greg Claytond314e812011-03-23 00:09:55 +0000143 GDBRemoteCommunicationServer gdb_server;
144 Error error;
Greg Clayton1cb64962011-03-24 04:28:38 +0000145 if (!listen_host_post.empty())
Greg Claytond314e812011-03-23 00:09:55 +0000146 {
147 std::auto_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor());
148 if (conn_ap.get())
149 {
Greg Clayton1cb64962011-03-24 04:28:38 +0000150 std::string connect_url ("listen://");
151 connect_url.append(listen_host_post.c_str());
152
153 printf ("Listening for a connection on %s...\n", listen_host_post.c_str());
154 if (conn_ap->Connect(connect_url.c_str(), &error) == eConnectionStatusSuccess)
Greg Claytond314e812011-03-23 00:09:55 +0000155 {
Greg Clayton1cb64962011-03-24 04:28:38 +0000156 printf ("Connection established.\n");
157 gdb_server.SetConnection (conn_ap.release());
Greg Claytond314e812011-03-23 00:09:55 +0000158 }
159 }
160 }
161
162
163 if (gdb_server.IsConnected())
164 {
Greg Clayton1cb64962011-03-24 04:28:38 +0000165 // After we connected, we need to get an initial ack from...
166 if (gdb_server.HandshakeWithClient(&error))
Greg Claytond314e812011-03-23 00:09:55 +0000167 {
168 bool interrupt = false;
169 bool done = false;
170 while (!interrupt && !done)
171 {
Greg Clayton1cb64962011-03-24 04:28:38 +0000172 if (!gdb_server.GetPacketAndSendResponse(NULL, error, interrupt, done))
173 break;
Greg Claytond314e812011-03-23 00:09:55 +0000174 }
175 }
176 else
177 {
Greg Clayton1cb64962011-03-24 04:28:38 +0000178 fprintf(stderr, "error: handshake with client failed\n");
Greg Claytond314e812011-03-23 00:09:55 +0000179 }
180 }
Greg Claytonb43767a2011-03-22 01:34:44 +0000181
Greg Clayton1cb64962011-03-24 04:28:38 +0000182 Debugger::Terminate();
183
Greg Claytonb43767a2011-03-22 01:34:44 +0000184 return 0;
185}