blob: 3c4deb9331708d3cbcc08fd61d1d7b766437904f [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>
Chris Lattner30fdc8d2010-06-08 16:52:24 +000021
22#include <string>
23
24#include "IOChannel.h"
Jim Inghame6bc6cb2012-02-08 05:23:15 +000025#include "lldb/API/SBBreakpoint.h"
Eli Friedmana382d472010-06-09 09:50:17 +000026#include "lldb/API/SBCommandInterpreter.h"
27#include "lldb/API/SBCommandReturnObject.h"
28#include "lldb/API/SBCommunication.h"
29#include "lldb/API/SBDebugger.h"
30#include "lldb/API/SBEvent.h"
31#include "lldb/API/SBHostOS.h"
32#include "lldb/API/SBListener.h"
Jim Ingham85e8b812011-02-19 02:53:09 +000033#include "lldb/API/SBStream.h"
Eli Friedmana382d472010-06-09 09:50:17 +000034#include "lldb/API/SBTarget.h"
35#include "lldb/API/SBThread.h"
36#include "lldb/API/SBProcess.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000037
38using namespace lldb;
39
40static void reset_stdin_termios ();
Greg Claytonf571b892012-02-02 19:28:31 +000041static bool g_old_stdin_termios_is_valid = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000042static struct termios g_old_stdin_termios;
43
Caroline Ticedd759852010-09-09 17:45:09 +000044static char *g_debugger_name = (char *) "";
Caroline Ticeefed6132010-11-19 20:47:54 +000045static Driver *g_driver = NULL;
Caroline Ticedd759852010-09-09 17:45:09 +000046
Chris Lattner30fdc8d2010-06-08 16:52:24 +000047// In the Driver::MainLoop, we change the terminal settings. This function is
48// added as an atexit handler to make sure we clean them up.
49static void
50reset_stdin_termios ()
51{
Greg Claytonf571b892012-02-02 19:28:31 +000052 if (g_old_stdin_termios_is_valid)
53 {
54 g_old_stdin_termios_is_valid = false;
55 ::tcsetattr (STDIN_FILENO, TCSANOW, &g_old_stdin_termios);
56 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +000057}
58
Greg Claytone0d378b2011-03-24 21:19:54 +000059typedef struct
Chris Lattner30fdc8d2010-06-08 16:52:24 +000060{
Greg Claytone0d378b2011-03-24 21:19:54 +000061 uint32_t usage_mask; // Used to mark options that can be used together. If (1 << n & usage_mask) != 0
62 // then this option belongs to option set n.
63 bool required; // This option is required (in the current usage level)
64 const char * long_option; // Full name for this option.
65 char short_option; // Single character for this option.
66 int option_has_arg; // no_argument, required_argument or optional_argument
Greg Claytonab65b342011-04-13 22:47:15 +000067 uint32_t completion_type; // Cookie the option class can use to do define the argument completion.
Greg Claytone0d378b2011-03-24 21:19:54 +000068 lldb::CommandArgumentType argument_type; // Type of argument this option takes
69 const char * usage_text; // Full text explaining what this options does and what (if any) argument to
70 // pass it.
71} OptionDefinition;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000072
Jim Inghame64f0dc2011-09-13 23:25:31 +000073#define LLDB_3_TO_5 LLDB_OPT_SET_3|LLDB_OPT_SET_4|LLDB_OPT_SET_5
74#define LLDB_4_TO_5 LLDB_OPT_SET_4|LLDB_OPT_SET_5
75
Greg Claytone0d378b2011-03-24 21:19:54 +000076static OptionDefinition g_options[] =
77{
Jim Ingham12e9a202011-09-15 21:30:02 +000078 { LLDB_OPT_SET_1, true , "help" , 'h', no_argument , NULL, eArgTypeNone,
79 "Prints out the usage information for the LLDB debugger." },
80 { LLDB_OPT_SET_2, true , "version" , 'v', no_argument , NULL, eArgTypeNone,
81 "Prints out the current version number of the LLDB debugger." },
82 { LLDB_OPT_SET_3, true , "arch" , 'a', required_argument, NULL, eArgTypeArchitecture,
83 "Tells the debugger to use the specified architecture when starting and running the program. <architecture> must "
84 "be one of the architectures for which the program was compiled." },
85 { LLDB_OPT_SET_3, true , "file" , 'f', required_argument, NULL, eArgTypeFilename,
86 "Tells the debugger to use the file <filename> as the program to be debugged." },
87 { LLDB_OPT_SET_4, true , "attach-name" , 'n', required_argument, NULL, eArgTypeProcessName,
88 "Tells the debugger to attach to a process with the given name." },
89 { LLDB_OPT_SET_4, true , "wait-for" , 'w', no_argument , NULL, eArgTypeNone,
90 "Tells the debugger to wait for a process with the given pid or name to launch before attaching." },
91 { LLDB_OPT_SET_5, true , "attach-pid" , 'p', required_argument, NULL, eArgTypePid,
92 "Tells the debugger to attach to a process with the given pid." },
93 { LLDB_3_TO_5, false, "script-language", 'l', required_argument, NULL, eArgTypeScriptLang,
94 "Tells the debugger to use the specified scripting language for user-defined scripts, rather than the default. "
95 "Valid scripting languages that can be specified include Python, Perl, Ruby and Tcl. Currently only the Python "
96 "extensions have been implemented." },
97 { LLDB_3_TO_5, false, "debug" , 'd', no_argument , NULL, eArgTypeNone,
98 "Tells the debugger to print out extra information for debugging itself." },
99 { LLDB_3_TO_5, false, "source" , 's', required_argument, NULL, eArgTypeFilename,
100 "Tells the debugger to read in and execute the file <file>, which should contain lldb commands." },
101 { LLDB_3_TO_5, false, "editor" , 'e', no_argument , NULL, eArgTypeNone,
102 "Tells the debugger to open source files using the host's \"external editor\" mechanism." },
103 { LLDB_3_TO_5, false, "no-lldbinit" , 'x', no_argument , NULL, eArgTypeNone,
104 "Do not automatically parse any '.lldbinit' files." },
Jim Inghame64f0dc2011-09-13 23:25:31 +0000105 { 0, false, NULL , 0 , 0 , NULL, eArgTypeNone, NULL }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000106};
107
Jim Inghame64f0dc2011-09-13 23:25:31 +0000108static const uint32_t last_option_set_with_args = 2;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000109
110Driver::Driver () :
111 SBBroadcaster ("Driver"),
Jim Ingham06942692011-08-13 00:22:20 +0000112 m_debugger (SBDebugger::Create(false)),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000113 m_editline_pty (),
114 m_editline_slave_fh (NULL),
115 m_editline_reader (),
116 m_io_channel_ap (),
117 m_option_data (),
118 m_waiting_for_command (false)
119{
Greg Claytonfc3f0272011-05-29 04:06:55 +0000120 // We want to be able to handle CTRL+D in the terminal to have it terminate
121 // certain input
122 m_debugger.SetCloseInputOnEOF (false);
Caroline Ticedd759852010-09-09 17:45:09 +0000123 g_debugger_name = (char *) m_debugger.GetInstanceName();
124 if (g_debugger_name == NULL)
125 g_debugger_name = (char *) "";
Caroline Ticeefed6132010-11-19 20:47:54 +0000126 g_driver = this;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000127}
128
129Driver::~Driver ()
130{
Caroline Ticeefed6132010-11-19 20:47:54 +0000131 g_driver = NULL;
132 g_debugger_name = NULL;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000133}
134
135void
136Driver::CloseIOChannelFile ()
137{
138 // Write and End of File sequence to the file descriptor to ensure any
139 // read functions can exit.
140 char eof_str[] = "\x04";
141 ::write (m_editline_pty.GetMasterFileDescriptor(), eof_str, strlen(eof_str));
142
143 m_editline_pty.CloseMasterFileDescriptor();
144
145 if (m_editline_slave_fh)
146 {
147 ::fclose (m_editline_slave_fh);
148 m_editline_slave_fh = NULL;
149 }
150}
151
Greg Claytonc982c762010-07-09 20:39:50 +0000152// This function takes INDENT, which tells how many spaces to output at the front
153// of each line; TEXT, which is the text that is to be output. It outputs the
154// text, on multiple lines if necessary, to RESULT, with INDENT spaces at the
155// front of each line. It breaks lines on spaces, tabs or newlines, shortening
156// the line if necessary to not break in the middle of a word. It assumes that
157// each output line should contain a maximum of OUTPUT_MAX_COLUMNS characters.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000158
159void
Greg Claytonc982c762010-07-09 20:39:50 +0000160OutputFormattedUsageText (FILE *out, int indent, const char *text, int output_max_columns)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000161{
162 int len = strlen (text);
163 std::string text_string (text);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000164
165 // Force indentation to be reasonable.
166 if (indent >= output_max_columns)
167 indent = 0;
168
169 // Will it all fit on one line?
170
171 if (len + indent < output_max_columns)
172 // Output as a single line
Greg Claytonc982c762010-07-09 20:39:50 +0000173 fprintf (out, "%*s%s\n", indent, "", text);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000174 else
175 {
176 // We need to break it up into multiple lines.
177 int text_width = output_max_columns - indent - 1;
178 int start = 0;
179 int end = start;
180 int final_end = len;
181 int sub_len;
182
183 while (end < final_end)
184 {
185 // Dont start the 'text' on a space, since we're already outputting the indentation.
186 while ((start < final_end) && (text[start] == ' '))
187 start++;
188
189 end = start + text_width;
190 if (end > final_end)
191 end = final_end;
192 else
193 {
194 // If we're not at the end of the text, make sure we break the line on white space.
195 while (end > start
196 && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
197 end--;
198 }
199 sub_len = end - start;
200 std::string substring = text_string.substr (start, sub_len);
Greg Claytonc982c762010-07-09 20:39:50 +0000201 fprintf (out, "%*s%s\n", indent, "", substring.c_str());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000202 start = end + 1;
203 }
204 }
205}
206
207void
Greg Claytone0d378b2011-03-24 21:19:54 +0000208ShowUsage (FILE *out, OptionDefinition *option_table, Driver::OptionData data)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000209{
210 uint32_t screen_width = 80;
211 uint32_t indent_level = 0;
212 const char *name = "lldb";
Jim Ingham86511212010-06-15 18:47:14 +0000213
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000214 fprintf (out, "\nUsage:\n\n");
215
216 indent_level += 2;
217
218
219 // First, show each usage level set of options, e.g. <cmd> [options-for-level-0]
220 // <cmd> [options-for-level-1]
221 // etc.
222
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000223 uint32_t num_options;
Jim Ingham86511212010-06-15 18:47:14 +0000224 uint32_t num_option_sets = 0;
225
226 for (num_options = 0; option_table[num_options].long_option != NULL; ++num_options)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000227 {
Jim Ingham86511212010-06-15 18:47:14 +0000228 uint32_t this_usage_mask = option_table[num_options].usage_mask;
229 if (this_usage_mask == LLDB_OPT_SET_ALL)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000230 {
Jim Ingham86511212010-06-15 18:47:14 +0000231 if (num_option_sets == 0)
232 num_option_sets = 1;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000233 }
234 else
235 {
Greg Claytonc982c762010-07-09 20:39:50 +0000236 for (uint32_t j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++)
Jim Ingham86511212010-06-15 18:47:14 +0000237 {
238 if (this_usage_mask & 1 << j)
239 {
240 if (num_option_sets <= j)
241 num_option_sets = j + 1;
242 }
243 }
244 }
245 }
246
247 for (uint32_t opt_set = 0; opt_set < num_option_sets; opt_set++)
248 {
249 uint32_t opt_set_mask;
250
251 opt_set_mask = 1 << opt_set;
252
253 if (opt_set > 0)
254 fprintf (out, "\n");
Greg Claytonc982c762010-07-09 20:39:50 +0000255 fprintf (out, "%*s%s", indent_level, "", name);
Jim Ingham556e6532011-08-16 23:15:02 +0000256 bool is_help_line = false;
Jim Ingham86511212010-06-15 18:47:14 +0000257
258 for (uint32_t i = 0; i < num_options; ++i)
259 {
260 if (option_table[i].usage_mask & opt_set_mask)
261 {
Caroline Ticedeaab222010-10-01 19:59:14 +0000262 CommandArgumentType arg_type = option_table[i].argument_type;
Greg Clayton9d0402b2011-02-20 02:15:07 +0000263 const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type);
Jim Ingham556e6532011-08-16 23:15:02 +0000264 // This is a bit of a hack, but there's no way to say certain options don't have arguments yet...
265 // so we do it by hand here.
266 if (option_table[i].short_option == 'h')
267 is_help_line = true;
268
Jim Ingham86511212010-06-15 18:47:14 +0000269 if (option_table[i].required)
270 {
271 if (option_table[i].option_has_arg == required_argument)
Greg Clayton9d0402b2011-02-20 02:15:07 +0000272 fprintf (out, " -%c <%s>", option_table[i].short_option, arg_name);
Jim Ingham86511212010-06-15 18:47:14 +0000273 else if (option_table[i].option_has_arg == optional_argument)
Greg Clayton9d0402b2011-02-20 02:15:07 +0000274 fprintf (out, " -%c [<%s>]", option_table[i].short_option, arg_name);
Jim Ingham86511212010-06-15 18:47:14 +0000275 else
276 fprintf (out, " -%c", option_table[i].short_option);
277 }
278 else
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 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000288 }
Jim Inghame64f0dc2011-09-13 23:25:31 +0000289 if (!is_help_line && (opt_set <= last_option_set_with_args))
Jim Ingham556e6532011-08-16 23:15:02 +0000290 fprintf (out, " [[--] <PROGRAM-ARG-1> [<PROGRAM_ARG-2> ...]]");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000291 }
292
293 fprintf (out, "\n\n");
294
295 // Now print out all the detailed information about the various options: long form, short form and help text:
296 // -- long_name <argument>
297 // - short <argument>
298 // help text
299
300 // This variable is used to keep track of which options' info we've printed out, because some options can be in
301 // more than one usage level, but we only want to print the long form of its information once.
302
303 Driver::OptionData::OptionSet options_seen;
304 Driver::OptionData::OptionSet::iterator pos;
305
306 indent_level += 5;
307
Jim Ingham86511212010-06-15 18:47:14 +0000308 for (uint32_t i = 0; i < num_options; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000309 {
310 // Only print this option if we haven't already seen it.
311 pos = options_seen.find (option_table[i].short_option);
312 if (pos == options_seen.end())
313 {
Caroline Ticedeaab222010-10-01 19:59:14 +0000314 CommandArgumentType arg_type = option_table[i].argument_type;
Greg Clayton9d0402b2011-02-20 02:15:07 +0000315 const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type);
Caroline Ticedeaab222010-10-01 19:59:14 +0000316
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000317 options_seen.insert (option_table[i].short_option);
Greg Claytonc982c762010-07-09 20:39:50 +0000318 fprintf (out, "%*s-%c ", indent_level, "", option_table[i].short_option);
Caroline Ticedeaab222010-10-01 19:59:14 +0000319 if (arg_type != eArgTypeNone)
Greg Clayton9d0402b2011-02-20 02:15:07 +0000320 fprintf (out, "<%s>", arg_name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000321 fprintf (out, "\n");
Greg Claytonc982c762010-07-09 20:39:50 +0000322 fprintf (out, "%*s--%s ", indent_level, "", option_table[i].long_option);
Caroline Ticedeaab222010-10-01 19:59:14 +0000323 if (arg_type != eArgTypeNone)
Greg Clayton9d0402b2011-02-20 02:15:07 +0000324 fprintf (out, "<%s>", arg_name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000325 fprintf (out, "\n");
326 indent_level += 5;
Greg Claytonc982c762010-07-09 20:39:50 +0000327 OutputFormattedUsageText (out, indent_level, option_table[i].usage_text, screen_width);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000328 indent_level -= 5;
329 fprintf (out, "\n");
330 }
331 }
332
333 indent_level -= 5;
334
Jim Inghama9deaf92011-08-16 23:57:58 +0000335 fprintf (out, "\n%*s(If you don't provide -f then the first argument will be the file to be debugged"
336 "\n%*s so '%s -- <filename> [<ARG1> [<ARG2>]]' also works."
337 "\n%*s Remember to end the options with \"--\" if any of your arguments have a \"-\" in them.)\n\n",
338 indent_level, "",
339 indent_level, "",
340 name,
341 indent_level, "");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000342}
343
344void
Greg Claytone0d378b2011-03-24 21:19:54 +0000345BuildGetOptTable (OptionDefinition *expanded_option_table, std::vector<struct option> &getopt_table,
Caroline Tice4ab31c92010-10-12 21:57:09 +0000346 uint32_t num_options)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000347{
348 if (num_options == 0)
349 return;
350
351 uint32_t i;
352 uint32_t j;
353 std::bitset<256> option_seen;
354
Caroline Tice4ab31c92010-10-12 21:57:09 +0000355 getopt_table.resize (num_options + 1);
356
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000357 for (i = 0, j = 0; i < num_options; ++i)
Greg Claytonc982c762010-07-09 20:39:50 +0000358 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000359 char short_opt = expanded_option_table[i].short_option;
Greg Claytonc982c762010-07-09 20:39:50 +0000360
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000361 if (option_seen.test(short_opt) == false)
Greg Claytonc982c762010-07-09 20:39:50 +0000362 {
Caroline Tice4ab31c92010-10-12 21:57:09 +0000363 getopt_table[j].name = expanded_option_table[i].long_option;
364 getopt_table[j].has_arg = expanded_option_table[i].option_has_arg;
365 getopt_table[j].flag = NULL;
366 getopt_table[j].val = expanded_option_table[i].short_option;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000367 option_seen.set(short_opt);
368 ++j;
Greg Claytonc982c762010-07-09 20:39:50 +0000369 }
370 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000371
Caroline Tice4ab31c92010-10-12 21:57:09 +0000372 getopt_table[j].name = NULL;
373 getopt_table[j].has_arg = 0;
374 getopt_table[j].flag = NULL;
375 getopt_table[j].val = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000376
377}
378
Greg Clayton66111032010-06-23 01:19:29 +0000379Driver::OptionData::OptionData () :
Greg Clayton8d846da2010-12-08 22:23:24 +0000380 m_args(),
Greg Clayton66111032010-06-23 01:19:29 +0000381 m_script_lang (lldb::eScriptLanguageDefault),
Greg Claytonc982c762010-07-09 20:39:50 +0000382 m_crash_log (),
Greg Clayton66111032010-06-23 01:19:29 +0000383 m_source_command_files (),
384 m_debug_mode (false),
Greg Claytonc982c762010-07-09 20:39:50 +0000385 m_print_version (false),
Greg Clayton66111032010-06-23 01:19:29 +0000386 m_print_help (false),
Jim Inghame64f0dc2011-09-13 23:25:31 +0000387 m_wait_for(false),
388 m_process_name(),
389 m_process_pid(LLDB_INVALID_PROCESS_ID),
Daniel Dunbara08823f2011-10-31 22:50:49 +0000390 m_use_external_editor(false),
Stephen Wilson71c21d12011-04-11 19:41:40 +0000391 m_seen_options()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000392{
Greg Clayton66111032010-06-23 01:19:29 +0000393}
394
395Driver::OptionData::~OptionData ()
396{
397}
398
399void
400Driver::OptionData::Clear ()
401{
Greg Clayton8d846da2010-12-08 22:23:24 +0000402 m_args.clear ();
Greg Clayton66111032010-06-23 01:19:29 +0000403 m_script_lang = lldb::eScriptLanguageDefault;
404 m_source_command_files.clear ();
405 m_debug_mode = false;
406 m_print_help = false;
407 m_print_version = false;
Jim Inghame40e4212010-08-30 19:44:40 +0000408 m_use_external_editor = false;
Jim Inghame64f0dc2011-09-13 23:25:31 +0000409 m_wait_for = false;
410 m_process_name.erase();
411 m_process_pid = LLDB_INVALID_PROCESS_ID;
Greg Clayton66111032010-06-23 01:19:29 +0000412}
413
414void
415Driver::ResetOptionValues ()
416{
417 m_option_data.Clear ();
418}
419
420const char *
421Driver::GetFilename() const
422{
Greg Clayton8d846da2010-12-08 22:23:24 +0000423 if (m_option_data.m_args.empty())
Greg Clayton66111032010-06-23 01:19:29 +0000424 return NULL;
Greg Clayton8d846da2010-12-08 22:23:24 +0000425 return m_option_data.m_args.front().c_str();
Greg Clayton66111032010-06-23 01:19:29 +0000426}
427
428const char *
429Driver::GetCrashLogFilename() const
430{
431 if (m_option_data.m_crash_log.empty())
432 return NULL;
433 return m_option_data.m_crash_log.c_str();
434}
435
436lldb::ScriptLanguage
437Driver::GetScriptLanguage() const
438{
439 return m_option_data.m_script_lang;
440}
441
442size_t
443Driver::GetNumSourceCommandFiles () const
444{
445 return m_option_data.m_source_command_files.size();
446}
447
448const char *
449Driver::GetSourceCommandFileAtIndex (uint32_t idx) const
450{
451 if (idx < m_option_data.m_source_command_files.size())
452 return m_option_data.m_source_command_files[idx].c_str();
453 return NULL;
454}
455
456bool
457Driver::GetDebugMode() const
458{
459 return m_option_data.m_debug_mode;
460}
461
462
463// Check the arguments that were passed to this program to make sure they are valid and to get their
464// argument values (if any). Return a boolean value indicating whether or not to start up the full
465// debugger (i.e. the Command Interpreter) or not. Return FALSE if the arguments were invalid OR
466// if the user only wanted help or version information.
467
468SBError
469Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exit)
470{
471 ResetOptionValues ();
472
473 SBCommandReturnObject result;
474
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000475 SBError error;
476 std::string option_string;
477 struct option *long_options = NULL;
Caroline Tice4ab31c92010-10-12 21:57:09 +0000478 std::vector<struct option> long_options_vector;
Greg Claytonc982c762010-07-09 20:39:50 +0000479 uint32_t num_options;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000480
Greg Claytonc982c762010-07-09 20:39:50 +0000481 for (num_options = 0; g_options[num_options].long_option != NULL; ++num_options)
482 /* Do Nothing. */;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000483
484 if (num_options == 0)
485 {
486 if (argc > 1)
487 error.SetErrorStringWithFormat ("invalid number of options");
488 return error;
489 }
490
Caroline Tice4ab31c92010-10-12 21:57:09 +0000491 BuildGetOptTable (g_options, long_options_vector, num_options);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000492
Caroline Tice4ab31c92010-10-12 21:57:09 +0000493 if (long_options_vector.empty())
494 long_options = NULL;
495 else
496 long_options = &long_options_vector.front();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000497
498 if (long_options == NULL)
499 {
500 error.SetErrorStringWithFormat ("invalid long options");
501 return error;
502 }
503
504 // Build the option_string argument for call to getopt_long.
505
506 for (int i = 0; long_options[i].name != NULL; ++i)
507 {
508 if (long_options[i].flag == NULL)
509 {
510 option_string.push_back ((char) long_options[i].val);
511 switch (long_options[i].has_arg)
512 {
513 default:
514 case no_argument:
515 break;
516 case required_argument:
517 option_string.push_back (':');
518 break;
519 case optional_argument:
520 option_string.append ("::");
521 break;
522 }
523 }
524 }
525
Jim Ingham06942692011-08-13 00:22:20 +0000526 // This is kind of a pain, but since we make the debugger in the Driver's constructor, we can't
527 // know at that point whether we should read in init files yet. So we don't read them in in the
528 // Driver constructor, then set the flags back to "read them in" here, and then if we see the
529 // "-n" flag, we'll turn it off again. Finally we have to read them in by hand later in the
530 // main loop.
531
532 m_debugger.SkipLLDBInitFiles (false);
533 m_debugger.SkipAppInitFiles (false);
534
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000535 // Prepare for & make calls to getopt_long.
Eli Friedmanadb35022010-06-13 19:18:49 +0000536#if __GLIBC__
537 optind = 0;
538#else
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000539 optreset = 1;
540 optind = 1;
Eli Friedmanadb35022010-06-13 19:18:49 +0000541#endif
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000542 int val;
543 while (1)
544 {
545 int long_options_index = -1;
Greg Claytonc982c762010-07-09 20:39:50 +0000546 val = ::getopt_long (argc, const_cast<char **>(argv), option_string.c_str(), long_options, &long_options_index);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000547
548 if (val == -1)
549 break;
550 else if (val == '?')
551 {
Greg Clayton66111032010-06-23 01:19:29 +0000552 m_option_data.m_print_help = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000553 error.SetErrorStringWithFormat ("unknown or ambiguous option");
554 break;
555 }
556 else if (val == 0)
557 continue;
558 else
559 {
Greg Clayton66111032010-06-23 01:19:29 +0000560 m_option_data.m_seen_options.insert ((char) val);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000561 if (long_options_index == -1)
562 {
563 for (int i = 0;
564 long_options[i].name || long_options[i].has_arg || long_options[i].flag || long_options[i].val;
565 ++i)
566 {
567 if (long_options[i].val == val)
568 {
569 long_options_index = i;
570 break;
571 }
572 }
573 }
574
575 if (long_options_index >= 0)
576 {
Greg Clayton66111032010-06-23 01:19:29 +0000577 const char short_option = (char) g_options[long_options_index].short_option;
578
579 switch (short_option)
580 {
581 case 'h':
582 m_option_data.m_print_help = true;
583 break;
584
585 case 'v':
586 m_option_data.m_print_version = true;
587 break;
588
589 case 'c':
590 m_option_data.m_crash_log = optarg;
591 break;
Greg Clayton6eee5aa2010-10-11 01:05:37 +0000592
Jim Inghame40e4212010-08-30 19:44:40 +0000593 case 'e':
594 m_option_data.m_use_external_editor = true;
595 break;
Greg Clayton6eee5aa2010-10-11 01:05:37 +0000596
Jim Inghame64f0dc2011-09-13 23:25:31 +0000597 case 'x':
Greg Clayton6eee5aa2010-10-11 01:05:37 +0000598 m_debugger.SkipLLDBInitFiles (true);
Jim Ingham06942692011-08-13 00:22:20 +0000599 m_debugger.SkipAppInitFiles (true);
Greg Clayton6eee5aa2010-10-11 01:05:37 +0000600 break;
601
Greg Clayton66111032010-06-23 01:19:29 +0000602 case 'f':
603 {
604 SBFileSpec file(optarg);
605 if (file.Exists())
Greg Clayton8d846da2010-12-08 22:23:24 +0000606 {
607 m_option_data.m_args.push_back (optarg);
608 }
Caroline Tice428a9a52010-09-10 04:48:55 +0000609 else if (file.ResolveExecutableLocation())
610 {
611 char path[PATH_MAX];
Johnny Chen25f3a3c2011-08-10 22:06:24 +0000612 file.GetPath (path, sizeof(path));
Greg Clayton8d846da2010-12-08 22:23:24 +0000613 m_option_data.m_args.push_back (path);
Caroline Tice428a9a52010-09-10 04:48:55 +0000614 }
Greg Clayton66111032010-06-23 01:19:29 +0000615 else
616 error.SetErrorStringWithFormat("file specified in --file (-f) option doesn't exist: '%s'", optarg);
617 }
618 break;
619
620 case 'a':
621 if (!m_debugger.SetDefaultArchitecture (optarg))
622 error.SetErrorStringWithFormat("invalid architecture in the -a or --arch option: '%s'", optarg);
623 break;
624
625 case 'l':
626 m_option_data.m_script_lang = m_debugger.GetScriptingLanguage (optarg);
627 break;
628
629 case 'd':
630 m_option_data.m_debug_mode = true;
631 break;
632
Jim Inghame64f0dc2011-09-13 23:25:31 +0000633 case 'n':
634 m_option_data.m_process_name = optarg;
635 break;
636
637 case 'w':
638 m_option_data.m_wait_for = true;
639 break;
640
641 case 'p':
642 {
643 char *remainder;
644 m_option_data.m_process_pid = strtol (optarg, &remainder, 0);
645 if (remainder == optarg || *remainder != '\0')
646 error.SetErrorStringWithFormat ("Could not convert process PID: \"%s\" into a pid.",
647 optarg);
648 }
649 break;
Greg Clayton66111032010-06-23 01:19:29 +0000650 case 's':
651 {
652 SBFileSpec file(optarg);
653 if (file.Exists())
654 m_option_data.m_source_command_files.push_back (optarg);
Caroline Tice428a9a52010-09-10 04:48:55 +0000655 else if (file.ResolveExecutableLocation())
656 {
657 char final_path[PATH_MAX];
Johnny Chen25f3a3c2011-08-10 22:06:24 +0000658 file.GetPath (final_path, sizeof(final_path));
Caroline Tice428a9a52010-09-10 04:48:55 +0000659 std::string path_str (final_path);
660 m_option_data.m_source_command_files.push_back (path_str);
661 }
Greg Clayton66111032010-06-23 01:19:29 +0000662 else
663 error.SetErrorStringWithFormat("file specified in --source (-s) option doesn't exist: '%s'", optarg);
664 }
665 break;
666
667 default:
668 m_option_data.m_print_help = true;
669 error.SetErrorStringWithFormat ("unrecognized option %c", short_option);
670 break;
671 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000672 }
673 else
674 {
675 error.SetErrorStringWithFormat ("invalid option with value %i", val);
676 }
677 if (error.Fail())
Caroline Tice4ab31c92010-10-12 21:57:09 +0000678 {
Greg Clayton66111032010-06-23 01:19:29 +0000679 return error;
Caroline Tice4ab31c92010-10-12 21:57:09 +0000680 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000681 }
682 }
Jim Ingham86511212010-06-15 18:47:14 +0000683
Greg Clayton66111032010-06-23 01:19:29 +0000684 if (error.Fail() || m_option_data.m_print_help)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000685 {
686 ShowUsage (out_fh, g_options, m_option_data);
Greg Claytone46dd322010-10-11 01:13:37 +0000687 exit = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000688 }
689 else if (m_option_data.m_print_version)
690 {
Greg Clayton66111032010-06-23 01:19:29 +0000691 ::fprintf (out_fh, "%s\n", m_debugger.GetVersionString());
692 exit = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000693 }
694 else if (! m_option_data.m_crash_log.empty())
695 {
696 // Handle crash log stuff here.
697 }
Jim Inghame64f0dc2011-09-13 23:25:31 +0000698 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 +0000699 {
Greg Clayton8d846da2010-12-08 22:23:24 +0000700 // Any arguments that are left over after option parsing are for
701 // the program. If a file was specified with -f then the filename
702 // is already in the m_option_data.m_args array, and any remaining args
703 // are arguments for the inferior program. If no file was specified with
704 // -f, then what is left is the program name followed by any arguments.
705
706 // Skip any options we consumed with getopt_long
707 argc -= optind;
708 argv += optind;
709
710 if (argc > 0)
711 {
712 for (int arg_idx=0; arg_idx<argc; ++arg_idx)
713 {
714 const char *arg = argv[arg_idx];
715 if (arg)
716 m_option_data.m_args.push_back (arg);
717 }
718 }
719
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000720 }
Jim Inghame64f0dc2011-09-13 23:25:31 +0000721 else
722 {
723 // Skip any options we consumed with getopt_long
724 argc -= optind;
725 argv += optind;
726
727 if (argc > 0)
728 ::fprintf (out_fh, "Warning: program arguments are ignored when attaching.\n");
729 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000730
Greg Clayton66111032010-06-23 01:19:29 +0000731 return error;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000732}
733
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000734size_t
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000735Driver::GetProcessSTDOUT ()
736{
737 // The process has stuff waiting for stdout; get it and write it out to the appropriate place.
738 char stdio_buffer[1024];
739 size_t len;
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000740 size_t total_bytes = 0;
Jim Ingham2976d002010-08-26 21:32:51 +0000741 while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0)
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000742 {
Caroline Tice969ed3d2011-05-02 20:41:46 +0000743 m_io_channel_ap->OutWrite (stdio_buffer, len, ASYNC);
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000744 total_bytes += len;
745 }
746 return total_bytes;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000747}
748
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000749size_t
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000750Driver::GetProcessSTDERR ()
751{
752 // The process has stuff waiting for stderr; get it and write it out to the appropriate place.
753 char stdio_buffer[1024];
754 size_t len;
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000755 size_t total_bytes = 0;
Jim Ingham2976d002010-08-26 21:32:51 +0000756 while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0)
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000757 {
Caroline Tice969ed3d2011-05-02 20:41:46 +0000758 m_io_channel_ap->ErrWrite (stdio_buffer, len, ASYNC);
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000759 total_bytes += len;
760 }
761 return total_bytes;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000762}
763
764void
Jim Ingham2976d002010-08-26 21:32:51 +0000765Driver::UpdateSelectedThread ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000766{
767 using namespace lldb;
Jim Ingham2976d002010-08-26 21:32:51 +0000768 SBProcess process(m_debugger.GetSelectedTarget().GetProcess());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000769 if (process.IsValid())
770 {
Jim Ingham2976d002010-08-26 21:32:51 +0000771 SBThread curr_thread (process.GetSelectedThread());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000772 SBThread thread;
773 StopReason curr_thread_stop_reason = eStopReasonInvalid;
774 curr_thread_stop_reason = curr_thread.GetStopReason();
775
776 if (!curr_thread.IsValid() ||
777 curr_thread_stop_reason == eStopReasonInvalid ||
778 curr_thread_stop_reason == eStopReasonNone)
779 {
780 // Prefer a thread that has just completed its plan over another thread as current thread.
781 SBThread plan_thread;
782 SBThread other_thread;
783 const size_t num_threads = process.GetNumThreads();
784 size_t i;
785 for (i = 0; i < num_threads; ++i)
786 {
787 thread = process.GetThreadAtIndex(i);
788 StopReason thread_stop_reason = thread.GetStopReason();
789 switch (thread_stop_reason)
790 {
791 default:
792 case eStopReasonInvalid:
793 case eStopReasonNone:
794 break;
795
796 case eStopReasonTrace:
797 case eStopReasonBreakpoint:
798 case eStopReasonWatchpoint:
799 case eStopReasonSignal:
800 case eStopReasonException:
801 if (!other_thread.IsValid())
802 other_thread = thread;
803 break;
804 case eStopReasonPlanComplete:
805 if (!plan_thread.IsValid())
806 plan_thread = thread;
807 break;
808 }
809 }
810 if (plan_thread.IsValid())
Jim Ingham2976d002010-08-26 21:32:51 +0000811 process.SetSelectedThread (plan_thread);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000812 else if (other_thread.IsValid())
Jim Ingham2976d002010-08-26 21:32:51 +0000813 process.SetSelectedThread (other_thread);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000814 else
815 {
816 if (curr_thread.IsValid())
817 thread = curr_thread;
818 else
819 thread = process.GetThreadAtIndex(0);
820
821 if (thread.IsValid())
Jim Ingham2976d002010-08-26 21:32:51 +0000822 process.SetSelectedThread (thread);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000823 }
824 }
825 }
826}
827
Jim Inghame6bc6cb2012-02-08 05:23:15 +0000828// This function handles events that were broadcast by the process.
829void
830Driver::HandleBreakpointEvent (const SBEvent &event)
831{
832 using namespace lldb;
833 const uint32_t event_type = SBBreakpoint::GetBreakpointEventTypeFromEvent (event);
834
835 if (event_type & eBreakpointEventTypeAdded
836 || event_type & eBreakpointEventTypeRemoved
837 || event_type & eBreakpointEventTypeEnabled
838 || event_type & eBreakpointEventTypeDisabled
839 || event_type & eBreakpointEventTypeCommandChanged
840 || event_type & eBreakpointEventTypeConditionChanged
841 || event_type & eBreakpointEventTypeIgnoreChanged
842 || event_type & eBreakpointEventTypeLocationsResolved)
843 {
844 // Don't do anything about these events, since the breakpoint commands already echo these actions.
845 }
846 else if (event_type & eBreakpointEventTypeLocationsAdded)
847 {
848 char message[256];
849 uint32_t num_new_locations = SBBreakpoint::GetNumBreakpointLocationsFromEvent(event);
850 if (num_new_locations > 0)
851 {
852 SBBreakpoint breakpoint = SBBreakpoint::GetBreakpointFromEvent(event);
Jim Inghamfab10e82012-03-06 00:37:27 +0000853 int message_len = ::snprintf (message, sizeof(message), "%d location%s added to breakpoint %d\n",
Jim Inghame6bc6cb2012-02-08 05:23:15 +0000854 num_new_locations,
Jim Inghamfab10e82012-03-06 00:37:27 +0000855 num_new_locations == 1 ? " " : "s ",
Jim Inghame6bc6cb2012-02-08 05:23:15 +0000856 breakpoint.GetID());
857 m_io_channel_ap->OutWrite(message, message_len, ASYNC);
858 }
859 }
860 else if (event_type & eBreakpointEventTypeLocationsRemoved)
861 {
862 // These locations just get disabled, not sure it is worth spamming folks about this on the command line.
863 }
864 else if (event_type & eBreakpointEventTypeLocationsResolved)
865 {
866 // This might be an interesting thing to note, but I'm going to leave it quiet for now, it just looked noisy.
867 }
868}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000869
870// This function handles events that were broadcast by the process.
871void
872Driver::HandleProcessEvent (const SBEvent &event)
873{
874 using namespace lldb;
875 const uint32_t event_type = event.GetType();
876
877 if (event_type & SBProcess::eBroadcastBitSTDOUT)
878 {
879 // The process has stdout available, get it and write it out to the
880 // appropriate place.
Caroline Tice969ed3d2011-05-02 20:41:46 +0000881 GetProcessSTDOUT ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000882 }
883 else if (event_type & SBProcess::eBroadcastBitSTDERR)
884 {
885 // The process has stderr available, get it and write it out to the
886 // appropriate place.
Caroline Tice969ed3d2011-05-02 20:41:46 +0000887 GetProcessSTDERR ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000888 }
889 else if (event_type & SBProcess::eBroadcastBitStateChanged)
890 {
891 // Drain all stout and stderr so we don't see any output come after
892 // we print our prompts
Caroline Tice969ed3d2011-05-02 20:41:46 +0000893 GetProcessSTDOUT ();
894 GetProcessSTDERR ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000895 // Something changed in the process; get the event and report the process's current status and location to
896 // the user.
897 StateType event_state = SBProcess::GetStateFromEvent (event);
898 if (event_state == eStateInvalid)
899 return;
900
901 SBProcess process (SBProcess::GetProcessFromEvent (event));
902 assert (process.IsValid());
903
904 switch (event_state)
905 {
906 case eStateInvalid:
907 case eStateUnloaded:
Greg Claytonb766a732011-02-04 01:58:07 +0000908 case eStateConnected:
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000909 case eStateAttaching:
910 case eStateLaunching:
911 case eStateStepping:
912 case eStateDetached:
913 {
914 char message[1024];
Greg Clayton61e7a582011-12-01 23:28:38 +0000915 int message_len = ::snprintf (message, sizeof(message), "Process %llu %s\n", process.GetProcessID(),
Greg Clayton66111032010-06-23 01:19:29 +0000916 m_debugger.StateAsCString (event_state));
Caroline Tice969ed3d2011-05-02 20:41:46 +0000917 m_io_channel_ap->OutWrite(message, message_len, ASYNC);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000918 }
919 break;
920
921 case eStateRunning:
922 // Don't be chatty when we run...
923 break;
924
925 case eStateExited:
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000926 {
927 SBCommandReturnObject result;
928 m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
Caroline Tice969ed3d2011-05-02 20:41:46 +0000929 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize(), ASYNC);
930 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize(), ASYNC);
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000931 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000932 break;
933
934 case eStateStopped:
935 case eStateCrashed:
936 case eStateSuspended:
937 // Make sure the program hasn't been auto-restarted:
938 if (SBProcess::GetRestartedFromEvent (event))
939 {
940 // FIXME: Do we want to report this, or would that just be annoyingly chatty?
941 char message[1024];
Greg Clayton61e7a582011-12-01 23:28:38 +0000942 int message_len = ::snprintf (message, sizeof(message), "Process %llu stopped and was programmatically restarted.\n",
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000943 process.GetProcessID());
Caroline Tice969ed3d2011-05-02 20:41:46 +0000944 m_io_channel_ap->OutWrite(message, message_len, ASYNC);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000945 }
946 else
947 {
Jim Ingham8499e1a2012-05-08 23:06:07 +0000948 if (GetDebugger().GetSelectedTarget() == process.GetTarget())
949 {
950 SBCommandReturnObject result;
951 UpdateSelectedThread ();
952 m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
953 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize(), ASYNC);
954 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize(), ASYNC);
955 }
956 else
957 {
958 SBStream out_stream;
959 uint32_t target_idx = GetDebugger().GetIndexOfTarget(process.GetTarget());
960 if (target_idx != UINT32_MAX)
961 out_stream.Printf ("Target %d: (", target_idx);
962 else
963 out_stream.Printf ("Target <unknown index>: (");
964 process.GetTarget().GetDescription (out_stream, eDescriptionLevelBrief);
965 out_stream.Printf (") stopped.\n");
966 m_io_channel_ap->OutWrite (out_stream.GetData(), out_stream.GetSize(), ASYNC);
967 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000968 }
969 break;
970 }
971 }
972}
973
974// This function handles events broadcast by the IOChannel (HasInput, UserInterrupt, or ThreadShouldExit).
975
976bool
977Driver::HandleIOEvent (const SBEvent &event)
978{
979 bool quit = false;
980
981 const uint32_t event_type = event.GetType();
982
983 if (event_type & IOChannel::eBroadcastBitHasUserInput)
984 {
985 // We got some input (i.e. a command string) from the user; pass it off to the command interpreter for
986 // handling.
987
988 const char *command_string = SBEvent::GetCStringFromEvent(event);
989 if (command_string == NULL)
Greg Claytonc982c762010-07-09 20:39:50 +0000990 command_string = "";
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000991 SBCommandReturnObject result;
Jim Ingham85e8b812011-02-19 02:53:09 +0000992
Caroline Ticeb5059ac2011-05-16 19:20:50 +0000993 // We don't want the result to bypass the OutWrite function in IOChannel, as this can result in odd
994 // output orderings and problems with the prompt.
Jim Ingham85e8b812011-02-19 02:53:09 +0000995 m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, true);
996
Caroline Ticeb5059ac2011-05-16 19:20:50 +0000997 if (result.GetOutputSize() > 0)
998 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize(), NO_ASYNC);
999
1000 if (result.GetErrorSize() > 0)
1001 m_io_channel_ap->OutWrite (result.GetError(), result.GetErrorSize(), NO_ASYNC);
1002
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001003 // We are done getting and running our command, we can now clear the
1004 // m_waiting_for_command so we can get another one.
1005 m_waiting_for_command = false;
1006
1007 // If our editline input reader is active, it means another input reader
1008 // got pushed onto the input reader and caused us to become deactivated.
1009 // When the input reader above us gets popped, we will get re-activated
1010 // and our prompt will refresh in our callback
1011 if (m_editline_reader.IsActive())
1012 {
1013 ReadyForCommand ();
1014 }
1015 }
1016 else if (event_type & IOChannel::eBroadcastBitUserInterrupt)
1017 {
1018 // This is here to handle control-c interrupts from the user. It has not yet really been implemented.
1019 // TO BE DONE: PROPERLY HANDLE CONTROL-C FROM USER
1020 //m_io_channel_ap->CancelInput();
1021 // Anything else? Send Interrupt to process?
1022 }
1023 else if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
1024 (event_type & IOChannel::eBroadcastBitThreadDidExit))
1025 {
1026 // If the IOChannel thread is trying to go away, then it is definitely
1027 // time to end the debugging session.
1028 quit = true;
1029 }
1030
1031 return quit;
1032}
1033
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001034void
1035Driver::MasterThreadBytesReceived (void *baton, const void *src, size_t src_len)
1036{
1037 Driver *driver = (Driver*)baton;
1038 driver->GetFromMaster ((const char *)src, src_len);
1039}
1040
1041void
1042Driver::GetFromMaster (const char *src, size_t src_len)
1043{
1044 // Echo the characters back to the Debugger's stdout, that way if you
1045 // type characters while a command is running, you'll see what you've typed.
Greg Clayton66111032010-06-23 01:19:29 +00001046 FILE *out_fh = m_debugger.GetOutputFileHandle();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001047 if (out_fh)
1048 ::fwrite (src, 1, src_len, out_fh);
1049}
1050
1051size_t
1052Driver::EditLineInputReaderCallback
1053(
1054 void *baton,
1055 SBInputReader *reader,
1056 InputReaderAction notification,
1057 const char *bytes,
1058 size_t bytes_len
1059)
1060{
1061 Driver *driver = (Driver *)baton;
1062
1063 switch (notification)
1064 {
1065 case eInputReaderActivate:
1066 break;
1067
1068 case eInputReaderReactivate:
1069 driver->ReadyForCommand();
1070 break;
1071
1072 case eInputReaderDeactivate:
1073 break;
Caroline Tice969ed3d2011-05-02 20:41:46 +00001074
1075 case eInputReaderAsynchronousOutputWritten:
1076 if (driver->m_io_channel_ap.get() != NULL)
1077 driver->m_io_channel_ap->RefreshPrompt();
1078 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001079
Caroline Ticeefed6132010-11-19 20:47:54 +00001080 case eInputReaderInterrupt:
1081 if (driver->m_io_channel_ap.get() != NULL)
1082 {
Caroline Tice969ed3d2011-05-02 20:41:46 +00001083 driver->m_io_channel_ap->OutWrite ("^C\n", 3, NO_ASYNC);
Caroline Ticeefed6132010-11-19 20:47:54 +00001084 driver->m_io_channel_ap->RefreshPrompt();
1085 }
1086 break;
1087
1088 case eInputReaderEndOfFile:
1089 if (driver->m_io_channel_ap.get() != NULL)
1090 {
Caroline Tice969ed3d2011-05-02 20:41:46 +00001091 driver->m_io_channel_ap->OutWrite ("^D\n", 3, NO_ASYNC);
Caroline Ticeefed6132010-11-19 20:47:54 +00001092 driver->m_io_channel_ap->RefreshPrompt ();
1093 }
1094 write (driver->m_editline_pty.GetMasterFileDescriptor(), "quit\n", 5);
1095 break;
1096
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001097 case eInputReaderGotToken:
1098 write (driver->m_editline_pty.GetMasterFileDescriptor(), bytes, bytes_len);
1099 break;
1100
1101 case eInputReaderDone:
1102 break;
1103 }
1104 return bytes_len;
1105}
1106
Greg Claytona9f7b792012-02-29 04:21:24 +00001107// Intercept when the quit command is called and tell our driver that it is done
1108static bool
1109QuitCommandOverrideCallback (void *baton, const char **argv)
1110{
1111 ((Driver *)baton)->SetIsDone();
1112 return true;
1113}
1114
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001115void
1116Driver::MainLoop ()
1117{
1118 char error_str[1024];
1119 if (m_editline_pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, error_str, sizeof(error_str)) == false)
1120 {
1121 ::fprintf (stderr, "error: failed to open driver pseudo terminal : %s", error_str);
1122 exit(1);
1123 }
1124 else
1125 {
1126 const char *driver_slave_name = m_editline_pty.GetSlaveName (error_str, sizeof(error_str));
1127 if (driver_slave_name == NULL)
1128 {
1129 ::fprintf (stderr, "error: failed to get slave name for driver pseudo terminal : %s", error_str);
1130 exit(2);
1131 }
1132 else
1133 {
1134 m_editline_slave_fh = ::fopen (driver_slave_name, "r+");
1135 if (m_editline_slave_fh == NULL)
1136 {
1137 SBError error;
1138 error.SetErrorToErrno();
1139 ::fprintf (stderr, "error: failed to get open slave for driver pseudo terminal : %s",
1140 error.GetCString());
1141 exit(3);
1142 }
1143
1144 ::setbuf (m_editline_slave_fh, NULL);
1145 }
1146 }
1147
Caroline Tice969ed3d2011-05-02 20:41:46 +00001148 lldb_utility::PseudoTerminal editline_output_pty;
1149 FILE *editline_output_slave_fh = NULL;
1150
1151 if (editline_output_pty.OpenFirstAvailableMaster (O_RDWR|O_NOCTTY, error_str, sizeof (error_str)) == false)
1152 {
1153 ::fprintf (stderr, "error: failed to open output pseudo terminal : %s", error_str);
1154 exit(1);
1155 }
1156 else
1157 {
1158 const char *output_slave_name = editline_output_pty.GetSlaveName (error_str, sizeof(error_str));
1159 if (output_slave_name == NULL)
1160 {
1161 ::fprintf (stderr, "error: failed to get slave name for output pseudo terminal : %s", error_str);
1162 exit(2);
1163 }
1164 else
1165 {
1166 editline_output_slave_fh = ::fopen (output_slave_name, "r+");
1167 if (editline_output_slave_fh == NULL)
1168 {
1169 SBError error;
1170 error.SetErrorToErrno();
1171 ::fprintf (stderr, "error: failed to get open slave for output pseudo terminal : %s",
1172 error.GetCString());
1173 exit(3);
1174 }
1175 ::setbuf (editline_output_slave_fh, NULL);
1176 }
1177 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001178
1179 // struct termios stdin_termios;
1180
1181 if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0)
Greg Claytonf571b892012-02-02 19:28:31 +00001182 {
1183 g_old_stdin_termios_is_valid = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001184 atexit (reset_stdin_termios);
Greg Claytonf571b892012-02-02 19:28:31 +00001185 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001186
1187 ::setbuf (stdin, NULL);
1188 ::setbuf (stdout, NULL);
1189
Greg Clayton66111032010-06-23 01:19:29 +00001190 m_debugger.SetErrorFileHandle (stderr, false);
1191 m_debugger.SetOutputFileHandle (stdout, false);
1192 m_debugger.SetInputFileHandle (stdin, true);
Jim Inghame40e4212010-08-30 19:44:40 +00001193
1194 m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001195
1196 // You have to drain anything that comes to the master side of the PTY. master_out_comm is
1197 // for that purpose. The reason you need to do this is a curious reason... editline will echo
1198 // characters to the PTY when it gets characters while el_gets is not running, and then when
1199 // you call el_gets (or el_getc) it will try to reset the terminal back to raw mode which blocks
1200 // if there are unconsumed characters in the out buffer.
1201 // However, you don't need to do anything with the characters, since editline will dump these
1202 // unconsumed characters after printing the prompt again in el_gets.
1203
Greg Claytond46c87a2010-12-04 02:39:47 +00001204 SBCommunication master_out_comm("driver.editline");
1205 master_out_comm.SetCloseOnEOF (false);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001206 master_out_comm.AdoptFileDesriptor(m_editline_pty.GetMasterFileDescriptor(), false);
1207 master_out_comm.SetReadThreadBytesReceivedCallback(Driver::MasterThreadBytesReceived, this);
1208
1209 if (master_out_comm.ReadThreadStart () == false)
1210 {
1211 ::fprintf (stderr, "error: failed to start master out read thread");
1212 exit(5);
1213 }
1214
Greg Clayton66111032010-06-23 01:19:29 +00001215 SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001216
Greg Claytona9f7b792012-02-29 04:21:24 +00001217 // Intercept when the quit command is called and tell our driver that it is done
1218 bool quit_success = sb_interpreter.SetCommandOverrideCallback ("quit", QuitCommandOverrideCallback, this);
1219 assert (quit_success);
1220
Caroline Tice969ed3d2011-05-02 20:41:46 +00001221 m_io_channel_ap.reset (new IOChannel(m_editline_slave_fh, editline_output_slave_fh, stdout, stderr, this));
1222
1223 SBCommunication out_comm_2("driver.editline_output");
1224 out_comm_2.SetCloseOnEOF (false);
1225 out_comm_2.AdoptFileDesriptor (editline_output_pty.GetMasterFileDescriptor(), false);
1226 out_comm_2.SetReadThreadBytesReceivedCallback (IOChannel::LibeditOutputBytesReceived, m_io_channel_ap.get());
1227
1228 if (out_comm_2.ReadThreadStart () == false)
1229 {
1230 ::fprintf (stderr, "error: failed to start libedit output read thread");
1231 exit (5);
1232 }
1233
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001234
1235 struct winsize window_size;
1236 if (isatty (STDIN_FILENO)
1237 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
1238 {
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001239 if (window_size.ws_col > 0)
Greg Claytona7015092010-09-18 01:14:36 +00001240 m_debugger.SetTerminalWidth (window_size.ws_col);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001241 }
1242
1243 // Since input can be redirected by the debugger, we must insert our editline
1244 // input reader in the queue so we know when our reader should be active
1245 // and so we can receive bytes only when we are supposed to.
Greg Clayton66111032010-06-23 01:19:29 +00001246 SBError err (m_editline_reader.Initialize (m_debugger,
1247 Driver::EditLineInputReaderCallback, // callback
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001248 this, // baton
1249 eInputReaderGranularityByte, // token_size
1250 NULL, // end token - NULL means never done
1251 NULL, // prompt - taken care of elsewhere
1252 false)); // echo input - don't need Debugger
1253 // to do this, we handle it elsewhere
1254
1255 if (err.Fail())
1256 {
1257 ::fprintf (stderr, "error: %s", err.GetCString());
1258 exit (6);
1259 }
1260
Greg Clayton66111032010-06-23 01:19:29 +00001261 m_debugger.PushInputReader (m_editline_reader);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001262
Greg Clayton66111032010-06-23 01:19:29 +00001263 SBListener listener(m_debugger.GetListener());
Jim Ingham4bddaeb2012-02-16 06:50:00 +00001264 listener.StartListeningForEventClass(m_debugger,
1265 SBTarget::GetBroadcasterClassName(),
1266 SBTarget::eBroadcastBitBreakpointChanged);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001267 if (listener.IsValid())
1268 {
1269
1270 listener.StartListeningForEvents (*m_io_channel_ap,
1271 IOChannel::eBroadcastBitHasUserInput |
1272 IOChannel::eBroadcastBitUserInterrupt |
1273 IOChannel::eBroadcastBitThreadShouldExit |
1274 IOChannel::eBroadcastBitThreadDidStart |
1275 IOChannel::eBroadcastBitThreadDidExit);
1276
1277 if (m_io_channel_ap->Start ())
1278 {
1279 bool iochannel_thread_exited = false;
1280
1281 listener.StartListeningForEvents (sb_interpreter.GetBroadcaster(),
Caroline Tice86a73f92011-05-03 20:53:11 +00001282 SBCommandInterpreter::eBroadcastBitQuitCommandReceived |
1283 SBCommandInterpreter::eBroadcastBitAsynchronousOutputData |
1284 SBCommandInterpreter::eBroadcastBitAsynchronousErrorData);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001285
1286 // Before we handle any options from the command line, we parse the
1287 // .lldbinit file in the user's home directory.
1288 SBCommandReturnObject result;
1289 sb_interpreter.SourceInitFileInHomeDirectory(result);
1290 if (GetDebugMode())
1291 {
Greg Clayton66111032010-06-23 01:19:29 +00001292 result.PutError (m_debugger.GetErrorFileHandle());
1293 result.PutOutput (m_debugger.GetOutputFileHandle());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001294 }
1295
1296 // Now we handle options we got from the command line
1297 char command_string[PATH_MAX * 2];
1298 const size_t num_source_command_files = GetNumSourceCommandFiles();
1299 if (num_source_command_files > 0)
1300 {
1301 for (size_t i=0; i < num_source_command_files; ++i)
1302 {
1303 const char *command_file = GetSourceCommandFileAtIndex(i);
Johnny Chen85ffddc2010-07-28 21:16:11 +00001304 ::snprintf (command_string, sizeof(command_string), "command source '%s'", command_file);
Greg Clayton66111032010-06-23 01:19:29 +00001305 m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, false);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001306 if (GetDebugMode())
1307 {
Greg Clayton66111032010-06-23 01:19:29 +00001308 result.PutError (m_debugger.GetErrorFileHandle());
1309 result.PutOutput (m_debugger.GetOutputFileHandle());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001310 }
1311 }
1312 }
1313
Greg Clayton8d846da2010-12-08 22:23:24 +00001314 const size_t num_args = m_option_data.m_args.size();
1315 if (num_args > 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001316 {
1317 char arch_name[64];
Greg Clayton66111032010-06-23 01:19:29 +00001318 if (m_debugger.GetDefaultArchitecture (arch_name, sizeof (arch_name)))
Greg Clayton8d846da2010-12-08 22:23:24 +00001319 ::snprintf (command_string,
1320 sizeof (command_string),
Greg Clayton7260f622011-04-18 08:33:37 +00001321 "target create --arch=%s '%s'",
Greg Clayton8d846da2010-12-08 22:23:24 +00001322 arch_name,
1323 m_option_data.m_args[0].c_str());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001324 else
Greg Clayton8d846da2010-12-08 22:23:24 +00001325 ::snprintf (command_string,
1326 sizeof(command_string),
Greg Clayton7260f622011-04-18 08:33:37 +00001327 "target create '%s'",
Greg Clayton8d846da2010-12-08 22:23:24 +00001328 m_option_data.m_args[0].c_str());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001329
Greg Clayton66111032010-06-23 01:19:29 +00001330 m_debugger.HandleCommand (command_string);
Greg Clayton8d846da2010-12-08 22:23:24 +00001331
1332 if (num_args > 1)
1333 {
Greg Clayton1d885962011-11-08 02:43:13 +00001334 m_debugger.HandleCommand ("settings clear target.run-args");
Greg Clayton8d846da2010-12-08 22:23:24 +00001335 char arg_cstr[1024];
1336 for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx)
1337 {
Jim Inghame64f0dc2011-09-13 23:25:31 +00001338 ::snprintf (arg_cstr,
1339 sizeof(arg_cstr),
Greg Clayton1d885962011-11-08 02:43:13 +00001340 "settings append target.run-args \"%s\"",
Jim Inghame64f0dc2011-09-13 23:25:31 +00001341 m_option_data.m_args[arg_idx].c_str());
Greg Clayton8d846da2010-12-08 22:23:24 +00001342 m_debugger.HandleCommand (arg_cstr);
1343 }
1344 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001345 }
1346
1347 // Now that all option parsing is done, we try and parse the .lldbinit
1348 // file in the current working directory
1349 sb_interpreter.SourceInitFileInCurrentWorkingDirectory (result);
1350 if (GetDebugMode())
1351 {
Greg Clayton66111032010-06-23 01:19:29 +00001352 result.PutError(m_debugger.GetErrorFileHandle());
1353 result.PutOutput(m_debugger.GetOutputFileHandle());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001354 }
1355
1356 SBEvent event;
1357
1358 // Make sure the IO channel is started up before we try to tell it we
1359 // are ready for input
1360 listener.WaitForEventForBroadcasterWithType (UINT32_MAX,
1361 *m_io_channel_ap,
1362 IOChannel::eBroadcastBitThreadDidStart,
1363 event);
Jim Inghame64f0dc2011-09-13 23:25:31 +00001364 // If we were asked to attach, then do that here:
1365 // I'm going to use the command string rather than directly
1366 // calling the API's because then I don't have to recode the
1367 // event handling here.
1368 if (!m_option_data.m_process_name.empty()
1369 || m_option_data.m_process_pid != LLDB_INVALID_PROCESS_ID)
1370 {
1371 std::string command_str("process attach ");
1372 if (m_option_data.m_process_pid != LLDB_INVALID_PROCESS_ID)
1373 {
1374 command_str.append("-p ");
1375 char pid_buffer[32];
Greg Clayton61e7a582011-12-01 23:28:38 +00001376 ::snprintf (pid_buffer, sizeof(pid_buffer), "%llu", m_option_data.m_process_pid);
Jim Inghame64f0dc2011-09-13 23:25:31 +00001377 command_str.append(pid_buffer);
1378 }
1379 else
1380 {
1381 command_str.append("-n \"");
1382 command_str.append(m_option_data.m_process_name);
1383 command_str.push_back('\"');
1384 if (m_option_data.m_wait_for)
1385 command_str.append(" -w");
1386 }
1387
1388 if (m_debugger.GetOutputFileHandle())
1389 ::fprintf (m_debugger.GetOutputFileHandle(),
1390 "Attaching to process with:\n %s\n",
1391 command_str.c_str());
1392
1393 // Force the attach to be synchronous:
1394 bool orig_async = m_debugger.GetAsync();
1395 m_debugger.SetAsync(true);
1396 m_debugger.HandleCommand(command_str.c_str());
1397 m_debugger.SetAsync(orig_async);
1398 }
1399
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001400 ReadyForCommand ();
1401
Greg Claytona9f7b792012-02-29 04:21:24 +00001402 while (!GetIsDone())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001403 {
1404 listener.WaitForEvent (UINT32_MAX, event);
1405 if (event.IsValid())
1406 {
1407 if (event.GetBroadcaster().IsValid())
1408 {
1409 uint32_t event_type = event.GetType();
1410 if (event.BroadcasterMatchesRef (*m_io_channel_ap))
1411 {
1412 if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
1413 (event_type & IOChannel::eBroadcastBitThreadDidExit))
1414 {
Greg Claytona9f7b792012-02-29 04:21:24 +00001415 SetIsDone();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001416 if (event_type & IOChannel::eBroadcastBitThreadDidExit)
1417 iochannel_thread_exited = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001418 }
1419 else
Greg Claytona9f7b792012-02-29 04:21:24 +00001420 {
1421 if (HandleIOEvent (event))
1422 SetIsDone();
1423 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001424 }
Jim Inghame6bc6cb2012-02-08 05:23:15 +00001425 else if (SBProcess::EventIsProcessEvent (event))
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001426 {
1427 HandleProcessEvent (event);
1428 }
Jim Inghame6bc6cb2012-02-08 05:23:15 +00001429 else if (SBBreakpoint::EventIsBreakpointEvent (event))
1430 {
1431 HandleBreakpointEvent (event);
1432 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001433 else if (event.BroadcasterMatchesRef (sb_interpreter.GetBroadcaster()))
1434 {
Greg Claytona9f7b792012-02-29 04:21:24 +00001435 // TODO: deprecate the eBroadcastBitQuitCommandReceived event
1436 // now that we have SBCommandInterpreter::SetCommandOverrideCallback()
1437 // that can take over a command
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001438 if (event_type & SBCommandInterpreter::eBroadcastBitQuitCommandReceived)
Greg Clayton74d41932012-01-31 04:56:17 +00001439 {
Greg Claytona9f7b792012-02-29 04:21:24 +00001440 SetIsDone();
Greg Clayton74d41932012-01-31 04:56:17 +00001441 }
Caroline Tice86a73f92011-05-03 20:53:11 +00001442 else if (event_type & SBCommandInterpreter::eBroadcastBitAsynchronousErrorData)
1443 {
1444 const char *data = SBEvent::GetCStringFromEvent (event);
1445 m_io_channel_ap->ErrWrite (data, strlen(data), ASYNC);
1446 }
1447 else if (event_type & SBCommandInterpreter::eBroadcastBitAsynchronousOutputData)
1448 {
1449 const char *data = SBEvent::GetCStringFromEvent (event);
1450 m_io_channel_ap->OutWrite (data, strlen(data), ASYNC);
1451 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001452 }
1453 }
1454 }
1455 }
1456
Greg Claytonf571b892012-02-02 19:28:31 +00001457 editline_output_pty.CloseMasterFileDescriptor();
1458 master_out_comm.Disconnect();
1459 out_comm_2.Disconnect();
1460 reset_stdin_termios();
1461 fclose (stdin);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001462
1463 CloseIOChannelFile ();
1464
1465 if (!iochannel_thread_exited)
1466 {
Greg Claytonb1320972010-07-14 00:18:15 +00001467 event.Clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001468 listener.GetNextEventForBroadcasterWithType (*m_io_channel_ap,
1469 IOChannel::eBroadcastBitThreadDidExit,
1470 event);
1471 if (!event.IsValid())
1472 {
1473 // Send end EOF to the driver file descriptor
1474 m_io_channel_ap->Stop();
1475 }
1476 }
1477
Jim Ingham12e9a202011-09-15 21:30:02 +00001478 SBDebugger::Destroy (m_debugger);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001479 }
1480 }
1481}
1482
1483
1484void
1485Driver::ReadyForCommand ()
1486{
1487 if (m_waiting_for_command == false)
1488 {
1489 m_waiting_for_command = true;
1490 BroadcastEventByType (Driver::eBroadcastBitReadyForInput, true);
1491 }
1492}
1493
1494
Caroline Ticedd759852010-09-09 17:45:09 +00001495void
1496sigwinch_handler (int signo)
1497{
1498 struct winsize window_size;
1499 if (isatty (STDIN_FILENO)
1500 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
1501 {
Jim Ingham57190ba2012-04-26 21:39:32 +00001502 if ((window_size.ws_col > 0) && g_driver != NULL)
Caroline Ticedd759852010-09-09 17:45:09 +00001503 {
Jim Ingham57190ba2012-04-26 21:39:32 +00001504 g_driver->GetDebugger().SetTerminalWidth (window_size.ws_col);
Caroline Ticedd759852010-09-09 17:45:09 +00001505 }
1506 }
1507}
1508
Caroline Ticeefed6132010-11-19 20:47:54 +00001509void
1510sigint_handler (int signo)
1511{
1512 static bool g_interrupt_sent = false;
1513 if (g_driver)
1514 {
1515 if (!g_interrupt_sent)
1516 {
1517 g_interrupt_sent = true;
1518 g_driver->GetDebugger().DispatchInputInterrupt();
1519 g_interrupt_sent = false;
1520 return;
1521 }
1522 }
1523
1524 exit (signo);
1525}
1526
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001527int
Jim Inghama462f5c2011-01-27 20:15:39 +00001528main (int argc, char const *argv[], const char *envp[])
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001529{
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001530 SBDebugger::Initialize();
1531
Greg Clayton2ccf8cf2010-11-07 21:02:03 +00001532 SBHostOS::ThreadCreated ("<lldb.driver.main-thread>");
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001533
Greg Clayton3fcbed62010-10-19 03:25:40 +00001534 signal (SIGPIPE, SIG_IGN);
Caroline Ticedd759852010-09-09 17:45:09 +00001535 signal (SIGWINCH, sigwinch_handler);
Caroline Ticeefed6132010-11-19 20:47:54 +00001536 signal (SIGINT, sigint_handler);
Caroline Ticedd759852010-09-09 17:45:09 +00001537
Greg Clayton66111032010-06-23 01:19:29 +00001538 // Create a scope for driver so that the driver object will destroy itself
1539 // before SBDebugger::Terminate() is called.
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001540 {
Greg Clayton66111032010-06-23 01:19:29 +00001541 Driver driver;
1542
1543 bool exit = false;
1544 SBError error (driver.ParseArgs (argc, argv, stdout, exit));
1545 if (error.Fail())
1546 {
1547 const char *error_cstr = error.GetCString ();
1548 if (error_cstr)
1549 ::fprintf (stderr, "error: %s\n", error_cstr);
1550 }
1551 else if (!exit)
1552 {
1553 driver.MainLoop ();
1554 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001555 }
1556
1557 SBDebugger::Terminate();
1558 return 0;
1559}