1 //===-- 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 <stdio.h>
13 #include <string.h>
14 #include <stdlib.h>
15 #include <limits.h>
16 #include <fcntl.h>
17 
18 #include <string>
19 
20 #include <thread>
21 #include "lldb/API/SBBreakpoint.h"
22 #include "lldb/API/SBCommandInterpreter.h"
23 #include "lldb/API/SBCommandReturnObject.h"
24 #include "lldb/API/SBCommunication.h"
25 #include "lldb/API/SBDebugger.h"
26 #include "lldb/API/SBEvent.h"
27 #include "lldb/API/SBHostOS.h"
28 #include "lldb/API/SBListener.h"
29 #include "lldb/API/SBStream.h"
30 #include "lldb/API/SBTarget.h"
31 #include "lldb/API/SBThread.h"
32 #include "lldb/API/SBProcess.h"
33 
34 using namespace lldb;
35 
36 static void reset_stdin_termios ();
37 static bool g_old_stdin_termios_is_valid = false;
38 static struct termios g_old_stdin_termios;
39 
40 static char *g_debugger_name =  (char *) "";
41 static Driver *g_driver = NULL;
42 
43 // In the Driver::MainLoop, we change the terminal settings.  This function is
44 // added as an atexit handler to make sure we clean them up.
45 static void
46 reset_stdin_termios ()
47 {
48     if (g_old_stdin_termios_is_valid)
49     {
50         g_old_stdin_termios_is_valid = false;
51         ::tcsetattr (STDIN_FILENO, TCSANOW, &g_old_stdin_termios);
52     }
53 }
54 
55 typedef struct
56 {
57     uint32_t usage_mask;                     // Used to mark options that can be used together.  If (1 << n & usage_mask) != 0
58                                              // then this option belongs to option set n.
59     bool required;                           // This option is required (in the current usage level)
60     const char * long_option;                // Full name for this option.
61     int short_option;                        // Single character for this option.
62     int option_has_arg;                      // no_argument, required_argument or optional_argument
63     uint32_t completion_type;                // Cookie the option class can use to do define the argument completion.
64     lldb::CommandArgumentType argument_type; // Type of argument this option takes
65     const char *  usage_text;                // Full text explaining what this options does and what (if any) argument to
66                                              // pass it.
67 } OptionDefinition;
68 
69 #define LLDB_3_TO_5 LLDB_OPT_SET_3|LLDB_OPT_SET_4|LLDB_OPT_SET_5
70 #define LLDB_4_TO_5 LLDB_OPT_SET_4|LLDB_OPT_SET_5
71 
72 static OptionDefinition g_options[] =
73 {
74     { LLDB_OPT_SET_1,    true , "help"           , 'h', no_argument      , 0,  eArgTypeNone,
75         "Prints out the usage information for the LLDB debugger." },
76     { LLDB_OPT_SET_2,    true , "version"        , 'v', no_argument      , 0,  eArgTypeNone,
77         "Prints out the current version number of the LLDB debugger." },
78     { LLDB_OPT_SET_3,    true , "arch"           , 'a', required_argument, 0,  eArgTypeArchitecture,
79         "Tells the debugger to use the specified architecture when starting and running the program.  <architecture> must "
80         "be one of the architectures for which the program was compiled." },
81     { LLDB_OPT_SET_3,    true , "file"           , 'f', required_argument, 0,  eArgTypeFilename,
82         "Tells the debugger to use the file <filename> as the program to be debugged." },
83     { LLDB_OPT_SET_3,    false, "core"           , 'c', required_argument, 0,  eArgTypeFilename,
84         "Tells the debugger to use the fullpath to <path> as the core file." },
85     { LLDB_OPT_SET_4,    true , "attach-name"    , 'n', required_argument, 0,  eArgTypeProcessName,
86         "Tells the debugger to attach to a process with the given name." },
87     { LLDB_OPT_SET_4,    true , "wait-for"       , 'w', no_argument      , 0,  eArgTypeNone,
88         "Tells the debugger to wait for a process with the given pid or name to launch before attaching." },
89     { LLDB_OPT_SET_5,    true , "attach-pid"     , 'p', required_argument, 0,  eArgTypePid,
90         "Tells the debugger to attach to a process with the given pid." },
91     { LLDB_3_TO_5,       false, "script-language", 'l', required_argument, 0,  eArgTypeScriptLang,
92         "Tells the debugger to use the specified scripting language for user-defined scripts, rather than the default.  "
93         "Valid scripting languages that can be specified include Python, Perl, Ruby and Tcl.  Currently only the Python "
94         "extensions have been implemented." },
95     { LLDB_3_TO_5,       false, "debug"          , 'd', no_argument      , 0,  eArgTypeNone,
96         "Tells the debugger to print out extra information for debugging itself." },
97     { LLDB_3_TO_5,       false, "source-quietly"          , 'b', no_argument      , 0,  eArgTypeNone,
98         "Tells the debugger to print out extra information for debugging itself." },
99     { LLDB_3_TO_5,       false, "source"         , 's', required_argument, 0,  eArgTypeFilename,
100         "Tells the debugger to read in and execute the lldb commands in the given file, after any file provided on the command line has been loaded." },
101     { LLDB_3_TO_5,       false, "one-line"         , 'o', required_argument, 0,  eArgTypeNone,
102         "Tells the debugger to execute this one-line lldb command after any file provided on the command line has been loaded." },
103     { LLDB_3_TO_5,       false, "source-before-file"         , 'S', required_argument, 0,  eArgTypeFilename,
104         "Tells the debugger to read in and execute the lldb commands in the given file, before any file provided on the command line has been loaded." },
105     { LLDB_3_TO_5,       false, "one-line-before-file"         , 'O', required_argument, 0,  eArgTypeNone,
106         "Tells the debugger to execute this one-line lldb command before any file provided on the command line has been loaded." },
107     { LLDB_3_TO_5,       false, "editor"         , 'e', no_argument      , 0,  eArgTypeNone,
108         "Tells the debugger to open source files using the host's \"external editor\" mechanism." },
109     { LLDB_3_TO_5,       false, "no-lldbinit"    , 'x', no_argument      , 0,  eArgTypeNone,
110         "Do not automatically parse any '.lldbinit' files." },
111     { LLDB_3_TO_5,       false, "no-use-colors"  , 'X', no_argument      , 0,  eArgTypeNone,
112         "Do not use colors." },
113     { LLDB_OPT_SET_6,    true , "python-path"    , 'P', no_argument      , 0,  eArgTypeNone,
114         "Prints out the path to the lldb.py file for this version of lldb." },
115     { 0,                 false, NULL             , 0  , 0                , 0,  eArgTypeNone,         NULL }
116 };
117 
118 static const uint32_t last_option_set_with_args = 2;
119 
120 Driver::Driver () :
121     SBBroadcaster ("Driver"),
122     m_debugger (SBDebugger::Create(false)),
123     m_option_data ()
124 {
125     // We want to be able to handle CTRL+D in the terminal to have it terminate
126     // certain input
127     m_debugger.SetCloseInputOnEOF (false);
128     g_debugger_name = (char *) m_debugger.GetInstanceName();
129     if (g_debugger_name == NULL)
130         g_debugger_name = (char *) "";
131     g_driver = this;
132 }
133 
134 Driver::~Driver ()
135 {
136     g_driver = NULL;
137     g_debugger_name = NULL;
138 }
139 
140 
141 // This function takes INDENT, which tells how many spaces to output at the front
142 // of each line; TEXT, which is the text that is to be output. It outputs the
143 // text, on multiple lines if necessary, to RESULT, with INDENT spaces at the
144 // front of each line.  It breaks lines on spaces, tabs or newlines, shortening
145 // the line if necessary to not break in the middle of a word. It assumes that
146 // each output line should contain a maximum of OUTPUT_MAX_COLUMNS characters.
147 
148 void
149 OutputFormattedUsageText (FILE *out, int indent, const char *text, int output_max_columns)
150 {
151     int len = strlen (text);
152     std::string text_string (text);
153 
154     // Force indentation to be reasonable.
155     if (indent >= output_max_columns)
156         indent = 0;
157 
158     // Will it all fit on one line?
159 
160     if (len + indent < output_max_columns)
161         // Output as a single line
162         fprintf (out, "%*s%s\n", indent, "", text);
163     else
164     {
165         // We need to break it up into multiple lines.
166         int text_width = output_max_columns - indent - 1;
167         int start = 0;
168         int end = start;
169         int final_end = len;
170         int sub_len;
171 
172         while (end < final_end)
173         {
174               // Dont start the 'text' on a space, since we're already outputting the indentation.
175               while ((start < final_end) && (text[start] == ' '))
176                   start++;
177 
178               end = start + text_width;
179               if (end > final_end)
180                   end = final_end;
181               else
182               {
183                   // If we're not at the end of the text, make sure we break the line on white space.
184                   while (end > start
185                          && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
186                       end--;
187               }
188               sub_len = end - start;
189               std::string substring = text_string.substr (start, sub_len);
190               fprintf (out, "%*s%s\n", indent, "", substring.c_str());
191               start = end + 1;
192         }
193     }
194 }
195 
196 void
197 ShowUsage (FILE *out, OptionDefinition *option_table, Driver::OptionData data)
198 {
199     uint32_t screen_width = 80;
200     uint32_t indent_level = 0;
201     const char *name = "lldb";
202 
203     fprintf (out, "\nUsage:\n\n");
204 
205     indent_level += 2;
206 
207 
208     // First, show each usage level set of options, e.g. <cmd> [options-for-level-0]
209     //                                                   <cmd> [options-for-level-1]
210     //                                                   etc.
211 
212     uint32_t num_options;
213     uint32_t num_option_sets = 0;
214 
215     for (num_options = 0; option_table[num_options].long_option != NULL; ++num_options)
216     {
217         uint32_t this_usage_mask = option_table[num_options].usage_mask;
218         if (this_usage_mask == LLDB_OPT_SET_ALL)
219         {
220             if (num_option_sets == 0)
221                 num_option_sets = 1;
222         }
223         else
224         {
225             for (uint32_t j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++)
226             {
227                 if (this_usage_mask & 1 << j)
228                 {
229                     if (num_option_sets <= j)
230                         num_option_sets = j + 1;
231                 }
232             }
233         }
234     }
235 
236     for (uint32_t opt_set = 0; opt_set < num_option_sets; opt_set++)
237     {
238         uint32_t opt_set_mask;
239 
240         opt_set_mask = 1 << opt_set;
241 
242         if (opt_set > 0)
243             fprintf (out, "\n");
244         fprintf (out, "%*s%s", indent_level, "", name);
245         bool is_help_line = false;
246 
247         for (uint32_t i = 0; i < num_options; ++i)
248         {
249             if (option_table[i].usage_mask & opt_set_mask)
250             {
251                 CommandArgumentType arg_type = option_table[i].argument_type;
252                 const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type);
253                 // This is a bit of a hack, but there's no way to say certain options don't have arguments yet...
254                 // so we do it by hand here.
255                 if (option_table[i].short_option == 'h')
256                     is_help_line = true;
257 
258                 if (option_table[i].required)
259                 {
260                     if (option_table[i].option_has_arg == required_argument)
261                         fprintf (out, " -%c <%s>", option_table[i].short_option, arg_name);
262                     else if (option_table[i].option_has_arg == optional_argument)
263                         fprintf (out, " -%c [<%s>]", option_table[i].short_option, arg_name);
264                     else
265                         fprintf (out, " -%c", option_table[i].short_option);
266                 }
267                 else
268                 {
269                     if (option_table[i].option_has_arg == required_argument)
270                         fprintf (out, " [-%c <%s>]", option_table[i].short_option, arg_name);
271                     else if (option_table[i].option_has_arg == optional_argument)
272                         fprintf (out, " [-%c [<%s>]]", option_table[i].short_option, arg_name);
273                     else
274                         fprintf (out, " [-%c]", option_table[i].short_option);
275                 }
276             }
277         }
278         if (!is_help_line && (opt_set <= last_option_set_with_args))
279             fprintf (out, " [[--] <PROGRAM-ARG-1> [<PROGRAM_ARG-2> ...]]");
280     }
281 
282     fprintf (out, "\n\n");
283 
284     // Now print out all the detailed information about the various options:  long form, short form and help text:
285     //   -- long_name <argument>
286     //   - short <argument>
287     //   help text
288 
289     // This variable is used to keep track of which options' info we've printed out, because some options can be in
290     // more than one usage level, but we only want to print the long form of its information once.
291 
292     Driver::OptionData::OptionSet options_seen;
293     Driver::OptionData::OptionSet::iterator pos;
294 
295     indent_level += 5;
296 
297     for (uint32_t i = 0; i < num_options; ++i)
298     {
299         // Only print this option if we haven't already seen it.
300         pos = options_seen.find (option_table[i].short_option);
301         if (pos == options_seen.end())
302         {
303             CommandArgumentType arg_type = option_table[i].argument_type;
304             const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type);
305 
306             options_seen.insert (option_table[i].short_option);
307             fprintf (out, "%*s-%c ", indent_level, "", option_table[i].short_option);
308             if (arg_type != eArgTypeNone)
309                 fprintf (out, "<%s>", arg_name);
310             fprintf (out, "\n");
311             fprintf (out, "%*s--%s ", indent_level, "", option_table[i].long_option);
312             if (arg_type != eArgTypeNone)
313                 fprintf (out, "<%s>", arg_name);
314             fprintf (out, "\n");
315             indent_level += 5;
316             OutputFormattedUsageText (out, indent_level, option_table[i].usage_text, screen_width);
317             indent_level -= 5;
318             fprintf (out, "\n");
319         }
320     }
321 
322     indent_level -= 5;
323 
324     fprintf (out, "\n%*sMultiple \"-s\" and \"-o\" options can be provided.  They will be processed from left to right in order, "
325                   "\n%*swith the source files and commands interleaved.  The same is true of the \"-S\" and \"-O\" options."
326                   "\n%*sThe before file and after file sets can intermixed freely, the command parser will sort them out."
327                   "\n%*sThe order of the file specifiers (\"-c\", \"-f\", etc.) is not significant in this regard.\n\n",
328              indent_level, "",
329              indent_level, "",
330              indent_level, "",
331              indent_level, "");
332 
333     fprintf (out, "\n%*s(If you don't provide -f then the first argument will be the file to be debugged"
334                   "\n%*s so '%s -- <filename> [<ARG1> [<ARG2>]]' also works."
335                   "\n%*s Remember to end the options with \"--\" if any of your arguments have a \"-\" in them.)\n\n",
336              indent_level, "",
337              indent_level, "",
338              name,
339              indent_level, "");
340 }
341 
342 void
343 BuildGetOptTable (OptionDefinition *expanded_option_table, std::vector<struct option> &getopt_table,
344                   uint32_t num_options)
345 {
346     if (num_options == 0)
347         return;
348 
349     uint32_t i;
350     uint32_t j;
351     std::bitset<256> option_seen;
352 
353     getopt_table.resize (num_options + 1);
354 
355     for (i = 0, j = 0; i < num_options; ++i)
356     {
357         char short_opt = expanded_option_table[i].short_option;
358 
359         if (option_seen.test(short_opt) == false)
360         {
361             getopt_table[j].name    = expanded_option_table[i].long_option;
362             getopt_table[j].has_arg = expanded_option_table[i].option_has_arg;
363             getopt_table[j].flag    = NULL;
364             getopt_table[j].val     = expanded_option_table[i].short_option;
365             option_seen.set(short_opt);
366             ++j;
367         }
368     }
369 
370     getopt_table[j].name    = NULL;
371     getopt_table[j].has_arg = 0;
372     getopt_table[j].flag    = NULL;
373     getopt_table[j].val     = 0;
374 
375 }
376 
377 Driver::OptionData::OptionData () :
378     m_args(),
379     m_script_lang (lldb::eScriptLanguageDefault),
380     m_core_file (),
381     m_crash_log (),
382     m_initial_commands (),
383     m_after_file_commands (),
384     m_debug_mode (false),
385     m_source_quietly(false),
386     m_print_version (false),
387     m_print_python_path (false),
388     m_print_help (false),
389     m_wait_for(false),
390     m_process_name(),
391     m_process_pid(LLDB_INVALID_PROCESS_ID),
392     m_use_external_editor(false),
393     m_seen_options()
394 {
395 }
396 
397 Driver::OptionData::~OptionData ()
398 {
399 }
400 
401 void
402 Driver::OptionData::Clear ()
403 {
404     m_args.clear ();
405     m_script_lang = lldb::eScriptLanguageDefault;
406     m_initial_commands.clear ();
407     m_after_file_commands.clear ();
408     m_debug_mode = false;
409     m_source_quietly = false;
410     m_print_help = false;
411     m_print_version = false;
412     m_print_python_path = false;
413     m_use_external_editor = false;
414     m_wait_for = false;
415     m_process_name.erase();
416     m_process_pid = LLDB_INVALID_PROCESS_ID;
417 }
418 
419 void
420 Driver::OptionData::AddInitialCommand (const char *command, bool before_file, bool is_file, SBError &error)
421 {
422     std::vector<std::pair<bool, std::string> > *command_set;
423     if (before_file)
424         command_set = &(m_initial_commands);
425     else
426         command_set = &(m_after_file_commands);
427 
428     if (is_file)
429     {
430         SBFileSpec file(command);
431         if (file.Exists())
432             command_set->push_back (std::pair<bool, std::string> (true, optarg));
433         else if (file.ResolveExecutableLocation())
434         {
435             char final_path[PATH_MAX];
436             file.GetPath (final_path, sizeof(final_path));
437             std::string path_str (final_path);
438             command_set->push_back (std::pair<bool, std::string> (true, path_str));
439         }
440         else
441             error.SetErrorStringWithFormat("file specified in --source (-s) option doesn't exist: '%s'", optarg);
442     }
443     else
444         command_set->push_back (std::pair<bool, std::string> (false, optarg));
445 }
446 
447 void
448 Driver::ResetOptionValues ()
449 {
450     m_option_data.Clear ();
451 }
452 
453 const char *
454 Driver::GetFilename() const
455 {
456     if (m_option_data.m_args.empty())
457         return NULL;
458     return m_option_data.m_args.front().c_str();
459 }
460 
461 const char *
462 Driver::GetCrashLogFilename() const
463 {
464     if (m_option_data.m_crash_log.empty())
465         return NULL;
466     return m_option_data.m_crash_log.c_str();
467 }
468 
469 lldb::ScriptLanguage
470 Driver::GetScriptLanguage() const
471 {
472     return m_option_data.m_script_lang;
473 }
474 
475 void
476 Driver::ExecuteInitialCommands (bool before_file)
477 {
478     size_t num_commands;
479     std::vector<std::pair<bool, std::string> > *command_set;
480     if (before_file)
481         command_set = &(m_option_data.m_initial_commands);
482     else
483         command_set = &(m_option_data.m_after_file_commands);
484 
485     num_commands = command_set->size();
486     SBCommandReturnObject result;
487     bool old_async = GetDebugger().GetAsync();
488     GetDebugger().SetAsync(false);
489     for (size_t idx = 0; idx < num_commands; idx++)
490     {
491         bool is_file = (*command_set)[idx].first;
492         const char *command = (*command_set)[idx].second.c_str();
493         char command_string[PATH_MAX * 2];
494         const bool dump_stream_only_if_no_immediate = true;
495         const char *executed_command = command;
496         if (is_file)
497         {
498             ::snprintf (command_string, sizeof(command_string), "command source '%s'", command);
499             executed_command = command_string;
500         }
501 
502         m_debugger.GetCommandInterpreter().HandleCommand (executed_command, result, false);
503         if (!m_option_data.m_source_quietly || result.Succeeded() == false)
504         {
505             const size_t output_size = result.GetOutputSize();
506             if (output_size > 0)
507             {
508                 const char *cstr = result.GetOutput(dump_stream_only_if_no_immediate);
509                 if (cstr)
510                     printf ("%s", cstr);
511             }
512             const size_t error_size = result.GetErrorSize();
513             if (error_size > 0)
514             {
515                 const char *cstr = result.GetError(dump_stream_only_if_no_immediate);
516                 if (cstr)
517                     printf ("%s", cstr);
518             }
519         }
520 
521         if (result.Succeeded() == false)
522         {
523             const char *type = before_file ? "before file" : "after_file";
524             if (is_file)
525                 ::fprintf(stderr, "Aborting %s command execution, command file: '%s' failed.\n", type, command);
526             else
527                 ::fprintf(stderr, "Aborting %s command execution, command: '%s' failed.\n", type, command);
528             break;
529         }
530         result.Clear();
531     }
532     GetDebugger().SetAsync(old_async);
533 }
534 
535 bool
536 Driver::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 
547 SBError
548 Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exiting)
549 {
550     ResetOptionValues ();
551 
552     SBCommandReturnObject result;
553 
554     SBError error;
555     std::string option_string;
556     struct option *long_options = NULL;
557     std::vector<struct option> long_options_vector;
558     uint32_t num_options;
559 
560     for (num_options = 0; g_options[num_options].long_option != NULL; ++num_options)
561         /* Do Nothing. */;
562 
563     if (num_options == 0)
564     {
565         if (argc > 1)
566             error.SetErrorStringWithFormat ("invalid number of options");
567         return error;
568     }
569 
570     BuildGetOptTable (g_options, long_options_vector, num_options);
571 
572     if (long_options_vector.empty())
573         long_options = NULL;
574     else
575         long_options = &long_options_vector.front();
576 
577     if (long_options == NULL)
578     {
579         error.SetErrorStringWithFormat ("invalid long options");
580         return error;
581     }
582 
583     // Build the option_string argument for call to getopt_long_only.
584 
585     for (int i = 0; long_options[i].name != NULL; ++i)
586     {
587         if (long_options[i].flag == NULL)
588         {
589             option_string.push_back ((char) long_options[i].val);
590             switch (long_options[i].has_arg)
591             {
592                 default:
593                 case no_argument:
594                     break;
595                 case required_argument:
596                     option_string.push_back (':');
597                     break;
598                 case optional_argument:
599                     option_string.append ("::");
600                     break;
601             }
602         }
603     }
604 
605     // This is kind of a pain, but since we make the debugger in the Driver's constructor, we can't
606     // know at that point whether we should read in init files yet.  So we don't read them in in the
607     // Driver constructor, then set the flags back to "read them in" here, and then if we see the
608     // "-n" flag, we'll turn it off again.  Finally we have to read them in by hand later in the
609     // main loop.
610 
611     m_debugger.SkipLLDBInitFiles (false);
612     m_debugger.SkipAppInitFiles (false);
613 
614     // Prepare for & make calls to getopt_long_only.
615 #if __GLIBC__
616     optind = 0;
617 #else
618     optreset = 1;
619     optind = 1;
620 #endif
621     int val;
622     while (1)
623     {
624         int long_options_index = -1;
625         val = ::getopt_long_only (argc, const_cast<char **>(argv), option_string.c_str(), long_options, &long_options_index);
626 
627         if (val == -1)
628             break;
629         else if (val == '?')
630         {
631             m_option_data.m_print_help = true;
632             error.SetErrorStringWithFormat ("unknown or ambiguous option");
633             break;
634         }
635         else if (val == 0)
636             continue;
637         else
638         {
639             m_option_data.m_seen_options.insert ((char) val);
640             if (long_options_index == -1)
641             {
642                 for (int i = 0;
643                      long_options[i].name || long_options[i].has_arg || long_options[i].flag || long_options[i].val;
644                      ++i)
645                 {
646                     if (long_options[i].val == val)
647                     {
648                         long_options_index = i;
649                         break;
650                     }
651                 }
652             }
653 
654             if (long_options_index >= 0)
655             {
656                 const int short_option = g_options[long_options_index].short_option;
657 
658                 switch (short_option)
659                 {
660                     case 'h':
661                         m_option_data.m_print_help = true;
662                         break;
663 
664                     case 'v':
665                         m_option_data.m_print_version = true;
666                         break;
667 
668                     case 'P':
669                         m_option_data.m_print_python_path = true;
670                         break;
671 
672                     case 'c':
673                         {
674                             SBFileSpec file(optarg);
675                             if (file.Exists())
676                             {
677                                 m_option_data.m_core_file = optarg;
678                             }
679                             else
680                                 error.SetErrorStringWithFormat("file specified in --core (-c) option doesn't exist: '%s'", optarg);
681                         }
682                         break;
683 
684                     case 'e':
685                         m_option_data.m_use_external_editor = true;
686                         break;
687 
688                     case 'x':
689                         m_debugger.SkipLLDBInitFiles (true);
690                         m_debugger.SkipAppInitFiles (true);
691                         break;
692 
693                     case 'X':
694                         m_debugger.SetUseColor (false);
695                         break;
696 
697                     case 'f':
698                         {
699                             SBFileSpec file(optarg);
700                             if (file.Exists())
701                             {
702                                 m_option_data.m_args.push_back (optarg);
703                             }
704                             else if (file.ResolveExecutableLocation())
705                             {
706                                 char path[PATH_MAX];
707                                 file.GetPath (path, sizeof(path));
708                                 m_option_data.m_args.push_back (path);
709                             }
710                             else
711                                 error.SetErrorStringWithFormat("file specified in --file (-f) option doesn't exist: '%s'", optarg);
712                         }
713                         break;
714 
715                     case 'a':
716                         if (!m_debugger.SetDefaultArchitecture (optarg))
717                             error.SetErrorStringWithFormat("invalid architecture in the -a or --arch option: '%s'", optarg);
718                         break;
719 
720                     case 'l':
721                         m_option_data.m_script_lang = m_debugger.GetScriptingLanguage (optarg);
722                         break;
723 
724                     case 'd':
725                         m_option_data.m_debug_mode = true;
726                         break;
727 
728                     case 'q':
729                         m_option_data.m_source_quietly = true;
730                         break;
731 
732                     case 'n':
733                         m_option_data.m_process_name = optarg;
734                         break;
735 
736                     case 'w':
737                         m_option_data.m_wait_for = true;
738                         break;
739 
740                     case 'p':
741                         {
742                             char *remainder;
743                             m_option_data.m_process_pid = strtol (optarg, &remainder, 0);
744                             if (remainder == optarg || *remainder != '\0')
745                                 error.SetErrorStringWithFormat ("Could not convert process PID: \"%s\" into a pid.",
746                                                                 optarg);
747                         }
748                         break;
749                     case 's':
750                         m_option_data.AddInitialCommand(optarg, false, true, error);
751                         break;
752                     case 'o':
753                         m_option_data.AddInitialCommand(optarg, false, false, error);
754                         break;
755                     case 'S':
756                         m_option_data.AddInitialCommand(optarg, true, true, error);
757                         break;
758                     case 'O':
759                         m_option_data.AddInitialCommand(optarg, true, false, error);
760                         break;
761                     default:
762                         m_option_data.m_print_help = true;
763                         error.SetErrorStringWithFormat ("unrecognized option %c", short_option);
764                         break;
765                 }
766             }
767             else
768             {
769                 error.SetErrorStringWithFormat ("invalid option with value %i", val);
770             }
771             if (error.Fail())
772             {
773                 return error;
774             }
775         }
776     }
777 
778     if (error.Fail() || m_option_data.m_print_help)
779     {
780         ShowUsage (out_fh, g_options, m_option_data);
781         exiting = true;
782     }
783     else if (m_option_data.m_print_version)
784     {
785         ::fprintf (out_fh, "%s\n", m_debugger.GetVersionString());
786         exiting = true;
787     }
788     else if (m_option_data.m_print_python_path)
789     {
790         SBFileSpec python_file_spec = SBHostOS::GetLLDBPythonPath();
791         if (python_file_spec.IsValid())
792         {
793             char python_path[PATH_MAX];
794             size_t num_chars = python_file_spec.GetPath(python_path, PATH_MAX);
795             if (num_chars < PATH_MAX)
796             {
797                 ::fprintf (out_fh, "%s\n", python_path);
798             }
799             else
800                 ::fprintf (out_fh, "<PATH TOO LONG>\n");
801         }
802         else
803             ::fprintf (out_fh, "<COULD NOT FIND PATH>\n");
804         exiting = true;
805     }
806     else if (m_option_data.m_process_name.empty() && m_option_data.m_process_pid == LLDB_INVALID_PROCESS_ID)
807     {
808         // Any arguments that are left over after option parsing are for
809         // the program. If a file was specified with -f then the filename
810         // is already in the m_option_data.m_args array, and any remaining args
811         // are arguments for the inferior program. If no file was specified with
812         // -f, then what is left is the program name followed by any arguments.
813 
814         // Skip any options we consumed with getopt_long_only
815         argc -= optind;
816         argv += optind;
817 
818         if (argc > 0)
819         {
820             for (int arg_idx=0; arg_idx<argc; ++arg_idx)
821             {
822                 const char *arg = argv[arg_idx];
823                 if (arg)
824                     m_option_data.m_args.push_back (arg);
825             }
826         }
827 
828     }
829     else
830     {
831         // Skip any options we consumed with getopt_long_only
832         argc -= optind;
833         //argv += optind; // Commented out to keep static analyzer happy
834 
835         if (argc > 0)
836             ::fprintf (out_fh, "Warning: program arguments are ignored when attaching.\n");
837     }
838 
839     return error;
840 }
841 
842 void
843 Driver::MainLoop ()
844 {
845     if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0)
846     {
847         g_old_stdin_termios_is_valid = true;
848         atexit (reset_stdin_termios);
849     }
850 
851     ::setbuf (stdin, NULL);
852     ::setbuf (stdout, NULL);
853 
854     m_debugger.SetErrorFileHandle (stderr, false);
855     m_debugger.SetOutputFileHandle (stdout, false);
856     m_debugger.SetInputFileHandle (stdin, true);
857 
858     m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor);
859 
860     struct winsize window_size;
861     if (isatty (STDIN_FILENO)
862         && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
863     {
864         if (window_size.ws_col > 0)
865             m_debugger.SetTerminalWidth (window_size.ws_col);
866     }
867 
868     SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter();
869 
870     // Before we handle any options from the command line, we parse the
871     // .lldbinit file in the user's home directory.
872     SBCommandReturnObject result;
873     sb_interpreter.SourceInitFileInHomeDirectory(result);
874     if (GetDebugMode())
875     {
876         result.PutError (m_debugger.GetErrorFileHandle());
877         result.PutOutput (m_debugger.GetOutputFileHandle());
878     }
879 
880     // Now we handle options we got from the command line
881     // First source in the commands specified to be run before the file arguments are processed.
882     ExecuteInitialCommands(true);
883 
884     // Was there a core file specified?
885     std::string core_file_spec("");
886     if (!m_option_data.m_core_file.empty())
887         core_file_spec.append("--core ").append(m_option_data.m_core_file);
888 
889     char command_string[PATH_MAX * 2];
890     const size_t num_args = m_option_data.m_args.size();
891     if (num_args > 0)
892     {
893         char arch_name[64];
894         if (m_debugger.GetDefaultArchitecture (arch_name, sizeof (arch_name)))
895             ::snprintf (command_string,
896                         sizeof (command_string),
897                         "target create --arch=%s %s \"%s\"",
898                         arch_name,
899                         core_file_spec.c_str(),
900                         m_option_data.m_args[0].c_str());
901         else
902             ::snprintf (command_string,
903                         sizeof(command_string),
904                         "target create %s \"%s\"",
905                         core_file_spec.c_str(),
906                         m_option_data.m_args[0].c_str());
907 
908         m_debugger.HandleCommand (command_string);
909 
910         if (num_args > 1)
911         {
912             m_debugger.HandleCommand ("settings clear target.run-args");
913             char arg_cstr[1024];
914             for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx)
915             {
916                 ::snprintf (arg_cstr,
917                             sizeof(arg_cstr),
918                             "settings append target.run-args \"%s\"",
919                             m_option_data.m_args[arg_idx].c_str());
920                 m_debugger.HandleCommand (arg_cstr);
921             }
922         }
923     }
924     else if (!core_file_spec.empty())
925     {
926         ::snprintf (command_string,
927                     sizeof(command_string),
928                     "target create %s",
929                     core_file_spec.c_str());
930         m_debugger.HandleCommand (command_string);;
931     }
932 
933     ExecuteInitialCommands(false);
934 
935     // Now that all option parsing is done, we try and parse the .lldbinit
936     // file in the current working directory
937     sb_interpreter.SourceInitFileInCurrentWorkingDirectory (result);
938     if (GetDebugMode())
939     {
940         result.PutError(m_debugger.GetErrorFileHandle());
941         result.PutOutput(m_debugger.GetOutputFileHandle());
942     }
943 
944     bool handle_events = true;
945     bool spawn_thread = false;
946     m_debugger.RunCommandInterpreter(handle_events, spawn_thread);
947 
948     reset_stdin_termios();
949     fclose (stdin);
950 
951     SBDebugger::Destroy (m_debugger);
952 }
953 
954 
955 void
956 Driver::ResizeWindow (unsigned short col)
957 {
958     GetDebugger().SetTerminalWidth (col);
959 }
960 
961 void
962 sigwinch_handler (int signo)
963 {
964     struct winsize window_size;
965     if (isatty (STDIN_FILENO)
966         && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
967     {
968         if ((window_size.ws_col > 0) && g_driver != NULL)
969         {
970             g_driver->ResizeWindow (window_size.ws_col);
971         }
972     }
973 }
974 
975 void
976 sigint_handler (int signo)
977 {
978 	static bool g_interrupt_sent = false;
979     if (g_driver)
980 	{
981 		if (!g_interrupt_sent)
982 		{
983 			g_interrupt_sent = true;
984         	g_driver->GetDebugger().DispatchInputInterrupt();
985 			g_interrupt_sent = false;
986 			return;
987 		}
988 	}
989 
990 	exit (signo);
991 }
992 
993 void
994 sigtstp_handler (int signo)
995 {
996     g_driver->GetDebugger().SaveInputTerminalState();
997     signal (signo, SIG_DFL);
998     kill (getpid(), signo);
999     signal (signo, sigtstp_handler);
1000 }
1001 
1002 void
1003 sigcont_handler (int signo)
1004 {
1005     g_driver->GetDebugger().RestoreInputTerminalState();
1006     signal (signo, SIG_DFL);
1007     kill (getpid(), signo);
1008     signal (signo, sigcont_handler);
1009 }
1010 
1011 int
1012 main (int argc, char const *argv[], const char *envp[])
1013 {
1014     SBDebugger::Initialize();
1015 
1016     SBHostOS::ThreadCreated ("<lldb.driver.main-thread>");
1017 
1018     signal (SIGPIPE, SIG_IGN);
1019     signal (SIGWINCH, sigwinch_handler);
1020     signal (SIGINT, sigint_handler);
1021     signal (SIGTSTP, sigtstp_handler);
1022     signal (SIGCONT, sigcont_handler);
1023 
1024     // Create a scope for driver so that the driver object will destroy itself
1025     // before SBDebugger::Terminate() is called.
1026     {
1027         Driver driver;
1028 
1029         bool exiting = false;
1030         SBError error (driver.ParseArgs (argc, argv, stdout, exiting));
1031         if (error.Fail())
1032         {
1033             const char *error_cstr = error.GetCString ();
1034             if (error_cstr)
1035                 ::fprintf (stderr, "error: %s\n", error_cstr);
1036         }
1037         else if (!exiting)
1038         {
1039             driver.MainLoop ();
1040         }
1041     }
1042 
1043     SBDebugger::Terminate();
1044     return 0;
1045 }
1046