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