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 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 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