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