blob: 6b0beb745badca18269d1964652453e2428e60f8 [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.
Eli Friedmanef2bc872010-06-13 19:18:49 +0000352#if __GLIBC__
353 optind = 0;
354#else
Chris Lattner24943d22010-06-08 16:52:24 +0000355 optreset = 1;
356 optind = 1;
Eli Friedmanef2bc872010-06-13 19:18:49 +0000357#endif
Chris Lattner24943d22010-06-08 16:52:24 +0000358 int val;
359 while (1)
360 {
361 int long_options_index = -1;
362 val = ::getopt_long (argc, (char * const *) argv, option_string.c_str(), long_options, &long_options_index);
363
364 if (val == -1)
365 break;
366 else if (val == '?')
367 {
368 data.m_print_help = true;
369 error.SetErrorStringWithFormat ("unknown or ambiguous option");
370 break;
371 }
372 else if (val == 0)
373 continue;
374 else
375 {
376 data.m_seen_options.insert ((char) val);
377 if (long_options_index == -1)
378 {
379 for (int i = 0;
380 long_options[i].name || long_options[i].has_arg || long_options[i].flag || long_options[i].val;
381 ++i)
382 {
383 if (long_options[i].val == val)
384 {
385 long_options_index = i;
386 break;
387 }
388 }
389 }
390
391 if (long_options_index >= 0)
392 {
393 error = Driver::SetOptionValue (long_options_index,
394 long_options[long_options_index].has_arg == no_argument ? NULL : optarg,
395 data);
396 }
397 else
398 {
399 error.SetErrorStringWithFormat ("invalid option with value %i", val);
400 }
401 if (error.Fail())
402 break;
403 }
404 }
405
406 return error;
407}
408
409Driver::OptionData::OptionData () :
410 m_filename(),
411 m_script_lang (lldb::eScriptLanguageDefault),
412 m_source_command_files (),
413 m_debug_mode (false),
414 m_print_help (false),
415 m_print_version (false)
416
417{
418}
419
420Driver::OptionData::~OptionData ()
421{
422}
423
424void
425Driver::OptionData::Clear ()
426{
427 m_filename.clear ();
428 m_script_lang = lldb::eScriptLanguageDefault;
429 m_source_command_files.clear ();
430 m_debug_mode = false;
431 m_print_help = false;
432 m_print_version = false;
433}
434
435SBError
436Driver::SetOptionValue (int option_idx, const char *option_arg, Driver::OptionData &option_data)
437{
438 SBError error;
439 const char short_option = (char) g_options[option_idx].short_option;
440
441 switch (short_option)
442 {
443 case 'h':
444 option_data.m_print_help = true;
445 break;
446
447 case 'v':
448 option_data.m_print_version = true;
449 break;
450
451 case 'c':
452 option_data.m_crash_log = option_arg;
453 break;
454
455 case 'f':
456 {
457 SBFileSpec file(option_arg);
458 if (file.Exists())
459 option_data.m_filename = option_arg;
460 else
461 error.SetErrorStringWithFormat("file specified in --file (-f) option doesn't exist: '%s'", option_arg);
462 }
463 break;
464
465 case 'a':
466 if (!SBDebugger::SetDefaultArchitecture (option_arg))
467 error.SetErrorStringWithFormat("invalid architecture in the -a or --arch option: '%s'", option_arg);
468 break;
469
470 case 'l':
471 option_data.m_script_lang = SBDebugger::GetScriptingLanguage (option_arg);
472 break;
473
474 case 'd':
475 option_data.m_debug_mode = true;
476 break;
477
478 case 's':
479 {
480 SBFileSpec file(option_arg);
481 if (file.Exists())
482 option_data.m_source_command_files.push_back (option_arg);
483 else
484 error.SetErrorStringWithFormat("file specified in --source (-s) option doesn't exist: '%s'", option_arg);
485 }
486 break;
487
488 default:
489 option_data.m_print_help = true;
490 error.SetErrorStringWithFormat ("unrecognized option %c", short_option);
491 break;
492 }
493
494 return error;
495}
496
497void
498Driver::ResetOptionValues ()
499{
500 m_option_data.Clear ();
501}
502
503const char *
504Driver::GetFilename() const
505{
506 if (m_option_data.m_filename.empty())
507 return NULL;
508 return m_option_data.m_filename.c_str();
509}
510
511const char *
512Driver::GetCrashLogFilename() const
513{
514 if (m_option_data.m_crash_log.empty())
515 return NULL;
516 return m_option_data.m_crash_log.c_str();
517}
518
519lldb::ScriptLanguage
520Driver::GetScriptLanguage() const
521{
522 return m_option_data.m_script_lang;
523}
524
525size_t
526Driver::GetNumSourceCommandFiles () const
527{
528 return m_option_data.m_source_command_files.size();
529}
530
531const char *
532Driver::GetSourceCommandFileAtIndex (uint32_t idx) const
533{
534 if (idx < m_option_data.m_source_command_files.size())
535 return m_option_data.m_source_command_files[idx].c_str();
536 return NULL;
537}
538
539bool
540Driver::GetDebugMode() const
541{
542 return m_option_data.m_debug_mode;
543}
544
545
546// Check the arguments that were passed to this program to make sure they are valid and to get their
547// argument values (if any). Return a boolean value indicating whether or not to start up the full
548// debugger (i.e. the Command Interpreter) or not. Return FALSE if the arguments were invalid OR
549// if the user only wanted help or version information.
550
551bool
552Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, FILE *err_fh)
553{
554 bool valid = true;
555
556 ResetOptionValues ();
557
558 if (argc == 2 && *(argv[1]) != '-')
559 {
560 m_option_data.m_filename = argv[1];
561 }
562 else
563 {
564 SBCommandReturnObject result;
565
566 SBError error = ParseOptions (m_option_data, argc, argv);
567 if (error.Fail())
568 {
569 const char *error_cstr = error.GetCString ();
570 if (error_cstr)
571 ::fprintf (err_fh, "error: %s\n", error_cstr);
572 }
573 }
574
575 // Check to see if they just invoked the debugger with a filename.
576
577
578 if (m_option_data.m_print_help)
579 {
580 ShowUsage (out_fh, g_options, m_option_data);
581 valid = false;
582 }
583 else if (m_option_data.m_print_version)
584 {
585 ::fprintf (out_fh, "%s\n", SBDebugger::GetVersionString());
586 valid = false;
587 }
588 else if (! m_option_data.m_crash_log.empty())
589 {
590 // Handle crash log stuff here.
591 }
592 else
593 {
594 // All other combinations are valid; do nothing more here.
595 }
596
597 return valid;
598}
599
600void
601Driver::GetProcessSTDOUT ()
602{
603 // The process has stuff waiting for stdout; get it and write it out to the appropriate place.
604 char stdio_buffer[1024];
605 size_t len;
606 while ((len = SBDebugger::GetCurrentTarget().GetProcess().GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0)
607 m_io_channel_ap->OutWrite (stdio_buffer, len);
608}
609
610void
611Driver::GetProcessSTDERR ()
612{
613 // The process has stuff waiting for stderr; get it and write it out to the appropriate place.
614 char stdio_buffer[1024];
615 size_t len;
616 while ((len = SBDebugger::GetCurrentTarget().GetProcess().GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0)
617 m_io_channel_ap->ErrWrite (stdio_buffer, len);
618}
619
620void
621Driver::UpdateCurrentThread ()
622{
623 using namespace lldb;
624 SBProcess process(SBDebugger::GetCurrentTarget().GetProcess());
625 if (process.IsValid())
626 {
627 SBThread curr_thread (process.GetCurrentThread());
628 SBThread thread;
629 StopReason curr_thread_stop_reason = eStopReasonInvalid;
630 curr_thread_stop_reason = curr_thread.GetStopReason();
631
632 if (!curr_thread.IsValid() ||
633 curr_thread_stop_reason == eStopReasonInvalid ||
634 curr_thread_stop_reason == eStopReasonNone)
635 {
636 // Prefer a thread that has just completed its plan over another thread as current thread.
637 SBThread plan_thread;
638 SBThread other_thread;
639 const size_t num_threads = process.GetNumThreads();
640 size_t i;
641 for (i = 0; i < num_threads; ++i)
642 {
643 thread = process.GetThreadAtIndex(i);
644 StopReason thread_stop_reason = thread.GetStopReason();
645 switch (thread_stop_reason)
646 {
647 default:
648 case eStopReasonInvalid:
649 case eStopReasonNone:
650 break;
651
652 case eStopReasonTrace:
653 case eStopReasonBreakpoint:
654 case eStopReasonWatchpoint:
655 case eStopReasonSignal:
656 case eStopReasonException:
657 if (!other_thread.IsValid())
658 other_thread = thread;
659 break;
660 case eStopReasonPlanComplete:
661 if (!plan_thread.IsValid())
662 plan_thread = thread;
663 break;
664 }
665 }
666 if (plan_thread.IsValid())
667 process.SetCurrentThread (plan_thread);
668 else if (other_thread.IsValid())
669 process.SetCurrentThread (other_thread);
670 else
671 {
672 if (curr_thread.IsValid())
673 thread = curr_thread;
674 else
675 thread = process.GetThreadAtIndex(0);
676
677 if (thread.IsValid())
678 process.SetCurrentThread (thread);
679 }
680 }
681 }
682}
683
684
685// This function handles events that were broadcast by the process.
686void
687Driver::HandleProcessEvent (const SBEvent &event)
688{
689 using namespace lldb;
690 const uint32_t event_type = event.GetType();
691
692 if (event_type & SBProcess::eBroadcastBitSTDOUT)
693 {
694 // The process has stdout available, get it and write it out to the
695 // appropriate place.
696 GetProcessSTDOUT ();
697 }
698 else if (event_type & SBProcess::eBroadcastBitSTDERR)
699 {
700 // The process has stderr available, get it and write it out to the
701 // appropriate place.
702 GetProcessSTDERR ();
703 }
704 else if (event_type & SBProcess::eBroadcastBitStateChanged)
705 {
706 // Drain all stout and stderr so we don't see any output come after
707 // we print our prompts
708 GetProcessSTDOUT ();
709 GetProcessSTDERR ();
710
711 // Something changed in the process; get the event and report the process's current status and location to
712 // the user.
713 StateType event_state = SBProcess::GetStateFromEvent (event);
714 if (event_state == eStateInvalid)
715 return;
716
717 SBProcess process (SBProcess::GetProcessFromEvent (event));
718 assert (process.IsValid());
719
720 switch (event_state)
721 {
722 case eStateInvalid:
723 case eStateUnloaded:
724 case eStateAttaching:
725 case eStateLaunching:
726 case eStateStepping:
727 case eStateDetached:
728 {
729 char message[1024];
730 int message_len = ::snprintf (message, sizeof(message), "Process %d %s\n", process.GetProcessID(),
731 SBDebugger::StateAsCString (event_state));
732 m_io_channel_ap->OutWrite(message, message_len);
733 }
734 break;
735
736 case eStateRunning:
737 // Don't be chatty when we run...
738 break;
739
740 case eStateExited:
741 SBDebugger::HandleCommand("status");
742 m_io_channel_ap->RefreshPrompt();
743 break;
744
745 case eStateStopped:
746 case eStateCrashed:
747 case eStateSuspended:
748 // Make sure the program hasn't been auto-restarted:
749 if (SBProcess::GetRestartedFromEvent (event))
750 {
751 // FIXME: Do we want to report this, or would that just be annoyingly chatty?
752 char message[1024];
753 int message_len = ::snprintf (message, sizeof(message), "Process %d stopped and was programmatically restarted.\n",
754 process.GetProcessID());
755 m_io_channel_ap->OutWrite(message, message_len);
756 }
757 else
758 {
759 UpdateCurrentThread ();
760 SBDebugger::HandleCommand("status");
761 m_io_channel_ap->RefreshPrompt();
762 }
763 break;
764 }
765 }
766}
767
768// This function handles events broadcast by the IOChannel (HasInput, UserInterrupt, or ThreadShouldExit).
769
770bool
771Driver::HandleIOEvent (const SBEvent &event)
772{
773 bool quit = false;
774
775 const uint32_t event_type = event.GetType();
776
777 if (event_type & IOChannel::eBroadcastBitHasUserInput)
778 {
779 // We got some input (i.e. a command string) from the user; pass it off to the command interpreter for
780 // handling.
781
782 const char *command_string = SBEvent::GetCStringFromEvent(event);
783 if (command_string == NULL)
784 command_string == "";
785 SBCommandReturnObject result;
786 if (SBDebugger::GetCommandInterpreter().HandleCommand (command_string, result, true) != lldb::eReturnStatusQuit)
787 {
788 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize());
789 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize());
790 }
791 // We are done getting and running our command, we can now clear the
792 // m_waiting_for_command so we can get another one.
793 m_waiting_for_command = false;
794
795 // If our editline input reader is active, it means another input reader
796 // got pushed onto the input reader and caused us to become deactivated.
797 // When the input reader above us gets popped, we will get re-activated
798 // and our prompt will refresh in our callback
799 if (m_editline_reader.IsActive())
800 {
801 ReadyForCommand ();
802 }
803 }
804 else if (event_type & IOChannel::eBroadcastBitUserInterrupt)
805 {
806 // This is here to handle control-c interrupts from the user. It has not yet really been implemented.
807 // TO BE DONE: PROPERLY HANDLE CONTROL-C FROM USER
808 //m_io_channel_ap->CancelInput();
809 // Anything else? Send Interrupt to process?
810 }
811 else if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
812 (event_type & IOChannel::eBroadcastBitThreadDidExit))
813 {
814 // If the IOChannel thread is trying to go away, then it is definitely
815 // time to end the debugging session.
816 quit = true;
817 }
818
819 return quit;
820}
821
822
823//struct CrashImageInfo
824//{
825// std::string path;
826// VMRange text_range;
827// UUID uuid;
828//};
829//
830//void
831//Driver::ParseCrashLog (const char *crash_log)
832//{
833// printf("Parsing crash log: %s\n", crash_log);
834//
835// char image_path[PATH_MAX];
836// std::vector<CrashImageInfo> crash_infos;
837// if (crash_log && crash_log[0])
838// {
839// FileSpec crash_log_file (crash_log);
840// STLStringArray crash_log_lines;
841// if (crash_log_file.ReadFileLines (crash_log_lines))
842// {
843// const size_t num_crash_log_lines = crash_log_lines.size();
844// size_t i;
845// for (i=0; i<num_crash_log_lines; ++i)
846// {
847// const char *line = crash_log_lines[i].c_str();
848// if (strstr (line, "Code Type:"))
849// {
850// char arch_string[256];
851// if (sscanf(line, "%s", arch_string))
852// {
853// if (strcmp(arch_string, "X86-64"))
854// lldb::GetDefaultArchitecture ().SetArch ("x86_64");
855// else if (strcmp(arch_string, "X86"))
856// lldb::GetDefaultArchitecture ().SetArch ("i386");
857// else
858// {
859// ArchSpec arch(arch_string);
860// if (arch.IsValid ())
861// lldb::GetDefaultArchitecture () = arch;
862// else
863// fprintf(stderr, "Unrecognized architecture: %s\n", arch_string);
864// }
865// }
866// }
867// else
868// if (strstr(line, "Path:"))
869// {
870// const char *p = line + strlen("Path:");
871// while (isspace(*p))
872// ++p;
873//
874// m_option_data.m_filename.assign (p);
875// }
876// else
877// if (strstr(line, "Binary Images:"))
878// {
879// while (++i < num_crash_log_lines)
880// {
881// if (crash_log_lines[i].empty())
882// break;
883//
884// line = crash_log_lines[i].c_str();
885// uint64_t text_start_addr;
886// uint64_t text_end_addr;
887// char uuid_cstr[64];
888// int bytes_consumed_before_uuid = 0;
889// int bytes_consumed_after_uuid = 0;
890//
891// int items_parsed = ::sscanf (line,
892// "%llx - %llx %*s %*s %*s %n%s %n",
893// &text_start_addr,
894// &text_end_addr,
895// &bytes_consumed_before_uuid,
896// uuid_cstr,
897// &bytes_consumed_after_uuid);
898//
899// if (items_parsed == 3)
900// {
901//
902// CrashImageInfo info;
903// info.text_range.SetBaseAddress(text_start_addr);
904// info.text_range.SetEndAddress(text_end_addr);
905//
906// if (uuid_cstr[0] == '<')
907// {
908// if (info.uuid.SetfromCString (&uuid_cstr[1]) == 0)
909// info.uuid.Clear();
910//
911// ::strncpy (image_path, line + bytes_consumed_after_uuid, sizeof(image_path));
912// }
913// else
914// {
915// ::strncpy (image_path, line + bytes_consumed_before_uuid, sizeof(image_path));
916// }
917//
918// info.path = image_path;
919//
920// crash_infos.push_back (info);
921//
922// info.uuid.GetAsCString(uuid_cstr, sizeof(uuid_cstr));
923//
924// printf("0x%16.16llx - 0x%16.16llx <%s> %s\n",
925// text_start_addr,
926// text_end_addr,
927// uuid_cstr,
928// image_path);
929// }
930// }
931// }
932// }
933// }
934//
935// if (crash_infos.size())
936// {
937// SBTarget target (SBDebugger::CreateTarget (crash_infos.front().path.c_str(),
938// lldb::GetDefaultArchitecture().AsCString (),
939// false));
940// if (target.IsValid())
941// {
942//
943// }
944// }
945// }
946//}
947//
948
949void
950Driver::MasterThreadBytesReceived (void *baton, const void *src, size_t src_len)
951{
952 Driver *driver = (Driver*)baton;
953 driver->GetFromMaster ((const char *)src, src_len);
954}
955
956void
957Driver::GetFromMaster (const char *src, size_t src_len)
958{
959 // Echo the characters back to the Debugger's stdout, that way if you
960 // type characters while a command is running, you'll see what you've typed.
961 FILE *out_fh = SBDebugger::GetOutputFileHandle();
962 if (out_fh)
963 ::fwrite (src, 1, src_len, out_fh);
964}
965
966size_t
967Driver::EditLineInputReaderCallback
968(
969 void *baton,
970 SBInputReader *reader,
971 InputReaderAction notification,
972 const char *bytes,
973 size_t bytes_len
974)
975{
976 Driver *driver = (Driver *)baton;
977
978 switch (notification)
979 {
980 case eInputReaderActivate:
981 break;
982
983 case eInputReaderReactivate:
984 driver->ReadyForCommand();
985 break;
986
987 case eInputReaderDeactivate:
988 break;
989
990 case eInputReaderGotToken:
991 write (driver->m_editline_pty.GetMasterFileDescriptor(), bytes, bytes_len);
992 break;
993
994 case eInputReaderDone:
995 break;
996 }
997 return bytes_len;
998}
999
1000void
1001Driver::MainLoop ()
1002{
1003 char error_str[1024];
1004 if (m_editline_pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, error_str, sizeof(error_str)) == false)
1005 {
1006 ::fprintf (stderr, "error: failed to open driver pseudo terminal : %s", error_str);
1007 exit(1);
1008 }
1009 else
1010 {
1011 const char *driver_slave_name = m_editline_pty.GetSlaveName (error_str, sizeof(error_str));
1012 if (driver_slave_name == NULL)
1013 {
1014 ::fprintf (stderr, "error: failed to get slave name for driver pseudo terminal : %s", error_str);
1015 exit(2);
1016 }
1017 else
1018 {
1019 m_editline_slave_fh = ::fopen (driver_slave_name, "r+");
1020 if (m_editline_slave_fh == NULL)
1021 {
1022 SBError error;
1023 error.SetErrorToErrno();
1024 ::fprintf (stderr, "error: failed to get open slave for driver pseudo terminal : %s",
1025 error.GetCString());
1026 exit(3);
1027 }
1028
1029 ::setbuf (m_editline_slave_fh, NULL);
1030 }
1031 }
1032
1033
1034 // struct termios stdin_termios;
1035
1036 if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0)
1037 atexit (reset_stdin_termios);
1038
1039 ::setbuf (stdin, NULL);
1040 ::setbuf (stdout, NULL);
1041
1042 SBDebugger::SetErrorFileHandle (stderr, false);
1043 SBDebugger::SetOutputFileHandle (stdout, false);
1044 SBDebugger::SetInputFileHandle (stdin, true);
1045
1046 // You have to drain anything that comes to the master side of the PTY. master_out_comm is
1047 // for that purpose. The reason you need to do this is a curious reason... editline will echo
1048 // characters to the PTY when it gets characters while el_gets is not running, and then when
1049 // you call el_gets (or el_getc) it will try to reset the terminal back to raw mode which blocks
1050 // if there are unconsumed characters in the out buffer.
1051 // However, you don't need to do anything with the characters, since editline will dump these
1052 // unconsumed characters after printing the prompt again in el_gets.
1053
1054 SBCommunication master_out_comm("driver.editline");
1055 master_out_comm.AdoptFileDesriptor(m_editline_pty.GetMasterFileDescriptor(), false);
1056 master_out_comm.SetReadThreadBytesReceivedCallback(Driver::MasterThreadBytesReceived, this);
1057
1058 if (master_out_comm.ReadThreadStart () == false)
1059 {
1060 ::fprintf (stderr, "error: failed to start master out read thread");
1061 exit(5);
1062 }
1063
1064// const char *crash_log = GetCrashLogFilename();
1065// if (crash_log)
1066// {
1067// ParseCrashLog (crash_log);
1068// }
1069//
1070 SBCommandInterpreter sb_interpreter = SBDebugger::GetCommandInterpreter();
1071
1072 m_io_channel_ap.reset (new IOChannel(m_editline_slave_fh, stdout, stderr, this));
1073
1074 struct winsize window_size;
1075 if (isatty (STDIN_FILENO)
1076 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
1077 {
1078 char buffer[25];
1079
1080 sprintf (buffer, "set term-width %d", window_size.ws_col);
1081 SBDebugger::HandleCommand ((const char *) buffer);
1082 }
1083
1084 // Since input can be redirected by the debugger, we must insert our editline
1085 // input reader in the queue so we know when our reader should be active
1086 // and so we can receive bytes only when we are supposed to.
1087 SBError err (m_editline_reader.Initialize (Driver::EditLineInputReaderCallback, // callback
1088 this, // baton
1089 eInputReaderGranularityByte, // token_size
1090 NULL, // end token - NULL means never done
1091 NULL, // prompt - taken care of elsewhere
1092 false)); // echo input - don't need Debugger
1093 // to do this, we handle it elsewhere
1094
1095 if (err.Fail())
1096 {
1097 ::fprintf (stderr, "error: %s", err.GetCString());
1098 exit (6);
1099 }
1100
1101 SBDebugger::PushInputReader (m_editline_reader);
1102
1103 SBListener listener(SBDebugger::GetListener());
1104 if (listener.IsValid())
1105 {
1106
1107 listener.StartListeningForEvents (*m_io_channel_ap,
1108 IOChannel::eBroadcastBitHasUserInput |
1109 IOChannel::eBroadcastBitUserInterrupt |
1110 IOChannel::eBroadcastBitThreadShouldExit |
1111 IOChannel::eBroadcastBitThreadDidStart |
1112 IOChannel::eBroadcastBitThreadDidExit);
1113
1114 if (m_io_channel_ap->Start ())
1115 {
1116 bool iochannel_thread_exited = false;
1117
1118 listener.StartListeningForEvents (sb_interpreter.GetBroadcaster(),
1119 SBCommandInterpreter::eBroadcastBitQuitCommandReceived);
1120
1121 // Before we handle any options from the command line, we parse the
1122 // .lldbinit file in the user's home directory.
1123 SBCommandReturnObject result;
1124 sb_interpreter.SourceInitFileInHomeDirectory(result);
1125 if (GetDebugMode())
1126 {
1127 result.PutError (SBDebugger::GetErrorFileHandle());
1128 result.PutOutput (SBDebugger::GetOutputFileHandle());
1129 }
1130
1131 // Now we handle options we got from the command line
1132 char command_string[PATH_MAX * 2];
1133 const size_t num_source_command_files = GetNumSourceCommandFiles();
1134 if (num_source_command_files > 0)
1135 {
1136 for (size_t i=0; i < num_source_command_files; ++i)
1137 {
1138 const char *command_file = GetSourceCommandFileAtIndex(i);
1139 ::snprintf (command_string, sizeof(command_string), "source '%s'", command_file);
1140 SBDebugger::GetCommandInterpreter().HandleCommand (command_string, result, false);
1141 if (GetDebugMode())
1142 {
1143 result.PutError (SBDebugger::GetErrorFileHandle());
1144 result.PutOutput (SBDebugger::GetOutputFileHandle());
1145 }
1146 }
1147 }
1148
1149 if (!m_option_data.m_filename.empty())
1150 {
1151 char arch_name[64];
1152 if (SBDebugger::GetDefaultArchitecture (arch_name, sizeof (arch_name)))
1153 ::snprintf (command_string, sizeof (command_string), "file --arch=%s '%s'", arch_name,
1154 m_option_data.m_filename.c_str());
1155 else
1156 ::snprintf (command_string, sizeof(command_string), "file '%s'", m_option_data.m_filename.c_str());
1157
1158 SBDebugger::HandleCommand (command_string);
1159 }
1160
1161 // Now that all option parsing is done, we try and parse the .lldbinit
1162 // file in the current working directory
1163 sb_interpreter.SourceInitFileInCurrentWorkingDirectory (result);
1164 if (GetDebugMode())
1165 {
1166 result.PutError(SBDebugger::GetErrorFileHandle());
1167 result.PutOutput(SBDebugger::GetOutputFileHandle());
1168 }
1169
1170 SBEvent event;
1171
1172 // Make sure the IO channel is started up before we try to tell it we
1173 // are ready for input
1174 listener.WaitForEventForBroadcasterWithType (UINT32_MAX,
1175 *m_io_channel_ap,
1176 IOChannel::eBroadcastBitThreadDidStart,
1177 event);
1178
1179 ReadyForCommand ();
1180
1181 bool done = false;
1182 while (!done)
1183 {
1184 listener.WaitForEvent (UINT32_MAX, event);
1185 if (event.IsValid())
1186 {
1187 if (event.GetBroadcaster().IsValid())
1188 {
1189 uint32_t event_type = event.GetType();
1190 if (event.BroadcasterMatchesRef (*m_io_channel_ap))
1191 {
1192 if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
1193 (event_type & IOChannel::eBroadcastBitThreadDidExit))
1194 {
1195 done = true;
1196 if (event_type & IOChannel::eBroadcastBitThreadDidExit)
1197 iochannel_thread_exited = true;
1198 break;
1199 }
1200 else
1201 done = HandleIOEvent (event);
1202 }
1203 else if (event.BroadcasterMatchesRef (SBDebugger::GetCurrentTarget().GetProcess().GetBroadcaster()))
1204 {
1205 HandleProcessEvent (event);
1206 }
1207 else if (event.BroadcasterMatchesRef (sb_interpreter.GetBroadcaster()))
1208 {
1209 if (event_type & SBCommandInterpreter::eBroadcastBitQuitCommandReceived)
1210 done = true;
1211 }
1212 }
1213 }
1214 }
1215
1216 reset_stdin_termios ();
1217
1218 CloseIOChannelFile ();
1219
1220 if (!iochannel_thread_exited)
1221 {
1222 SBEvent event;
1223 listener.GetNextEventForBroadcasterWithType (*m_io_channel_ap,
1224 IOChannel::eBroadcastBitThreadDidExit,
1225 event);
1226 if (!event.IsValid())
1227 {
1228 // Send end EOF to the driver file descriptor
1229 m_io_channel_ap->Stop();
1230 }
1231 }
1232
1233 SBProcess process = SBDebugger::GetCurrentTarget().GetProcess();
1234 if (process.IsValid())
1235 process.Destroy();
1236 }
1237 }
1238}
1239
1240
1241void
1242Driver::ReadyForCommand ()
1243{
1244 if (m_waiting_for_command == false)
1245 {
1246 m_waiting_for_command = true;
1247 BroadcastEventByType (Driver::eBroadcastBitReadyForInput, true);
1248 }
1249}
1250
1251
1252int
1253main (int argc, char const *argv[])
1254{
1255
1256 SBDebugger::Initialize();
1257
1258 SBHostOS::ThreadCreated ("[main]");
1259
1260 // Do a little setup on the debugger before we get going
1261 SBDebugger::SetAsync(true);
1262 Driver driver;
1263
1264 bool valid_args = driver.ParseArgs (argc, argv, stdout, stderr);
1265 if (valid_args)
1266 {
1267 driver.MainLoop ();
1268 }
1269
1270 SBDebugger::Terminate();
1271 return 0;
1272}