blob: 842d67df4001a61f4129eb553c0bbc8fbf23793e [file] [log] [blame]
Chris Lattner24943d22010-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 Friedmanf2f321d2010-06-09 09:50:17 +000017#include <string.h>
18#include <stdlib.h>
19#include <limits.h>
Eli Friedmand6e167d2010-06-09 19:11:30 +000020#include <fcntl.h>
Chris Lattner24943d22010-06-08 16:52:24 +000021
22#include <string>
23
24#include "IOChannel.h"
Eli Friedmanf2f321d2010-06-09 09:50:17 +000025#include "lldb/API/SBCommandInterpreter.h"
26#include "lldb/API/SBCommandReturnObject.h"
27#include "lldb/API/SBCommunication.h"
28#include "lldb/API/SBDebugger.h"
29#include "lldb/API/SBEvent.h"
30#include "lldb/API/SBHostOS.h"
31#include "lldb/API/SBListener.h"
32#include "lldb/API/SBSourceManager.h"
33#include "lldb/API/SBTarget.h"
34#include "lldb/API/SBThread.h"
35#include "lldb/API/SBProcess.h"
Chris Lattner24943d22010-06-08 16:52:24 +000036
37using namespace lldb;
38
39static void reset_stdin_termios ();
40static struct termios g_old_stdin_termios;
41
Caroline Ticeb8314fe2010-09-09 17:45:09 +000042static char *g_debugger_name = (char *) "";
43
Chris Lattner24943d22010-06-08 16:52:24 +000044// In the Driver::MainLoop, we change the terminal settings. This function is
45// added as an atexit handler to make sure we clean them up.
46static void
47reset_stdin_termios ()
48{
49 ::tcsetattr (STDIN_FILENO, TCSANOW, &g_old_stdin_termios);
50}
51
52static lldb::OptionDefinition g_options[] =
53{
Caroline Tice4d6675c2010-10-01 19:59:14 +000054 { LLDB_OPT_SET_1, true, "help", 'h', no_argument, NULL, NULL, eArgTypeNone,
Chris Lattner24943d22010-06-08 16:52:24 +000055 "Prints out the usage information for the LLDB debugger." },
56
Caroline Tice4d6675c2010-10-01 19:59:14 +000057 { LLDB_OPT_SET_2, true, "version", 'v', no_argument, NULL, NULL, eArgTypeNone,
Chris Lattner24943d22010-06-08 16:52:24 +000058 "Prints out the current version number of the LLDB debugger." },
59
Caroline Tice4d6675c2010-10-01 19:59:14 +000060 { LLDB_OPT_SET_3, true, "arch", 'a', required_argument, NULL, NULL, eArgTypeArchitecture,
Chris Lattner24943d22010-06-08 16:52:24 +000061 "Tells the debugger to use the specified architecture when starting and running the program. <architecture> must be one of the architectures for which the program was compiled." },
62
Caroline Tice4d6675c2010-10-01 19:59:14 +000063 { LLDB_OPT_SET_3 | LLDB_OPT_SET_4, false, "script-language",'l', required_argument, NULL, NULL, eArgTypeScriptLang,
Chris Lattner24943d22010-06-08 16:52:24 +000064 "Tells the debugger to use the specified scripting language for user-defined scripts, rather than the default. Valid scripting languages that can be specified include Python, Perl, Ruby and Tcl. Currently only the Python extensions have been implemented." },
65
Caroline Tice4d6675c2010-10-01 19:59:14 +000066 { LLDB_OPT_SET_3 | LLDB_OPT_SET_4, false, "debug", 'd', no_argument, NULL, NULL, eArgTypeNone,
Chris Lattner24943d22010-06-08 16:52:24 +000067 "Tells the debugger to print out extra information for debugging itself." },
68
Caroline Tice4d6675c2010-10-01 19:59:14 +000069 { LLDB_OPT_SET_3 | LLDB_OPT_SET_4, false, "source", 's', required_argument, NULL, NULL, eArgTypeFilename,
Chris Lattner24943d22010-06-08 16:52:24 +000070 "Tells the debugger to read in and execute the file <file>, which should contain lldb commands." },
71
Caroline Tice4d6675c2010-10-01 19:59:14 +000072 { LLDB_OPT_SET_3, true, "file", 'f', required_argument, NULL, NULL, eArgTypeFilename,
Jim Ingham34e9a982010-06-15 18:47:14 +000073 "Tells the debugger to use the file <filename> as the program to be debugged." },
74
Caroline Tice4d6675c2010-10-01 19:59:14 +000075 { LLDB_OPT_SET_ALL, false, "editor", 'e', no_argument, NULL, NULL, eArgTypeNone,
Jim Ingham74989e82010-08-30 19:44:40 +000076 "Tells the debugger to open source files using the host's \"external editor\" mechanism." },
77
Caroline Tice4d6675c2010-10-01 19:59:14 +000078// { LLDB_OPT_SET_4, true, "crash-log", 'c', required_argument, NULL, NULL, eArgTypeFilename,
Greg Clayton12bec712010-06-28 21:30:43 +000079// "Load executable images from a crash log for symbolication." },
Chris Lattner24943d22010-06-08 16:52:24 +000080
Caroline Tice4d6675c2010-10-01 19:59:14 +000081 { 0, false, NULL, 0, 0, NULL, NULL, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +000082};
83
84
85Driver::Driver () :
86 SBBroadcaster ("Driver"),
Greg Clayton63094e02010-06-23 01:19:29 +000087 m_debugger (SBDebugger::Create()),
Chris Lattner24943d22010-06-08 16:52:24 +000088 m_editline_pty (),
89 m_editline_slave_fh (NULL),
90 m_editline_reader (),
91 m_io_channel_ap (),
92 m_option_data (),
93 m_waiting_for_command (false)
94{
Caroline Ticeb8314fe2010-09-09 17:45:09 +000095 g_debugger_name = (char *) m_debugger.GetInstanceName();
96 if (g_debugger_name == NULL)
97 g_debugger_name = (char *) "";
Chris Lattner24943d22010-06-08 16:52:24 +000098}
99
100Driver::~Driver ()
101{
102}
103
104void
105Driver::CloseIOChannelFile ()
106{
107 // Write and End of File sequence to the file descriptor to ensure any
108 // read functions can exit.
109 char eof_str[] = "\x04";
110 ::write (m_editline_pty.GetMasterFileDescriptor(), eof_str, strlen(eof_str));
111
112 m_editline_pty.CloseMasterFileDescriptor();
113
114 if (m_editline_slave_fh)
115 {
116 ::fclose (m_editline_slave_fh);
117 m_editline_slave_fh = NULL;
118 }
119}
120
Greg Clayton54e7afa2010-07-09 20:39:50 +0000121// This function takes INDENT, which tells how many spaces to output at the front
122// of each line; TEXT, which is the text that is to be output. It outputs the
123// text, on multiple lines if necessary, to RESULT, with INDENT spaces at the
124// front of each line. It breaks lines on spaces, tabs or newlines, shortening
125// the line if necessary to not break in the middle of a word. It assumes that
126// each output line should contain a maximum of OUTPUT_MAX_COLUMNS characters.
Chris Lattner24943d22010-06-08 16:52:24 +0000127
128void
Greg Clayton54e7afa2010-07-09 20:39:50 +0000129OutputFormattedUsageText (FILE *out, int indent, const char *text, int output_max_columns)
Chris Lattner24943d22010-06-08 16:52:24 +0000130{
131 int len = strlen (text);
132 std::string text_string (text);
Chris Lattner24943d22010-06-08 16:52:24 +0000133
134 // Force indentation to be reasonable.
135 if (indent >= output_max_columns)
136 indent = 0;
137
138 // Will it all fit on one line?
139
140 if (len + indent < output_max_columns)
141 // Output as a single line
Greg Clayton54e7afa2010-07-09 20:39:50 +0000142 fprintf (out, "%*s%s\n", indent, "", text);
Chris Lattner24943d22010-06-08 16:52:24 +0000143 else
144 {
145 // We need to break it up into multiple lines.
146 int text_width = output_max_columns - indent - 1;
147 int start = 0;
148 int end = start;
149 int final_end = len;
150 int sub_len;
151
152 while (end < final_end)
153 {
154 // Dont start the 'text' on a space, since we're already outputting the indentation.
155 while ((start < final_end) && (text[start] == ' '))
156 start++;
157
158 end = start + text_width;
159 if (end > final_end)
160 end = final_end;
161 else
162 {
163 // If we're not at the end of the text, make sure we break the line on white space.
164 while (end > start
165 && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
166 end--;
167 }
168 sub_len = end - start;
169 std::string substring = text_string.substr (start, sub_len);
Greg Clayton54e7afa2010-07-09 20:39:50 +0000170 fprintf (out, "%*s%s\n", indent, "", substring.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000171 start = end + 1;
172 }
173 }
174}
175
Caroline Tice4d6675c2010-10-01 19:59:14 +0000176void
177GetArgumentName (const CommandArgumentType arg_type, std::string &arg_name)
178{
179 //Fudge this function here, since we can't call the "real" version in lldb_private::CommandObject...
180
181 switch (arg_type)
182 {
183 // Make cases for all the arg_types used in Driver.cpp
184
185 case eArgTypeNone:
186 arg_name = "";
187 break;
188
189 case eArgTypeArchitecture:
190 arg_name = "architecture";
191 break;
192
193 case eArgTypeScriptLang:
194 arg_name = "script-language";
195 break;
196
197 case eArgTypeFilename:
198 arg_name = "filename";
199 break;
200 }
201 return;
202}
203
204
Chris Lattner24943d22010-06-08 16:52:24 +0000205void
206ShowUsage (FILE *out, lldb::OptionDefinition *option_table, Driver::OptionData data)
207{
208 uint32_t screen_width = 80;
209 uint32_t indent_level = 0;
210 const char *name = "lldb";
Jim Ingham34e9a982010-06-15 18:47:14 +0000211
Chris Lattner24943d22010-06-08 16:52:24 +0000212 fprintf (out, "\nUsage:\n\n");
213
214 indent_level += 2;
215
216
217 // First, show each usage level set of options, e.g. <cmd> [options-for-level-0]
218 // <cmd> [options-for-level-1]
219 // etc.
220
Chris Lattner24943d22010-06-08 16:52:24 +0000221 uint32_t num_options;
Jim Ingham34e9a982010-06-15 18:47:14 +0000222 uint32_t num_option_sets = 0;
223
224 for (num_options = 0; option_table[num_options].long_option != NULL; ++num_options)
Chris Lattner24943d22010-06-08 16:52:24 +0000225 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000226 uint32_t this_usage_mask = option_table[num_options].usage_mask;
227 if (this_usage_mask == LLDB_OPT_SET_ALL)
Chris Lattner24943d22010-06-08 16:52:24 +0000228 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000229 if (num_option_sets == 0)
230 num_option_sets = 1;
Chris Lattner24943d22010-06-08 16:52:24 +0000231 }
232 else
233 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000234 for (uint32_t j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++)
Jim Ingham34e9a982010-06-15 18:47:14 +0000235 {
236 if (this_usage_mask & 1 << j)
237 {
238 if (num_option_sets <= j)
239 num_option_sets = j + 1;
240 }
241 }
242 }
243 }
244
245 for (uint32_t opt_set = 0; opt_set < num_option_sets; opt_set++)
246 {
247 uint32_t opt_set_mask;
248
249 opt_set_mask = 1 << opt_set;
250
251 if (opt_set > 0)
252 fprintf (out, "\n");
Greg Clayton54e7afa2010-07-09 20:39:50 +0000253 fprintf (out, "%*s%s", indent_level, "", name);
Jim Ingham34e9a982010-06-15 18:47:14 +0000254
255 for (uint32_t i = 0; i < num_options; ++i)
256 {
257 if (option_table[i].usage_mask & opt_set_mask)
258 {
Caroline Tice4d6675c2010-10-01 19:59:14 +0000259 CommandArgumentType arg_type = option_table[i].argument_type;
260 std::string arg_name;
261 GetArgumentName (arg_type, arg_name);
Jim Ingham34e9a982010-06-15 18:47:14 +0000262 if (option_table[i].required)
263 {
264 if (option_table[i].option_has_arg == required_argument)
Caroline Tice4d6675c2010-10-01 19:59:14 +0000265 fprintf (out, " -%c <%s>", option_table[i].short_option, arg_name.c_str());
Jim Ingham34e9a982010-06-15 18:47:14 +0000266 else if (option_table[i].option_has_arg == optional_argument)
Caroline Tice4d6675c2010-10-01 19:59:14 +0000267 fprintf (out, " -%c [<%s>]", option_table[i].short_option, arg_name.c_str());
Jim Ingham34e9a982010-06-15 18:47:14 +0000268 else
269 fprintf (out, " -%c", option_table[i].short_option);
270 }
271 else
272 {
273 if (option_table[i].option_has_arg == required_argument)
Caroline Tice4d6675c2010-10-01 19:59:14 +0000274 fprintf (out, " [-%c <%s>]", option_table[i].short_option, arg_name.c_str());
Jim Ingham34e9a982010-06-15 18:47:14 +0000275 else if (option_table[i].option_has_arg == optional_argument)
Caroline Tice4d6675c2010-10-01 19:59:14 +0000276 fprintf (out, " [-%c [<%s>]]", option_table[i].short_option, arg_name.c_str());
Jim Ingham34e9a982010-06-15 18:47:14 +0000277 else
278 fprintf (out, " [-%c]", option_table[i].short_option);
279 }
280 }
Chris Lattner24943d22010-06-08 16:52:24 +0000281 }
282 }
283
284 fprintf (out, "\n\n");
285
286 // Now print out all the detailed information about the various options: long form, short form and help text:
287 // -- long_name <argument>
288 // - short <argument>
289 // help text
290
291 // This variable is used to keep track of which options' info we've printed out, because some options can be in
292 // more than one usage level, but we only want to print the long form of its information once.
293
294 Driver::OptionData::OptionSet options_seen;
295 Driver::OptionData::OptionSet::iterator pos;
296
297 indent_level += 5;
298
Jim Ingham34e9a982010-06-15 18:47:14 +0000299 for (uint32_t i = 0; i < num_options; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000300 {
301 // Only print this option if we haven't already seen it.
302 pos = options_seen.find (option_table[i].short_option);
303 if (pos == options_seen.end())
304 {
Caroline Tice4d6675c2010-10-01 19:59:14 +0000305 CommandArgumentType arg_type = option_table[i].argument_type;
306 std::string arg_name;
307 GetArgumentName (arg_type, arg_name);
308
Chris Lattner24943d22010-06-08 16:52:24 +0000309 options_seen.insert (option_table[i].short_option);
Greg Clayton54e7afa2010-07-09 20:39:50 +0000310 fprintf (out, "%*s-%c ", indent_level, "", option_table[i].short_option);
Caroline Tice4d6675c2010-10-01 19:59:14 +0000311 if (arg_type != eArgTypeNone)
312 fprintf (out, "<%s>", arg_name.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000313 fprintf (out, "\n");
Greg Clayton54e7afa2010-07-09 20:39:50 +0000314 fprintf (out, "%*s--%s ", indent_level, "", option_table[i].long_option);
Caroline Tice4d6675c2010-10-01 19:59:14 +0000315 if (arg_type != eArgTypeNone)
316 fprintf (out, "<%s>", arg_name.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000317 fprintf (out, "\n");
318 indent_level += 5;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000319 OutputFormattedUsageText (out, indent_level, option_table[i].usage_text, screen_width);
Chris Lattner24943d22010-06-08 16:52:24 +0000320 indent_level -= 5;
321 fprintf (out, "\n");
322 }
323 }
324
325 indent_level -= 5;
326
Greg Clayton54e7afa2010-07-09 20:39:50 +0000327 fprintf (out, "\n%*s('%s <filename>' also works, to specify the file to be debugged.)\n\n",
328 indent_level, "", name);
Chris Lattner24943d22010-06-08 16:52:24 +0000329}
330
331void
Greg Clayton54e7afa2010-07-09 20:39:50 +0000332BuildGetOptTable (lldb::OptionDefinition *expanded_option_table, struct option **getopt_table, uint32_t num_options)
Chris Lattner24943d22010-06-08 16:52:24 +0000333{
334 if (num_options == 0)
335 return;
336
337 uint32_t i;
338 uint32_t j;
339 std::bitset<256> option_seen;
340
341 for (i = 0, j = 0; i < num_options; ++i)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000342 {
Chris Lattner24943d22010-06-08 16:52:24 +0000343 char short_opt = expanded_option_table[i].short_option;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000344
Chris Lattner24943d22010-06-08 16:52:24 +0000345 if (option_seen.test(short_opt) == false)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000346 {
Chris Lattner24943d22010-06-08 16:52:24 +0000347 (*getopt_table)[j].name = expanded_option_table[i].long_option;
348 (*getopt_table)[j].has_arg = expanded_option_table[i].option_has_arg;
349 (*getopt_table)[j].flag = NULL;
350 (*getopt_table)[j].val = expanded_option_table[i].short_option;
351 option_seen.set(short_opt);
352 ++j;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000353 }
354 }
Chris Lattner24943d22010-06-08 16:52:24 +0000355
356 (*getopt_table)[j].name = NULL;
357 (*getopt_table)[j].has_arg = 0;
358 (*getopt_table)[j].flag = NULL;
359 (*getopt_table)[j].val = 0;
360
361}
362
Greg Clayton63094e02010-06-23 01:19:29 +0000363Driver::OptionData::OptionData () :
364 m_filename(),
365 m_script_lang (lldb::eScriptLanguageDefault),
Greg Clayton54e7afa2010-07-09 20:39:50 +0000366 m_crash_log (),
Greg Clayton63094e02010-06-23 01:19:29 +0000367 m_source_command_files (),
368 m_debug_mode (false),
Greg Clayton54e7afa2010-07-09 20:39:50 +0000369 m_print_version (false),
Greg Clayton63094e02010-06-23 01:19:29 +0000370 m_print_help (false),
Jim Ingham74989e82010-08-30 19:44:40 +0000371 m_seen_options(),
372 m_use_external_editor(false)
Chris Lattner24943d22010-06-08 16:52:24 +0000373{
Greg Clayton63094e02010-06-23 01:19:29 +0000374}
375
376Driver::OptionData::~OptionData ()
377{
378}
379
380void
381Driver::OptionData::Clear ()
382{
383 m_filename.clear ();
384 m_script_lang = lldb::eScriptLanguageDefault;
385 m_source_command_files.clear ();
386 m_debug_mode = false;
387 m_print_help = false;
388 m_print_version = false;
Jim Ingham74989e82010-08-30 19:44:40 +0000389 m_use_external_editor = false;
Greg Clayton63094e02010-06-23 01:19:29 +0000390}
391
392void
393Driver::ResetOptionValues ()
394{
395 m_option_data.Clear ();
396}
397
398const char *
399Driver::GetFilename() const
400{
401 if (m_option_data.m_filename.empty())
402 return NULL;
403 return m_option_data.m_filename.c_str();
404}
405
406const char *
407Driver::GetCrashLogFilename() const
408{
409 if (m_option_data.m_crash_log.empty())
410 return NULL;
411 return m_option_data.m_crash_log.c_str();
412}
413
414lldb::ScriptLanguage
415Driver::GetScriptLanguage() const
416{
417 return m_option_data.m_script_lang;
418}
419
420size_t
421Driver::GetNumSourceCommandFiles () const
422{
423 return m_option_data.m_source_command_files.size();
424}
425
426const char *
427Driver::GetSourceCommandFileAtIndex (uint32_t idx) const
428{
429 if (idx < m_option_data.m_source_command_files.size())
430 return m_option_data.m_source_command_files[idx].c_str();
431 return NULL;
432}
433
434bool
435Driver::GetDebugMode() const
436{
437 return m_option_data.m_debug_mode;
438}
439
440
441// Check the arguments that were passed to this program to make sure they are valid and to get their
442// argument values (if any). Return a boolean value indicating whether or not to start up the full
443// debugger (i.e. the Command Interpreter) or not. Return FALSE if the arguments were invalid OR
444// if the user only wanted help or version information.
445
446SBError
447Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exit)
448{
449 ResetOptionValues ();
450
451 SBCommandReturnObject result;
452
Chris Lattner24943d22010-06-08 16:52:24 +0000453 SBError error;
454 std::string option_string;
455 struct option *long_options = NULL;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000456 uint32_t num_options;
Chris Lattner24943d22010-06-08 16:52:24 +0000457
Greg Clayton54e7afa2010-07-09 20:39:50 +0000458 for (num_options = 0; g_options[num_options].long_option != NULL; ++num_options)
459 /* Do Nothing. */;
Chris Lattner24943d22010-06-08 16:52:24 +0000460
461 if (num_options == 0)
462 {
463 if (argc > 1)
464 error.SetErrorStringWithFormat ("invalid number of options");
465 return error;
466 }
467
468 long_options = (struct option *) malloc ((num_options + 1) * sizeof (struct option));
469
470 BuildGetOptTable (g_options, &long_options, num_options);
471
472 if (long_options == NULL)
473 {
474 error.SetErrorStringWithFormat ("invalid long options");
475 return error;
476 }
477
478 // Build the option_string argument for call to getopt_long.
479
480 for (int i = 0; long_options[i].name != NULL; ++i)
481 {
482 if (long_options[i].flag == NULL)
483 {
484 option_string.push_back ((char) long_options[i].val);
485 switch (long_options[i].has_arg)
486 {
487 default:
488 case no_argument:
489 break;
490 case required_argument:
491 option_string.push_back (':');
492 break;
493 case optional_argument:
494 option_string.append ("::");
495 break;
496 }
497 }
498 }
499
500 // Prepare for & make calls to getopt_long.
Eli Friedmanef2bc872010-06-13 19:18:49 +0000501#if __GLIBC__
502 optind = 0;
503#else
Chris Lattner24943d22010-06-08 16:52:24 +0000504 optreset = 1;
505 optind = 1;
Eli Friedmanef2bc872010-06-13 19:18:49 +0000506#endif
Chris Lattner24943d22010-06-08 16:52:24 +0000507 int val;
508 while (1)
509 {
510 int long_options_index = -1;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000511 val = ::getopt_long (argc, const_cast<char **>(argv), option_string.c_str(), long_options, &long_options_index);
Chris Lattner24943d22010-06-08 16:52:24 +0000512
513 if (val == -1)
514 break;
515 else if (val == '?')
516 {
Greg Clayton63094e02010-06-23 01:19:29 +0000517 m_option_data.m_print_help = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000518 error.SetErrorStringWithFormat ("unknown or ambiguous option");
519 break;
520 }
521 else if (val == 0)
522 continue;
523 else
524 {
Greg Clayton63094e02010-06-23 01:19:29 +0000525 m_option_data.m_seen_options.insert ((char) val);
Chris Lattner24943d22010-06-08 16:52:24 +0000526 if (long_options_index == -1)
527 {
528 for (int i = 0;
529 long_options[i].name || long_options[i].has_arg || long_options[i].flag || long_options[i].val;
530 ++i)
531 {
532 if (long_options[i].val == val)
533 {
534 long_options_index = i;
535 break;
536 }
537 }
538 }
539
540 if (long_options_index >= 0)
541 {
Greg Clayton63094e02010-06-23 01:19:29 +0000542 const char short_option = (char) g_options[long_options_index].short_option;
543
544 switch (short_option)
545 {
546 case 'h':
547 m_option_data.m_print_help = true;
548 break;
549
550 case 'v':
551 m_option_data.m_print_version = true;
552 break;
553
554 case 'c':
555 m_option_data.m_crash_log = optarg;
556 break;
Jim Ingham74989e82010-08-30 19:44:40 +0000557 case 'e':
558 m_option_data.m_use_external_editor = true;
559 break;
560
Greg Clayton63094e02010-06-23 01:19:29 +0000561 case 'f':
562 {
563 SBFileSpec file(optarg);
564 if (file.Exists())
565 m_option_data.m_filename = optarg;
Caroline Ticeeddffe92010-09-10 04:48:55 +0000566 else if (file.ResolveExecutableLocation())
567 {
568 char path[PATH_MAX];
569 int path_len;
570 file.GetPath (path, path_len);
571 m_option_data.m_filename = path;
572 }
Greg Clayton63094e02010-06-23 01:19:29 +0000573 else
574 error.SetErrorStringWithFormat("file specified in --file (-f) option doesn't exist: '%s'", optarg);
575 }
576 break;
577
578 case 'a':
579 if (!m_debugger.SetDefaultArchitecture (optarg))
580 error.SetErrorStringWithFormat("invalid architecture in the -a or --arch option: '%s'", optarg);
581 break;
582
583 case 'l':
584 m_option_data.m_script_lang = m_debugger.GetScriptingLanguage (optarg);
585 break;
586
587 case 'd':
588 m_option_data.m_debug_mode = true;
589 break;
590
591 case 's':
592 {
593 SBFileSpec file(optarg);
594 if (file.Exists())
595 m_option_data.m_source_command_files.push_back (optarg);
Caroline Ticeeddffe92010-09-10 04:48:55 +0000596 else if (file.ResolveExecutableLocation())
597 {
598 char final_path[PATH_MAX];
599 size_t path_len;
600 file.GetPath (final_path, path_len);
601 std::string path_str (final_path);
602 m_option_data.m_source_command_files.push_back (path_str);
603 }
Greg Clayton63094e02010-06-23 01:19:29 +0000604 else
605 error.SetErrorStringWithFormat("file specified in --source (-s) option doesn't exist: '%s'", optarg);
606 }
607 break;
608
609 default:
610 m_option_data.m_print_help = true;
611 error.SetErrorStringWithFormat ("unrecognized option %c", short_option);
612 break;
613 }
Chris Lattner24943d22010-06-08 16:52:24 +0000614 }
615 else
616 {
617 error.SetErrorStringWithFormat ("invalid option with value %i", val);
618 }
619 if (error.Fail())
Greg Clayton63094e02010-06-23 01:19:29 +0000620 return error;
Chris Lattner24943d22010-06-08 16:52:24 +0000621 }
622 }
Jim Ingham34e9a982010-06-15 18:47:14 +0000623
624 // If there is a trailing argument, it is the filename.
625 if (optind == argc - 1)
626 {
627 if (m_option_data.m_filename.empty())
Chris Lattner24943d22010-06-08 16:52:24 +0000628 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000629 m_option_data.m_filename = argv[optind];
Chris Lattner24943d22010-06-08 16:52:24 +0000630 }
Jim Ingham34e9a982010-06-15 18:47:14 +0000631 else
632 {
Greg Clayton63094e02010-06-23 01:19:29 +0000633 error.SetErrorStringWithFormat ("error: don't provide a file both on in the -f option and as an argument.");
Jim Ingham34e9a982010-06-15 18:47:14 +0000634 }
635
Chris Lattner24943d22010-06-08 16:52:24 +0000636 }
Jim Ingham34e9a982010-06-15 18:47:14 +0000637 else if (optind < argc - 1)
638 {
639 // Trailing extra arguments...
Greg Clayton63094e02010-06-23 01:19:29 +0000640 error.SetErrorStringWithFormat ("error: trailing extra arguments - only one the filename is allowed.");
Jim Ingham34e9a982010-06-15 18:47:14 +0000641 }
642
Greg Clayton63094e02010-06-23 01:19:29 +0000643 if (error.Fail() || m_option_data.m_print_help)
Chris Lattner24943d22010-06-08 16:52:24 +0000644 {
645 ShowUsage (out_fh, g_options, m_option_data);
Chris Lattner24943d22010-06-08 16:52:24 +0000646 }
647 else if (m_option_data.m_print_version)
648 {
Greg Clayton63094e02010-06-23 01:19:29 +0000649 ::fprintf (out_fh, "%s\n", m_debugger.GetVersionString());
650 exit = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000651 }
652 else if (! m_option_data.m_crash_log.empty())
653 {
654 // Handle crash log stuff here.
655 }
656 else
657 {
658 // All other combinations are valid; do nothing more here.
659 }
660
Greg Clayton63094e02010-06-23 01:19:29 +0000661 return error;
Chris Lattner24943d22010-06-08 16:52:24 +0000662}
663
Caroline Tice757500e2010-09-29 18:35:42 +0000664size_t
Chris Lattner24943d22010-06-08 16:52:24 +0000665Driver::GetProcessSTDOUT ()
666{
667 // The process has stuff waiting for stdout; get it and write it out to the appropriate place.
668 char stdio_buffer[1024];
669 size_t len;
Caroline Tice757500e2010-09-29 18:35:42 +0000670 size_t total_bytes = 0;
Jim Inghamc8332952010-08-26 21:32:51 +0000671 while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0)
Caroline Tice757500e2010-09-29 18:35:42 +0000672 {
Chris Lattner24943d22010-06-08 16:52:24 +0000673 m_io_channel_ap->OutWrite (stdio_buffer, len);
Caroline Tice757500e2010-09-29 18:35:42 +0000674 total_bytes += len;
675 }
676 return total_bytes;
Chris Lattner24943d22010-06-08 16:52:24 +0000677}
678
Caroline Tice757500e2010-09-29 18:35:42 +0000679size_t
Chris Lattner24943d22010-06-08 16:52:24 +0000680Driver::GetProcessSTDERR ()
681{
682 // The process has stuff waiting for stderr; get it and write it out to the appropriate place.
683 char stdio_buffer[1024];
684 size_t len;
Caroline Tice757500e2010-09-29 18:35:42 +0000685 size_t total_bytes = 0;
Jim Inghamc8332952010-08-26 21:32:51 +0000686 while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0)
Caroline Tice757500e2010-09-29 18:35:42 +0000687 {
Chris Lattner24943d22010-06-08 16:52:24 +0000688 m_io_channel_ap->ErrWrite (stdio_buffer, len);
Caroline Tice757500e2010-09-29 18:35:42 +0000689 total_bytes += len;
690 }
691 return total_bytes;
Chris Lattner24943d22010-06-08 16:52:24 +0000692}
693
694void
Jim Inghamc8332952010-08-26 21:32:51 +0000695Driver::UpdateSelectedThread ()
Chris Lattner24943d22010-06-08 16:52:24 +0000696{
697 using namespace lldb;
Jim Inghamc8332952010-08-26 21:32:51 +0000698 SBProcess process(m_debugger.GetSelectedTarget().GetProcess());
Chris Lattner24943d22010-06-08 16:52:24 +0000699 if (process.IsValid())
700 {
Jim Inghamc8332952010-08-26 21:32:51 +0000701 SBThread curr_thread (process.GetSelectedThread());
Chris Lattner24943d22010-06-08 16:52:24 +0000702 SBThread thread;
703 StopReason curr_thread_stop_reason = eStopReasonInvalid;
704 curr_thread_stop_reason = curr_thread.GetStopReason();
705
706 if (!curr_thread.IsValid() ||
707 curr_thread_stop_reason == eStopReasonInvalid ||
708 curr_thread_stop_reason == eStopReasonNone)
709 {
710 // Prefer a thread that has just completed its plan over another thread as current thread.
711 SBThread plan_thread;
712 SBThread other_thread;
713 const size_t num_threads = process.GetNumThreads();
714 size_t i;
715 for (i = 0; i < num_threads; ++i)
716 {
717 thread = process.GetThreadAtIndex(i);
718 StopReason thread_stop_reason = thread.GetStopReason();
719 switch (thread_stop_reason)
720 {
721 default:
722 case eStopReasonInvalid:
723 case eStopReasonNone:
724 break;
725
726 case eStopReasonTrace:
727 case eStopReasonBreakpoint:
728 case eStopReasonWatchpoint:
729 case eStopReasonSignal:
730 case eStopReasonException:
731 if (!other_thread.IsValid())
732 other_thread = thread;
733 break;
734 case eStopReasonPlanComplete:
735 if (!plan_thread.IsValid())
736 plan_thread = thread;
737 break;
738 }
739 }
740 if (plan_thread.IsValid())
Jim Inghamc8332952010-08-26 21:32:51 +0000741 process.SetSelectedThread (plan_thread);
Chris Lattner24943d22010-06-08 16:52:24 +0000742 else if (other_thread.IsValid())
Jim Inghamc8332952010-08-26 21:32:51 +0000743 process.SetSelectedThread (other_thread);
Chris Lattner24943d22010-06-08 16:52:24 +0000744 else
745 {
746 if (curr_thread.IsValid())
747 thread = curr_thread;
748 else
749 thread = process.GetThreadAtIndex(0);
750
751 if (thread.IsValid())
Jim Inghamc8332952010-08-26 21:32:51 +0000752 process.SetSelectedThread (thread);
Chris Lattner24943d22010-06-08 16:52:24 +0000753 }
754 }
755 }
756}
757
758
759// This function handles events that were broadcast by the process.
760void
761Driver::HandleProcessEvent (const SBEvent &event)
762{
763 using namespace lldb;
764 const uint32_t event_type = event.GetType();
765
766 if (event_type & SBProcess::eBroadcastBitSTDOUT)
767 {
768 // The process has stdout available, get it and write it out to the
769 // appropriate place.
Caroline Tice757500e2010-09-29 18:35:42 +0000770 if (GetProcessSTDOUT ())
771 m_io_channel_ap->RefreshPrompt();
Chris Lattner24943d22010-06-08 16:52:24 +0000772 }
773 else if (event_type & SBProcess::eBroadcastBitSTDERR)
774 {
775 // The process has stderr available, get it and write it out to the
776 // appropriate place.
Caroline Tice757500e2010-09-29 18:35:42 +0000777 if (GetProcessSTDERR ())
778 m_io_channel_ap->RefreshPrompt();
Chris Lattner24943d22010-06-08 16:52:24 +0000779 }
780 else if (event_type & SBProcess::eBroadcastBitStateChanged)
781 {
782 // Drain all stout and stderr so we don't see any output come after
783 // we print our prompts
Caroline Tice757500e2010-09-29 18:35:42 +0000784 if (GetProcessSTDOUT ()
785 || GetProcessSTDERR ())
786 m_io_channel_ap->RefreshPrompt();
Chris Lattner24943d22010-06-08 16:52:24 +0000787
788 // Something changed in the process; get the event and report the process's current status and location to
789 // the user.
790 StateType event_state = SBProcess::GetStateFromEvent (event);
791 if (event_state == eStateInvalid)
792 return;
793
794 SBProcess process (SBProcess::GetProcessFromEvent (event));
795 assert (process.IsValid());
796
797 switch (event_state)
798 {
799 case eStateInvalid:
800 case eStateUnloaded:
801 case eStateAttaching:
802 case eStateLaunching:
803 case eStateStepping:
804 case eStateDetached:
805 {
806 char message[1024];
807 int message_len = ::snprintf (message, sizeof(message), "Process %d %s\n", process.GetProcessID(),
Greg Clayton63094e02010-06-23 01:19:29 +0000808 m_debugger.StateAsCString (event_state));
Chris Lattner24943d22010-06-08 16:52:24 +0000809 m_io_channel_ap->OutWrite(message, message_len);
810 }
811 break;
812
813 case eStateRunning:
814 // Don't be chatty when we run...
815 break;
816
817 case eStateExited:
Caroline Tice757500e2010-09-29 18:35:42 +0000818 {
819 SBCommandReturnObject result;
820 m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
821 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize());
822 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize());
823 m_io_channel_ap->RefreshPrompt();
824 }
Chris Lattner24943d22010-06-08 16:52:24 +0000825 break;
826
827 case eStateStopped:
828 case eStateCrashed:
829 case eStateSuspended:
830 // Make sure the program hasn't been auto-restarted:
831 if (SBProcess::GetRestartedFromEvent (event))
832 {
833 // FIXME: Do we want to report this, or would that just be annoyingly chatty?
834 char message[1024];
835 int message_len = ::snprintf (message, sizeof(message), "Process %d stopped and was programmatically restarted.\n",
836 process.GetProcessID());
837 m_io_channel_ap->OutWrite(message, message_len);
Caroline Tice757500e2010-09-29 18:35:42 +0000838 m_io_channel_ap->RefreshPrompt ();
Chris Lattner24943d22010-06-08 16:52:24 +0000839 }
840 else
841 {
Caroline Tice757500e2010-09-29 18:35:42 +0000842 SBCommandReturnObject result;
Jim Inghamc8332952010-08-26 21:32:51 +0000843 UpdateSelectedThread ();
Caroline Tice757500e2010-09-29 18:35:42 +0000844 m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
845 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize());
846 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize());
847 m_io_channel_ap->RefreshPrompt ();
Chris Lattner24943d22010-06-08 16:52:24 +0000848 }
849 break;
850 }
851 }
852}
853
854// This function handles events broadcast by the IOChannel (HasInput, UserInterrupt, or ThreadShouldExit).
855
856bool
857Driver::HandleIOEvent (const SBEvent &event)
858{
859 bool quit = false;
860
861 const uint32_t event_type = event.GetType();
862
863 if (event_type & IOChannel::eBroadcastBitHasUserInput)
864 {
865 // We got some input (i.e. a command string) from the user; pass it off to the command interpreter for
866 // handling.
867
868 const char *command_string = SBEvent::GetCStringFromEvent(event);
869 if (command_string == NULL)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000870 command_string = "";
Chris Lattner24943d22010-06-08 16:52:24 +0000871 SBCommandReturnObject result;
Greg Clayton63094e02010-06-23 01:19:29 +0000872 if (m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, true) != lldb::eReturnStatusQuit)
Chris Lattner24943d22010-06-08 16:52:24 +0000873 {
874 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize());
875 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize());
876 }
877 // We are done getting and running our command, we can now clear the
878 // m_waiting_for_command so we can get another one.
879 m_waiting_for_command = false;
880
881 // If our editline input reader is active, it means another input reader
882 // got pushed onto the input reader and caused us to become deactivated.
883 // When the input reader above us gets popped, we will get re-activated
884 // and our prompt will refresh in our callback
885 if (m_editline_reader.IsActive())
886 {
887 ReadyForCommand ();
888 }
889 }
890 else if (event_type & IOChannel::eBroadcastBitUserInterrupt)
891 {
892 // This is here to handle control-c interrupts from the user. It has not yet really been implemented.
893 // TO BE DONE: PROPERLY HANDLE CONTROL-C FROM USER
894 //m_io_channel_ap->CancelInput();
895 // Anything else? Send Interrupt to process?
896 }
897 else if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
898 (event_type & IOChannel::eBroadcastBitThreadDidExit))
899 {
900 // If the IOChannel thread is trying to go away, then it is definitely
901 // time to end the debugging session.
902 quit = true;
903 }
904
905 return quit;
906}
907
908
909//struct CrashImageInfo
910//{
911// std::string path;
912// VMRange text_range;
913// UUID uuid;
914//};
915//
916//void
917//Driver::ParseCrashLog (const char *crash_log)
918//{
919// printf("Parsing crash log: %s\n", crash_log);
920//
921// char image_path[PATH_MAX];
922// std::vector<CrashImageInfo> crash_infos;
923// if (crash_log && crash_log[0])
924// {
925// FileSpec crash_log_file (crash_log);
926// STLStringArray crash_log_lines;
927// if (crash_log_file.ReadFileLines (crash_log_lines))
928// {
929// const size_t num_crash_log_lines = crash_log_lines.size();
930// size_t i;
931// for (i=0; i<num_crash_log_lines; ++i)
932// {
933// const char *line = crash_log_lines[i].c_str();
934// if (strstr (line, "Code Type:"))
935// {
936// char arch_string[256];
937// if (sscanf(line, "%s", arch_string))
938// {
939// if (strcmp(arch_string, "X86-64"))
940// lldb::GetDefaultArchitecture ().SetArch ("x86_64");
941// else if (strcmp(arch_string, "X86"))
942// lldb::GetDefaultArchitecture ().SetArch ("i386");
943// else
944// {
945// ArchSpec arch(arch_string);
946// if (arch.IsValid ())
947// lldb::GetDefaultArchitecture () = arch;
948// else
949// fprintf(stderr, "Unrecognized architecture: %s\n", arch_string);
950// }
951// }
952// }
953// else
954// if (strstr(line, "Path:"))
955// {
956// const char *p = line + strlen("Path:");
957// while (isspace(*p))
958// ++p;
959//
960// m_option_data.m_filename.assign (p);
961// }
962// else
963// if (strstr(line, "Binary Images:"))
964// {
965// while (++i < num_crash_log_lines)
966// {
967// if (crash_log_lines[i].empty())
968// break;
969//
970// line = crash_log_lines[i].c_str();
971// uint64_t text_start_addr;
972// uint64_t text_end_addr;
973// char uuid_cstr[64];
974// int bytes_consumed_before_uuid = 0;
975// int bytes_consumed_after_uuid = 0;
976//
977// int items_parsed = ::sscanf (line,
978// "%llx - %llx %*s %*s %*s %n%s %n",
979// &text_start_addr,
980// &text_end_addr,
981// &bytes_consumed_before_uuid,
982// uuid_cstr,
983// &bytes_consumed_after_uuid);
984//
985// if (items_parsed == 3)
986// {
987//
988// CrashImageInfo info;
989// info.text_range.SetBaseAddress(text_start_addr);
990// info.text_range.SetEndAddress(text_end_addr);
991//
992// if (uuid_cstr[0] == '<')
993// {
994// if (info.uuid.SetfromCString (&uuid_cstr[1]) == 0)
995// info.uuid.Clear();
996//
997// ::strncpy (image_path, line + bytes_consumed_after_uuid, sizeof(image_path));
998// }
999// else
1000// {
1001// ::strncpy (image_path, line + bytes_consumed_before_uuid, sizeof(image_path));
1002// }
1003//
1004// info.path = image_path;
1005//
1006// crash_infos.push_back (info);
1007//
1008// info.uuid.GetAsCString(uuid_cstr, sizeof(uuid_cstr));
1009//
1010// printf("0x%16.16llx - 0x%16.16llx <%s> %s\n",
1011// text_start_addr,
1012// text_end_addr,
1013// uuid_cstr,
1014// image_path);
1015// }
1016// }
1017// }
1018// }
1019// }
1020//
1021// if (crash_infos.size())
1022// {
Greg Clayton63094e02010-06-23 01:19:29 +00001023// SBTarget target (m_debugger.CreateTarget (crash_infos.front().path.c_str(),
Chris Lattner24943d22010-06-08 16:52:24 +00001024// lldb::GetDefaultArchitecture().AsCString (),
1025// false));
1026// if (target.IsValid())
1027// {
1028//
1029// }
1030// }
1031// }
1032//}
1033//
1034
1035void
1036Driver::MasterThreadBytesReceived (void *baton, const void *src, size_t src_len)
1037{
1038 Driver *driver = (Driver*)baton;
1039 driver->GetFromMaster ((const char *)src, src_len);
1040}
1041
1042void
1043Driver::GetFromMaster (const char *src, size_t src_len)
1044{
1045 // Echo the characters back to the Debugger's stdout, that way if you
1046 // type characters while a command is running, you'll see what you've typed.
Greg Clayton63094e02010-06-23 01:19:29 +00001047 FILE *out_fh = m_debugger.GetOutputFileHandle();
Chris Lattner24943d22010-06-08 16:52:24 +00001048 if (out_fh)
1049 ::fwrite (src, 1, src_len, out_fh);
1050}
1051
1052size_t
1053Driver::EditLineInputReaderCallback
1054(
1055 void *baton,
1056 SBInputReader *reader,
1057 InputReaderAction notification,
1058 const char *bytes,
1059 size_t bytes_len
1060)
1061{
1062 Driver *driver = (Driver *)baton;
1063
1064 switch (notification)
1065 {
1066 case eInputReaderActivate:
1067 break;
1068
1069 case eInputReaderReactivate:
1070 driver->ReadyForCommand();
1071 break;
1072
1073 case eInputReaderDeactivate:
1074 break;
1075
1076 case eInputReaderGotToken:
1077 write (driver->m_editline_pty.GetMasterFileDescriptor(), bytes, bytes_len);
1078 break;
1079
1080 case eInputReaderDone:
1081 break;
1082 }
1083 return bytes_len;
1084}
1085
1086void
1087Driver::MainLoop ()
1088{
1089 char error_str[1024];
1090 if (m_editline_pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, error_str, sizeof(error_str)) == false)
1091 {
1092 ::fprintf (stderr, "error: failed to open driver pseudo terminal : %s", error_str);
1093 exit(1);
1094 }
1095 else
1096 {
1097 const char *driver_slave_name = m_editline_pty.GetSlaveName (error_str, sizeof(error_str));
1098 if (driver_slave_name == NULL)
1099 {
1100 ::fprintf (stderr, "error: failed to get slave name for driver pseudo terminal : %s", error_str);
1101 exit(2);
1102 }
1103 else
1104 {
1105 m_editline_slave_fh = ::fopen (driver_slave_name, "r+");
1106 if (m_editline_slave_fh == NULL)
1107 {
1108 SBError error;
1109 error.SetErrorToErrno();
1110 ::fprintf (stderr, "error: failed to get open slave for driver pseudo terminal : %s",
1111 error.GetCString());
1112 exit(3);
1113 }
1114
1115 ::setbuf (m_editline_slave_fh, NULL);
1116 }
1117 }
1118
1119
1120 // struct termios stdin_termios;
1121
1122 if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0)
1123 atexit (reset_stdin_termios);
1124
1125 ::setbuf (stdin, NULL);
1126 ::setbuf (stdout, NULL);
1127
Greg Clayton63094e02010-06-23 01:19:29 +00001128 m_debugger.SetErrorFileHandle (stderr, false);
1129 m_debugger.SetOutputFileHandle (stdout, false);
1130 m_debugger.SetInputFileHandle (stdin, true);
Jim Ingham74989e82010-08-30 19:44:40 +00001131
1132 m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor);
Chris Lattner24943d22010-06-08 16:52:24 +00001133
1134 // You have to drain anything that comes to the master side of the PTY. master_out_comm is
1135 // for that purpose. The reason you need to do this is a curious reason... editline will echo
1136 // characters to the PTY when it gets characters while el_gets is not running, and then when
1137 // you call el_gets (or el_getc) it will try to reset the terminal back to raw mode which blocks
1138 // if there are unconsumed characters in the out buffer.
1139 // However, you don't need to do anything with the characters, since editline will dump these
1140 // unconsumed characters after printing the prompt again in el_gets.
1141
1142 SBCommunication master_out_comm("driver.editline");
1143 master_out_comm.AdoptFileDesriptor(m_editline_pty.GetMasterFileDescriptor(), false);
1144 master_out_comm.SetReadThreadBytesReceivedCallback(Driver::MasterThreadBytesReceived, this);
1145
1146 if (master_out_comm.ReadThreadStart () == false)
1147 {
1148 ::fprintf (stderr, "error: failed to start master out read thread");
1149 exit(5);
1150 }
1151
1152// const char *crash_log = GetCrashLogFilename();
1153// if (crash_log)
1154// {
1155// ParseCrashLog (crash_log);
1156// }
1157//
Greg Clayton63094e02010-06-23 01:19:29 +00001158 SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter();
Chris Lattner24943d22010-06-08 16:52:24 +00001159
1160 m_io_channel_ap.reset (new IOChannel(m_editline_slave_fh, stdout, stderr, this));
1161
1162 struct winsize window_size;
1163 if (isatty (STDIN_FILENO)
1164 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
1165 {
Caroline Tice6e4c5ce2010-09-04 00:03:46 +00001166 if (window_size.ws_col > 0)
Greg Clayton238c0a12010-09-18 01:14:36 +00001167 m_debugger.SetTerminalWidth (window_size.ws_col);
Chris Lattner24943d22010-06-08 16:52:24 +00001168 }
1169
1170 // Since input can be redirected by the debugger, we must insert our editline
1171 // input reader in the queue so we know when our reader should be active
1172 // and so we can receive bytes only when we are supposed to.
Greg Clayton63094e02010-06-23 01:19:29 +00001173 SBError err (m_editline_reader.Initialize (m_debugger,
1174 Driver::EditLineInputReaderCallback, // callback
Chris Lattner24943d22010-06-08 16:52:24 +00001175 this, // baton
1176 eInputReaderGranularityByte, // token_size
1177 NULL, // end token - NULL means never done
1178 NULL, // prompt - taken care of elsewhere
1179 false)); // echo input - don't need Debugger
1180 // to do this, we handle it elsewhere
1181
1182 if (err.Fail())
1183 {
1184 ::fprintf (stderr, "error: %s", err.GetCString());
1185 exit (6);
1186 }
1187
Greg Clayton63094e02010-06-23 01:19:29 +00001188 m_debugger.PushInputReader (m_editline_reader);
Chris Lattner24943d22010-06-08 16:52:24 +00001189
Greg Clayton63094e02010-06-23 01:19:29 +00001190 SBListener listener(m_debugger.GetListener());
Chris Lattner24943d22010-06-08 16:52:24 +00001191 if (listener.IsValid())
1192 {
1193
1194 listener.StartListeningForEvents (*m_io_channel_ap,
1195 IOChannel::eBroadcastBitHasUserInput |
1196 IOChannel::eBroadcastBitUserInterrupt |
1197 IOChannel::eBroadcastBitThreadShouldExit |
1198 IOChannel::eBroadcastBitThreadDidStart |
1199 IOChannel::eBroadcastBitThreadDidExit);
1200
1201 if (m_io_channel_ap->Start ())
1202 {
1203 bool iochannel_thread_exited = false;
1204
1205 listener.StartListeningForEvents (sb_interpreter.GetBroadcaster(),
1206 SBCommandInterpreter::eBroadcastBitQuitCommandReceived);
1207
1208 // Before we handle any options from the command line, we parse the
1209 // .lldbinit file in the user's home directory.
1210 SBCommandReturnObject result;
1211 sb_interpreter.SourceInitFileInHomeDirectory(result);
1212 if (GetDebugMode())
1213 {
Greg Clayton63094e02010-06-23 01:19:29 +00001214 result.PutError (m_debugger.GetErrorFileHandle());
1215 result.PutOutput (m_debugger.GetOutputFileHandle());
Chris Lattner24943d22010-06-08 16:52:24 +00001216 }
1217
1218 // Now we handle options we got from the command line
1219 char command_string[PATH_MAX * 2];
1220 const size_t num_source_command_files = GetNumSourceCommandFiles();
1221 if (num_source_command_files > 0)
1222 {
1223 for (size_t i=0; i < num_source_command_files; ++i)
1224 {
1225 const char *command_file = GetSourceCommandFileAtIndex(i);
Johnny Chen7c984242010-07-28 21:16:11 +00001226 ::snprintf (command_string, sizeof(command_string), "command source '%s'", command_file);
Greg Clayton63094e02010-06-23 01:19:29 +00001227 m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, false);
Chris Lattner24943d22010-06-08 16:52:24 +00001228 if (GetDebugMode())
1229 {
Greg Clayton63094e02010-06-23 01:19:29 +00001230 result.PutError (m_debugger.GetErrorFileHandle());
1231 result.PutOutput (m_debugger.GetOutputFileHandle());
Chris Lattner24943d22010-06-08 16:52:24 +00001232 }
1233 }
1234 }
1235
1236 if (!m_option_data.m_filename.empty())
1237 {
1238 char arch_name[64];
Greg Clayton63094e02010-06-23 01:19:29 +00001239 if (m_debugger.GetDefaultArchitecture (arch_name, sizeof (arch_name)))
Chris Lattner24943d22010-06-08 16:52:24 +00001240 ::snprintf (command_string, sizeof (command_string), "file --arch=%s '%s'", arch_name,
1241 m_option_data.m_filename.c_str());
1242 else
1243 ::snprintf (command_string, sizeof(command_string), "file '%s'", m_option_data.m_filename.c_str());
1244
Greg Clayton63094e02010-06-23 01:19:29 +00001245 m_debugger.HandleCommand (command_string);
Chris Lattner24943d22010-06-08 16:52:24 +00001246 }
1247
1248 // Now that all option parsing is done, we try and parse the .lldbinit
1249 // file in the current working directory
1250 sb_interpreter.SourceInitFileInCurrentWorkingDirectory (result);
1251 if (GetDebugMode())
1252 {
Greg Clayton63094e02010-06-23 01:19:29 +00001253 result.PutError(m_debugger.GetErrorFileHandle());
1254 result.PutOutput(m_debugger.GetOutputFileHandle());
Chris Lattner24943d22010-06-08 16:52:24 +00001255 }
1256
1257 SBEvent event;
1258
1259 // Make sure the IO channel is started up before we try to tell it we
1260 // are ready for input
1261 listener.WaitForEventForBroadcasterWithType (UINT32_MAX,
1262 *m_io_channel_ap,
1263 IOChannel::eBroadcastBitThreadDidStart,
1264 event);
1265
1266 ReadyForCommand ();
1267
1268 bool done = false;
1269 while (!done)
1270 {
1271 listener.WaitForEvent (UINT32_MAX, event);
1272 if (event.IsValid())
1273 {
1274 if (event.GetBroadcaster().IsValid())
1275 {
1276 uint32_t event_type = event.GetType();
1277 if (event.BroadcasterMatchesRef (*m_io_channel_ap))
1278 {
1279 if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
1280 (event_type & IOChannel::eBroadcastBitThreadDidExit))
1281 {
1282 done = true;
1283 if (event_type & IOChannel::eBroadcastBitThreadDidExit)
1284 iochannel_thread_exited = true;
1285 break;
1286 }
1287 else
1288 done = HandleIOEvent (event);
1289 }
Jim Inghamc8332952010-08-26 21:32:51 +00001290 else if (event.BroadcasterMatchesRef (m_debugger.GetSelectedTarget().GetProcess().GetBroadcaster()))
Chris Lattner24943d22010-06-08 16:52:24 +00001291 {
1292 HandleProcessEvent (event);
1293 }
1294 else if (event.BroadcasterMatchesRef (sb_interpreter.GetBroadcaster()))
1295 {
1296 if (event_type & SBCommandInterpreter::eBroadcastBitQuitCommandReceived)
1297 done = true;
1298 }
1299 }
1300 }
1301 }
1302
1303 reset_stdin_termios ();
1304
1305 CloseIOChannelFile ();
1306
1307 if (!iochannel_thread_exited)
1308 {
Greg Claytonbef15832010-07-14 00:18:15 +00001309 event.Clear();
Chris Lattner24943d22010-06-08 16:52:24 +00001310 listener.GetNextEventForBroadcasterWithType (*m_io_channel_ap,
1311 IOChannel::eBroadcastBitThreadDidExit,
1312 event);
1313 if (!event.IsValid())
1314 {
1315 // Send end EOF to the driver file descriptor
1316 m_io_channel_ap->Stop();
1317 }
1318 }
1319
Jim Inghamc8332952010-08-26 21:32:51 +00001320 SBProcess process = m_debugger.GetSelectedTarget().GetProcess();
Chris Lattner24943d22010-06-08 16:52:24 +00001321 if (process.IsValid())
1322 process.Destroy();
1323 }
1324 }
1325}
1326
1327
1328void
1329Driver::ReadyForCommand ()
1330{
1331 if (m_waiting_for_command == false)
1332 {
1333 m_waiting_for_command = true;
1334 BroadcastEventByType (Driver::eBroadcastBitReadyForInput, true);
1335 }
1336}
1337
1338
Caroline Ticeb8314fe2010-09-09 17:45:09 +00001339void
1340sigwinch_handler (int signo)
1341{
1342 struct winsize window_size;
1343 if (isatty (STDIN_FILENO)
1344 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
1345 {
1346 if ((window_size.ws_col > 0) && (strlen (g_debugger_name) > 0))
1347 {
1348 char width_str_buffer[25];
1349 ::sprintf (width_str_buffer, "%d", window_size.ws_col);
1350 SBDebugger::SetInternalVariable ("term-width", width_str_buffer, g_debugger_name);
1351 }
1352 }
1353}
1354
Chris Lattner24943d22010-06-08 16:52:24 +00001355int
1356main (int argc, char const *argv[])
1357{
Chris Lattner24943d22010-06-08 16:52:24 +00001358 SBDebugger::Initialize();
1359
1360 SBHostOS::ThreadCreated ("[main]");
1361
Caroline Ticeb8314fe2010-09-09 17:45:09 +00001362 signal (SIGWINCH, sigwinch_handler);
1363
Greg Clayton63094e02010-06-23 01:19:29 +00001364 // Create a scope for driver so that the driver object will destroy itself
1365 // before SBDebugger::Terminate() is called.
Chris Lattner24943d22010-06-08 16:52:24 +00001366 {
Greg Clayton63094e02010-06-23 01:19:29 +00001367 Driver driver;
1368
1369 bool exit = false;
1370 SBError error (driver.ParseArgs (argc, argv, stdout, exit));
1371 if (error.Fail())
1372 {
1373 const char *error_cstr = error.GetCString ();
1374 if (error_cstr)
1375 ::fprintf (stderr, "error: %s\n", error_cstr);
1376 }
1377 else if (!exit)
1378 {
1379 driver.MainLoop ();
1380 }
Chris Lattner24943d22010-06-08 16:52:24 +00001381 }
1382
1383 SBDebugger::Terminate();
1384 return 0;
1385}