1 //===-- 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
10 #include "lldb/lldb-python.h"
11
12 // C Includes
13 #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
21 // C++ Includes
22
23 // Other libraries and framework includes
24 #include "lldb/Core/Error.h"
25 #include "lldb/Core/ConnectionFileDescriptor.h"
26 #include "lldb/Core/ConnectionMachPort.h"
27 #include "lldb/Core/Debugger.h"
28 #include "lldb/Core/StreamFile.h"
29 #include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h"
30 #include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h"
31 using namespace lldb;
32 using namespace lldb_private;
33
34 //----------------------------------------------------------------------
35 // option descriptors for getopt_long_only()
36 //----------------------------------------------------------------------
37
38 int g_debug = 0;
39 int g_verbose = 0;
40
41 static struct option g_long_options[] =
42 {
43 { "debug", no_argument, &g_debug, 1 },
44 { "verbose", no_argument, &g_verbose, 1 },
45 { "log-file", required_argument, NULL, 'l' },
46 { "log-flags", required_argument, NULL, 'f' },
47 { "listen", required_argument, NULL, 'L' },
48 { NULL, 0, NULL, 0 }
49 };
50
51 //----------------------------------------------------------------------
52 // Watch for signals
53 //----------------------------------------------------------------------
54 int g_sigpipe_received = 0;
55 void
signal_handler(int signo)56 signal_handler(int signo)
57 {
58 switch (signo)
59 {
60 case SIGPIPE:
61 g_sigpipe_received = 1;
62 break;
63 }
64 }
65
66 //----------------------------------------------------------------------
67 // main
68 //----------------------------------------------------------------------
69 int
main(int argc,char * argv[])70 main (int argc, char *argv[])
71 {
72 signal (SIGPIPE, signal_handler);
73 int long_option_index = 0;
74 StreamSP log_stream_sp;
75 Args log_args;
76 Error error;
77 std::string listen_host_port;
78 int ch;
79 Debugger::Initialize();
80
81 // ConnectionMachPort a;
82 // ConnectionMachPort b;
83 //
84 // lldb::ConnectionStatus status;
85 // const char *bootstrap_service_name = "HelloWorld";
86 // status = a.BootstrapCheckIn(bootstrap_service_name, &error);
87 //
88 // if (status != eConnectionStatusSuccess)
89 // {
90 // fprintf(stderr, "%s", error.AsCString());
91 // return 1;
92 // }
93 // status = b.BootstrapLookup (bootstrap_service_name, &error);
94 // if (status != eConnectionStatusSuccess)
95 // {
96 // fprintf(stderr, "%s", error.AsCString());
97 // return 2;
98 // }
99 //
100 // if (a.Write ("hello", 5, status, &error) == 5)
101 // {
102 // char buf[32];
103 // memset(buf, 0, sizeof(buf));
104 // if (b.Read (buf, 5, status, &error))
105 // {
106 // printf("read returned bytes: %s", buf);
107 // }
108 // else
109 // {
110 // fprintf(stderr, "%s", error.AsCString());
111 // return 4;
112 // }
113 // }
114 // else
115 // {
116 // fprintf(stderr, "%s", error.AsCString());
117 // return 3;
118 // }
119
120 while ((ch = getopt_long_only(argc, argv, "l:f:L:", g_long_options, &long_option_index)) != -1)
121 {
122 // DNBLogDebug("option: ch == %c (0x%2.2x) --%s%c%s\n",
123 // ch, (uint8_t)ch,
124 // g_long_options[long_option_index].name,
125 // g_long_options[long_option_index].has_arg ? '=' : ' ',
126 // optarg ? optarg : "");
127 switch (ch)
128 {
129 case 0: // Any optional that auto set themselves will return 0
130 break;
131
132 case 'l': // Set Log File
133 if (optarg && optarg[0])
134 {
135 if ((strcasecmp(optarg, "stdout") == 0) || (strcmp(optarg, "/dev/stdout") == 0))
136 {
137 log_stream_sp.reset (new StreamFile (stdout, false));
138 }
139 else if ((strcasecmp(optarg, "stderr") == 0) || (strcmp(optarg, "/dev/stderr") == 0))
140 {
141 log_stream_sp.reset (new StreamFile (stderr, false));
142 }
143 else
144 {
145 FILE *log_file = fopen(optarg, "w");
146 if (log_file)
147 {
148 setlinebuf(log_file);
149 log_stream_sp.reset (new StreamFile (log_file, true));
150 }
151 else
152 {
153 const char *errno_str = strerror(errno);
154 fprintf (stderr, "Failed to open log file '%s' for writing: errno = %i (%s)", optarg, errno, errno_str ? errno_str : "unknown error");
155 }
156
157 }
158
159 }
160 break;
161
162 case 'f': // Log Flags
163 if (optarg && optarg[0])
164 log_args.AppendArgument(optarg);
165 break;
166
167 case 'L':
168 listen_host_port.append (optarg);
169 break;
170 }
171 }
172
173 if (log_stream_sp)
174 {
175 if (log_args.GetArgumentCount() == 0)
176 log_args.AppendArgument("default");
177 ProcessGDBRemoteLog::EnableLog (log_stream_sp, 0,log_args.GetConstArgumentVector(), log_stream_sp.get());
178 }
179
180 // Skip any options we consumed with getopt_long_only
181 argc -= optind;
182 argv += optind;
183
184
185 GDBRemoteCommunicationServer gdb_server (true);
186 if (!listen_host_port.empty())
187 {
188 std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor());
189 if (conn_ap.get())
190 {
191 std::string connect_url ("listen://");
192 connect_url.append(listen_host_port.c_str());
193
194 printf ("Listening for a connection on %s...\n", listen_host_port.c_str());
195 if (conn_ap->Connect(connect_url.c_str(), &error) == eConnectionStatusSuccess)
196 {
197 printf ("Connection established.\n");
198 gdb_server.SetConnection (conn_ap.release());
199 }
200 }
201 }
202
203
204 if (gdb_server.IsConnected())
205 {
206 // After we connected, we need to get an initial ack from...
207 if (gdb_server.HandshakeWithClient(&error))
208 {
209 bool interrupt = false;
210 bool done = false;
211 while (!interrupt && !done)
212 {
213 if (!gdb_server.GetPacketAndSendResponse (UINT32_MAX, error, interrupt, done))
214 break;
215 }
216
217 if (error.Fail())
218 {
219 fprintf(stderr, "error: %s\n", error.AsCString());
220 }
221 }
222 else
223 {
224 fprintf(stderr, "error: handshake with client failed\n");
225 }
226 }
227
228 Debugger::Terminate();
229
230 return 0;
231 }
232