blob: 875adc22283ac3e1b2e0ea4f6e06e047dd341ae7 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- Driver.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 "Driver.h"
11
12#include <getopt.h>
13#include <libgen.h>
14#include <sys/ioctl.h>
15#include <termios.h>
16#include <unistd.h>
Eli Friedmana382d472010-06-09 09:50:17 +000017#include <string.h>
18#include <stdlib.h>
19#include <limits.h>
Eli Friedman07b16272010-06-09 19:11:30 +000020#include <fcntl.h>
Daniel Malead01b2952012-11-29 21:49:15 +000021#include <inttypes.h>
Chris Lattner30fdc8d2010-06-08 16:52:24 +000022
23#include <string>
24
25#include "IOChannel.h"
Jim Inghame6bc6cb2012-02-08 05:23:15 +000026#include "lldb/API/SBBreakpoint.h"
Eli Friedmana382d472010-06-09 09:50:17 +000027#include "lldb/API/SBCommandInterpreter.h"
28#include "lldb/API/SBCommandReturnObject.h"
29#include "lldb/API/SBCommunication.h"
30#include "lldb/API/SBDebugger.h"
31#include "lldb/API/SBEvent.h"
32#include "lldb/API/SBHostOS.h"
33#include "lldb/API/SBListener.h"
Jim Ingham85e8b812011-02-19 02:53:09 +000034#include "lldb/API/SBStream.h"
Eli Friedmana382d472010-06-09 09:50:17 +000035#include "lldb/API/SBTarget.h"
36#include "lldb/API/SBThread.h"
37#include "lldb/API/SBProcess.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000038
39using namespace lldb;
40
41static void reset_stdin_termios ();
Greg Claytonf571b892012-02-02 19:28:31 +000042static bool g_old_stdin_termios_is_valid = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000043static struct termios g_old_stdin_termios;
44
Caroline Ticedd759852010-09-09 17:45:09 +000045static char *g_debugger_name = (char *) "";
Caroline Ticeefed6132010-11-19 20:47:54 +000046static Driver *g_driver = NULL;
Caroline Ticedd759852010-09-09 17:45:09 +000047
Chris Lattner30fdc8d2010-06-08 16:52:24 +000048// In the Driver::MainLoop, we change the terminal settings. This function is
49// added as an atexit handler to make sure we clean them up.
50static void
51reset_stdin_termios ()
52{
Greg Claytonf571b892012-02-02 19:28:31 +000053 if (g_old_stdin_termios_is_valid)
54 {
55 g_old_stdin_termios_is_valid = false;
56 ::tcsetattr (STDIN_FILENO, TCSANOW, &g_old_stdin_termios);
57 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +000058}
59
Greg Claytone0d378b2011-03-24 21:19:54 +000060typedef struct
Chris Lattner30fdc8d2010-06-08 16:52:24 +000061{
Greg Claytone0d378b2011-03-24 21:19:54 +000062 uint32_t usage_mask; // Used to mark options that can be used together. If (1 << n & usage_mask) != 0
63 // then this option belongs to option set n.
64 bool required; // This option is required (in the current usage level)
65 const char * long_option; // Full name for this option.
Greg Clayton3bcdfc02012-12-04 00:32:51 +000066 int short_option; // Single character for this option.
Greg Claytone0d378b2011-03-24 21:19:54 +000067 int option_has_arg; // no_argument, required_argument or optional_argument
Greg Claytonab65b342011-04-13 22:47:15 +000068 uint32_t completion_type; // Cookie the option class can use to do define the argument completion.
Greg Claytone0d378b2011-03-24 21:19:54 +000069 lldb::CommandArgumentType argument_type; // Type of argument this option takes
70 const char * usage_text; // Full text explaining what this options does and what (if any) argument to
71 // pass it.
72} OptionDefinition;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000073
Jim Inghame64f0dc2011-09-13 23:25:31 +000074#define LLDB_3_TO_5 LLDB_OPT_SET_3|LLDB_OPT_SET_4|LLDB_OPT_SET_5
75#define LLDB_4_TO_5 LLDB_OPT_SET_4|LLDB_OPT_SET_5
76
Greg Claytone0d378b2011-03-24 21:19:54 +000077static OptionDefinition g_options[] =
78{
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +000079 { LLDB_OPT_SET_1, true , "help" , 'h', no_argument , 0, eArgTypeNone,
Jim Ingham12e9a202011-09-15 21:30:02 +000080 "Prints out the usage information for the LLDB debugger." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +000081 { LLDB_OPT_SET_2, true , "version" , 'v', no_argument , 0, eArgTypeNone,
Jim Ingham12e9a202011-09-15 21:30:02 +000082 "Prints out the current version number of the LLDB debugger." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +000083 { LLDB_OPT_SET_3, true , "arch" , 'a', required_argument, 0, eArgTypeArchitecture,
Jim Ingham12e9a202011-09-15 21:30:02 +000084 "Tells the debugger to use the specified architecture when starting and running the program. <architecture> must "
85 "be one of the architectures for which the program was compiled." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +000086 { LLDB_OPT_SET_3, true , "file" , 'f', required_argument, 0, eArgTypeFilename,
Jim Ingham12e9a202011-09-15 21:30:02 +000087 "Tells the debugger to use the file <filename> as the program to be debugged." },
Jason Molenda67c3cf52012-10-24 03:29:40 +000088 { LLDB_OPT_SET_3, false, "core" , 'c', required_argument, 0, eArgTypeFilename,
Johnny Cheneb46f782012-08-15 22:10:42 +000089 "Tells the debugger to use the fullpath to <path> as the core file." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +000090 { LLDB_OPT_SET_4, true , "attach-name" , 'n', required_argument, 0, eArgTypeProcessName,
Jim Ingham12e9a202011-09-15 21:30:02 +000091 "Tells the debugger to attach to a process with the given name." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +000092 { LLDB_OPT_SET_4, true , "wait-for" , 'w', no_argument , 0, eArgTypeNone,
Jim Ingham12e9a202011-09-15 21:30:02 +000093 "Tells the debugger to wait for a process with the given pid or name to launch before attaching." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +000094 { LLDB_OPT_SET_5, true , "attach-pid" , 'p', required_argument, 0, eArgTypePid,
Jim Ingham12e9a202011-09-15 21:30:02 +000095 "Tells the debugger to attach to a process with the given pid." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +000096 { LLDB_3_TO_5, false, "script-language", 'l', required_argument, 0, eArgTypeScriptLang,
Jim Ingham12e9a202011-09-15 21:30:02 +000097 "Tells the debugger to use the specified scripting language for user-defined scripts, rather than the default. "
98 "Valid scripting languages that can be specified include Python, Perl, Ruby and Tcl. Currently only the Python "
99 "extensions have been implemented." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +0000100 { LLDB_3_TO_5, false, "debug" , 'd', no_argument , 0, eArgTypeNone,
Jim Ingham12e9a202011-09-15 21:30:02 +0000101 "Tells the debugger to print out extra information for debugging itself." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +0000102 { LLDB_3_TO_5, false, "source" , 's', required_argument, 0, eArgTypeFilename,
Jim Ingham12e9a202011-09-15 21:30:02 +0000103 "Tells the debugger to read in and execute the file <file>, which should contain lldb commands." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +0000104 { LLDB_3_TO_5, false, "editor" , 'e', no_argument , 0, eArgTypeNone,
Jim Ingham12e9a202011-09-15 21:30:02 +0000105 "Tells the debugger to open source files using the host's \"external editor\" mechanism." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +0000106 { LLDB_3_TO_5, false, "no-lldbinit" , 'x', no_argument , 0, eArgTypeNone,
Jim Ingham12e9a202011-09-15 21:30:02 +0000107 "Do not automatically parse any '.lldbinit' files." },
Michael Sartainc3ce7f272013-05-23 20:47:45 +0000108 { LLDB_3_TO_5, false, "no-use-colors" , 'o', no_argument , 0, eArgTypeNone,
109 "Do not use colors." },
110 { LLDB_OPT_SET_6, true , "python-path" , 'P', no_argument , 0, eArgTypeNone,
Jim Inghame2231ac2012-12-21 22:22:26 +0000111 "Prints out the path to the lldb.py file for this version of lldb." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +0000112 { 0, false, NULL , 0 , 0 , 0, eArgTypeNone, NULL }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000113};
114
Jim Inghame64f0dc2011-09-13 23:25:31 +0000115static const uint32_t last_option_set_with_args = 2;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000116
117Driver::Driver () :
118 SBBroadcaster ("Driver"),
Jim Ingham06942692011-08-13 00:22:20 +0000119 m_debugger (SBDebugger::Create(false)),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000120 m_editline_pty (),
121 m_editline_slave_fh (NULL),
122 m_editline_reader (),
123 m_io_channel_ap (),
124 m_option_data (),
Greg Claytoneea37ee2013-05-14 17:36:51 +0000125 m_executing_user_command (false),
Daniel Malea926758b2012-12-17 17:40:07 +0000126 m_waiting_for_command (false),
127 m_done(false)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000128{
Greg Claytonfc3f0272011-05-29 04:06:55 +0000129 // We want to be able to handle CTRL+D in the terminal to have it terminate
130 // certain input
131 m_debugger.SetCloseInputOnEOF (false);
Caroline Ticedd759852010-09-09 17:45:09 +0000132 g_debugger_name = (char *) m_debugger.GetInstanceName();
133 if (g_debugger_name == NULL)
134 g_debugger_name = (char *) "";
Caroline Ticeefed6132010-11-19 20:47:54 +0000135 g_driver = this;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000136}
137
138Driver::~Driver ()
139{
Caroline Ticeefed6132010-11-19 20:47:54 +0000140 g_driver = NULL;
141 g_debugger_name = NULL;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000142}
143
144void
145Driver::CloseIOChannelFile ()
146{
Johnny Chene26c7212012-05-16 22:01:10 +0000147 // Write an End of File sequence to the file descriptor to ensure any
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000148 // read functions can exit.
149 char eof_str[] = "\x04";
150 ::write (m_editline_pty.GetMasterFileDescriptor(), eof_str, strlen(eof_str));
151
152 m_editline_pty.CloseMasterFileDescriptor();
153
154 if (m_editline_slave_fh)
155 {
156 ::fclose (m_editline_slave_fh);
157 m_editline_slave_fh = NULL;
158 }
159}
160
Greg Claytonc982c762010-07-09 20:39:50 +0000161// This function takes INDENT, which tells how many spaces to output at the front
162// of each line; TEXT, which is the text that is to be output. It outputs the
163// text, on multiple lines if necessary, to RESULT, with INDENT spaces at the
164// front of each line. It breaks lines on spaces, tabs or newlines, shortening
165// the line if necessary to not break in the middle of a word. It assumes that
166// each output line should contain a maximum of OUTPUT_MAX_COLUMNS characters.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000167
168void
Greg Claytonc982c762010-07-09 20:39:50 +0000169OutputFormattedUsageText (FILE *out, int indent, const char *text, int output_max_columns)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000170{
171 int len = strlen (text);
172 std::string text_string (text);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000173
174 // Force indentation to be reasonable.
175 if (indent >= output_max_columns)
176 indent = 0;
177
178 // Will it all fit on one line?
179
180 if (len + indent < output_max_columns)
181 // Output as a single line
Greg Claytonc982c762010-07-09 20:39:50 +0000182 fprintf (out, "%*s%s\n", indent, "", text);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000183 else
184 {
185 // We need to break it up into multiple lines.
186 int text_width = output_max_columns - indent - 1;
187 int start = 0;
188 int end = start;
189 int final_end = len;
190 int sub_len;
191
192 while (end < final_end)
193 {
194 // Dont start the 'text' on a space, since we're already outputting the indentation.
195 while ((start < final_end) && (text[start] == ' '))
196 start++;
197
198 end = start + text_width;
199 if (end > final_end)
200 end = final_end;
201 else
202 {
203 // If we're not at the end of the text, make sure we break the line on white space.
204 while (end > start
205 && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
206 end--;
207 }
208 sub_len = end - start;
209 std::string substring = text_string.substr (start, sub_len);
Greg Claytonc982c762010-07-09 20:39:50 +0000210 fprintf (out, "%*s%s\n", indent, "", substring.c_str());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000211 start = end + 1;
212 }
213 }
214}
215
216void
Greg Claytone0d378b2011-03-24 21:19:54 +0000217ShowUsage (FILE *out, OptionDefinition *option_table, Driver::OptionData data)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000218{
219 uint32_t screen_width = 80;
220 uint32_t indent_level = 0;
221 const char *name = "lldb";
Jim Ingham86511212010-06-15 18:47:14 +0000222
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000223 fprintf (out, "\nUsage:\n\n");
224
225 indent_level += 2;
226
227
228 // First, show each usage level set of options, e.g. <cmd> [options-for-level-0]
229 // <cmd> [options-for-level-1]
230 // etc.
231
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000232 uint32_t num_options;
Jim Ingham86511212010-06-15 18:47:14 +0000233 uint32_t num_option_sets = 0;
234
235 for (num_options = 0; option_table[num_options].long_option != NULL; ++num_options)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000236 {
Jim Ingham86511212010-06-15 18:47:14 +0000237 uint32_t this_usage_mask = option_table[num_options].usage_mask;
238 if (this_usage_mask == LLDB_OPT_SET_ALL)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000239 {
Jim Ingham86511212010-06-15 18:47:14 +0000240 if (num_option_sets == 0)
241 num_option_sets = 1;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000242 }
243 else
244 {
Greg Claytonc982c762010-07-09 20:39:50 +0000245 for (uint32_t j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++)
Jim Ingham86511212010-06-15 18:47:14 +0000246 {
247 if (this_usage_mask & 1 << j)
248 {
249 if (num_option_sets <= j)
250 num_option_sets = j + 1;
251 }
252 }
253 }
254 }
255
256 for (uint32_t opt_set = 0; opt_set < num_option_sets; opt_set++)
257 {
258 uint32_t opt_set_mask;
259
260 opt_set_mask = 1 << opt_set;
261
262 if (opt_set > 0)
263 fprintf (out, "\n");
Greg Claytonc982c762010-07-09 20:39:50 +0000264 fprintf (out, "%*s%s", indent_level, "", name);
Jim Ingham556e6532011-08-16 23:15:02 +0000265 bool is_help_line = false;
Jim Ingham86511212010-06-15 18:47:14 +0000266
267 for (uint32_t i = 0; i < num_options; ++i)
268 {
269 if (option_table[i].usage_mask & opt_set_mask)
270 {
Caroline Ticedeaab222010-10-01 19:59:14 +0000271 CommandArgumentType arg_type = option_table[i].argument_type;
Greg Clayton9d0402b2011-02-20 02:15:07 +0000272 const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type);
Jim Ingham556e6532011-08-16 23:15:02 +0000273 // This is a bit of a hack, but there's no way to say certain options don't have arguments yet...
274 // so we do it by hand here.
275 if (option_table[i].short_option == 'h')
276 is_help_line = true;
277
Jim Ingham86511212010-06-15 18:47:14 +0000278 if (option_table[i].required)
279 {
280 if (option_table[i].option_has_arg == required_argument)
Greg Clayton9d0402b2011-02-20 02:15:07 +0000281 fprintf (out, " -%c <%s>", option_table[i].short_option, arg_name);
Jim Ingham86511212010-06-15 18:47:14 +0000282 else if (option_table[i].option_has_arg == optional_argument)
Greg Clayton9d0402b2011-02-20 02:15:07 +0000283 fprintf (out, " -%c [<%s>]", option_table[i].short_option, arg_name);
Jim Ingham86511212010-06-15 18:47:14 +0000284 else
285 fprintf (out, " -%c", option_table[i].short_option);
286 }
287 else
288 {
289 if (option_table[i].option_has_arg == required_argument)
Greg Clayton9d0402b2011-02-20 02:15:07 +0000290 fprintf (out, " [-%c <%s>]", option_table[i].short_option, arg_name);
Jim Ingham86511212010-06-15 18:47:14 +0000291 else if (option_table[i].option_has_arg == optional_argument)
Greg Clayton9d0402b2011-02-20 02:15:07 +0000292 fprintf (out, " [-%c [<%s>]]", option_table[i].short_option, arg_name);
Jim Ingham86511212010-06-15 18:47:14 +0000293 else
294 fprintf (out, " [-%c]", option_table[i].short_option);
295 }
296 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000297 }
Jim Inghame64f0dc2011-09-13 23:25:31 +0000298 if (!is_help_line && (opt_set <= last_option_set_with_args))
Jim Ingham556e6532011-08-16 23:15:02 +0000299 fprintf (out, " [[--] <PROGRAM-ARG-1> [<PROGRAM_ARG-2> ...]]");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000300 }
301
302 fprintf (out, "\n\n");
303
304 // Now print out all the detailed information about the various options: long form, short form and help text:
305 // -- long_name <argument>
306 // - short <argument>
307 // help text
308
309 // This variable is used to keep track of which options' info we've printed out, because some options can be in
310 // more than one usage level, but we only want to print the long form of its information once.
311
312 Driver::OptionData::OptionSet options_seen;
313 Driver::OptionData::OptionSet::iterator pos;
314
315 indent_level += 5;
316
Jim Ingham86511212010-06-15 18:47:14 +0000317 for (uint32_t i = 0; i < num_options; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000318 {
319 // Only print this option if we haven't already seen it.
320 pos = options_seen.find (option_table[i].short_option);
321 if (pos == options_seen.end())
322 {
Caroline Ticedeaab222010-10-01 19:59:14 +0000323 CommandArgumentType arg_type = option_table[i].argument_type;
Greg Clayton9d0402b2011-02-20 02:15:07 +0000324 const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type);
Caroline Ticedeaab222010-10-01 19:59:14 +0000325
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000326 options_seen.insert (option_table[i].short_option);
Greg Claytonc982c762010-07-09 20:39:50 +0000327 fprintf (out, "%*s-%c ", indent_level, "", option_table[i].short_option);
Caroline Ticedeaab222010-10-01 19:59:14 +0000328 if (arg_type != eArgTypeNone)
Greg Clayton9d0402b2011-02-20 02:15:07 +0000329 fprintf (out, "<%s>", arg_name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000330 fprintf (out, "\n");
Greg Claytonc982c762010-07-09 20:39:50 +0000331 fprintf (out, "%*s--%s ", indent_level, "", option_table[i].long_option);
Caroline Ticedeaab222010-10-01 19:59:14 +0000332 if (arg_type != eArgTypeNone)
Greg Clayton9d0402b2011-02-20 02:15:07 +0000333 fprintf (out, "<%s>", arg_name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000334 fprintf (out, "\n");
335 indent_level += 5;
Greg Claytonc982c762010-07-09 20:39:50 +0000336 OutputFormattedUsageText (out, indent_level, option_table[i].usage_text, screen_width);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000337 indent_level -= 5;
338 fprintf (out, "\n");
339 }
340 }
341
342 indent_level -= 5;
343
Jim Inghama9deaf92011-08-16 23:57:58 +0000344 fprintf (out, "\n%*s(If you don't provide -f then the first argument will be the file to be debugged"
345 "\n%*s so '%s -- <filename> [<ARG1> [<ARG2>]]' also works."
346 "\n%*s Remember to end the options with \"--\" if any of your arguments have a \"-\" in them.)\n\n",
347 indent_level, "",
348 indent_level, "",
349 name,
350 indent_level, "");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000351}
352
353void
Greg Claytone0d378b2011-03-24 21:19:54 +0000354BuildGetOptTable (OptionDefinition *expanded_option_table, std::vector<struct option> &getopt_table,
Caroline Tice4ab31c92010-10-12 21:57:09 +0000355 uint32_t num_options)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000356{
357 if (num_options == 0)
358 return;
359
360 uint32_t i;
361 uint32_t j;
362 std::bitset<256> option_seen;
363
Caroline Tice4ab31c92010-10-12 21:57:09 +0000364 getopt_table.resize (num_options + 1);
365
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000366 for (i = 0, j = 0; i < num_options; ++i)
Greg Claytonc982c762010-07-09 20:39:50 +0000367 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000368 char short_opt = expanded_option_table[i].short_option;
Greg Claytonc982c762010-07-09 20:39:50 +0000369
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000370 if (option_seen.test(short_opt) == false)
Greg Claytonc982c762010-07-09 20:39:50 +0000371 {
Caroline Tice4ab31c92010-10-12 21:57:09 +0000372 getopt_table[j].name = expanded_option_table[i].long_option;
373 getopt_table[j].has_arg = expanded_option_table[i].option_has_arg;
374 getopt_table[j].flag = NULL;
375 getopt_table[j].val = expanded_option_table[i].short_option;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000376 option_seen.set(short_opt);
377 ++j;
Greg Claytonc982c762010-07-09 20:39:50 +0000378 }
379 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000380
Caroline Tice4ab31c92010-10-12 21:57:09 +0000381 getopt_table[j].name = NULL;
382 getopt_table[j].has_arg = 0;
383 getopt_table[j].flag = NULL;
384 getopt_table[j].val = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000385
386}
387
Greg Clayton66111032010-06-23 01:19:29 +0000388Driver::OptionData::OptionData () :
Greg Clayton8d846da2010-12-08 22:23:24 +0000389 m_args(),
Greg Clayton66111032010-06-23 01:19:29 +0000390 m_script_lang (lldb::eScriptLanguageDefault),
Johnny Cheneb46f782012-08-15 22:10:42 +0000391 m_core_file (),
Greg Claytonc982c762010-07-09 20:39:50 +0000392 m_crash_log (),
Greg Clayton66111032010-06-23 01:19:29 +0000393 m_source_command_files (),
394 m_debug_mode (false),
Greg Claytonc982c762010-07-09 20:39:50 +0000395 m_print_version (false),
Jim Inghame2231ac2012-12-21 22:22:26 +0000396 m_print_python_path (false),
Greg Clayton66111032010-06-23 01:19:29 +0000397 m_print_help (false),
Jim Inghame64f0dc2011-09-13 23:25:31 +0000398 m_wait_for(false),
399 m_process_name(),
400 m_process_pid(LLDB_INVALID_PROCESS_ID),
Daniel Dunbara08823f2011-10-31 22:50:49 +0000401 m_use_external_editor(false),
Stephen Wilson71c21d12011-04-11 19:41:40 +0000402 m_seen_options()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000403{
Greg Clayton66111032010-06-23 01:19:29 +0000404}
405
406Driver::OptionData::~OptionData ()
407{
408}
409
410void
411Driver::OptionData::Clear ()
412{
Greg Clayton8d846da2010-12-08 22:23:24 +0000413 m_args.clear ();
Greg Clayton66111032010-06-23 01:19:29 +0000414 m_script_lang = lldb::eScriptLanguageDefault;
415 m_source_command_files.clear ();
416 m_debug_mode = false;
417 m_print_help = false;
418 m_print_version = false;
Jim Inghame2231ac2012-12-21 22:22:26 +0000419 m_print_python_path = false;
Jim Inghame40e4212010-08-30 19:44:40 +0000420 m_use_external_editor = false;
Jim Inghame64f0dc2011-09-13 23:25:31 +0000421 m_wait_for = false;
422 m_process_name.erase();
423 m_process_pid = LLDB_INVALID_PROCESS_ID;
Greg Clayton66111032010-06-23 01:19:29 +0000424}
425
426void
427Driver::ResetOptionValues ()
428{
429 m_option_data.Clear ();
430}
431
432const char *
433Driver::GetFilename() const
434{
Greg Clayton8d846da2010-12-08 22:23:24 +0000435 if (m_option_data.m_args.empty())
Greg Clayton66111032010-06-23 01:19:29 +0000436 return NULL;
Greg Clayton8d846da2010-12-08 22:23:24 +0000437 return m_option_data.m_args.front().c_str();
Greg Clayton66111032010-06-23 01:19:29 +0000438}
439
440const char *
441Driver::GetCrashLogFilename() const
442{
443 if (m_option_data.m_crash_log.empty())
444 return NULL;
445 return m_option_data.m_crash_log.c_str();
446}
447
448lldb::ScriptLanguage
449Driver::GetScriptLanguage() const
450{
451 return m_option_data.m_script_lang;
452}
453
454size_t
455Driver::GetNumSourceCommandFiles () const
456{
457 return m_option_data.m_source_command_files.size();
458}
459
460const char *
461Driver::GetSourceCommandFileAtIndex (uint32_t idx) const
462{
463 if (idx < m_option_data.m_source_command_files.size())
464 return m_option_data.m_source_command_files[idx].c_str();
465 return NULL;
466}
467
468bool
469Driver::GetDebugMode() const
470{
471 return m_option_data.m_debug_mode;
472}
473
474
475// Check the arguments that were passed to this program to make sure they are valid and to get their
476// argument values (if any). Return a boolean value indicating whether or not to start up the full
477// debugger (i.e. the Command Interpreter) or not. Return FALSE if the arguments were invalid OR
478// if the user only wanted help or version information.
479
480SBError
481Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exit)
482{
483 ResetOptionValues ();
484
485 SBCommandReturnObject result;
486
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000487 SBError error;
488 std::string option_string;
489 struct option *long_options = NULL;
Caroline Tice4ab31c92010-10-12 21:57:09 +0000490 std::vector<struct option> long_options_vector;
Greg Claytonc982c762010-07-09 20:39:50 +0000491 uint32_t num_options;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000492
Greg Claytonc982c762010-07-09 20:39:50 +0000493 for (num_options = 0; g_options[num_options].long_option != NULL; ++num_options)
494 /* Do Nothing. */;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000495
496 if (num_options == 0)
497 {
498 if (argc > 1)
499 error.SetErrorStringWithFormat ("invalid number of options");
500 return error;
501 }
502
Caroline Tice4ab31c92010-10-12 21:57:09 +0000503 BuildGetOptTable (g_options, long_options_vector, num_options);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000504
Caroline Tice4ab31c92010-10-12 21:57:09 +0000505 if (long_options_vector.empty())
506 long_options = NULL;
507 else
508 long_options = &long_options_vector.front();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000509
510 if (long_options == NULL)
511 {
512 error.SetErrorStringWithFormat ("invalid long options");
513 return error;
514 }
515
Greg Claytonb7ad58a2013-04-04 20:35:24 +0000516 // Build the option_string argument for call to getopt_long_only.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000517
518 for (int i = 0; long_options[i].name != NULL; ++i)
519 {
520 if (long_options[i].flag == NULL)
521 {
522 option_string.push_back ((char) long_options[i].val);
523 switch (long_options[i].has_arg)
524 {
525 default:
526 case no_argument:
527 break;
528 case required_argument:
529 option_string.push_back (':');
530 break;
531 case optional_argument:
532 option_string.append ("::");
533 break;
534 }
535 }
536 }
537
Jim Ingham06942692011-08-13 00:22:20 +0000538 // This is kind of a pain, but since we make the debugger in the Driver's constructor, we can't
539 // know at that point whether we should read in init files yet. So we don't read them in in the
540 // Driver constructor, then set the flags back to "read them in" here, and then if we see the
541 // "-n" flag, we'll turn it off again. Finally we have to read them in by hand later in the
542 // main loop.
543
544 m_debugger.SkipLLDBInitFiles (false);
545 m_debugger.SkipAppInitFiles (false);
546
Greg Claytonb7ad58a2013-04-04 20:35:24 +0000547 // Prepare for & make calls to getopt_long_only.
Eli Friedmanadb35022010-06-13 19:18:49 +0000548#if __GLIBC__
549 optind = 0;
550#else
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000551 optreset = 1;
552 optind = 1;
Eli Friedmanadb35022010-06-13 19:18:49 +0000553#endif
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000554 int val;
555 while (1)
556 {
557 int long_options_index = -1;
Greg Claytonb7ad58a2013-04-04 20:35:24 +0000558 val = ::getopt_long_only (argc, const_cast<char **>(argv), option_string.c_str(), long_options, &long_options_index);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000559
560 if (val == -1)
561 break;
562 else if (val == '?')
563 {
Greg Clayton66111032010-06-23 01:19:29 +0000564 m_option_data.m_print_help = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000565 error.SetErrorStringWithFormat ("unknown or ambiguous option");
566 break;
567 }
568 else if (val == 0)
569 continue;
570 else
571 {
Greg Clayton66111032010-06-23 01:19:29 +0000572 m_option_data.m_seen_options.insert ((char) val);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000573 if (long_options_index == -1)
574 {
575 for (int i = 0;
576 long_options[i].name || long_options[i].has_arg || long_options[i].flag || long_options[i].val;
577 ++i)
578 {
579 if (long_options[i].val == val)
580 {
581 long_options_index = i;
582 break;
583 }
584 }
585 }
586
587 if (long_options_index >= 0)
588 {
Greg Clayton3bcdfc02012-12-04 00:32:51 +0000589 const int short_option = g_options[long_options_index].short_option;
Greg Clayton66111032010-06-23 01:19:29 +0000590
591 switch (short_option)
592 {
593 case 'h':
594 m_option_data.m_print_help = true;
595 break;
596
597 case 'v':
598 m_option_data.m_print_version = true;
599 break;
600
Jim Inghame2231ac2012-12-21 22:22:26 +0000601 case 'P':
602 m_option_data.m_print_python_path = true;
603 break;
604
Greg Clayton66111032010-06-23 01:19:29 +0000605 case 'c':
Johnny Cheneb46f782012-08-15 22:10:42 +0000606 {
607 SBFileSpec file(optarg);
608 if (file.Exists())
609 {
610 m_option_data.m_core_file = optarg;
611 }
612 else
613 error.SetErrorStringWithFormat("file specified in --core (-c) option doesn't exist: '%s'", optarg);
614 }
Greg Clayton66111032010-06-23 01:19:29 +0000615 break;
Johnny Cheneb46f782012-08-15 22:10:42 +0000616
Jim Inghame40e4212010-08-30 19:44:40 +0000617 case 'e':
618 m_option_data.m_use_external_editor = true;
619 break;
Greg Clayton6eee5aa2010-10-11 01:05:37 +0000620
Jim Inghame64f0dc2011-09-13 23:25:31 +0000621 case 'x':
Greg Clayton6eee5aa2010-10-11 01:05:37 +0000622 m_debugger.SkipLLDBInitFiles (true);
Jim Ingham06942692011-08-13 00:22:20 +0000623 m_debugger.SkipAppInitFiles (true);
Greg Clayton6eee5aa2010-10-11 01:05:37 +0000624 break;
625
Michael Sartainc3ce7f272013-05-23 20:47:45 +0000626 case 'o':
627 m_debugger.SetUseColor (false);
628 break;
629
Greg Clayton66111032010-06-23 01:19:29 +0000630 case 'f':
631 {
632 SBFileSpec file(optarg);
633 if (file.Exists())
Greg Clayton8d846da2010-12-08 22:23:24 +0000634 {
635 m_option_data.m_args.push_back (optarg);
636 }
Caroline Tice428a9a52010-09-10 04:48:55 +0000637 else if (file.ResolveExecutableLocation())
638 {
639 char path[PATH_MAX];
Johnny Chen25f3a3c2011-08-10 22:06:24 +0000640 file.GetPath (path, sizeof(path));
Greg Clayton8d846da2010-12-08 22:23:24 +0000641 m_option_data.m_args.push_back (path);
Caroline Tice428a9a52010-09-10 04:48:55 +0000642 }
Greg Clayton66111032010-06-23 01:19:29 +0000643 else
644 error.SetErrorStringWithFormat("file specified in --file (-f) option doesn't exist: '%s'", optarg);
645 }
646 break;
647
648 case 'a':
649 if (!m_debugger.SetDefaultArchitecture (optarg))
650 error.SetErrorStringWithFormat("invalid architecture in the -a or --arch option: '%s'", optarg);
651 break;
652
653 case 'l':
654 m_option_data.m_script_lang = m_debugger.GetScriptingLanguage (optarg);
655 break;
656
657 case 'd':
658 m_option_data.m_debug_mode = true;
659 break;
660
Jim Inghame64f0dc2011-09-13 23:25:31 +0000661 case 'n':
662 m_option_data.m_process_name = optarg;
663 break;
664
665 case 'w':
666 m_option_data.m_wait_for = true;
667 break;
668
669 case 'p':
670 {
671 char *remainder;
672 m_option_data.m_process_pid = strtol (optarg, &remainder, 0);
673 if (remainder == optarg || *remainder != '\0')
674 error.SetErrorStringWithFormat ("Could not convert process PID: \"%s\" into a pid.",
675 optarg);
676 }
677 break;
Greg Clayton66111032010-06-23 01:19:29 +0000678 case 's':
679 {
680 SBFileSpec file(optarg);
681 if (file.Exists())
682 m_option_data.m_source_command_files.push_back (optarg);
Caroline Tice428a9a52010-09-10 04:48:55 +0000683 else if (file.ResolveExecutableLocation())
684 {
685 char final_path[PATH_MAX];
Johnny Chen25f3a3c2011-08-10 22:06:24 +0000686 file.GetPath (final_path, sizeof(final_path));
Caroline Tice428a9a52010-09-10 04:48:55 +0000687 std::string path_str (final_path);
688 m_option_data.m_source_command_files.push_back (path_str);
689 }
Greg Clayton66111032010-06-23 01:19:29 +0000690 else
691 error.SetErrorStringWithFormat("file specified in --source (-s) option doesn't exist: '%s'", optarg);
692 }
693 break;
694
695 default:
696 m_option_data.m_print_help = true;
697 error.SetErrorStringWithFormat ("unrecognized option %c", short_option);
698 break;
699 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000700 }
701 else
702 {
703 error.SetErrorStringWithFormat ("invalid option with value %i", val);
704 }
705 if (error.Fail())
Caroline Tice4ab31c92010-10-12 21:57:09 +0000706 {
Greg Clayton66111032010-06-23 01:19:29 +0000707 return error;
Caroline Tice4ab31c92010-10-12 21:57:09 +0000708 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000709 }
710 }
Jim Ingham86511212010-06-15 18:47:14 +0000711
Greg Clayton66111032010-06-23 01:19:29 +0000712 if (error.Fail() || m_option_data.m_print_help)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000713 {
714 ShowUsage (out_fh, g_options, m_option_data);
Greg Claytone46dd322010-10-11 01:13:37 +0000715 exit = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000716 }
717 else if (m_option_data.m_print_version)
718 {
Greg Clayton66111032010-06-23 01:19:29 +0000719 ::fprintf (out_fh, "%s\n", m_debugger.GetVersionString());
720 exit = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000721 }
Jim Inghame2231ac2012-12-21 22:22:26 +0000722 else if (m_option_data.m_print_python_path)
723 {
724 SBFileSpec python_file_spec = SBHostOS::GetLLDBPythonPath();
725 if (python_file_spec.IsValid())
726 {
727 char python_path[PATH_MAX];
728 size_t num_chars = python_file_spec.GetPath(python_path, PATH_MAX);
729 if (num_chars < PATH_MAX)
730 {
731 ::fprintf (out_fh, "%s\n", python_path);
732 }
733 else
734 ::fprintf (out_fh, "<PATH TOO LONG>\n");
735 }
736 else
737 ::fprintf (out_fh, "<COULD NOT FIND PATH>\n");
738 exit = true;
739 }
Jim Inghame64f0dc2011-09-13 23:25:31 +0000740 else if (m_option_data.m_process_name.empty() && m_option_data.m_process_pid == LLDB_INVALID_PROCESS_ID)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000741 {
Greg Clayton8d846da2010-12-08 22:23:24 +0000742 // Any arguments that are left over after option parsing are for
743 // the program. If a file was specified with -f then the filename
744 // is already in the m_option_data.m_args array, and any remaining args
745 // are arguments for the inferior program. If no file was specified with
746 // -f, then what is left is the program name followed by any arguments.
747
Greg Claytonb7ad58a2013-04-04 20:35:24 +0000748 // Skip any options we consumed with getopt_long_only
Greg Clayton8d846da2010-12-08 22:23:24 +0000749 argc -= optind;
750 argv += optind;
751
752 if (argc > 0)
753 {
754 for (int arg_idx=0; arg_idx<argc; ++arg_idx)
755 {
756 const char *arg = argv[arg_idx];
757 if (arg)
758 m_option_data.m_args.push_back (arg);
759 }
760 }
761
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000762 }
Jim Inghame64f0dc2011-09-13 23:25:31 +0000763 else
764 {
Greg Claytonb7ad58a2013-04-04 20:35:24 +0000765 // Skip any options we consumed with getopt_long_only
Jim Inghame64f0dc2011-09-13 23:25:31 +0000766 argc -= optind;
Greg Clayton23f59502012-07-17 03:23:13 +0000767 //argv += optind; // Commented out to keep static analyzer happy
Jim Inghame64f0dc2011-09-13 23:25:31 +0000768
769 if (argc > 0)
770 ::fprintf (out_fh, "Warning: program arguments are ignored when attaching.\n");
771 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000772
Greg Clayton66111032010-06-23 01:19:29 +0000773 return error;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000774}
775
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000776size_t
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000777Driver::GetProcessSTDOUT ()
778{
779 // The process has stuff waiting for stdout; get it and write it out to the appropriate place.
780 char stdio_buffer[1024];
781 size_t len;
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000782 size_t total_bytes = 0;
Jim Ingham2976d002010-08-26 21:32:51 +0000783 while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0)
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000784 {
Greg Claytoneea37ee2013-05-14 17:36:51 +0000785 m_io_channel_ap->OutWrite (stdio_buffer, len, NO_ASYNC);
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000786 total_bytes += len;
787 }
788 return total_bytes;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000789}
790
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000791size_t
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000792Driver::GetProcessSTDERR ()
793{
794 // The process has stuff waiting for stderr; get it and write it out to the appropriate place.
795 char stdio_buffer[1024];
796 size_t len;
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000797 size_t total_bytes = 0;
Jim Ingham2976d002010-08-26 21:32:51 +0000798 while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0)
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000799 {
Greg Claytoneea37ee2013-05-14 17:36:51 +0000800 m_io_channel_ap->ErrWrite (stdio_buffer, len, NO_ASYNC);
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000801 total_bytes += len;
802 }
803 return total_bytes;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000804}
805
806void
Jim Ingham2976d002010-08-26 21:32:51 +0000807Driver::UpdateSelectedThread ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000808{
809 using namespace lldb;
Jim Ingham2976d002010-08-26 21:32:51 +0000810 SBProcess process(m_debugger.GetSelectedTarget().GetProcess());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000811 if (process.IsValid())
812 {
Jim Ingham2976d002010-08-26 21:32:51 +0000813 SBThread curr_thread (process.GetSelectedThread());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000814 SBThread thread;
815 StopReason curr_thread_stop_reason = eStopReasonInvalid;
816 curr_thread_stop_reason = curr_thread.GetStopReason();
817
818 if (!curr_thread.IsValid() ||
819 curr_thread_stop_reason == eStopReasonInvalid ||
820 curr_thread_stop_reason == eStopReasonNone)
821 {
822 // Prefer a thread that has just completed its plan over another thread as current thread.
823 SBThread plan_thread;
824 SBThread other_thread;
825 const size_t num_threads = process.GetNumThreads();
826 size_t i;
827 for (i = 0; i < num_threads; ++i)
828 {
829 thread = process.GetThreadAtIndex(i);
830 StopReason thread_stop_reason = thread.GetStopReason();
831 switch (thread_stop_reason)
832 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000833 case eStopReasonInvalid:
834 case eStopReasonNone:
835 break;
836
837 case eStopReasonTrace:
838 case eStopReasonBreakpoint:
839 case eStopReasonWatchpoint:
840 case eStopReasonSignal:
841 case eStopReasonException:
Greg Clayton90ba8112012-12-05 00:16:59 +0000842 case eStopReasonExec:
Andrew Kaylorf85defa2012-12-20 23:08:03 +0000843 case eStopReasonThreadExiting:
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000844 if (!other_thread.IsValid())
845 other_thread = thread;
846 break;
847 case eStopReasonPlanComplete:
848 if (!plan_thread.IsValid())
849 plan_thread = thread;
850 break;
851 }
852 }
853 if (plan_thread.IsValid())
Jim Ingham2976d002010-08-26 21:32:51 +0000854 process.SetSelectedThread (plan_thread);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000855 else if (other_thread.IsValid())
Jim Ingham2976d002010-08-26 21:32:51 +0000856 process.SetSelectedThread (other_thread);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000857 else
858 {
859 if (curr_thread.IsValid())
860 thread = curr_thread;
861 else
862 thread = process.GetThreadAtIndex(0);
863
864 if (thread.IsValid())
Jim Ingham2976d002010-08-26 21:32:51 +0000865 process.SetSelectedThread (thread);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000866 }
867 }
868 }
869}
870
Jim Inghame6bc6cb2012-02-08 05:23:15 +0000871// This function handles events that were broadcast by the process.
872void
873Driver::HandleBreakpointEvent (const SBEvent &event)
874{
875 using namespace lldb;
876 const uint32_t event_type = SBBreakpoint::GetBreakpointEventTypeFromEvent (event);
877
878 if (event_type & eBreakpointEventTypeAdded
879 || event_type & eBreakpointEventTypeRemoved
880 || event_type & eBreakpointEventTypeEnabled
881 || event_type & eBreakpointEventTypeDisabled
882 || event_type & eBreakpointEventTypeCommandChanged
883 || event_type & eBreakpointEventTypeConditionChanged
884 || event_type & eBreakpointEventTypeIgnoreChanged
885 || event_type & eBreakpointEventTypeLocationsResolved)
886 {
887 // Don't do anything about these events, since the breakpoint commands already echo these actions.
888 }
889 else if (event_type & eBreakpointEventTypeLocationsAdded)
890 {
891 char message[256];
892 uint32_t num_new_locations = SBBreakpoint::GetNumBreakpointLocationsFromEvent(event);
893 if (num_new_locations > 0)
894 {
895 SBBreakpoint breakpoint = SBBreakpoint::GetBreakpointFromEvent(event);
Jim Inghamfab10e82012-03-06 00:37:27 +0000896 int message_len = ::snprintf (message, sizeof(message), "%d location%s added to breakpoint %d\n",
Jim Inghame6bc6cb2012-02-08 05:23:15 +0000897 num_new_locations,
Jason Molenda65c28cb2012-09-28 01:50:47 +0000898 num_new_locations == 1 ? "" : "s",
Jim Inghame6bc6cb2012-02-08 05:23:15 +0000899 breakpoint.GetID());
900 m_io_channel_ap->OutWrite(message, message_len, ASYNC);
901 }
902 }
903 else if (event_type & eBreakpointEventTypeLocationsRemoved)
904 {
905 // These locations just get disabled, not sure it is worth spamming folks about this on the command line.
906 }
907 else if (event_type & eBreakpointEventTypeLocationsResolved)
908 {
909 // This might be an interesting thing to note, but I'm going to leave it quiet for now, it just looked noisy.
910 }
911}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000912
913// This function handles events that were broadcast by the process.
914void
915Driver::HandleProcessEvent (const SBEvent &event)
916{
917 using namespace lldb;
918 const uint32_t event_type = event.GetType();
919
920 if (event_type & SBProcess::eBroadcastBitSTDOUT)
921 {
922 // The process has stdout available, get it and write it out to the
923 // appropriate place.
Caroline Tice969ed3d2011-05-02 20:41:46 +0000924 GetProcessSTDOUT ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000925 }
926 else if (event_type & SBProcess::eBroadcastBitSTDERR)
927 {
928 // The process has stderr available, get it and write it out to the
929 // appropriate place.
Caroline Tice969ed3d2011-05-02 20:41:46 +0000930 GetProcessSTDERR ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000931 }
932 else if (event_type & SBProcess::eBroadcastBitStateChanged)
933 {
934 // Drain all stout and stderr so we don't see any output come after
935 // we print our prompts
Caroline Tice969ed3d2011-05-02 20:41:46 +0000936 GetProcessSTDOUT ();
937 GetProcessSTDERR ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000938 // Something changed in the process; get the event and report the process's current status and location to
939 // the user.
940 StateType event_state = SBProcess::GetStateFromEvent (event);
941 if (event_state == eStateInvalid)
942 return;
943
944 SBProcess process (SBProcess::GetProcessFromEvent (event));
945 assert (process.IsValid());
946
947 switch (event_state)
948 {
949 case eStateInvalid:
950 case eStateUnloaded:
Greg Claytonb766a732011-02-04 01:58:07 +0000951 case eStateConnected:
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000952 case eStateAttaching:
953 case eStateLaunching:
954 case eStateStepping:
955 case eStateDetached:
956 {
957 char message[1024];
Daniel Malead01b2952012-11-29 21:49:15 +0000958 int message_len = ::snprintf (message, sizeof(message), "Process %" PRIu64 " %s\n", process.GetProcessID(),
Greg Clayton66111032010-06-23 01:19:29 +0000959 m_debugger.StateAsCString (event_state));
Caroline Tice969ed3d2011-05-02 20:41:46 +0000960 m_io_channel_ap->OutWrite(message, message_len, ASYNC);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000961 }
962 break;
963
964 case eStateRunning:
965 // Don't be chatty when we run...
966 break;
967
968 case eStateExited:
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000969 {
970 SBCommandReturnObject result;
971 m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
Caroline Tice969ed3d2011-05-02 20:41:46 +0000972 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize(), ASYNC);
973 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize(), ASYNC);
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000974 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000975 break;
976
977 case eStateStopped:
978 case eStateCrashed:
979 case eStateSuspended:
980 // Make sure the program hasn't been auto-restarted:
981 if (SBProcess::GetRestartedFromEvent (event))
982 {
Jim Ingham0161b492013-02-09 01:29:05 +0000983 size_t num_reasons = SBProcess::GetNumRestartedReasonsFromEvent(event);
984 if (num_reasons > 0)
985 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000986 // FIXME: Do we want to report this, or would that just be annoyingly chatty?
Jim Ingham0161b492013-02-09 01:29:05 +0000987 if (num_reasons == 1)
988 {
989 char message[1024];
990 const char *reason = SBProcess::GetRestartedReasonAtIndexFromEvent (event, 0);
991 int message_len = ::snprintf (message, sizeof(message), "Process %" PRIu64 " stopped and restarted: %s\n",
992 process.GetProcessID(), reason ? reason : "<UNKNOWN REASON>");
993 m_io_channel_ap->OutWrite(message, message_len, ASYNC);
994 }
995 else
996 {
997 char message[1024];
998 int message_len = ::snprintf (message, sizeof(message), "Process %" PRIu64 " stopped and restarted, reasons:\n",
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000999 process.GetProcessID());
Jim Ingham0161b492013-02-09 01:29:05 +00001000 m_io_channel_ap->OutWrite(message, message_len, ASYNC);
1001 for (size_t i = 0; i < num_reasons; i++)
1002 {
1003 const char *reason = SBProcess::GetRestartedReasonAtIndexFromEvent (event, i);
1004 int message_len = ::snprintf(message, sizeof(message), "\t%s\n", reason ? reason : "<UNKNOWN REASON>");
1005 m_io_channel_ap->OutWrite(message, message_len, ASYNC);
1006 }
1007 }
1008 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001009 }
1010 else
1011 {
Jim Ingham8499e1a2012-05-08 23:06:07 +00001012 if (GetDebugger().GetSelectedTarget() == process.GetTarget())
1013 {
1014 SBCommandReturnObject result;
1015 UpdateSelectedThread ();
1016 m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
1017 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize(), ASYNC);
1018 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize(), ASYNC);
1019 }
1020 else
1021 {
1022 SBStream out_stream;
1023 uint32_t target_idx = GetDebugger().GetIndexOfTarget(process.GetTarget());
1024 if (target_idx != UINT32_MAX)
1025 out_stream.Printf ("Target %d: (", target_idx);
1026 else
1027 out_stream.Printf ("Target <unknown index>: (");
1028 process.GetTarget().GetDescription (out_stream, eDescriptionLevelBrief);
1029 out_stream.Printf (") stopped.\n");
1030 m_io_channel_ap->OutWrite (out_stream.GetData(), out_stream.GetSize(), ASYNC);
1031 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001032 }
1033 break;
1034 }
1035 }
1036}
1037
Jim Ingham4f465cf2012-10-10 18:32:14 +00001038void
1039Driver::HandleThreadEvent (const SBEvent &event)
1040{
1041 // At present the only thread event we handle is the Frame Changed event, and all we do for that is just
1042 // reprint the thread status for that thread.
1043 using namespace lldb;
1044 const uint32_t event_type = event.GetType();
Jim Inghamc3faa192012-12-11 02:31:48 +00001045 if (event_type == SBThread::eBroadcastBitStackChanged
1046 || event_type == SBThread::eBroadcastBitThreadSelected)
Jim Ingham4f465cf2012-10-10 18:32:14 +00001047 {
1048 SBThread thread = SBThread::GetThreadFromEvent (event);
1049 if (thread.IsValid())
1050 {
1051 SBStream out_stream;
1052 thread.GetStatus(out_stream);
1053 m_io_channel_ap->OutWrite (out_stream.GetData (), out_stream.GetSize (), ASYNC);
1054 }
1055 }
1056}
1057
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001058// This function handles events broadcast by the IOChannel (HasInput, UserInterrupt, or ThreadShouldExit).
1059
1060bool
1061Driver::HandleIOEvent (const SBEvent &event)
1062{
1063 bool quit = false;
1064
1065 const uint32_t event_type = event.GetType();
1066
1067 if (event_type & IOChannel::eBroadcastBitHasUserInput)
1068 {
1069 // We got some input (i.e. a command string) from the user; pass it off to the command interpreter for
1070 // handling.
1071
1072 const char *command_string = SBEvent::GetCStringFromEvent(event);
1073 if (command_string == NULL)
Greg Claytonc982c762010-07-09 20:39:50 +00001074 command_string = "";
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001075 SBCommandReturnObject result;
Jim Ingham85e8b812011-02-19 02:53:09 +00001076
Caroline Ticeb5059ac2011-05-16 19:20:50 +00001077 // We don't want the result to bypass the OutWrite function in IOChannel, as this can result in odd
1078 // output orderings and problems with the prompt.
Greg Claytoneea37ee2013-05-14 17:36:51 +00001079
1080 // Note that we are in the process of executing a command
1081 m_executing_user_command = true;
1082
Jim Ingham85e8b812011-02-19 02:53:09 +00001083 m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, true);
1084
Greg Claytoneea37ee2013-05-14 17:36:51 +00001085 // Note that we are back from executing a user command
1086 m_executing_user_command = false;
1087
1088 // Display any STDOUT/STDERR _prior_ to emitting the command result text
1089 GetProcessSTDOUT ();
1090 GetProcessSTDERR ();
1091
Enrico Granatacd4d24d2012-10-16 20:57:12 +00001092 const bool only_if_no_immediate = true;
1093
Greg Claytoneea37ee2013-05-14 17:36:51 +00001094 // Now emit the command output text from the command we just executed
Enrico Granata430e5402012-10-16 21:11:14 +00001095 const size_t output_size = result.GetOutputSize();
Enrico Granatacd4d24d2012-10-16 20:57:12 +00001096 if (output_size > 0)
1097 m_io_channel_ap->OutWrite (result.GetOutput(only_if_no_immediate), output_size, NO_ASYNC);
1098
Greg Claytoneea37ee2013-05-14 17:36:51 +00001099 // Now emit the command error text from the command we just executed
Enrico Granata430e5402012-10-16 21:11:14 +00001100 const size_t error_size = result.GetErrorSize();
Enrico Granatacd4d24d2012-10-16 20:57:12 +00001101 if (error_size > 0)
1102 m_io_channel_ap->OutWrite (result.GetError(only_if_no_immediate), error_size, NO_ASYNC);
Caroline Ticeb5059ac2011-05-16 19:20:50 +00001103
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001104 // We are done getting and running our command, we can now clear the
1105 // m_waiting_for_command so we can get another one.
1106 m_waiting_for_command = false;
1107
1108 // If our editline input reader is active, it means another input reader
1109 // got pushed onto the input reader and caused us to become deactivated.
1110 // When the input reader above us gets popped, we will get re-activated
1111 // and our prompt will refresh in our callback
1112 if (m_editline_reader.IsActive())
1113 {
1114 ReadyForCommand ();
1115 }
1116 }
1117 else if (event_type & IOChannel::eBroadcastBitUserInterrupt)
1118 {
1119 // This is here to handle control-c interrupts from the user. It has not yet really been implemented.
1120 // TO BE DONE: PROPERLY HANDLE CONTROL-C FROM USER
1121 //m_io_channel_ap->CancelInput();
1122 // Anything else? Send Interrupt to process?
1123 }
1124 else if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
1125 (event_type & IOChannel::eBroadcastBitThreadDidExit))
1126 {
1127 // If the IOChannel thread is trying to go away, then it is definitely
1128 // time to end the debugging session.
1129 quit = true;
1130 }
1131
1132 return quit;
1133}
1134
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001135void
1136Driver::MasterThreadBytesReceived (void *baton, const void *src, size_t src_len)
1137{
1138 Driver *driver = (Driver*)baton;
1139 driver->GetFromMaster ((const char *)src, src_len);
1140}
1141
1142void
1143Driver::GetFromMaster (const char *src, size_t src_len)
1144{
1145 // Echo the characters back to the Debugger's stdout, that way if you
1146 // type characters while a command is running, you'll see what you've typed.
Greg Clayton66111032010-06-23 01:19:29 +00001147 FILE *out_fh = m_debugger.GetOutputFileHandle();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001148 if (out_fh)
1149 ::fwrite (src, 1, src_len, out_fh);
1150}
1151
1152size_t
1153Driver::EditLineInputReaderCallback
1154(
1155 void *baton,
1156 SBInputReader *reader,
1157 InputReaderAction notification,
1158 const char *bytes,
1159 size_t bytes_len
1160)
1161{
1162 Driver *driver = (Driver *)baton;
1163
1164 switch (notification)
1165 {
1166 case eInputReaderActivate:
1167 break;
1168
1169 case eInputReaderReactivate:
Greg Claytoneea37ee2013-05-14 17:36:51 +00001170 if (driver->m_executing_user_command == false)
1171 driver->ReadyForCommand();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001172 break;
1173
1174 case eInputReaderDeactivate:
1175 break;
Caroline Tice969ed3d2011-05-02 20:41:46 +00001176
1177 case eInputReaderAsynchronousOutputWritten:
1178 if (driver->m_io_channel_ap.get() != NULL)
1179 driver->m_io_channel_ap->RefreshPrompt();
1180 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001181
Caroline Ticeefed6132010-11-19 20:47:54 +00001182 case eInputReaderInterrupt:
1183 if (driver->m_io_channel_ap.get() != NULL)
1184 {
Jim Inghamcfc09352012-07-27 23:57:19 +00001185 SBProcess process(driver->GetDebugger().GetSelectedTarget().GetProcess());
Jim Inghamd242f1c2012-06-01 01:07:02 +00001186 if (!driver->m_io_channel_ap->EditLineHasCharacters()
Jim Inghamcfc09352012-07-27 23:57:19 +00001187 && process.IsValid()
1188 && (process.GetState() == lldb::eStateRunning || process.GetState() == lldb::eStateAttaching))
Jim Inghamd242f1c2012-06-01 01:07:02 +00001189 {
Jim Inghamcfc09352012-07-27 23:57:19 +00001190 process.SendAsyncInterrupt ();
Jim Inghamd242f1c2012-06-01 01:07:02 +00001191 }
1192 else
1193 {
1194 driver->m_io_channel_ap->OutWrite ("^C\n", 3, NO_ASYNC);
1195 // I wish I could erase the entire input line, but there's no public API for that.
1196 driver->m_io_channel_ap->EraseCharsBeforeCursor();
1197 driver->m_io_channel_ap->RefreshPrompt();
1198 }
Caroline Ticeefed6132010-11-19 20:47:54 +00001199 }
1200 break;
1201
1202 case eInputReaderEndOfFile:
1203 if (driver->m_io_channel_ap.get() != NULL)
1204 {
Caroline Tice969ed3d2011-05-02 20:41:46 +00001205 driver->m_io_channel_ap->OutWrite ("^D\n", 3, NO_ASYNC);
Caroline Ticeefed6132010-11-19 20:47:54 +00001206 driver->m_io_channel_ap->RefreshPrompt ();
1207 }
1208 write (driver->m_editline_pty.GetMasterFileDescriptor(), "quit\n", 5);
1209 break;
1210
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001211 case eInputReaderGotToken:
1212 write (driver->m_editline_pty.GetMasterFileDescriptor(), bytes, bytes_len);
1213 break;
1214
1215 case eInputReaderDone:
1216 break;
1217 }
1218 return bytes_len;
1219}
1220
1221void
1222Driver::MainLoop ()
1223{
1224 char error_str[1024];
1225 if (m_editline_pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, error_str, sizeof(error_str)) == false)
1226 {
1227 ::fprintf (stderr, "error: failed to open driver pseudo terminal : %s", error_str);
1228 exit(1);
1229 }
1230 else
1231 {
1232 const char *driver_slave_name = m_editline_pty.GetSlaveName (error_str, sizeof(error_str));
1233 if (driver_slave_name == NULL)
1234 {
1235 ::fprintf (stderr, "error: failed to get slave name for driver pseudo terminal : %s", error_str);
1236 exit(2);
1237 }
1238 else
1239 {
1240 m_editline_slave_fh = ::fopen (driver_slave_name, "r+");
1241 if (m_editline_slave_fh == NULL)
1242 {
1243 SBError error;
1244 error.SetErrorToErrno();
1245 ::fprintf (stderr, "error: failed to get open slave for driver pseudo terminal : %s",
1246 error.GetCString());
1247 exit(3);
1248 }
1249
1250 ::setbuf (m_editline_slave_fh, NULL);
1251 }
1252 }
1253
Caroline Tice969ed3d2011-05-02 20:41:46 +00001254 lldb_utility::PseudoTerminal editline_output_pty;
1255 FILE *editline_output_slave_fh = NULL;
1256
1257 if (editline_output_pty.OpenFirstAvailableMaster (O_RDWR|O_NOCTTY, error_str, sizeof (error_str)) == false)
1258 {
1259 ::fprintf (stderr, "error: failed to open output pseudo terminal : %s", error_str);
1260 exit(1);
1261 }
1262 else
1263 {
1264 const char *output_slave_name = editline_output_pty.GetSlaveName (error_str, sizeof(error_str));
1265 if (output_slave_name == NULL)
1266 {
1267 ::fprintf (stderr, "error: failed to get slave name for output pseudo terminal : %s", error_str);
1268 exit(2);
1269 }
1270 else
1271 {
1272 editline_output_slave_fh = ::fopen (output_slave_name, "r+");
1273 if (editline_output_slave_fh == NULL)
1274 {
1275 SBError error;
1276 error.SetErrorToErrno();
1277 ::fprintf (stderr, "error: failed to get open slave for output pseudo terminal : %s",
1278 error.GetCString());
1279 exit(3);
1280 }
1281 ::setbuf (editline_output_slave_fh, NULL);
1282 }
1283 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001284
1285 // struct termios stdin_termios;
1286
1287 if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0)
Greg Claytonf571b892012-02-02 19:28:31 +00001288 {
1289 g_old_stdin_termios_is_valid = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001290 atexit (reset_stdin_termios);
Greg Claytonf571b892012-02-02 19:28:31 +00001291 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001292
1293 ::setbuf (stdin, NULL);
1294 ::setbuf (stdout, NULL);
1295
Greg Clayton66111032010-06-23 01:19:29 +00001296 m_debugger.SetErrorFileHandle (stderr, false);
1297 m_debugger.SetOutputFileHandle (stdout, false);
1298 m_debugger.SetInputFileHandle (stdin, true);
Jim Inghame40e4212010-08-30 19:44:40 +00001299
1300 m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001301
1302 // You have to drain anything that comes to the master side of the PTY. master_out_comm is
1303 // for that purpose. The reason you need to do this is a curious reason... editline will echo
1304 // characters to the PTY when it gets characters while el_gets is not running, and then when
1305 // you call el_gets (or el_getc) it will try to reset the terminal back to raw mode which blocks
1306 // if there are unconsumed characters in the out buffer.
1307 // However, you don't need to do anything with the characters, since editline will dump these
1308 // unconsumed characters after printing the prompt again in el_gets.
1309
Greg Claytond46c87a2010-12-04 02:39:47 +00001310 SBCommunication master_out_comm("driver.editline");
1311 master_out_comm.SetCloseOnEOF (false);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001312 master_out_comm.AdoptFileDesriptor(m_editline_pty.GetMasterFileDescriptor(), false);
1313 master_out_comm.SetReadThreadBytesReceivedCallback(Driver::MasterThreadBytesReceived, this);
1314
1315 if (master_out_comm.ReadThreadStart () == false)
1316 {
1317 ::fprintf (stderr, "error: failed to start master out read thread");
1318 exit(5);
1319 }
1320
Greg Clayton66111032010-06-23 01:19:29 +00001321 SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001322
Caroline Tice969ed3d2011-05-02 20:41:46 +00001323 m_io_channel_ap.reset (new IOChannel(m_editline_slave_fh, editline_output_slave_fh, stdout, stderr, this));
1324
1325 SBCommunication out_comm_2("driver.editline_output");
1326 out_comm_2.SetCloseOnEOF (false);
1327 out_comm_2.AdoptFileDesriptor (editline_output_pty.GetMasterFileDescriptor(), false);
1328 out_comm_2.SetReadThreadBytesReceivedCallback (IOChannel::LibeditOutputBytesReceived, m_io_channel_ap.get());
1329
1330 if (out_comm_2.ReadThreadStart () == false)
1331 {
1332 ::fprintf (stderr, "error: failed to start libedit output read thread");
1333 exit (5);
1334 }
1335
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001336
1337 struct winsize window_size;
1338 if (isatty (STDIN_FILENO)
1339 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
1340 {
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001341 if (window_size.ws_col > 0)
Greg Claytona7015092010-09-18 01:14:36 +00001342 m_debugger.SetTerminalWidth (window_size.ws_col);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001343 }
1344
1345 // Since input can be redirected by the debugger, we must insert our editline
1346 // input reader in the queue so we know when our reader should be active
1347 // and so we can receive bytes only when we are supposed to.
Greg Clayton66111032010-06-23 01:19:29 +00001348 SBError err (m_editline_reader.Initialize (m_debugger,
1349 Driver::EditLineInputReaderCallback, // callback
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001350 this, // baton
1351 eInputReaderGranularityByte, // token_size
1352 NULL, // end token - NULL means never done
1353 NULL, // prompt - taken care of elsewhere
1354 false)); // echo input - don't need Debugger
1355 // to do this, we handle it elsewhere
1356
1357 if (err.Fail())
1358 {
1359 ::fprintf (stderr, "error: %s", err.GetCString());
1360 exit (6);
1361 }
1362
Greg Clayton66111032010-06-23 01:19:29 +00001363 m_debugger.PushInputReader (m_editline_reader);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001364
Greg Clayton66111032010-06-23 01:19:29 +00001365 SBListener listener(m_debugger.GetListener());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001366 if (listener.IsValid())
1367 {
1368
Jim Ingham4f465cf2012-10-10 18:32:14 +00001369 listener.StartListeningForEventClass(m_debugger,
1370 SBTarget::GetBroadcasterClassName(),
1371 SBTarget::eBroadcastBitBreakpointChanged);
1372 listener.StartListeningForEventClass(m_debugger,
1373 SBThread::GetBroadcasterClassName(),
Jim Inghamc3faa192012-12-11 02:31:48 +00001374 SBThread::eBroadcastBitStackChanged |
1375 SBThread::eBroadcastBitThreadSelected);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001376 listener.StartListeningForEvents (*m_io_channel_ap,
1377 IOChannel::eBroadcastBitHasUserInput |
1378 IOChannel::eBroadcastBitUserInterrupt |
1379 IOChannel::eBroadcastBitThreadShouldExit |
1380 IOChannel::eBroadcastBitThreadDidStart |
1381 IOChannel::eBroadcastBitThreadDidExit);
1382
1383 if (m_io_channel_ap->Start ())
1384 {
1385 bool iochannel_thread_exited = false;
1386
1387 listener.StartListeningForEvents (sb_interpreter.GetBroadcaster(),
Caroline Tice86a73f92011-05-03 20:53:11 +00001388 SBCommandInterpreter::eBroadcastBitQuitCommandReceived |
1389 SBCommandInterpreter::eBroadcastBitAsynchronousOutputData |
1390 SBCommandInterpreter::eBroadcastBitAsynchronousErrorData);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001391
1392 // Before we handle any options from the command line, we parse the
1393 // .lldbinit file in the user's home directory.
1394 SBCommandReturnObject result;
1395 sb_interpreter.SourceInitFileInHomeDirectory(result);
1396 if (GetDebugMode())
1397 {
Greg Clayton66111032010-06-23 01:19:29 +00001398 result.PutError (m_debugger.GetErrorFileHandle());
1399 result.PutOutput (m_debugger.GetOutputFileHandle());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001400 }
1401
1402 // Now we handle options we got from the command line
1403 char command_string[PATH_MAX * 2];
1404 const size_t num_source_command_files = GetNumSourceCommandFiles();
Enrico Granataaa0c8ff2012-12-13 20:20:11 +00001405 const bool dump_stream_only_if_no_immediate = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001406 if (num_source_command_files > 0)
1407 {
1408 for (size_t i=0; i < num_source_command_files; ++i)
1409 {
1410 const char *command_file = GetSourceCommandFileAtIndex(i);
Johnny Chen85ffddc2010-07-28 21:16:11 +00001411 ::snprintf (command_string, sizeof(command_string), "command source '%s'", command_file);
Greg Clayton66111032010-06-23 01:19:29 +00001412 m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, false);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001413 if (GetDebugMode())
1414 {
Greg Clayton66111032010-06-23 01:19:29 +00001415 result.PutError (m_debugger.GetErrorFileHandle());
1416 result.PutOutput (m_debugger.GetOutputFileHandle());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001417 }
Enrico Granataaa0c8ff2012-12-13 20:20:11 +00001418
1419 // if the command sourcing generated an error - dump the result object
Enrico Granatadc3f4f92012-12-14 00:52:54 +00001420 if (result.Succeeded() == false)
Enrico Granataaa0c8ff2012-12-13 20:20:11 +00001421 {
1422 const size_t output_size = result.GetOutputSize();
1423 if (output_size > 0)
1424 m_io_channel_ap->OutWrite (result.GetOutput(dump_stream_only_if_no_immediate), output_size, NO_ASYNC);
Enrico Granatadc3f4f92012-12-14 00:52:54 +00001425 const size_t error_size = result.GetErrorSize();
1426 if (error_size > 0)
1427 m_io_channel_ap->OutWrite (result.GetError(dump_stream_only_if_no_immediate), error_size, NO_ASYNC);
Enrico Granataaa0c8ff2012-12-13 20:20:11 +00001428 }
1429
1430 result.Clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001431 }
1432 }
1433
Johnny Cheneb46f782012-08-15 22:10:42 +00001434 // Was there a core file specified?
1435 std::string core_file_spec("");
1436 if (!m_option_data.m_core_file.empty())
1437 core_file_spec.append("--core ").append(m_option_data.m_core_file);
1438
Greg Clayton8d846da2010-12-08 22:23:24 +00001439 const size_t num_args = m_option_data.m_args.size();
1440 if (num_args > 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001441 {
1442 char arch_name[64];
Greg Clayton66111032010-06-23 01:19:29 +00001443 if (m_debugger.GetDefaultArchitecture (arch_name, sizeof (arch_name)))
Greg Clayton8d846da2010-12-08 22:23:24 +00001444 ::snprintf (command_string,
1445 sizeof (command_string),
Johnny Cheneb46f782012-08-15 22:10:42 +00001446 "target create --arch=%s %s \"%s\"",
Greg Clayton8d846da2010-12-08 22:23:24 +00001447 arch_name,
Johnny Cheneb46f782012-08-15 22:10:42 +00001448 core_file_spec.c_str(),
Greg Clayton8d846da2010-12-08 22:23:24 +00001449 m_option_data.m_args[0].c_str());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001450 else
Greg Clayton8d846da2010-12-08 22:23:24 +00001451 ::snprintf (command_string,
1452 sizeof(command_string),
Johnny Cheneb46f782012-08-15 22:10:42 +00001453 "target create %s \"%s\"",
1454 core_file_spec.c_str(),
Greg Clayton8d846da2010-12-08 22:23:24 +00001455 m_option_data.m_args[0].c_str());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001456
Greg Clayton66111032010-06-23 01:19:29 +00001457 m_debugger.HandleCommand (command_string);
Greg Clayton8d846da2010-12-08 22:23:24 +00001458
1459 if (num_args > 1)
1460 {
Greg Clayton1d885962011-11-08 02:43:13 +00001461 m_debugger.HandleCommand ("settings clear target.run-args");
Greg Clayton8d846da2010-12-08 22:23:24 +00001462 char arg_cstr[1024];
1463 for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx)
1464 {
Jim Inghame64f0dc2011-09-13 23:25:31 +00001465 ::snprintf (arg_cstr,
1466 sizeof(arg_cstr),
Greg Clayton1d885962011-11-08 02:43:13 +00001467 "settings append target.run-args \"%s\"",
Jim Inghame64f0dc2011-09-13 23:25:31 +00001468 m_option_data.m_args[arg_idx].c_str());
Greg Clayton8d846da2010-12-08 22:23:24 +00001469 m_debugger.HandleCommand (arg_cstr);
1470 }
1471 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001472 }
Johnny Cheneb46f782012-08-15 22:10:42 +00001473 else if (!core_file_spec.empty())
1474 {
1475 ::snprintf (command_string,
1476 sizeof(command_string),
1477 "target create %s",
1478 core_file_spec.c_str());
1479 m_debugger.HandleCommand (command_string);;
1480 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001481
1482 // Now that all option parsing is done, we try and parse the .lldbinit
1483 // file in the current working directory
1484 sb_interpreter.SourceInitFileInCurrentWorkingDirectory (result);
1485 if (GetDebugMode())
1486 {
Greg Clayton66111032010-06-23 01:19:29 +00001487 result.PutError(m_debugger.GetErrorFileHandle());
1488 result.PutOutput(m_debugger.GetOutputFileHandle());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001489 }
1490
1491 SBEvent event;
1492
1493 // Make sure the IO channel is started up before we try to tell it we
1494 // are ready for input
1495 listener.WaitForEventForBroadcasterWithType (UINT32_MAX,
1496 *m_io_channel_ap,
1497 IOChannel::eBroadcastBitThreadDidStart,
1498 event);
Jim Inghame64f0dc2011-09-13 23:25:31 +00001499 // If we were asked to attach, then do that here:
1500 // I'm going to use the command string rather than directly
1501 // calling the API's because then I don't have to recode the
1502 // event handling here.
1503 if (!m_option_data.m_process_name.empty()
1504 || m_option_data.m_process_pid != LLDB_INVALID_PROCESS_ID)
1505 {
1506 std::string command_str("process attach ");
1507 if (m_option_data.m_process_pid != LLDB_INVALID_PROCESS_ID)
1508 {
1509 command_str.append("-p ");
1510 char pid_buffer[32];
Daniel Malead01b2952012-11-29 21:49:15 +00001511 ::snprintf (pid_buffer, sizeof(pid_buffer), "%" PRIu64, m_option_data.m_process_pid);
Jim Inghame64f0dc2011-09-13 23:25:31 +00001512 command_str.append(pid_buffer);
1513 }
1514 else
1515 {
1516 command_str.append("-n \"");
1517 command_str.append(m_option_data.m_process_name);
1518 command_str.push_back('\"');
1519 if (m_option_data.m_wait_for)
1520 command_str.append(" -w");
1521 }
1522
1523 if (m_debugger.GetOutputFileHandle())
1524 ::fprintf (m_debugger.GetOutputFileHandle(),
1525 "Attaching to process with:\n %s\n",
1526 command_str.c_str());
1527
1528 // Force the attach to be synchronous:
1529 bool orig_async = m_debugger.GetAsync();
1530 m_debugger.SetAsync(true);
1531 m_debugger.HandleCommand(command_str.c_str());
1532 m_debugger.SetAsync(orig_async);
1533 }
1534
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001535 ReadyForCommand ();
1536
Greg Claytona9f7b792012-02-29 04:21:24 +00001537 while (!GetIsDone())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001538 {
1539 listener.WaitForEvent (UINT32_MAX, event);
1540 if (event.IsValid())
1541 {
1542 if (event.GetBroadcaster().IsValid())
1543 {
1544 uint32_t event_type = event.GetType();
1545 if (event.BroadcasterMatchesRef (*m_io_channel_ap))
1546 {
1547 if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
1548 (event_type & IOChannel::eBroadcastBitThreadDidExit))
1549 {
Greg Claytona9f7b792012-02-29 04:21:24 +00001550 SetIsDone();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001551 if (event_type & IOChannel::eBroadcastBitThreadDidExit)
1552 iochannel_thread_exited = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001553 }
1554 else
Greg Claytona9f7b792012-02-29 04:21:24 +00001555 {
1556 if (HandleIOEvent (event))
1557 SetIsDone();
1558 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001559 }
Jim Inghame6bc6cb2012-02-08 05:23:15 +00001560 else if (SBProcess::EventIsProcessEvent (event))
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001561 {
1562 HandleProcessEvent (event);
1563 }
Jim Inghame6bc6cb2012-02-08 05:23:15 +00001564 else if (SBBreakpoint::EventIsBreakpointEvent (event))
1565 {
1566 HandleBreakpointEvent (event);
1567 }
Jim Ingham4f465cf2012-10-10 18:32:14 +00001568 else if (SBThread::EventIsThreadEvent (event))
1569 {
1570 HandleThreadEvent (event);
1571 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001572 else if (event.BroadcasterMatchesRef (sb_interpreter.GetBroadcaster()))
1573 {
Greg Claytona9f7b792012-02-29 04:21:24 +00001574 // TODO: deprecate the eBroadcastBitQuitCommandReceived event
1575 // now that we have SBCommandInterpreter::SetCommandOverrideCallback()
1576 // that can take over a command
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001577 if (event_type & SBCommandInterpreter::eBroadcastBitQuitCommandReceived)
Greg Clayton74d41932012-01-31 04:56:17 +00001578 {
Greg Claytona9f7b792012-02-29 04:21:24 +00001579 SetIsDone();
Greg Clayton74d41932012-01-31 04:56:17 +00001580 }
Caroline Tice86a73f92011-05-03 20:53:11 +00001581 else if (event_type & SBCommandInterpreter::eBroadcastBitAsynchronousErrorData)
1582 {
1583 const char *data = SBEvent::GetCStringFromEvent (event);
1584 m_io_channel_ap->ErrWrite (data, strlen(data), ASYNC);
1585 }
1586 else if (event_type & SBCommandInterpreter::eBroadcastBitAsynchronousOutputData)
1587 {
1588 const char *data = SBEvent::GetCStringFromEvent (event);
1589 m_io_channel_ap->OutWrite (data, strlen(data), ASYNC);
1590 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001591 }
1592 }
1593 }
1594 }
1595
Michael Sartain816cf1d2013-05-22 23:31:28 +00001596 master_out_comm.SetReadThreadBytesReceivedCallback(NULL, NULL);
Greg Claytonf571b892012-02-02 19:28:31 +00001597 master_out_comm.Disconnect();
Michael Sartain816cf1d2013-05-22 23:31:28 +00001598 master_out_comm.ReadThreadStop();
1599
1600 out_comm_2.SetReadThreadBytesReceivedCallback(NULL, NULL);
Greg Claytonf571b892012-02-02 19:28:31 +00001601 out_comm_2.Disconnect();
Michael Sartain816cf1d2013-05-22 23:31:28 +00001602 out_comm_2.ReadThreadStop();
1603
1604 editline_output_pty.CloseMasterFileDescriptor();
Greg Claytonf571b892012-02-02 19:28:31 +00001605 reset_stdin_termios();
1606 fclose (stdin);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001607
1608 CloseIOChannelFile ();
1609
1610 if (!iochannel_thread_exited)
1611 {
Greg Claytonb1320972010-07-14 00:18:15 +00001612 event.Clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001613 listener.GetNextEventForBroadcasterWithType (*m_io_channel_ap,
1614 IOChannel::eBroadcastBitThreadDidExit,
1615 event);
1616 if (!event.IsValid())
1617 {
1618 // Send end EOF to the driver file descriptor
1619 m_io_channel_ap->Stop();
1620 }
1621 }
1622
Jim Ingham12e9a202011-09-15 21:30:02 +00001623 SBDebugger::Destroy (m_debugger);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001624 }
1625 }
1626}
1627
1628
1629void
1630Driver::ReadyForCommand ()
1631{
1632 if (m_waiting_for_command == false)
1633 {
1634 m_waiting_for_command = true;
1635 BroadcastEventByType (Driver::eBroadcastBitReadyForInput, true);
1636 }
1637}
1638
Jim Inghamc46fe7c2013-02-22 22:56:55 +00001639void
1640Driver::ResizeWindow (unsigned short col)
1641{
1642 GetDebugger().SetTerminalWidth (col);
1643 if (m_io_channel_ap.get() != NULL)
1644 {
1645 m_io_channel_ap->ElResize();
1646 }
1647}
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001648
Caroline Ticedd759852010-09-09 17:45:09 +00001649void
1650sigwinch_handler (int signo)
1651{
1652 struct winsize window_size;
1653 if (isatty (STDIN_FILENO)
1654 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
1655 {
Jim Ingham57190ba2012-04-26 21:39:32 +00001656 if ((window_size.ws_col > 0) && g_driver != NULL)
Caroline Ticedd759852010-09-09 17:45:09 +00001657 {
Jim Inghamc46fe7c2013-02-22 22:56:55 +00001658 g_driver->ResizeWindow (window_size.ws_col);
Caroline Ticedd759852010-09-09 17:45:09 +00001659 }
1660 }
1661}
1662
Caroline Ticeefed6132010-11-19 20:47:54 +00001663void
1664sigint_handler (int signo)
1665{
1666 static bool g_interrupt_sent = false;
1667 if (g_driver)
1668 {
1669 if (!g_interrupt_sent)
1670 {
1671 g_interrupt_sent = true;
1672 g_driver->GetDebugger().DispatchInputInterrupt();
1673 g_interrupt_sent = false;
1674 return;
1675 }
1676 }
1677
1678 exit (signo);
1679}
1680
Jim Inghamc5917d92012-11-30 20:23:19 +00001681void
1682sigtstp_handler (int signo)
1683{
1684 g_driver->GetDebugger().SaveInputTerminalState();
1685 signal (signo, SIG_DFL);
1686 kill (getpid(), signo);
1687 signal (signo, sigtstp_handler);
1688}
1689
1690void
1691sigcont_handler (int signo)
1692{
1693 g_driver->GetDebugger().RestoreInputTerminalState();
1694 signal (signo, SIG_DFL);
1695 kill (getpid(), signo);
1696 signal (signo, sigcont_handler);
1697}
1698
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001699int
Jim Inghama462f5c2011-01-27 20:15:39 +00001700main (int argc, char const *argv[], const char *envp[])
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001701{
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001702 SBDebugger::Initialize();
1703
Greg Clayton2ccf8cf2010-11-07 21:02:03 +00001704 SBHostOS::ThreadCreated ("<lldb.driver.main-thread>");
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001705
Greg Clayton3fcbed62010-10-19 03:25:40 +00001706 signal (SIGPIPE, SIG_IGN);
Caroline Ticedd759852010-09-09 17:45:09 +00001707 signal (SIGWINCH, sigwinch_handler);
Caroline Ticeefed6132010-11-19 20:47:54 +00001708 signal (SIGINT, sigint_handler);
Jim Inghamc5917d92012-11-30 20:23:19 +00001709 signal (SIGTSTP, sigtstp_handler);
1710 signal (SIGCONT, sigcont_handler);
Caroline Ticedd759852010-09-09 17:45:09 +00001711
Greg Clayton66111032010-06-23 01:19:29 +00001712 // Create a scope for driver so that the driver object will destroy itself
1713 // before SBDebugger::Terminate() is called.
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001714 {
Greg Clayton66111032010-06-23 01:19:29 +00001715 Driver driver;
1716
1717 bool exit = false;
1718 SBError error (driver.ParseArgs (argc, argv, stdout, exit));
1719 if (error.Fail())
1720 {
1721 const char *error_cstr = error.GetCString ();
1722 if (error_cstr)
1723 ::fprintf (stderr, "error: %s\n", error_cstr);
1724 }
1725 else if (!exit)
1726 {
1727 driver.MainLoop ();
1728 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001729 }
1730
1731 SBDebugger::Terminate();
1732 return 0;
1733}