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