blob: 9d9281bbae6712349f60db6f0870f822391f738a [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
42// In the Driver::MainLoop, we change the terminal settings. This function is
43// added as an atexit handler to make sure we clean them up.
44static void
45reset_stdin_termios ()
46{
47 ::tcsetattr (STDIN_FILENO, TCSANOW, &g_old_stdin_termios);
48}
49
50static lldb::OptionDefinition g_options[] =
51{
Jim Ingham34e9a982010-06-15 18:47:14 +000052 { LLDB_OPT_SET_1, true, "help", 'h', no_argument, NULL, NULL, NULL,
Chris Lattner24943d22010-06-08 16:52:24 +000053 "Prints out the usage information for the LLDB debugger." },
54
Jim Ingham34e9a982010-06-15 18:47:14 +000055 { LLDB_OPT_SET_2, true, "version", 'v', no_argument, NULL, NULL, NULL,
Chris Lattner24943d22010-06-08 16:52:24 +000056 "Prints out the current version number of the LLDB debugger." },
57
Jim Ingham34e9a982010-06-15 18:47:14 +000058 { LLDB_OPT_SET_3, false, "arch", 'a', required_argument, NULL, NULL, "<architecture>",
Chris Lattner24943d22010-06-08 16:52:24 +000059 "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." },
60
Jim Ingham34e9a982010-06-15 18:47:14 +000061 { LLDB_OPT_SET_3 | LLDB_OPT_SET_4, false, "script-language",'l', required_argument, NULL, NULL, "<scripting-language>",
Chris Lattner24943d22010-06-08 16:52:24 +000062 "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." },
63
Jim Ingham34e9a982010-06-15 18:47:14 +000064 { LLDB_OPT_SET_3 | LLDB_OPT_SET_4, false, "debug", 'd', no_argument, NULL, NULL, NULL,
Chris Lattner24943d22010-06-08 16:52:24 +000065 "Tells the debugger to print out extra information for debugging itself." },
66
Jim Ingham34e9a982010-06-15 18:47:14 +000067 { LLDB_OPT_SET_3 | LLDB_OPT_SET_4, false, "source", 's', required_argument, NULL, NULL, "<file>",
Chris Lattner24943d22010-06-08 16:52:24 +000068 "Tells the debugger to read in and execute the file <file>, which should contain lldb commands." },
69
Jim Ingham34e9a982010-06-15 18:47:14 +000070 { LLDB_OPT_SET_3, false, "file", 'f', required_argument, NULL, NULL, "<filename>",
71 "Tells the debugger to use the file <filename> as the program to be debugged." },
72
73 { LLDB_OPT_SET_4, false, "crash-log", 'c', required_argument, NULL, NULL, "<file>",
Chris Lattner24943d22010-06-08 16:52:24 +000074 "Load executable images from a crash log for symbolication." },
75
76 { 0, false, NULL, 0, 0, NULL, NULL, NULL, NULL }
77};
78
79
80Driver::Driver () :
81 SBBroadcaster ("Driver"),
Greg Clayton63094e02010-06-23 01:19:29 +000082 m_debugger (SBDebugger::Create()),
Chris Lattner24943d22010-06-08 16:52:24 +000083 m_editline_pty (),
84 m_editline_slave_fh (NULL),
85 m_editline_reader (),
86 m_io_channel_ap (),
87 m_option_data (),
88 m_waiting_for_command (false)
89{
90}
91
92Driver::~Driver ()
93{
94}
95
96void
97Driver::CloseIOChannelFile ()
98{
99 // Write and End of File sequence to the file descriptor to ensure any
100 // read functions can exit.
101 char eof_str[] = "\x04";
102 ::write (m_editline_pty.GetMasterFileDescriptor(), eof_str, strlen(eof_str));
103
104 m_editline_pty.CloseMasterFileDescriptor();
105
106 if (m_editline_slave_fh)
107 {
108 ::fclose (m_editline_slave_fh);
109 m_editline_slave_fh = NULL;
110 }
111}
112
113// This function takes INDENT, which tells how many spaces to output at the front of each line; SPACES, which is
114// a string that is output_max_columns long, containing spaces; and TEXT, which is the text that is to be output.
115// It outputs the text, on multiple lines if necessary, to RESULT, with INDENT spaces at the front of each line. It
116// breaks lines on spaces, tabs or newlines, shortening the line if necessary to not break in the middle of a word.
117// It assumes that each output line should contain a maximum of OUTPUT_MAX_COLUMNS characters.
118
119void
120OutputFormattedUsageText (FILE *out, int indent, char *spaces, const char *text, int output_max_columns)
121{
122 int len = strlen (text);
123 std::string text_string (text);
124 std::string spaces_string (spaces);
125
126 // Force indentation to be reasonable.
127 if (indent >= output_max_columns)
128 indent = 0;
129
130 // Will it all fit on one line?
131
132 if (len + indent < output_max_columns)
133 // Output as a single line
134 fprintf (out, "%s%s\n", spaces_string.substr (0, indent).c_str(), text);
135 else
136 {
137 // We need to break it up into multiple lines.
138 int text_width = output_max_columns - indent - 1;
139 int start = 0;
140 int end = start;
141 int final_end = len;
142 int sub_len;
143
144 while (end < final_end)
145 {
146 // Dont start the 'text' on a space, since we're already outputting the indentation.
147 while ((start < final_end) && (text[start] == ' '))
148 start++;
149
150 end = start + text_width;
151 if (end > final_end)
152 end = final_end;
153 else
154 {
155 // If we're not at the end of the text, make sure we break the line on white space.
156 while (end > start
157 && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
158 end--;
159 }
160 sub_len = end - start;
161 std::string substring = text_string.substr (start, sub_len);
162 fprintf (out, "%s%s\n", spaces_string.substr(0, indent).c_str(), substring.c_str());
163 start = end + 1;
164 }
165 }
166}
167
168void
169ShowUsage (FILE *out, lldb::OptionDefinition *option_table, Driver::OptionData data)
170{
171 uint32_t screen_width = 80;
172 uint32_t indent_level = 0;
173 const char *name = "lldb";
174 char spaces[screen_width+1];
175 uint32_t i;
Jim Ingham34e9a982010-06-15 18:47:14 +0000176
Chris Lattner24943d22010-06-08 16:52:24 +0000177 for (i = 0; i < screen_width; ++i)
178 spaces[i] = ' ';
179 spaces[i] = '\n';
180
181 std::string spaces_string (spaces);
182
183 fprintf (out, "\nUsage:\n\n");
184
185 indent_level += 2;
186
187
188 // First, show each usage level set of options, e.g. <cmd> [options-for-level-0]
189 // <cmd> [options-for-level-1]
190 // etc.
191
Chris Lattner24943d22010-06-08 16:52:24 +0000192 uint32_t num_options;
Jim Ingham34e9a982010-06-15 18:47:14 +0000193 uint32_t num_option_sets = 0;
194
195 for (num_options = 0; option_table[num_options].long_option != NULL; ++num_options)
Chris Lattner24943d22010-06-08 16:52:24 +0000196 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000197 uint32_t this_usage_mask = option_table[num_options].usage_mask;
198 if (this_usage_mask == LLDB_OPT_SET_ALL)
Chris Lattner24943d22010-06-08 16:52:24 +0000199 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000200 if (num_option_sets == 0)
201 num_option_sets = 1;
Chris Lattner24943d22010-06-08 16:52:24 +0000202 }
203 else
204 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000205 for (int j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++)
206 {
207 if (this_usage_mask & 1 << j)
208 {
209 if (num_option_sets <= j)
210 num_option_sets = j + 1;
211 }
212 }
213 }
214 }
215
216 for (uint32_t opt_set = 0; opt_set < num_option_sets; opt_set++)
217 {
218 uint32_t opt_set_mask;
219
220 opt_set_mask = 1 << opt_set;
221
222 if (opt_set > 0)
223 fprintf (out, "\n");
224 fprintf (out, "%s%s", spaces_string.substr(0, indent_level).c_str(), name);
225
226 for (uint32_t i = 0; i < num_options; ++i)
227 {
228 if (option_table[i].usage_mask & opt_set_mask)
229 {
230 if (option_table[i].required)
231 {
232 if (option_table[i].option_has_arg == required_argument)
233 fprintf (out, " -%c %s", option_table[i].short_option, option_table[i].argument_name);
234 else if (option_table[i].option_has_arg == optional_argument)
235 fprintf (out, " -%c [%s]", option_table[i].short_option, option_table[i].argument_name);
236 else
237 fprintf (out, " -%c", option_table[i].short_option);
238 }
239 else
240 {
241 if (option_table[i].option_has_arg == required_argument)
242 fprintf (out, " [-%c %s]", option_table[i].short_option, option_table[i].argument_name);
243 else if (option_table[i].option_has_arg == optional_argument)
244 fprintf (out, " [-%c [%s]]", option_table[i].short_option, option_table[i].argument_name);
245 else
246 fprintf (out, " [-%c]", option_table[i].short_option);
247 }
248 }
Chris Lattner24943d22010-06-08 16:52:24 +0000249 }
250 }
251
252 fprintf (out, "\n\n");
253
254 // Now print out all the detailed information about the various options: long form, short form and help text:
255 // -- long_name <argument>
256 // - short <argument>
257 // help text
258
259 // This variable is used to keep track of which options' info we've printed out, because some options can be in
260 // more than one usage level, but we only want to print the long form of its information once.
261
262 Driver::OptionData::OptionSet options_seen;
263 Driver::OptionData::OptionSet::iterator pos;
264
265 indent_level += 5;
266
Jim Ingham34e9a982010-06-15 18:47:14 +0000267 for (uint32_t i = 0; i < num_options; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000268 {
269 // Only print this option if we haven't already seen it.
270 pos = options_seen.find (option_table[i].short_option);
271 if (pos == options_seen.end())
272 {
273 options_seen.insert (option_table[i].short_option);
274 fprintf (out, "%s-%c ", spaces_string.substr(0, indent_level).c_str(), option_table[i].short_option);
275 if (option_table[i].argument_name != NULL)
276 fprintf (out, "%s", option_table[i].argument_name);
277 fprintf (out, "\n");
278 fprintf (out, "%s--%s ", spaces_string.substr(0, indent_level).c_str(), option_table[i].long_option);
279 if (option_table[i].argument_name != NULL)
280 fprintf (out, "%s", option_table[i].argument_name);
281 fprintf (out, "\n");
282 indent_level += 5;
283 OutputFormattedUsageText (out, indent_level, spaces, option_table[i].usage_text, screen_width);
284 indent_level -= 5;
285 fprintf (out, "\n");
286 }
287 }
288
289 indent_level -= 5;
290
291 fprintf (out, "\n%s('%s <filename>' also works, to specify the file to be debugged.)\n\n",
292 spaces_string.substr(0, indent_level).c_str(), name);
293}
294
295void
296BuildGetOptTable (lldb::OptionDefinition *expanded_option_table, struct option **getopt_table, int num_options)
297{
298 if (num_options == 0)
299 return;
300
301 uint32_t i;
302 uint32_t j;
303 std::bitset<256> option_seen;
304
305 for (i = 0, j = 0; i < num_options; ++i)
306 {
307 char short_opt = expanded_option_table[i].short_option;
308
309 if (option_seen.test(short_opt) == false)
310 {
311 (*getopt_table)[j].name = expanded_option_table[i].long_option;
312 (*getopt_table)[j].has_arg = expanded_option_table[i].option_has_arg;
313 (*getopt_table)[j].flag = NULL;
314 (*getopt_table)[j].val = expanded_option_table[i].short_option;
315 option_seen.set(short_opt);
316 ++j;
317 }
318 }
319
320 (*getopt_table)[j].name = NULL;
321 (*getopt_table)[j].has_arg = 0;
322 (*getopt_table)[j].flag = NULL;
323 (*getopt_table)[j].val = 0;
324
325}
326
Greg Clayton63094e02010-06-23 01:19:29 +0000327Driver::OptionData::OptionData () :
328 m_filename(),
329 m_script_lang (lldb::eScriptLanguageDefault),
330 m_source_command_files (),
331 m_debug_mode (false),
332 m_print_help (false),
333 m_print_version (false)
334
Chris Lattner24943d22010-06-08 16:52:24 +0000335{
Greg Clayton63094e02010-06-23 01:19:29 +0000336}
337
338Driver::OptionData::~OptionData ()
339{
340}
341
342void
343Driver::OptionData::Clear ()
344{
345 m_filename.clear ();
346 m_script_lang = lldb::eScriptLanguageDefault;
347 m_source_command_files.clear ();
348 m_debug_mode = false;
349 m_print_help = false;
350 m_print_version = false;
351}
352
353void
354Driver::ResetOptionValues ()
355{
356 m_option_data.Clear ();
357}
358
359const char *
360Driver::GetFilename() const
361{
362 if (m_option_data.m_filename.empty())
363 return NULL;
364 return m_option_data.m_filename.c_str();
365}
366
367const char *
368Driver::GetCrashLogFilename() const
369{
370 if (m_option_data.m_crash_log.empty())
371 return NULL;
372 return m_option_data.m_crash_log.c_str();
373}
374
375lldb::ScriptLanguage
376Driver::GetScriptLanguage() const
377{
378 return m_option_data.m_script_lang;
379}
380
381size_t
382Driver::GetNumSourceCommandFiles () const
383{
384 return m_option_data.m_source_command_files.size();
385}
386
387const char *
388Driver::GetSourceCommandFileAtIndex (uint32_t idx) const
389{
390 if (idx < m_option_data.m_source_command_files.size())
391 return m_option_data.m_source_command_files[idx].c_str();
392 return NULL;
393}
394
395bool
396Driver::GetDebugMode() const
397{
398 return m_option_data.m_debug_mode;
399}
400
401
402// Check the arguments that were passed to this program to make sure they are valid and to get their
403// argument values (if any). Return a boolean value indicating whether or not to start up the full
404// debugger (i.e. the Command Interpreter) or not. Return FALSE if the arguments were invalid OR
405// if the user only wanted help or version information.
406
407SBError
408Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exit)
409{
410 ResetOptionValues ();
411
412 SBCommandReturnObject result;
413
Chris Lattner24943d22010-06-08 16:52:24 +0000414 SBError error;
415 std::string option_string;
416 struct option *long_options = NULL;
417 int num_options;
418
419 for (num_options = 0; g_options[num_options].long_option != NULL; ++num_options);
420
421 if (num_options == 0)
422 {
423 if (argc > 1)
424 error.SetErrorStringWithFormat ("invalid number of options");
425 return error;
426 }
427
428 long_options = (struct option *) malloc ((num_options + 1) * sizeof (struct option));
429
430 BuildGetOptTable (g_options, &long_options, num_options);
431
432 if (long_options == NULL)
433 {
434 error.SetErrorStringWithFormat ("invalid long options");
435 return error;
436 }
437
438 // Build the option_string argument for call to getopt_long.
439
440 for (int i = 0; long_options[i].name != NULL; ++i)
441 {
442 if (long_options[i].flag == NULL)
443 {
444 option_string.push_back ((char) long_options[i].val);
445 switch (long_options[i].has_arg)
446 {
447 default:
448 case no_argument:
449 break;
450 case required_argument:
451 option_string.push_back (':');
452 break;
453 case optional_argument:
454 option_string.append ("::");
455 break;
456 }
457 }
458 }
459
460 // Prepare for & make calls to getopt_long.
Eli Friedmanef2bc872010-06-13 19:18:49 +0000461#if __GLIBC__
462 optind = 0;
463#else
Chris Lattner24943d22010-06-08 16:52:24 +0000464 optreset = 1;
465 optind = 1;
Eli Friedmanef2bc872010-06-13 19:18:49 +0000466#endif
Chris Lattner24943d22010-06-08 16:52:24 +0000467 int val;
468 while (1)
469 {
470 int long_options_index = -1;
471 val = ::getopt_long (argc, (char * const *) argv, option_string.c_str(), long_options, &long_options_index);
472
473 if (val == -1)
474 break;
475 else if (val == '?')
476 {
Greg Clayton63094e02010-06-23 01:19:29 +0000477 m_option_data.m_print_help = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000478 error.SetErrorStringWithFormat ("unknown or ambiguous option");
479 break;
480 }
481 else if (val == 0)
482 continue;
483 else
484 {
Greg Clayton63094e02010-06-23 01:19:29 +0000485 m_option_data.m_seen_options.insert ((char) val);
Chris Lattner24943d22010-06-08 16:52:24 +0000486 if (long_options_index == -1)
487 {
488 for (int i = 0;
489 long_options[i].name || long_options[i].has_arg || long_options[i].flag || long_options[i].val;
490 ++i)
491 {
492 if (long_options[i].val == val)
493 {
494 long_options_index = i;
495 break;
496 }
497 }
498 }
499
500 if (long_options_index >= 0)
501 {
Greg Clayton63094e02010-06-23 01:19:29 +0000502 const char short_option = (char) g_options[long_options_index].short_option;
503
504 switch (short_option)
505 {
506 case 'h':
507 m_option_data.m_print_help = true;
508 break;
509
510 case 'v':
511 m_option_data.m_print_version = true;
512 break;
513
514 case 'c':
515 m_option_data.m_crash_log = optarg;
516 break;
517
518 case 'f':
519 {
520 SBFileSpec file(optarg);
521 if (file.Exists())
522 m_option_data.m_filename = optarg;
523 else
524 error.SetErrorStringWithFormat("file specified in --file (-f) option doesn't exist: '%s'", optarg);
525 }
526 break;
527
528 case 'a':
529 if (!m_debugger.SetDefaultArchitecture (optarg))
530 error.SetErrorStringWithFormat("invalid architecture in the -a or --arch option: '%s'", optarg);
531 break;
532
533 case 'l':
534 m_option_data.m_script_lang = m_debugger.GetScriptingLanguage (optarg);
535 break;
536
537 case 'd':
538 m_option_data.m_debug_mode = true;
539 break;
540
541 case 's':
542 {
543 SBFileSpec file(optarg);
544 if (file.Exists())
545 m_option_data.m_source_command_files.push_back (optarg);
546 else
547 error.SetErrorStringWithFormat("file specified in --source (-s) option doesn't exist: '%s'", optarg);
548 }
549 break;
550
551 default:
552 m_option_data.m_print_help = true;
553 error.SetErrorStringWithFormat ("unrecognized option %c", short_option);
554 break;
555 }
Chris Lattner24943d22010-06-08 16:52:24 +0000556 }
557 else
558 {
559 error.SetErrorStringWithFormat ("invalid option with value %i", val);
560 }
561 if (error.Fail())
Greg Clayton63094e02010-06-23 01:19:29 +0000562 return error;
Chris Lattner24943d22010-06-08 16:52:24 +0000563 }
564 }
Jim Ingham34e9a982010-06-15 18:47:14 +0000565
566 // If there is a trailing argument, it is the filename.
567 if (optind == argc - 1)
568 {
569 if (m_option_data.m_filename.empty())
Chris Lattner24943d22010-06-08 16:52:24 +0000570 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000571 m_option_data.m_filename = argv[optind];
Chris Lattner24943d22010-06-08 16:52:24 +0000572 }
Jim Ingham34e9a982010-06-15 18:47:14 +0000573 else
574 {
Greg Clayton63094e02010-06-23 01:19:29 +0000575 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 +0000576 }
577
Chris Lattner24943d22010-06-08 16:52:24 +0000578 }
Jim Ingham34e9a982010-06-15 18:47:14 +0000579 else if (optind < argc - 1)
580 {
581 // Trailing extra arguments...
Greg Clayton63094e02010-06-23 01:19:29 +0000582 error.SetErrorStringWithFormat ("error: trailing extra arguments - only one the filename is allowed.");
Jim Ingham34e9a982010-06-15 18:47:14 +0000583 }
584
Greg Clayton63094e02010-06-23 01:19:29 +0000585 if (error.Fail() || m_option_data.m_print_help)
Chris Lattner24943d22010-06-08 16:52:24 +0000586 {
587 ShowUsage (out_fh, g_options, m_option_data);
Chris Lattner24943d22010-06-08 16:52:24 +0000588 }
589 else if (m_option_data.m_print_version)
590 {
Greg Clayton63094e02010-06-23 01:19:29 +0000591 ::fprintf (out_fh, "%s\n", m_debugger.GetVersionString());
592 exit = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000593 }
594 else if (! m_option_data.m_crash_log.empty())
595 {
596 // Handle crash log stuff here.
597 }
598 else
599 {
600 // All other combinations are valid; do nothing more here.
601 }
602
Greg Clayton63094e02010-06-23 01:19:29 +0000603 return error;
Chris Lattner24943d22010-06-08 16:52:24 +0000604}
605
606void
607Driver::GetProcessSTDOUT ()
608{
609 // The process has stuff waiting for stdout; get it and write it out to the appropriate place.
610 char stdio_buffer[1024];
611 size_t len;
Greg Clayton63094e02010-06-23 01:19:29 +0000612 while ((len = m_debugger.GetCurrentTarget().GetProcess().GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0)
Chris Lattner24943d22010-06-08 16:52:24 +0000613 m_io_channel_ap->OutWrite (stdio_buffer, len);
614}
615
616void
617Driver::GetProcessSTDERR ()
618{
619 // The process has stuff waiting for stderr; get it and write it out to the appropriate place.
620 char stdio_buffer[1024];
621 size_t len;
Greg Clayton63094e02010-06-23 01:19:29 +0000622 while ((len = m_debugger.GetCurrentTarget().GetProcess().GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0)
Chris Lattner24943d22010-06-08 16:52:24 +0000623 m_io_channel_ap->ErrWrite (stdio_buffer, len);
624}
625
626void
627Driver::UpdateCurrentThread ()
628{
629 using namespace lldb;
Greg Clayton63094e02010-06-23 01:19:29 +0000630 SBProcess process(m_debugger.GetCurrentTarget().GetProcess());
Chris Lattner24943d22010-06-08 16:52:24 +0000631 if (process.IsValid())
632 {
633 SBThread curr_thread (process.GetCurrentThread());
634 SBThread thread;
635 StopReason curr_thread_stop_reason = eStopReasonInvalid;
636 curr_thread_stop_reason = curr_thread.GetStopReason();
637
638 if (!curr_thread.IsValid() ||
639 curr_thread_stop_reason == eStopReasonInvalid ||
640 curr_thread_stop_reason == eStopReasonNone)
641 {
642 // Prefer a thread that has just completed its plan over another thread as current thread.
643 SBThread plan_thread;
644 SBThread other_thread;
645 const size_t num_threads = process.GetNumThreads();
646 size_t i;
647 for (i = 0; i < num_threads; ++i)
648 {
649 thread = process.GetThreadAtIndex(i);
650 StopReason thread_stop_reason = thread.GetStopReason();
651 switch (thread_stop_reason)
652 {
653 default:
654 case eStopReasonInvalid:
655 case eStopReasonNone:
656 break;
657
658 case eStopReasonTrace:
659 case eStopReasonBreakpoint:
660 case eStopReasonWatchpoint:
661 case eStopReasonSignal:
662 case eStopReasonException:
663 if (!other_thread.IsValid())
664 other_thread = thread;
665 break;
666 case eStopReasonPlanComplete:
667 if (!plan_thread.IsValid())
668 plan_thread = thread;
669 break;
670 }
671 }
672 if (plan_thread.IsValid())
673 process.SetCurrentThread (plan_thread);
674 else if (other_thread.IsValid())
675 process.SetCurrentThread (other_thread);
676 else
677 {
678 if (curr_thread.IsValid())
679 thread = curr_thread;
680 else
681 thread = process.GetThreadAtIndex(0);
682
683 if (thread.IsValid())
684 process.SetCurrentThread (thread);
685 }
686 }
687 }
688}
689
690
691// This function handles events that were broadcast by the process.
692void
693Driver::HandleProcessEvent (const SBEvent &event)
694{
695 using namespace lldb;
696 const uint32_t event_type = event.GetType();
697
698 if (event_type & SBProcess::eBroadcastBitSTDOUT)
699 {
700 // The process has stdout available, get it and write it out to the
701 // appropriate place.
702 GetProcessSTDOUT ();
703 }
704 else if (event_type & SBProcess::eBroadcastBitSTDERR)
705 {
706 // The process has stderr available, get it and write it out to the
707 // appropriate place.
708 GetProcessSTDERR ();
709 }
710 else if (event_type & SBProcess::eBroadcastBitStateChanged)
711 {
712 // Drain all stout and stderr so we don't see any output come after
713 // we print our prompts
714 GetProcessSTDOUT ();
715 GetProcessSTDERR ();
716
717 // Something changed in the process; get the event and report the process's current status and location to
718 // the user.
719 StateType event_state = SBProcess::GetStateFromEvent (event);
720 if (event_state == eStateInvalid)
721 return;
722
723 SBProcess process (SBProcess::GetProcessFromEvent (event));
724 assert (process.IsValid());
725
726 switch (event_state)
727 {
728 case eStateInvalid:
729 case eStateUnloaded:
730 case eStateAttaching:
731 case eStateLaunching:
732 case eStateStepping:
733 case eStateDetached:
734 {
735 char message[1024];
736 int message_len = ::snprintf (message, sizeof(message), "Process %d %s\n", process.GetProcessID(),
Greg Clayton63094e02010-06-23 01:19:29 +0000737 m_debugger.StateAsCString (event_state));
Chris Lattner24943d22010-06-08 16:52:24 +0000738 m_io_channel_ap->OutWrite(message, message_len);
739 }
740 break;
741
742 case eStateRunning:
743 // Don't be chatty when we run...
744 break;
745
746 case eStateExited:
Greg Clayton63094e02010-06-23 01:19:29 +0000747 m_debugger.HandleCommand("process status");
Chris Lattner24943d22010-06-08 16:52:24 +0000748 m_io_channel_ap->RefreshPrompt();
749 break;
750
751 case eStateStopped:
752 case eStateCrashed:
753 case eStateSuspended:
754 // Make sure the program hasn't been auto-restarted:
755 if (SBProcess::GetRestartedFromEvent (event))
756 {
757 // FIXME: Do we want to report this, or would that just be annoyingly chatty?
758 char message[1024];
759 int message_len = ::snprintf (message, sizeof(message), "Process %d stopped and was programmatically restarted.\n",
760 process.GetProcessID());
761 m_io_channel_ap->OutWrite(message, message_len);
762 }
763 else
764 {
765 UpdateCurrentThread ();
Greg Clayton63094e02010-06-23 01:19:29 +0000766 m_debugger.HandleCommand("process status");
Chris Lattner24943d22010-06-08 16:52:24 +0000767 m_io_channel_ap->RefreshPrompt();
768 }
769 break;
770 }
771 }
772}
773
774// This function handles events broadcast by the IOChannel (HasInput, UserInterrupt, or ThreadShouldExit).
775
776bool
777Driver::HandleIOEvent (const SBEvent &event)
778{
779 bool quit = false;
780
781 const uint32_t event_type = event.GetType();
782
783 if (event_type & IOChannel::eBroadcastBitHasUserInput)
784 {
785 // We got some input (i.e. a command string) from the user; pass it off to the command interpreter for
786 // handling.
787
788 const char *command_string = SBEvent::GetCStringFromEvent(event);
789 if (command_string == NULL)
790 command_string == "";
791 SBCommandReturnObject result;
Greg Clayton63094e02010-06-23 01:19:29 +0000792 if (m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, true) != lldb::eReturnStatusQuit)
Chris Lattner24943d22010-06-08 16:52:24 +0000793 {
794 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize());
795 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize());
796 }
797 // We are done getting and running our command, we can now clear the
798 // m_waiting_for_command so we can get another one.
799 m_waiting_for_command = false;
800
801 // If our editline input reader is active, it means another input reader
802 // got pushed onto the input reader and caused us to become deactivated.
803 // When the input reader above us gets popped, we will get re-activated
804 // and our prompt will refresh in our callback
805 if (m_editline_reader.IsActive())
806 {
807 ReadyForCommand ();
808 }
809 }
810 else if (event_type & IOChannel::eBroadcastBitUserInterrupt)
811 {
812 // This is here to handle control-c interrupts from the user. It has not yet really been implemented.
813 // TO BE DONE: PROPERLY HANDLE CONTROL-C FROM USER
814 //m_io_channel_ap->CancelInput();
815 // Anything else? Send Interrupt to process?
816 }
817 else if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
818 (event_type & IOChannel::eBroadcastBitThreadDidExit))
819 {
820 // If the IOChannel thread is trying to go away, then it is definitely
821 // time to end the debugging session.
822 quit = true;
823 }
824
825 return quit;
826}
827
828
829//struct CrashImageInfo
830//{
831// std::string path;
832// VMRange text_range;
833// UUID uuid;
834//};
835//
836//void
837//Driver::ParseCrashLog (const char *crash_log)
838//{
839// printf("Parsing crash log: %s\n", crash_log);
840//
841// char image_path[PATH_MAX];
842// std::vector<CrashImageInfo> crash_infos;
843// if (crash_log && crash_log[0])
844// {
845// FileSpec crash_log_file (crash_log);
846// STLStringArray crash_log_lines;
847// if (crash_log_file.ReadFileLines (crash_log_lines))
848// {
849// const size_t num_crash_log_lines = crash_log_lines.size();
850// size_t i;
851// for (i=0; i<num_crash_log_lines; ++i)
852// {
853// const char *line = crash_log_lines[i].c_str();
854// if (strstr (line, "Code Type:"))
855// {
856// char arch_string[256];
857// if (sscanf(line, "%s", arch_string))
858// {
859// if (strcmp(arch_string, "X86-64"))
860// lldb::GetDefaultArchitecture ().SetArch ("x86_64");
861// else if (strcmp(arch_string, "X86"))
862// lldb::GetDefaultArchitecture ().SetArch ("i386");
863// else
864// {
865// ArchSpec arch(arch_string);
866// if (arch.IsValid ())
867// lldb::GetDefaultArchitecture () = arch;
868// else
869// fprintf(stderr, "Unrecognized architecture: %s\n", arch_string);
870// }
871// }
872// }
873// else
874// if (strstr(line, "Path:"))
875// {
876// const char *p = line + strlen("Path:");
877// while (isspace(*p))
878// ++p;
879//
880// m_option_data.m_filename.assign (p);
881// }
882// else
883// if (strstr(line, "Binary Images:"))
884// {
885// while (++i < num_crash_log_lines)
886// {
887// if (crash_log_lines[i].empty())
888// break;
889//
890// line = crash_log_lines[i].c_str();
891// uint64_t text_start_addr;
892// uint64_t text_end_addr;
893// char uuid_cstr[64];
894// int bytes_consumed_before_uuid = 0;
895// int bytes_consumed_after_uuid = 0;
896//
897// int items_parsed = ::sscanf (line,
898// "%llx - %llx %*s %*s %*s %n%s %n",
899// &text_start_addr,
900// &text_end_addr,
901// &bytes_consumed_before_uuid,
902// uuid_cstr,
903// &bytes_consumed_after_uuid);
904//
905// if (items_parsed == 3)
906// {
907//
908// CrashImageInfo info;
909// info.text_range.SetBaseAddress(text_start_addr);
910// info.text_range.SetEndAddress(text_end_addr);
911//
912// if (uuid_cstr[0] == '<')
913// {
914// if (info.uuid.SetfromCString (&uuid_cstr[1]) == 0)
915// info.uuid.Clear();
916//
917// ::strncpy (image_path, line + bytes_consumed_after_uuid, sizeof(image_path));
918// }
919// else
920// {
921// ::strncpy (image_path, line + bytes_consumed_before_uuid, sizeof(image_path));
922// }
923//
924// info.path = image_path;
925//
926// crash_infos.push_back (info);
927//
928// info.uuid.GetAsCString(uuid_cstr, sizeof(uuid_cstr));
929//
930// printf("0x%16.16llx - 0x%16.16llx <%s> %s\n",
931// text_start_addr,
932// text_end_addr,
933// uuid_cstr,
934// image_path);
935// }
936// }
937// }
938// }
939// }
940//
941// if (crash_infos.size())
942// {
Greg Clayton63094e02010-06-23 01:19:29 +0000943// SBTarget target (m_debugger.CreateTarget (crash_infos.front().path.c_str(),
Chris Lattner24943d22010-06-08 16:52:24 +0000944// lldb::GetDefaultArchitecture().AsCString (),
945// false));
946// if (target.IsValid())
947// {
948//
949// }
950// }
951// }
952//}
953//
954
955void
956Driver::MasterThreadBytesReceived (void *baton, const void *src, size_t src_len)
957{
958 Driver *driver = (Driver*)baton;
959 driver->GetFromMaster ((const char *)src, src_len);
960}
961
962void
963Driver::GetFromMaster (const char *src, size_t src_len)
964{
965 // Echo the characters back to the Debugger's stdout, that way if you
966 // type characters while a command is running, you'll see what you've typed.
Greg Clayton63094e02010-06-23 01:19:29 +0000967 FILE *out_fh = m_debugger.GetOutputFileHandle();
Chris Lattner24943d22010-06-08 16:52:24 +0000968 if (out_fh)
969 ::fwrite (src, 1, src_len, out_fh);
970}
971
972size_t
973Driver::EditLineInputReaderCallback
974(
975 void *baton,
976 SBInputReader *reader,
977 InputReaderAction notification,
978 const char *bytes,
979 size_t bytes_len
980)
981{
982 Driver *driver = (Driver *)baton;
983
984 switch (notification)
985 {
986 case eInputReaderActivate:
987 break;
988
989 case eInputReaderReactivate:
990 driver->ReadyForCommand();
991 break;
992
993 case eInputReaderDeactivate:
994 break;
995
996 case eInputReaderGotToken:
997 write (driver->m_editline_pty.GetMasterFileDescriptor(), bytes, bytes_len);
998 break;
999
1000 case eInputReaderDone:
1001 break;
1002 }
1003 return bytes_len;
1004}
1005
1006void
1007Driver::MainLoop ()
1008{
1009 char error_str[1024];
1010 if (m_editline_pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, error_str, sizeof(error_str)) == false)
1011 {
1012 ::fprintf (stderr, "error: failed to open driver pseudo terminal : %s", error_str);
1013 exit(1);
1014 }
1015 else
1016 {
1017 const char *driver_slave_name = m_editline_pty.GetSlaveName (error_str, sizeof(error_str));
1018 if (driver_slave_name == NULL)
1019 {
1020 ::fprintf (stderr, "error: failed to get slave name for driver pseudo terminal : %s", error_str);
1021 exit(2);
1022 }
1023 else
1024 {
1025 m_editline_slave_fh = ::fopen (driver_slave_name, "r+");
1026 if (m_editline_slave_fh == NULL)
1027 {
1028 SBError error;
1029 error.SetErrorToErrno();
1030 ::fprintf (stderr, "error: failed to get open slave for driver pseudo terminal : %s",
1031 error.GetCString());
1032 exit(3);
1033 }
1034
1035 ::setbuf (m_editline_slave_fh, NULL);
1036 }
1037 }
1038
1039
1040 // struct termios stdin_termios;
1041
1042 if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0)
1043 atexit (reset_stdin_termios);
1044
1045 ::setbuf (stdin, NULL);
1046 ::setbuf (stdout, NULL);
1047
Greg Clayton63094e02010-06-23 01:19:29 +00001048 m_debugger.SetErrorFileHandle (stderr, false);
1049 m_debugger.SetOutputFileHandle (stdout, false);
1050 m_debugger.SetInputFileHandle (stdin, true);
Chris Lattner24943d22010-06-08 16:52:24 +00001051
1052 // You have to drain anything that comes to the master side of the PTY. master_out_comm is
1053 // for that purpose. The reason you need to do this is a curious reason... editline will echo
1054 // characters to the PTY when it gets characters while el_gets is not running, and then when
1055 // you call el_gets (or el_getc) it will try to reset the terminal back to raw mode which blocks
1056 // if there are unconsumed characters in the out buffer.
1057 // However, you don't need to do anything with the characters, since editline will dump these
1058 // unconsumed characters after printing the prompt again in el_gets.
1059
1060 SBCommunication master_out_comm("driver.editline");
1061 master_out_comm.AdoptFileDesriptor(m_editline_pty.GetMasterFileDescriptor(), false);
1062 master_out_comm.SetReadThreadBytesReceivedCallback(Driver::MasterThreadBytesReceived, this);
1063
1064 if (master_out_comm.ReadThreadStart () == false)
1065 {
1066 ::fprintf (stderr, "error: failed to start master out read thread");
1067 exit(5);
1068 }
1069
1070// const char *crash_log = GetCrashLogFilename();
1071// if (crash_log)
1072// {
1073// ParseCrashLog (crash_log);
1074// }
1075//
Greg Clayton63094e02010-06-23 01:19:29 +00001076 SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter();
Chris Lattner24943d22010-06-08 16:52:24 +00001077
1078 m_io_channel_ap.reset (new IOChannel(m_editline_slave_fh, stdout, stderr, this));
1079
1080 struct winsize window_size;
1081 if (isatty (STDIN_FILENO)
1082 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
1083 {
1084 char buffer[25];
1085
1086 sprintf (buffer, "set term-width %d", window_size.ws_col);
Greg Clayton63094e02010-06-23 01:19:29 +00001087 m_debugger.HandleCommand ((const char *) buffer);
Chris Lattner24943d22010-06-08 16:52:24 +00001088 }
1089
1090 // Since input can be redirected by the debugger, we must insert our editline
1091 // input reader in the queue so we know when our reader should be active
1092 // and so we can receive bytes only when we are supposed to.
Greg Clayton63094e02010-06-23 01:19:29 +00001093 SBError err (m_editline_reader.Initialize (m_debugger,
1094 Driver::EditLineInputReaderCallback, // callback
Chris Lattner24943d22010-06-08 16:52:24 +00001095 this, // baton
1096 eInputReaderGranularityByte, // token_size
1097 NULL, // end token - NULL means never done
1098 NULL, // prompt - taken care of elsewhere
1099 false)); // echo input - don't need Debugger
1100 // to do this, we handle it elsewhere
1101
1102 if (err.Fail())
1103 {
1104 ::fprintf (stderr, "error: %s", err.GetCString());
1105 exit (6);
1106 }
1107
Greg Clayton63094e02010-06-23 01:19:29 +00001108 m_debugger.PushInputReader (m_editline_reader);
Chris Lattner24943d22010-06-08 16:52:24 +00001109
Greg Clayton63094e02010-06-23 01:19:29 +00001110 SBListener listener(m_debugger.GetListener());
Chris Lattner24943d22010-06-08 16:52:24 +00001111 if (listener.IsValid())
1112 {
1113
1114 listener.StartListeningForEvents (*m_io_channel_ap,
1115 IOChannel::eBroadcastBitHasUserInput |
1116 IOChannel::eBroadcastBitUserInterrupt |
1117 IOChannel::eBroadcastBitThreadShouldExit |
1118 IOChannel::eBroadcastBitThreadDidStart |
1119 IOChannel::eBroadcastBitThreadDidExit);
1120
1121 if (m_io_channel_ap->Start ())
1122 {
1123 bool iochannel_thread_exited = false;
1124
1125 listener.StartListeningForEvents (sb_interpreter.GetBroadcaster(),
1126 SBCommandInterpreter::eBroadcastBitQuitCommandReceived);
1127
1128 // Before we handle any options from the command line, we parse the
1129 // .lldbinit file in the user's home directory.
1130 SBCommandReturnObject result;
1131 sb_interpreter.SourceInitFileInHomeDirectory(result);
1132 if (GetDebugMode())
1133 {
Greg Clayton63094e02010-06-23 01:19:29 +00001134 result.PutError (m_debugger.GetErrorFileHandle());
1135 result.PutOutput (m_debugger.GetOutputFileHandle());
Chris Lattner24943d22010-06-08 16:52:24 +00001136 }
1137
1138 // Now we handle options we got from the command line
1139 char command_string[PATH_MAX * 2];
1140 const size_t num_source_command_files = GetNumSourceCommandFiles();
1141 if (num_source_command_files > 0)
1142 {
1143 for (size_t i=0; i < num_source_command_files; ++i)
1144 {
1145 const char *command_file = GetSourceCommandFileAtIndex(i);
1146 ::snprintf (command_string, sizeof(command_string), "source '%s'", command_file);
Greg Clayton63094e02010-06-23 01:19:29 +00001147 m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, false);
Chris Lattner24943d22010-06-08 16:52:24 +00001148 if (GetDebugMode())
1149 {
Greg Clayton63094e02010-06-23 01:19:29 +00001150 result.PutError (m_debugger.GetErrorFileHandle());
1151 result.PutOutput (m_debugger.GetOutputFileHandle());
Chris Lattner24943d22010-06-08 16:52:24 +00001152 }
1153 }
1154 }
1155
1156 if (!m_option_data.m_filename.empty())
1157 {
1158 char arch_name[64];
Greg Clayton63094e02010-06-23 01:19:29 +00001159 if (m_debugger.GetDefaultArchitecture (arch_name, sizeof (arch_name)))
Chris Lattner24943d22010-06-08 16:52:24 +00001160 ::snprintf (command_string, sizeof (command_string), "file --arch=%s '%s'", arch_name,
1161 m_option_data.m_filename.c_str());
1162 else
1163 ::snprintf (command_string, sizeof(command_string), "file '%s'", m_option_data.m_filename.c_str());
1164
Greg Clayton63094e02010-06-23 01:19:29 +00001165 m_debugger.HandleCommand (command_string);
Chris Lattner24943d22010-06-08 16:52:24 +00001166 }
1167
1168 // Now that all option parsing is done, we try and parse the .lldbinit
1169 // file in the current working directory
1170 sb_interpreter.SourceInitFileInCurrentWorkingDirectory (result);
1171 if (GetDebugMode())
1172 {
Greg Clayton63094e02010-06-23 01:19:29 +00001173 result.PutError(m_debugger.GetErrorFileHandle());
1174 result.PutOutput(m_debugger.GetOutputFileHandle());
Chris Lattner24943d22010-06-08 16:52:24 +00001175 }
1176
1177 SBEvent event;
1178
1179 // Make sure the IO channel is started up before we try to tell it we
1180 // are ready for input
1181 listener.WaitForEventForBroadcasterWithType (UINT32_MAX,
1182 *m_io_channel_ap,
1183 IOChannel::eBroadcastBitThreadDidStart,
1184 event);
1185
1186 ReadyForCommand ();
1187
1188 bool done = false;
1189 while (!done)
1190 {
1191 listener.WaitForEvent (UINT32_MAX, event);
1192 if (event.IsValid())
1193 {
1194 if (event.GetBroadcaster().IsValid())
1195 {
1196 uint32_t event_type = event.GetType();
1197 if (event.BroadcasterMatchesRef (*m_io_channel_ap))
1198 {
1199 if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
1200 (event_type & IOChannel::eBroadcastBitThreadDidExit))
1201 {
1202 done = true;
1203 if (event_type & IOChannel::eBroadcastBitThreadDidExit)
1204 iochannel_thread_exited = true;
1205 break;
1206 }
1207 else
1208 done = HandleIOEvent (event);
1209 }
Greg Clayton63094e02010-06-23 01:19:29 +00001210 else if (event.BroadcasterMatchesRef (m_debugger.GetCurrentTarget().GetProcess().GetBroadcaster()))
Chris Lattner24943d22010-06-08 16:52:24 +00001211 {
1212 HandleProcessEvent (event);
1213 }
1214 else if (event.BroadcasterMatchesRef (sb_interpreter.GetBroadcaster()))
1215 {
1216 if (event_type & SBCommandInterpreter::eBroadcastBitQuitCommandReceived)
1217 done = true;
1218 }
1219 }
1220 }
1221 }
1222
1223 reset_stdin_termios ();
1224
1225 CloseIOChannelFile ();
1226
1227 if (!iochannel_thread_exited)
1228 {
1229 SBEvent event;
1230 listener.GetNextEventForBroadcasterWithType (*m_io_channel_ap,
1231 IOChannel::eBroadcastBitThreadDidExit,
1232 event);
1233 if (!event.IsValid())
1234 {
1235 // Send end EOF to the driver file descriptor
1236 m_io_channel_ap->Stop();
1237 }
1238 }
1239
Greg Clayton63094e02010-06-23 01:19:29 +00001240 SBProcess process = m_debugger.GetCurrentTarget().GetProcess();
Chris Lattner24943d22010-06-08 16:52:24 +00001241 if (process.IsValid())
1242 process.Destroy();
1243 }
1244 }
1245}
1246
1247
1248void
1249Driver::ReadyForCommand ()
1250{
1251 if (m_waiting_for_command == false)
1252 {
1253 m_waiting_for_command = true;
1254 BroadcastEventByType (Driver::eBroadcastBitReadyForInput, true);
1255 }
1256}
1257
1258
1259int
1260main (int argc, char const *argv[])
1261{
Chris Lattner24943d22010-06-08 16:52:24 +00001262 SBDebugger::Initialize();
1263
1264 SBHostOS::ThreadCreated ("[main]");
1265
Greg Clayton63094e02010-06-23 01:19:29 +00001266 // Create a scope for driver so that the driver object will destroy itself
1267 // before SBDebugger::Terminate() is called.
Chris Lattner24943d22010-06-08 16:52:24 +00001268 {
Greg Clayton63094e02010-06-23 01:19:29 +00001269 Driver driver;
1270
1271 bool exit = false;
1272 SBError error (driver.ParseArgs (argc, argv, stdout, exit));
1273 if (error.Fail())
1274 {
1275 const char *error_cstr = error.GetCString ();
1276 if (error_cstr)
1277 ::fprintf (stderr, "error: %s\n", error_cstr);
1278 }
1279 else if (!exit)
1280 {
1281 driver.MainLoop ();
1282 }
Chris Lattner24943d22010-06-08 16:52:24 +00001283 }
1284
1285 SBDebugger::Terminate();
1286 return 0;
1287}