• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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