Driver.cpp revision 263363
1251881Speter//===-- Driver.cpp ----------------------------------------------*- C++ -*-===//
2251881Speter//
3251881Speter//                     The LLVM Compiler Infrastructure
4251881Speter//
5251881Speter// This file is distributed under the University of Illinois Open Source
6251881Speter// License. See LICENSE.TXT for details.
7251881Speter//
8251881Speter//===----------------------------------------------------------------------===//
9251881Speter
10251881Speter#include "Driver.h"
11251881Speter
12251881Speter#include <stdio.h>
13251881Speter#include <string.h>
14251881Speter#include <stdlib.h>
15251881Speter#include <limits.h>
16251881Speter#include <fcntl.h>
17251881Speter
18251881Speter#include <string>
19251881Speter
20251881Speter#include <thread>
21251881Speter#include "IOChannel.h"
22251881Speter#include "lldb/API/SBBreakpoint.h"
23251881Speter#include "lldb/API/SBCommandInterpreter.h"
24251881Speter#include "lldb/API/SBCommandReturnObject.h"
25299742Sdim#include "lldb/API/SBCommunication.h"
26299742Sdim#include "lldb/API/SBDebugger.h"
27251881Speter#include "lldb/API/SBEvent.h"
28251881Speter#include "lldb/API/SBHostOS.h"
29251881Speter#include "lldb/API/SBListener.h"
30251881Speter#include "lldb/API/SBStream.h"
31251881Speter#include "lldb/API/SBTarget.h"
32251881Speter#include "lldb/API/SBThread.h"
33251881Speter#include "lldb/API/SBProcess.h"
34251881Speter
35251881Speterusing namespace lldb;
36251881Speter
37251881Speterstatic void reset_stdin_termios ();
38251881Speterstatic bool g_old_stdin_termios_is_valid = false;
39251881Speterstatic struct termios g_old_stdin_termios;
40251881Speter
41251881Speterstatic char *g_debugger_name =  (char *) "";
42251881Speterstatic Driver *g_driver = NULL;
43251881Speter
44251881Speter// In the Driver::MainLoop, we change the terminal settings.  This function is
45251881Speter// added as an atexit handler to make sure we clean them up.
46251881Speterstatic void
47251881Speterreset_stdin_termios ()
48299742Sdim{
49299742Sdim    if (g_old_stdin_termios_is_valid)
50251881Speter    {
51251881Speter        g_old_stdin_termios_is_valid = false;
52251881Speter        ::tcsetattr (STDIN_FILENO, TCSANOW, &g_old_stdin_termios);
53299742Sdim    }
54299742Sdim}
55251881Speter
56251881Spetertypedef struct
57251881Speter{
58251881Speter    uint32_t usage_mask;                     // Used to mark options that can be used together.  If (1 << n & usage_mask) != 0
59251881Speter                                             // then this option belongs to option set n.
60251881Speter    bool required;                           // This option is required (in the current usage level)
61251881Speter    const char * long_option;                // Full name for this option.
62251881Speter    int short_option;                        // Single character for this option.
63251881Speter    int option_has_arg;                      // no_argument, required_argument or optional_argument
64251881Speter    uint32_t completion_type;                // Cookie the option class can use to do define the argument completion.
65251881Speter    lldb::CommandArgumentType argument_type; // Type of argument this option takes
66251881Speter    const char *  usage_text;                // Full text explaining what this options does and what (if any) argument to
67251881Speter                                             // pass it.
68251881Speter} OptionDefinition;
69251881Speter
70251881Speter#define LLDB_3_TO_5 LLDB_OPT_SET_3|LLDB_OPT_SET_4|LLDB_OPT_SET_5
71251881Speter#define LLDB_4_TO_5 LLDB_OPT_SET_4|LLDB_OPT_SET_5
72251881Speter
73251881Speterstatic OptionDefinition g_options[] =
74251881Speter{
75251881Speter    { LLDB_OPT_SET_1,    true , "help"           , 'h', no_argument      , 0,  eArgTypeNone,
76251881Speter        "Prints out the usage information for the LLDB debugger." },
77251881Speter    { LLDB_OPT_SET_2,    true , "version"        , 'v', no_argument      , 0,  eArgTypeNone,
78251881Speter        "Prints out the current version number of the LLDB debugger." },
79251881Speter    { LLDB_OPT_SET_3,    true , "arch"           , 'a', required_argument, 0,  eArgTypeArchitecture,
80251881Speter        "Tells the debugger to use the specified architecture when starting and running the program.  <architecture> must "
81251881Speter        "be one of the architectures for which the program was compiled." },
82251881Speter    { LLDB_OPT_SET_3,    true , "file"           , 'f', required_argument, 0,  eArgTypeFilename,
83251881Speter        "Tells the debugger to use the file <filename> as the program to be debugged." },
84251881Speter    { LLDB_OPT_SET_3,    false, "core"           , 'c', required_argument, 0,  eArgTypeFilename,
85251881Speter        "Tells the debugger to use the fullpath to <path> as the core file." },
86251881Speter    { LLDB_OPT_SET_4,    true , "attach-name"    , 'n', required_argument, 0,  eArgTypeProcessName,
87251881Speter        "Tells the debugger to attach to a process with the given name." },
88251881Speter    { LLDB_OPT_SET_4,    true , "wait-for"       , 'w', no_argument      , 0,  eArgTypeNone,
89251881Speter        "Tells the debugger to wait for a process with the given pid or name to launch before attaching." },
90251881Speter    { LLDB_OPT_SET_5,    true , "attach-pid"     , 'p', required_argument, 0,  eArgTypePid,
91251881Speter        "Tells the debugger to attach to a process with the given pid." },
92251881Speter    { LLDB_3_TO_5,       false, "script-language", 'l', required_argument, 0,  eArgTypeScriptLang,
93251881Speter        "Tells the debugger to use the specified scripting language for user-defined scripts, rather than the default.  "
94251881Speter        "Valid scripting languages that can be specified include Python, Perl, Ruby and Tcl.  Currently only the Python "
95251881Speter        "extensions have been implemented." },
96251881Speter    { LLDB_3_TO_5,       false, "debug"          , 'd', no_argument      , 0,  eArgTypeNone,
97251881Speter        "Tells the debugger to print out extra information for debugging itself." },
98251881Speter    { LLDB_3_TO_5,       false, "source-quietly"          , 'b', no_argument      , 0,  eArgTypeNone,
99251881Speter        "Tells the debugger to print out extra information for debugging itself." },
100251881Speter    { LLDB_3_TO_5,       false, "source"         , 's', required_argument, 0,  eArgTypeFilename,
101251881Speter        "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." },
102251881Speter    { LLDB_3_TO_5,       false, "one-line"         , 'o', required_argument, 0,  eArgTypeNone,
103251881Speter        "Tells the debugger to execute this one-line lldb command after any file provided on the command line has been loaded." },
104251881Speter    { LLDB_3_TO_5,       false, "source-before-file"         , 'S', required_argument, 0,  eArgTypeFilename,
105251881Speter        "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." },
106251881Speter    { LLDB_3_TO_5,       false, "one-line-before-file"         , 'O', required_argument, 0,  eArgTypeNone,
107251881Speter        "Tells the debugger to execute this one-line lldb command before any file provided on the command line has been loaded." },
108251881Speter    { LLDB_3_TO_5,       false, "editor"         , 'e', no_argument      , 0,  eArgTypeNone,
109251881Speter        "Tells the debugger to open source files using the host's \"external editor\" mechanism." },
110251881Speter    { LLDB_3_TO_5,       false, "no-lldbinit"    , 'x', no_argument      , 0,  eArgTypeNone,
111251881Speter        "Do not automatically parse any '.lldbinit' files." },
112251881Speter    { LLDB_3_TO_5,       false, "no-use-colors"  , 'X', no_argument      , 0,  eArgTypeNone,
113251881Speter        "Do not use colors." },
114251881Speter    { LLDB_OPT_SET_6,    true , "python-path"    , 'P', no_argument      , 0,  eArgTypeNone,
115251881Speter        "Prints out the path to the lldb.py file for this version of lldb." },
116251881Speter    { 0,                 false, NULL             , 0  , 0                , 0,  eArgTypeNone,         NULL }
117251881Speter};
118251881Speter
119251881Speterstatic const uint32_t last_option_set_with_args = 2;
120251881Speter
121251881SpeterDriver::Driver () :
122251881Speter    SBBroadcaster ("Driver"),
123251881Speter    m_debugger (SBDebugger::Create(false)),
124251881Speter    m_editline_pty (),
125251881Speter    m_editline_slave_fh (NULL),
126251881Speter    m_editline_reader (),
127251881Speter    m_io_channel_ap (),
128251881Speter    m_option_data (),
129251881Speter    m_executing_user_command (false),
130251881Speter    m_waiting_for_command (false),
131251881Speter    m_done(false)
132251881Speter{
133251881Speter    // We want to be able to handle CTRL+D in the terminal to have it terminate
134251881Speter    // certain input
135251881Speter    m_debugger.SetCloseInputOnEOF (false);
136251881Speter    g_debugger_name = (char *) m_debugger.GetInstanceName();
137251881Speter    if (g_debugger_name == NULL)
138251881Speter        g_debugger_name = (char *) "";
139251881Speter    g_driver = this;
140251881Speter}
141251881Speter
142251881SpeterDriver::~Driver ()
143251881Speter{
144251881Speter    g_driver = NULL;
145251881Speter    g_debugger_name = NULL;
146251881Speter}
147251881Speter
148251881Spetervoid
149251881SpeterDriver::CloseIOChannelFile ()
150299742Sdim{
151299742Sdim    // Write an End of File sequence to the file descriptor to ensure any
152251881Speter    // read functions can exit.
153251881Speter    char eof_str[] = "\x04";
154251881Speter    int mfd = m_editline_pty.GetMasterFileDescriptor();
155251881Speter    if (mfd != -1)
156251881Speter        ::write (m_editline_pty.GetMasterFileDescriptor(), eof_str, strlen(eof_str));
157251881Speter
158251881Speter    m_editline_pty.CloseMasterFileDescriptor();
159251881Speter
160251881Speter    if (m_editline_slave_fh)
161251881Speter    {
162251881Speter        ::fclose (m_editline_slave_fh);
163251881Speter        m_editline_slave_fh = NULL;
164251881Speter    }
165251881Speter}
166251881Speter
167251881Speter// This function takes INDENT, which tells how many spaces to output at the front
168251881Speter// of each line; TEXT, which is the text that is to be output. It outputs the
169251881Speter// text, on multiple lines if necessary, to RESULT, with INDENT spaces at the
170251881Speter// front of each line.  It breaks lines on spaces, tabs or newlines, shortening
171251881Speter// the line if necessary to not break in the middle of a word. It assumes that
172251881Speter// each output line should contain a maximum of OUTPUT_MAX_COLUMNS characters.
173251881Speter
174251881Spetervoid
175251881SpeterOutputFormattedUsageText (FILE *out, int indent, const char *text, int output_max_columns)
176251881Speter{
177251881Speter    int len = strlen (text);
178251881Speter    std::string text_string (text);
179251881Speter
180251881Speter    // Force indentation to be reasonable.
181251881Speter    if (indent >= output_max_columns)
182251881Speter        indent = 0;
183251881Speter
184251881Speter    // Will it all fit on one line?
185251881Speter
186251881Speter    if (len + indent < output_max_columns)
187251881Speter        // Output as a single line
188251881Speter        fprintf (out, "%*s%s\n", indent, "", text);
189251881Speter    else
190251881Speter    {
191251881Speter        // We need to break it up into multiple lines.
192251881Speter        int text_width = output_max_columns - indent - 1;
193251881Speter        int start = 0;
194251881Speter        int end = start;
195251881Speter        int final_end = len;
196251881Speter        int sub_len;
197251881Speter
198251881Speter        while (end < final_end)
199251881Speter        {
200251881Speter              // Dont start the 'text' on a space, since we're already outputting the indentation.
201251881Speter              while ((start < final_end) && (text[start] == ' '))
202251881Speter                  start++;
203251881Speter
204251881Speter              end = start + text_width;
205251881Speter              if (end > final_end)
206251881Speter                  end = final_end;
207251881Speter              else
208251881Speter              {
209251881Speter                  // If we're not at the end of the text, make sure we break the line on white space.
210251881Speter                  while (end > start
211251881Speter                         && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
212251881Speter                      end--;
213299742Sdim              }
214251881Speter              sub_len = end - start;
215299742Sdim              std::string substring = text_string.substr (start, sub_len);
216299742Sdim              fprintf (out, "%*s%s\n", indent, "", substring.c_str());
217299742Sdim              start = end + 1;
218251881Speter        }
219251881Speter    }
220299742Sdim}
221251881Speter
222251881Spetervoid
223251881SpeterShowUsage (FILE *out, OptionDefinition *option_table, Driver::OptionData data)
224251881Speter{
225251881Speter    uint32_t screen_width = 80;
226251881Speter    uint32_t indent_level = 0;
227251881Speter    const char *name = "lldb";
228251881Speter
229251881Speter    fprintf (out, "\nUsage:\n\n");
230251881Speter
231251881Speter    indent_level += 2;
232251881Speter
233251881Speter
234251881Speter    // First, show each usage level set of options, e.g. <cmd> [options-for-level-0]
235251881Speter    //                                                   <cmd> [options-for-level-1]
236251881Speter    //                                                   etc.
237251881Speter
238251881Speter    uint32_t num_options;
239251881Speter    uint32_t num_option_sets = 0;
240251881Speter
241251881Speter    for (num_options = 0; option_table[num_options].long_option != NULL; ++num_options)
242251881Speter    {
243251881Speter        uint32_t this_usage_mask = option_table[num_options].usage_mask;
244251881Speter        if (this_usage_mask == LLDB_OPT_SET_ALL)
245251881Speter        {
246251881Speter            if (num_option_sets == 0)
247251881Speter                num_option_sets = 1;
248251881Speter        }
249251881Speter        else
250251881Speter        {
251251881Speter            for (uint32_t j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++)
252251881Speter            {
253251881Speter                if (this_usage_mask & 1 << j)
254251881Speter                {
255251881Speter                    if (num_option_sets <= j)
256251881Speter                        num_option_sets = j + 1;
257251881Speter                }
258251881Speter            }
259251881Speter        }
260251881Speter    }
261251881Speter
262251881Speter    for (uint32_t opt_set = 0; opt_set < num_option_sets; opt_set++)
263251881Speter    {
264251881Speter        uint32_t opt_set_mask;
265251881Speter
266251881Speter        opt_set_mask = 1 << opt_set;
267251881Speter
268251881Speter        if (opt_set > 0)
269251881Speter            fprintf (out, "\n");
270251881Speter        fprintf (out, "%*s%s", indent_level, "", name);
271251881Speter        bool is_help_line = false;
272251881Speter
273251881Speter        for (uint32_t i = 0; i < num_options; ++i)
274251881Speter        {
275251881Speter            if (option_table[i].usage_mask & opt_set_mask)
276251881Speter            {
277251881Speter                CommandArgumentType arg_type = option_table[i].argument_type;
278251881Speter                const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type);
279251881Speter                // This is a bit of a hack, but there's no way to say certain options don't have arguments yet...
280251881Speter                // so we do it by hand here.
281251881Speter                if (option_table[i].short_option == 'h')
282251881Speter                    is_help_line = true;
283251881Speter
284251881Speter                if (option_table[i].required)
285251881Speter                {
286251881Speter                    if (option_table[i].option_has_arg == required_argument)
287251881Speter                        fprintf (out, " -%c <%s>", option_table[i].short_option, arg_name);
288251881Speter                    else if (option_table[i].option_has_arg == optional_argument)
289251881Speter                        fprintf (out, " -%c [<%s>]", option_table[i].short_option, arg_name);
290251881Speter                    else
291251881Speter                        fprintf (out, " -%c", option_table[i].short_option);
292251881Speter                }
293251881Speter                else
294251881Speter                {
295251881Speter                    if (option_table[i].option_has_arg == required_argument)
296251881Speter                        fprintf (out, " [-%c <%s>]", option_table[i].short_option, arg_name);
297251881Speter                    else if (option_table[i].option_has_arg == optional_argument)
298251881Speter                        fprintf (out, " [-%c [<%s>]]", option_table[i].short_option, arg_name);
299251881Speter                    else
300251881Speter                        fprintf (out, " [-%c]", option_table[i].short_option);
301251881Speter                }
302251881Speter            }
303251881Speter        }
304299742Sdim        if (!is_help_line && (opt_set <= last_option_set_with_args))
305299742Sdim            fprintf (out, " [[--] <PROGRAM-ARG-1> [<PROGRAM_ARG-2> ...]]");
306299742Sdim    }
307299742Sdim
308299742Sdim    fprintf (out, "\n\n");
309299742Sdim
310251881Speter    // Now print out all the detailed information about the various options:  long form, short form and help text:
311251881Speter    //   -- long_name <argument>
312251881Speter    //   - short <argument>
313251881Speter    //   help text
314251881Speter
315251881Speter    // This variable is used to keep track of which options' info we've printed out, because some options can be in
316251881Speter    // more than one usage level, but we only want to print the long form of its information once.
317251881Speter
318251881Speter    Driver::OptionData::OptionSet options_seen;
319251881Speter    Driver::OptionData::OptionSet::iterator pos;
320251881Speter
321251881Speter    indent_level += 5;
322251881Speter
323251881Speter    for (uint32_t i = 0; i < num_options; ++i)
324251881Speter    {
325251881Speter        // Only print this option if we haven't already seen it.
326251881Speter        pos = options_seen.find (option_table[i].short_option);
327251881Speter        if (pos == options_seen.end())
328251881Speter        {
329251881Speter            CommandArgumentType arg_type = option_table[i].argument_type;
330251881Speter            const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type);
331251881Speter
332251881Speter            options_seen.insert (option_table[i].short_option);
333251881Speter            fprintf (out, "%*s-%c ", indent_level, "", option_table[i].short_option);
334251881Speter            if (arg_type != eArgTypeNone)
335251881Speter                fprintf (out, "<%s>", arg_name);
336251881Speter            fprintf (out, "\n");
337251881Speter            fprintf (out, "%*s--%s ", indent_level, "", option_table[i].long_option);
338251881Speter            if (arg_type != eArgTypeNone)
339251881Speter                fprintf (out, "<%s>", arg_name);
340251881Speter            fprintf (out, "\n");
341251881Speter            indent_level += 5;
342251881Speter            OutputFormattedUsageText (out, indent_level, option_table[i].usage_text, screen_width);
343251881Speter            indent_level -= 5;
344251881Speter            fprintf (out, "\n");
345251881Speter        }
346251881Speter    }
347251881Speter
348251881Speter    indent_level -= 5;
349251881Speter
350251881Speter    fprintf (out, "\n%*sMultiple \"-s\" and \"-o\" options can be provided.  They will be processed from left to right in order, "
351251881Speter                  "\n%*swith the source files and commands interleaved.  The same is true of the \"-S\" and \"-O\" options."
352251881Speter                  "\n%*sThe before file and after file sets can intermixed freely, the command parser will sort them out."
353251881Speter                  "\n%*sThe order of the file specifiers (\"-c\", \"-f\", etc.) is not significant in this regard.\n\n",
354251881Speter             indent_level, "",
355251881Speter             indent_level, "",
356251881Speter             indent_level, "",
357251881Speter             indent_level, "");
358251881Speter
359251881Speter    fprintf (out, "\n%*s(If you don't provide -f then the first argument will be the file to be debugged"
360251881Speter                  "\n%*s so '%s -- <filename> [<ARG1> [<ARG2>]]' also works."
361251881Speter                  "\n%*s Remember to end the options with \"--\" if any of your arguments have a \"-\" in them.)\n\n",
362251881Speter             indent_level, "",
363251881Speter             indent_level, "",
364251881Speter             name,
365251881Speter             indent_level, "");
366251881Speter}
367251881Speter
368251881Spetervoid
369251881SpeterBuildGetOptTable (OptionDefinition *expanded_option_table, std::vector<struct option> &getopt_table,
370251881Speter                  uint32_t num_options)
371251881Speter{
372251881Speter    if (num_options == 0)
373251881Speter        return;
374251881Speter
375251881Speter    uint32_t i;
376251881Speter    uint32_t j;
377251881Speter    std::bitset<256> option_seen;
378251881Speter
379251881Speter    getopt_table.resize (num_options + 1);
380251881Speter
381251881Speter    for (i = 0, j = 0; i < num_options; ++i)
382251881Speter    {
383251881Speter        char short_opt = expanded_option_table[i].short_option;
384251881Speter
385251881Speter        if (option_seen.test(short_opt) == false)
386251881Speter        {
387251881Speter            getopt_table[j].name    = expanded_option_table[i].long_option;
388251881Speter            getopt_table[j].has_arg = expanded_option_table[i].option_has_arg;
389251881Speter            getopt_table[j].flag    = NULL;
390251881Speter            getopt_table[j].val     = expanded_option_table[i].short_option;
391251881Speter            option_seen.set(short_opt);
392251881Speter            ++j;
393251881Speter        }
394251881Speter    }
395251881Speter
396251881Speter    getopt_table[j].name    = NULL;
397251881Speter    getopt_table[j].has_arg = 0;
398251881Speter    getopt_table[j].flag    = NULL;
399251881Speter    getopt_table[j].val     = 0;
400251881Speter
401251881Speter}
402251881Speter
403251881SpeterDriver::OptionData::OptionData () :
404251881Speter    m_args(),
405251881Speter    m_script_lang (lldb::eScriptLanguageDefault),
406251881Speter    m_core_file (),
407251881Speter    m_crash_log (),
408251881Speter    m_initial_commands (),
409251881Speter    m_after_file_commands (),
410299742Sdim    m_debug_mode (false),
411251881Speter    m_source_quietly(false),
412251881Speter    m_print_version (false),
413251881Speter    m_print_python_path (false),
414251881Speter    m_print_help (false),
415299742Sdim    m_wait_for(false),
416299742Sdim    m_process_name(),
417251881Speter    m_process_pid(LLDB_INVALID_PROCESS_ID),
418251881Speter    m_use_external_editor(false),
419251881Speter    m_seen_options()
420251881Speter{
421251881Speter}
422251881Speter
423251881SpeterDriver::OptionData::~OptionData ()
424251881Speter{
425251881Speter}
426299742Sdim
427251881Spetervoid
428251881SpeterDriver::OptionData::Clear ()
429251881Speter{
430251881Speter    m_args.clear ();
431251881Speter    m_script_lang = lldb::eScriptLanguageDefault;
432251881Speter    m_initial_commands.clear ();
433251881Speter    m_after_file_commands.clear ();
434251881Speter    m_debug_mode = false;
435251881Speter    m_source_quietly = false;
436251881Speter    m_print_help = false;
437251881Speter    m_print_version = false;
438251881Speter    m_print_python_path = false;
439251881Speter    m_use_external_editor = false;
440251881Speter    m_wait_for = false;
441251881Speter    m_process_name.erase();
442251881Speter    m_process_pid = LLDB_INVALID_PROCESS_ID;
443251881Speter}
444251881Speter
445251881Spetervoid
446299742SdimDriver::OptionData::AddInitialCommand (const char *command, bool before_file, bool is_file, SBError &error)
447299742Sdim{
448299742Sdim    std::vector<std::pair<bool, std::string> > *command_set;
449251881Speter    if (before_file)
450251881Speter        command_set = &(m_initial_commands);
451251881Speter    else
452251881Speter        command_set = &(m_after_file_commands);
453299742Sdim
454299742Sdim    if (is_file)
455251881Speter    {
456251881Speter        SBFileSpec file(command);
457251881Speter        if (file.Exists())
458251881Speter            command_set->push_back (std::pair<bool, std::string> (true, optarg));
459299742Sdim        else if (file.ResolveExecutableLocation())
460299742Sdim        {
461299742Sdim            char final_path[PATH_MAX];
462251881Speter            file.GetPath (final_path, sizeof(final_path));
463251881Speter            std::string path_str (final_path);
464251881Speter            command_set->push_back (std::pair<bool, std::string> (true, path_str));
465251881Speter        }
466251881Speter        else
467251881Speter            error.SetErrorStringWithFormat("file specified in --source (-s) option doesn't exist: '%s'", optarg);
468251881Speter    }
469251881Speter    else
470251881Speter        command_set->push_back (std::pair<bool, std::string> (false, optarg));
471251881Speter}
472251881Speter
473251881Spetervoid
474251881SpeterDriver::ResetOptionValues ()
475251881Speter{
476299742Sdim    m_option_data.Clear ();
477299742Sdim}
478251881Speter
479251881Speterconst char *
480251881SpeterDriver::GetFilename() const
481251881Speter{
482299742Sdim    if (m_option_data.m_args.empty())
483299742Sdim        return NULL;
484251881Speter    return m_option_data.m_args.front().c_str();
485251881Speter}
486251881Speter
487251881Speterconst char *
488251881SpeterDriver::GetCrashLogFilename() const
489251881Speter{
490251881Speter    if (m_option_data.m_crash_log.empty())
491251881Speter        return NULL;
492251881Speter    return m_option_data.m_crash_log.c_str();
493251881Speter}
494251881Speter
495251881Speterlldb::ScriptLanguage
496251881SpeterDriver::GetScriptLanguage() const
497251881Speter{
498299742Sdim    return m_option_data.m_script_lang;
499299742Sdim}
500251881Speter
501251881Spetervoid
502251881SpeterDriver::ExecuteInitialCommands (bool before_file)
503251881Speter{
504251881Speter    size_t num_commands;
505251881Speter    std::vector<std::pair<bool, std::string> > *command_set;
506251881Speter    if (before_file)
507251881Speter        command_set = &(m_option_data.m_initial_commands);
508251881Speter    else
509251881Speter        command_set = &(m_option_data.m_after_file_commands);
510251881Speter
511251881Speter    num_commands = command_set->size();
512251881Speter    SBCommandReturnObject result;
513251881Speter    bool old_async = GetDebugger().GetAsync();
514251881Speter    GetDebugger().SetAsync(false);
515251881Speter    for (size_t idx = 0; idx < num_commands; idx++)
516251881Speter    {
517251881Speter        bool is_file = (*command_set)[idx].first;
518251881Speter        const char *command = (*command_set)[idx].second.c_str();
519251881Speter        char command_string[PATH_MAX * 2];
520251881Speter        const bool dump_stream_only_if_no_immediate = true;
521251881Speter        const char *executed_command = command;
522251881Speter        if (is_file)
523251881Speter        {
524251881Speter            ::snprintf (command_string, sizeof(command_string), "command source '%s'", command);
525251881Speter            executed_command = command_string;
526251881Speter        }
527251881Speter
528251881Speter        m_debugger.GetCommandInterpreter().HandleCommand (executed_command, result, false);
529251881Speter        if (!m_option_data.m_source_quietly || result.Succeeded() == false)
530251881Speter        {
531251881Speter            const size_t output_size = result.GetOutputSize();
532251881Speter            if (output_size > 0)
533251881Speter                m_io_channel_ap->OutWrite (result.GetOutput(dump_stream_only_if_no_immediate), output_size, NO_ASYNC);
534251881Speter            const size_t error_size = result.GetErrorSize();
535251881Speter            if (error_size > 0)
536251881Speter                m_io_channel_ap->OutWrite (result.GetError(dump_stream_only_if_no_immediate), error_size, NO_ASYNC);
537251881Speter        }
538251881Speter
539251881Speter        if (result.Succeeded() == false)
540251881Speter        {
541251881Speter            char error_buffer[1024];
542251881Speter            size_t error_size;
543251881Speter            const char *type = before_file ? "before file" : "after_file";
544251881Speter            if (is_file)
545251881Speter                error_size = ::snprintf(error_buffer, sizeof(error_buffer), "Aborting %s command execution, command file: '%s' failed.\n", type, command);
546251881Speter            else
547251881Speter                error_size = ::snprintf(error_buffer, sizeof(error_buffer), "Aborting %s command execution, command: '%s' failed.\n", type, command);
548251881Speter
549251881Speter            m_io_channel_ap->OutWrite(error_buffer, error_size, NO_ASYNC);
550251881Speter            break;
551251881Speter        }
552251881Speter        result.Clear();
553251881Speter    }
554251881Speter    GetDebugger().SetAsync(old_async);
555251881Speter}
556251881Speter
557251881Speterbool
558251881SpeterDriver::GetDebugMode() const
559251881Speter{
560251881Speter    return m_option_data.m_debug_mode;
561251881Speter}
562251881Speter
563251881Speter
564251881Speter// Check the arguments that were passed to this program to make sure they are valid and to get their
565251881Speter// argument values (if any).  Return a boolean value indicating whether or not to start up the full
566251881Speter// debugger (i.e. the Command Interpreter) or not.  Return FALSE if the arguments were invalid OR
567251881Speter// if the user only wanted help or version information.
568251881Speter
569251881SpeterSBError
570251881SpeterDriver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exiting)
571251881Speter{
572251881Speter    ResetOptionValues ();
573251881Speter
574251881Speter    SBCommandReturnObject result;
575251881Speter
576251881Speter    SBError error;
577251881Speter    std::string option_string;
578251881Speter    struct option *long_options = NULL;
579251881Speter    std::vector<struct option> long_options_vector;
580269847Speter    uint32_t num_options;
581251881Speter
582251881Speter    for (num_options = 0; g_options[num_options].long_option != NULL; ++num_options)
583299742Sdim        /* Do Nothing. */;
584251881Speter
585251881Speter    if (num_options == 0)
586251881Speter    {
587251881Speter        if (argc > 1)
588251881Speter            error.SetErrorStringWithFormat ("invalid number of options");
589251881Speter        return error;
590251881Speter    }
591299742Sdim
592251881Speter    BuildGetOptTable (g_options, long_options_vector, num_options);
593251881Speter
594251881Speter    if (long_options_vector.empty())
595251881Speter        long_options = NULL;
596251881Speter    else
597251881Speter        long_options = &long_options_vector.front();
598251881Speter
599299742Sdim    if (long_options == NULL)
600251881Speter    {
601299742Sdim        error.SetErrorStringWithFormat ("invalid long options");
602253734Speter        return error;
603251881Speter    }
604299742Sdim
605251881Speter    // Build the option_string argument for call to getopt_long_only.
606
607    for (int i = 0; long_options[i].name != NULL; ++i)
608    {
609        if (long_options[i].flag == NULL)
610        {
611            option_string.push_back ((char) long_options[i].val);
612            switch (long_options[i].has_arg)
613            {
614                default:
615                case no_argument:
616                    break;
617                case required_argument:
618                    option_string.push_back (':');
619                    break;
620                case optional_argument:
621                    option_string.append ("::");
622                    break;
623            }
624        }
625    }
626
627    // This is kind of a pain, but since we make the debugger in the Driver's constructor, we can't
628    // know at that point whether we should read in init files yet.  So we don't read them in in the
629    // Driver constructor, then set the flags back to "read them in" here, and then if we see the
630    // "-n" flag, we'll turn it off again.  Finally we have to read them in by hand later in the
631    // main loop.
632
633    m_debugger.SkipLLDBInitFiles (false);
634    m_debugger.SkipAppInitFiles (false);
635
636    // Prepare for & make calls to getopt_long_only.
637#if __GLIBC__
638    optind = 0;
639#else
640    optreset = 1;
641    optind = 1;
642#endif
643    int val;
644    while (1)
645    {
646        int long_options_index = -1;
647        val = ::getopt_long_only (argc, const_cast<char **>(argv), option_string.c_str(), long_options, &long_options_index);
648
649        if (val == -1)
650            break;
651        else if (val == '?')
652        {
653            m_option_data.m_print_help = true;
654            error.SetErrorStringWithFormat ("unknown or ambiguous option");
655            break;
656        }
657        else if (val == 0)
658            continue;
659        else
660        {
661            m_option_data.m_seen_options.insert ((char) val);
662            if (long_options_index == -1)
663            {
664                for (int i = 0;
665                     long_options[i].name || long_options[i].has_arg || long_options[i].flag || long_options[i].val;
666                     ++i)
667                {
668                    if (long_options[i].val == val)
669                    {
670                        long_options_index = i;
671                        break;
672                    }
673                }
674            }
675
676            if (long_options_index >= 0)
677            {
678                const int short_option = g_options[long_options_index].short_option;
679
680                switch (short_option)
681                {
682                    case 'h':
683                        m_option_data.m_print_help = true;
684                        break;
685
686                    case 'v':
687                        m_option_data.m_print_version = true;
688                        break;
689
690                    case 'P':
691                        m_option_data.m_print_python_path = true;
692                        break;
693
694                    case 'c':
695                        {
696                            SBFileSpec file(optarg);
697                            if (file.Exists())
698                            {
699                                m_option_data.m_core_file = optarg;
700                            }
701                            else
702                                error.SetErrorStringWithFormat("file specified in --core (-c) option doesn't exist: '%s'", optarg);
703                        }
704                        break;
705
706                    case 'e':
707                        m_option_data.m_use_external_editor = true;
708                        break;
709
710                    case 'x':
711                        m_debugger.SkipLLDBInitFiles (true);
712                        m_debugger.SkipAppInitFiles (true);
713                        break;
714
715                    case 'X':
716                        m_debugger.SetUseColor (false);
717                        break;
718
719                    case 'f':
720                        {
721                            SBFileSpec file(optarg);
722                            if (file.Exists())
723                            {
724                                m_option_data.m_args.push_back (optarg);
725                            }
726                            else if (file.ResolveExecutableLocation())
727                            {
728                                char path[PATH_MAX];
729                                file.GetPath (path, sizeof(path));
730                                m_option_data.m_args.push_back (path);
731                            }
732                            else
733                                error.SetErrorStringWithFormat("file specified in --file (-f) option doesn't exist: '%s'", optarg);
734                        }
735                        break;
736
737                    case 'a':
738                        if (!m_debugger.SetDefaultArchitecture (optarg))
739                            error.SetErrorStringWithFormat("invalid architecture in the -a or --arch option: '%s'", optarg);
740                        break;
741
742                    case 'l':
743                        m_option_data.m_script_lang = m_debugger.GetScriptingLanguage (optarg);
744                        break;
745
746                    case 'd':
747                        m_option_data.m_debug_mode = true;
748                        break;
749
750                    case 'q':
751                        m_option_data.m_source_quietly = true;
752                        break;
753
754                    case 'n':
755                        m_option_data.m_process_name = optarg;
756                        break;
757
758                    case 'w':
759                        m_option_data.m_wait_for = true;
760                        break;
761
762                    case 'p':
763                        {
764                            char *remainder;
765                            m_option_data.m_process_pid = strtol (optarg, &remainder, 0);
766                            if (remainder == optarg || *remainder != '\0')
767                                error.SetErrorStringWithFormat ("Could not convert process PID: \"%s\" into a pid.",
768                                                                optarg);
769                        }
770                        break;
771                    case 's':
772                        m_option_data.AddInitialCommand(optarg, false, true, error);
773                        break;
774                    case 'o':
775                        m_option_data.AddInitialCommand(optarg, false, false, error);
776                        break;
777                    case 'S':
778                        m_option_data.AddInitialCommand(optarg, true, true, error);
779                        break;
780                    case 'O':
781                        m_option_data.AddInitialCommand(optarg, true, false, error);
782                        break;
783                    default:
784                        m_option_data.m_print_help = true;
785                        error.SetErrorStringWithFormat ("unrecognized option %c", short_option);
786                        break;
787                }
788            }
789            else
790            {
791                error.SetErrorStringWithFormat ("invalid option with value %i", val);
792            }
793            if (error.Fail())
794            {
795                return error;
796            }
797        }
798    }
799
800    if (error.Fail() || m_option_data.m_print_help)
801    {
802        ShowUsage (out_fh, g_options, m_option_data);
803        exiting = true;
804    }
805    else if (m_option_data.m_print_version)
806    {
807        ::fprintf (out_fh, "%s\n", m_debugger.GetVersionString());
808        exiting = true;
809    }
810    else if (m_option_data.m_print_python_path)
811    {
812        SBFileSpec python_file_spec = SBHostOS::GetLLDBPythonPath();
813        if (python_file_spec.IsValid())
814        {
815            char python_path[PATH_MAX];
816            size_t num_chars = python_file_spec.GetPath(python_path, PATH_MAX);
817            if (num_chars < PATH_MAX)
818            {
819                ::fprintf (out_fh, "%s\n", python_path);
820            }
821            else
822                ::fprintf (out_fh, "<PATH TOO LONG>\n");
823        }
824        else
825            ::fprintf (out_fh, "<COULD NOT FIND PATH>\n");
826        exiting = true;
827    }
828    else if (m_option_data.m_process_name.empty() && m_option_data.m_process_pid == LLDB_INVALID_PROCESS_ID)
829    {
830        // Any arguments that are left over after option parsing are for
831        // the program. If a file was specified with -f then the filename
832        // is already in the m_option_data.m_args array, and any remaining args
833        // are arguments for the inferior program. If no file was specified with
834        // -f, then what is left is the program name followed by any arguments.
835
836        // Skip any options we consumed with getopt_long_only
837        argc -= optind;
838        argv += optind;
839
840        if (argc > 0)
841        {
842            for (int arg_idx=0; arg_idx<argc; ++arg_idx)
843            {
844                const char *arg = argv[arg_idx];
845                if (arg)
846                    m_option_data.m_args.push_back (arg);
847            }
848        }
849
850    }
851    else
852    {
853        // Skip any options we consumed with getopt_long_only
854        argc -= optind;
855        //argv += optind; // Commented out to keep static analyzer happy
856
857        if (argc > 0)
858            ::fprintf (out_fh, "Warning: program arguments are ignored when attaching.\n");
859    }
860
861    return error;
862}
863
864size_t
865Driver::GetProcessSTDOUT ()
866{
867    //  The process has stuff waiting for stdout; get it and write it out to the appropriate place.
868    char stdio_buffer[1024];
869    size_t len;
870    size_t total_bytes = 0;
871    while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0)
872    {
873        m_io_channel_ap->OutWrite (stdio_buffer, len, NO_ASYNC);
874        total_bytes += len;
875    }
876    return total_bytes;
877}
878
879size_t
880Driver::GetProcessSTDERR ()
881{
882    //  The process has stuff waiting for stderr; get it and write it out to the appropriate place.
883    char stdio_buffer[1024];
884    size_t len;
885    size_t total_bytes = 0;
886    while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0)
887    {
888        m_io_channel_ap->ErrWrite (stdio_buffer, len, NO_ASYNC);
889        total_bytes += len;
890    }
891    return total_bytes;
892}
893
894void
895Driver::UpdateSelectedThread ()
896{
897    using namespace lldb;
898    SBProcess process(m_debugger.GetSelectedTarget().GetProcess());
899    if (process.IsValid())
900    {
901        SBThread curr_thread (process.GetSelectedThread());
902        SBThread thread;
903        StopReason curr_thread_stop_reason = eStopReasonInvalid;
904        curr_thread_stop_reason = curr_thread.GetStopReason();
905
906        if (!curr_thread.IsValid() ||
907            curr_thread_stop_reason == eStopReasonInvalid ||
908            curr_thread_stop_reason == eStopReasonNone)
909        {
910            // Prefer a thread that has just completed its plan over another thread as current thread.
911            SBThread plan_thread;
912            SBThread other_thread;
913            const size_t num_threads = process.GetNumThreads();
914            size_t i;
915            for (i = 0; i < num_threads; ++i)
916            {
917                thread = process.GetThreadAtIndex(i);
918                StopReason thread_stop_reason = thread.GetStopReason();
919                switch (thread_stop_reason)
920                {
921                case eStopReasonInvalid:
922                case eStopReasonNone:
923                    break;
924
925                case eStopReasonTrace:
926                case eStopReasonBreakpoint:
927                case eStopReasonWatchpoint:
928                case eStopReasonSignal:
929                case eStopReasonException:
930                case eStopReasonExec:
931                case eStopReasonThreadExiting:
932                    if (!other_thread.IsValid())
933                        other_thread = thread;
934                    break;
935                case eStopReasonPlanComplete:
936                    if (!plan_thread.IsValid())
937                        plan_thread = thread;
938                    break;
939                }
940            }
941            if (plan_thread.IsValid())
942                process.SetSelectedThread (plan_thread);
943            else if (other_thread.IsValid())
944                process.SetSelectedThread (other_thread);
945            else
946            {
947                if (curr_thread.IsValid())
948                    thread = curr_thread;
949                else
950                    thread = process.GetThreadAtIndex(0);
951
952                if (thread.IsValid())
953                    process.SetSelectedThread (thread);
954            }
955        }
956    }
957}
958
959// This function handles events that were broadcast by the process.
960void
961Driver::HandleBreakpointEvent (const SBEvent &event)
962{
963    using namespace lldb;
964    const uint32_t event_type = SBBreakpoint::GetBreakpointEventTypeFromEvent (event);
965
966    if (event_type & eBreakpointEventTypeAdded
967        || event_type & eBreakpointEventTypeRemoved
968        || event_type & eBreakpointEventTypeEnabled
969        || event_type & eBreakpointEventTypeDisabled
970        || event_type & eBreakpointEventTypeCommandChanged
971        || event_type & eBreakpointEventTypeConditionChanged
972        || event_type & eBreakpointEventTypeIgnoreChanged
973        || event_type & eBreakpointEventTypeLocationsResolved)
974    {
975        // Don't do anything about these events, since the breakpoint commands already echo these actions.
976    }
977    else if (event_type & eBreakpointEventTypeLocationsAdded)
978    {
979        char message[256];
980        uint32_t num_new_locations = SBBreakpoint::GetNumBreakpointLocationsFromEvent(event);
981        if (num_new_locations > 0)
982        {
983            SBBreakpoint breakpoint = SBBreakpoint::GetBreakpointFromEvent(event);
984            int message_len = ::snprintf (message, sizeof(message), "%d location%s added to breakpoint %d\n",
985                                          num_new_locations,
986                                          num_new_locations == 1 ? "" : "s",
987                                          breakpoint.GetID());
988            m_io_channel_ap->OutWrite(message, message_len, ASYNC);
989        }
990    }
991    else if (event_type & eBreakpointEventTypeLocationsRemoved)
992    {
993       // These locations just get disabled, not sure it is worth spamming folks about this on the command line.
994    }
995    else if (event_type & eBreakpointEventTypeLocationsResolved)
996    {
997       // This might be an interesting thing to note, but I'm going to leave it quiet for now, it just looked noisy.
998    }
999}
1000
1001// This function handles events that were broadcast by the process.
1002void
1003Driver::HandleProcessEvent (const SBEvent &event)
1004{
1005    using namespace lldb;
1006    const uint32_t event_type = event.GetType();
1007
1008    if (event_type & SBProcess::eBroadcastBitSTDOUT)
1009    {
1010        // The process has stdout available, get it and write it out to the
1011        // appropriate place.
1012        GetProcessSTDOUT ();
1013    }
1014    else if (event_type & SBProcess::eBroadcastBitSTDERR)
1015    {
1016        // The process has stderr available, get it and write it out to the
1017        // appropriate place.
1018        GetProcessSTDERR ();
1019    }
1020    else if (event_type & SBProcess::eBroadcastBitStateChanged)
1021    {
1022        // Drain all stout and stderr so we don't see any output come after
1023        // we print our prompts
1024        GetProcessSTDOUT ();
1025        GetProcessSTDERR ();
1026        // Something changed in the process;  get the event and report the process's current status and location to
1027        // the user.
1028        StateType event_state = SBProcess::GetStateFromEvent (event);
1029        if (event_state == eStateInvalid)
1030            return;
1031
1032        SBProcess process (SBProcess::GetProcessFromEvent (event));
1033        assert (process.IsValid());
1034
1035        switch (event_state)
1036        {
1037        case eStateInvalid:
1038        case eStateUnloaded:
1039        case eStateConnected:
1040        case eStateAttaching:
1041        case eStateLaunching:
1042        case eStateStepping:
1043        case eStateDetached:
1044            {
1045                char message[1024];
1046                int message_len = ::snprintf (message, sizeof(message), "Process %" PRIu64 " %s\n", process.GetProcessID(),
1047                                              m_debugger.StateAsCString (event_state));
1048                m_io_channel_ap->OutWrite(message, message_len, ASYNC);
1049            }
1050            break;
1051
1052        case eStateRunning:
1053            // Don't be chatty when we run...
1054            break;
1055
1056        case eStateExited:
1057            {
1058                SBCommandReturnObject result;
1059                m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
1060                m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize(), ASYNC);
1061                m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize(), ASYNC);
1062            }
1063            break;
1064
1065        case eStateStopped:
1066        case eStateCrashed:
1067        case eStateSuspended:
1068            // Make sure the program hasn't been auto-restarted:
1069            if (SBProcess::GetRestartedFromEvent (event))
1070            {
1071                size_t num_reasons = SBProcess::GetNumRestartedReasonsFromEvent(event);
1072                if (num_reasons > 0)
1073                {
1074                // FIXME: Do we want to report this, or would that just be annoyingly chatty?
1075                    if (num_reasons == 1)
1076                    {
1077                        char message[1024];
1078                        const char *reason = SBProcess::GetRestartedReasonAtIndexFromEvent (event, 0);
1079                        int message_len = ::snprintf (message, sizeof(message), "Process %" PRIu64 " stopped and restarted: %s\n",
1080                                              process.GetProcessID(), reason ? reason : "<UNKNOWN REASON>");
1081                        m_io_channel_ap->OutWrite(message, message_len, ASYNC);
1082                    }
1083                    else
1084                    {
1085                        char message[1024];
1086                        int message_len = ::snprintf (message, sizeof(message), "Process %" PRIu64 " stopped and restarted, reasons:\n",
1087                                              process.GetProcessID());
1088                        m_io_channel_ap->OutWrite(message, message_len, ASYNC);
1089                        for (size_t i = 0; i < num_reasons; i++)
1090                        {
1091                            const char *reason = SBProcess::GetRestartedReasonAtIndexFromEvent (event, i);
1092                            int message_len = ::snprintf(message, sizeof(message), "\t%s\n", reason ? reason : "<UNKNOWN REASON>");
1093                            m_io_channel_ap->OutWrite(message, message_len, ASYNC);
1094                        }
1095                    }
1096                }
1097            }
1098            else
1099            {
1100                if (GetDebugger().GetSelectedTarget() == process.GetTarget())
1101                {
1102                    SBCommandReturnObject result;
1103                    UpdateSelectedThread ();
1104                    m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
1105                    m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize(), ASYNC);
1106                    m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize(), ASYNC);
1107                }
1108                else
1109                {
1110                    SBStream out_stream;
1111                    uint32_t target_idx = GetDebugger().GetIndexOfTarget(process.GetTarget());
1112                    if (target_idx != UINT32_MAX)
1113                        out_stream.Printf ("Target %d: (", target_idx);
1114                    else
1115                        out_stream.Printf ("Target <unknown index>: (");
1116                    process.GetTarget().GetDescription (out_stream, eDescriptionLevelBrief);
1117                    out_stream.Printf (") stopped.\n");
1118                    m_io_channel_ap->OutWrite (out_stream.GetData(), out_stream.GetSize(), ASYNC);
1119                }
1120            }
1121            break;
1122        }
1123    }
1124}
1125
1126void
1127Driver::HandleThreadEvent (const SBEvent &event)
1128{
1129    // At present the only thread event we handle is the Frame Changed event, and all we do for that is just
1130    // reprint the thread status for that thread.
1131    using namespace lldb;
1132    const uint32_t event_type = event.GetType();
1133    if (event_type == SBThread::eBroadcastBitStackChanged
1134        || event_type == SBThread::eBroadcastBitThreadSelected)
1135    {
1136        SBThread thread = SBThread::GetThreadFromEvent (event);
1137        if (thread.IsValid())
1138        {
1139            SBStream out_stream;
1140            thread.GetStatus(out_stream);
1141            m_io_channel_ap->OutWrite (out_stream.GetData (), out_stream.GetSize (), ASYNC);
1142        }
1143    }
1144}
1145
1146//  This function handles events broadcast by the IOChannel (HasInput, UserInterrupt, or ThreadShouldExit).
1147
1148bool
1149Driver::HandleIOEvent (const SBEvent &event)
1150{
1151    bool quit = false;
1152
1153    const uint32_t event_type = event.GetType();
1154
1155    if (event_type & IOChannel::eBroadcastBitHasUserInput)
1156    {
1157        // We got some input (i.e. a command string) from the user; pass it off to the command interpreter for
1158        // handling.
1159
1160        const char *command_string = SBEvent::GetCStringFromEvent(event);
1161        if (command_string == NULL)
1162            command_string = "";
1163        SBCommandReturnObject result;
1164
1165        // We don't want the result to bypass the OutWrite function in IOChannel, as this can result in odd
1166        // output orderings and problems with the prompt.
1167
1168        // Note that we are in the process of executing a command
1169        m_executing_user_command = true;
1170
1171        m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, true);
1172
1173        // Note that we are back from executing a user command
1174        m_executing_user_command = false;
1175
1176        // Display any STDOUT/STDERR _prior_ to emitting the command result text
1177        GetProcessSTDOUT ();
1178        GetProcessSTDERR ();
1179
1180        const bool only_if_no_immediate = true;
1181
1182        // Now emit the command output text from the command we just executed
1183        const size_t output_size = result.GetOutputSize();
1184        if (output_size > 0)
1185            m_io_channel_ap->OutWrite (result.GetOutput(only_if_no_immediate), output_size, NO_ASYNC);
1186
1187        // Now emit the command error text from the command we just executed
1188        const size_t error_size = result.GetErrorSize();
1189        if (error_size > 0)
1190            m_io_channel_ap->OutWrite (result.GetError(only_if_no_immediate), error_size, NO_ASYNC);
1191
1192        // We are done getting and running our command, we can now clear the
1193        // m_waiting_for_command so we can get another one.
1194        m_waiting_for_command = false;
1195
1196        // If our editline input reader is active, it means another input reader
1197        // got pushed onto the input reader and caused us to become deactivated.
1198        // When the input reader above us gets popped, we will get re-activated
1199        // and our prompt will refresh in our callback
1200        if (m_editline_reader.IsActive())
1201        {
1202            ReadyForCommand ();
1203        }
1204    }
1205    else if (event_type & IOChannel::eBroadcastBitUserInterrupt)
1206    {
1207        // This is here to handle control-c interrupts from the user.  It has not yet really been implemented.
1208        // TO BE DONE:  PROPERLY HANDLE CONTROL-C FROM USER
1209        //m_io_channel_ap->CancelInput();
1210        // Anything else?  Send Interrupt to process?
1211    }
1212    else if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
1213             (event_type & IOChannel::eBroadcastBitThreadDidExit))
1214    {
1215        // If the IOChannel thread is trying to go away, then it is definitely
1216        // time to end the debugging session.
1217        quit = true;
1218    }
1219
1220    return quit;
1221}
1222
1223void
1224Driver::MasterThreadBytesReceived (void *baton, const void *src, size_t src_len)
1225{
1226    Driver *driver = (Driver*)baton;
1227    driver->GetFromMaster ((const char *)src, src_len);
1228}
1229
1230void
1231Driver::GetFromMaster (const char *src, size_t src_len)
1232{
1233    // Echo the characters back to the Debugger's stdout, that way if you
1234    // type characters while a command is running, you'll see what you've typed.
1235    FILE *out_fh = m_debugger.GetOutputFileHandle();
1236    if (out_fh)
1237        ::fwrite (src, 1, src_len, out_fh);
1238}
1239
1240size_t
1241Driver::EditLineInputReaderCallback
1242(
1243    void *baton,
1244    SBInputReader *reader,
1245    InputReaderAction notification,
1246    const char *bytes,
1247    size_t bytes_len
1248)
1249{
1250    Driver *driver = (Driver *)baton;
1251
1252    switch (notification)
1253    {
1254    case eInputReaderActivate:
1255        break;
1256
1257    case eInputReaderReactivate:
1258        if (driver->m_executing_user_command == false)
1259            driver->ReadyForCommand();
1260        break;
1261
1262    case eInputReaderDeactivate:
1263        break;
1264
1265    case eInputReaderAsynchronousOutputWritten:
1266        if (driver->m_io_channel_ap.get() != NULL)
1267            driver->m_io_channel_ap->RefreshPrompt();
1268        break;
1269
1270    case eInputReaderInterrupt:
1271        if (driver->m_io_channel_ap.get() != NULL)
1272        {
1273            SBProcess process(driver->GetDebugger().GetSelectedTarget().GetProcess());
1274            if (!driver->m_io_channel_ap->EditLineHasCharacters()
1275                &&  process.IsValid()
1276                && (process.GetState() == lldb::eStateRunning || process.GetState() == lldb::eStateAttaching))
1277            {
1278                process.SendAsyncInterrupt ();
1279            }
1280            else
1281            {
1282                driver->m_io_channel_ap->OutWrite ("^C\n", 3, NO_ASYNC);
1283                // I wish I could erase the entire input line, but there's no public API for that.
1284                driver->m_io_channel_ap->EraseCharsBeforeCursor();
1285                driver->m_io_channel_ap->RefreshPrompt();
1286            }
1287        }
1288        break;
1289
1290    case eInputReaderEndOfFile:
1291        if (driver->m_io_channel_ap.get() != NULL)
1292        {
1293            driver->m_io_channel_ap->OutWrite ("^D\n", 3, NO_ASYNC);
1294            driver->m_io_channel_ap->RefreshPrompt ();
1295        }
1296        write (driver->m_editline_pty.GetMasterFileDescriptor(), "quit\n", 5);
1297        break;
1298
1299    case eInputReaderGotToken:
1300        write (driver->m_editline_pty.GetMasterFileDescriptor(), bytes, bytes_len);
1301        break;
1302
1303    case eInputReaderDone:
1304        break;
1305    }
1306    return bytes_len;
1307}
1308
1309void
1310Driver::MainLoop ()
1311{
1312#if defined(_MSC_VER)
1313    m_editline_slave_fh = stdin;
1314    FILE *editline_output_slave_fh = stdout;
1315    lldb_utility::PseudoTerminal editline_output_pty;
1316#else
1317
1318    char error_str[1024];
1319    if (m_editline_pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, error_str, sizeof(error_str)) == false)
1320    {
1321        ::fprintf (stderr, "error: failed to open driver pseudo terminal : %s", error_str);
1322        exit(1);
1323    }
1324    else
1325    {
1326        const char *driver_slave_name = m_editline_pty.GetSlaveName (error_str, sizeof(error_str));
1327        if (driver_slave_name == NULL)
1328        {
1329            ::fprintf (stderr, "error: failed to get slave name for driver pseudo terminal : %s", error_str);
1330            exit(2);
1331        }
1332        else
1333        {
1334            m_editline_slave_fh = ::fopen (driver_slave_name, "r+");
1335            if (m_editline_slave_fh == NULL)
1336            {
1337                SBError error;
1338                error.SetErrorToErrno();
1339                ::fprintf (stderr, "error: failed to get open slave for driver pseudo terminal : %s",
1340                           error.GetCString());
1341                exit(3);
1342            }
1343
1344            ::setbuf (m_editline_slave_fh, NULL);
1345        }
1346    }
1347
1348    lldb_utility::PseudoTerminal editline_output_pty;
1349    FILE *editline_output_slave_fh = NULL;
1350
1351    if (editline_output_pty.OpenFirstAvailableMaster (O_RDWR|O_NOCTTY, error_str, sizeof (error_str)) == false)
1352    {
1353        ::fprintf (stderr, "error: failed to open output pseudo terminal : %s", error_str);
1354        exit(1);
1355    }
1356    else
1357    {
1358        const char *output_slave_name = editline_output_pty.GetSlaveName (error_str, sizeof(error_str));
1359        if (output_slave_name == NULL)
1360        {
1361            ::fprintf (stderr, "error: failed to get slave name for output pseudo terminal : %s", error_str);
1362            exit(2);
1363        }
1364        else
1365        {
1366            editline_output_slave_fh = ::fopen (output_slave_name, "r+");
1367            if (editline_output_slave_fh == NULL)
1368            {
1369                SBError error;
1370                error.SetErrorToErrno();
1371                ::fprintf (stderr, "error: failed to get open slave for output pseudo terminal : %s",
1372                           error.GetCString());
1373                exit(3);
1374            }
1375            ::setbuf (editline_output_slave_fh, NULL);
1376        }
1377    }
1378#endif
1379
1380   // struct termios stdin_termios;
1381
1382    if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0)
1383    {
1384        g_old_stdin_termios_is_valid = true;
1385        atexit (reset_stdin_termios);
1386    }
1387
1388    ::setbuf (stdin, NULL);
1389    ::setbuf (stdout, NULL);
1390
1391    m_debugger.SetErrorFileHandle (stderr, false);
1392    m_debugger.SetOutputFileHandle (stdout, false);
1393    m_debugger.SetInputFileHandle (stdin, true);
1394
1395    m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor);
1396
1397    // You have to drain anything that comes to the master side of the PTY.  master_out_comm is
1398    // for that purpose.  The reason you need to do this is a curious reason...  editline will echo
1399    // characters to the PTY when it gets characters while el_gets is not running, and then when
1400    // you call el_gets (or el_getc) it will try to reset the terminal back to raw mode which blocks
1401    // if there are unconsumed characters in the out buffer.
1402    // However, you don't need to do anything with the characters, since editline will dump these
1403    // unconsumed characters after printing the prompt again in el_gets.
1404
1405    SBCommunication master_out_comm("driver.editline");
1406    master_out_comm.SetCloseOnEOF (false);
1407    master_out_comm.AdoptFileDesriptor(m_editline_pty.GetMasterFileDescriptor(), false);
1408    master_out_comm.SetReadThreadBytesReceivedCallback(Driver::MasterThreadBytesReceived, this);
1409
1410    if (master_out_comm.ReadThreadStart () == false)
1411    {
1412        ::fprintf (stderr, "error: failed to start master out read thread");
1413        exit(5);
1414    }
1415
1416    SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter();
1417
1418    m_io_channel_ap.reset (new IOChannel(m_editline_slave_fh, editline_output_slave_fh, stdout, stderr, this));
1419
1420#if !defined (_MSC_VER)
1421    SBCommunication out_comm_2("driver.editline_output");
1422    out_comm_2.SetCloseOnEOF (false);
1423    out_comm_2.AdoptFileDesriptor (editline_output_pty.GetMasterFileDescriptor(), false);
1424    out_comm_2.SetReadThreadBytesReceivedCallback (IOChannel::LibeditOutputBytesReceived, m_io_channel_ap.get());
1425
1426    if (out_comm_2.ReadThreadStart () == false)
1427    {
1428        ::fprintf (stderr, "error: failed to start libedit output read thread");
1429        exit (5);
1430    }
1431#endif
1432
1433
1434    struct winsize window_size;
1435    if (isatty (STDIN_FILENO)
1436        && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
1437    {
1438        if (window_size.ws_col > 0)
1439            m_debugger.SetTerminalWidth (window_size.ws_col);
1440    }
1441
1442    // Since input can be redirected by the debugger, we must insert our editline
1443    // input reader in the queue so we know when our reader should be active
1444    // and so we can receive bytes only when we are supposed to.
1445    SBError err (m_editline_reader.Initialize (m_debugger,
1446                                               Driver::EditLineInputReaderCallback, // callback
1447                                               this,                              // baton
1448                                               eInputReaderGranularityByte,       // token_size
1449                                               NULL,                              // end token - NULL means never done
1450                                               NULL,                              // prompt - taken care of elsewhere
1451                                               false));                           // echo input - don't need Debugger
1452                                                                                  // to do this, we handle it elsewhere
1453
1454    if (err.Fail())
1455    {
1456        ::fprintf (stderr, "error: %s", err.GetCString());
1457        exit (6);
1458    }
1459
1460    m_debugger.PushInputReader (m_editline_reader);
1461
1462    SBListener listener(m_debugger.GetListener());
1463    if (listener.IsValid())
1464    {
1465
1466        listener.StartListeningForEventClass(m_debugger,
1467                                         SBTarget::GetBroadcasterClassName(),
1468                                         SBTarget::eBroadcastBitBreakpointChanged);
1469        listener.StartListeningForEventClass(m_debugger,
1470                                         SBThread::GetBroadcasterClassName(),
1471                                         SBThread::eBroadcastBitStackChanged |
1472                                         SBThread::eBroadcastBitThreadSelected);
1473        listener.StartListeningForEvents (*m_io_channel_ap,
1474                                          IOChannel::eBroadcastBitHasUserInput |
1475                                          IOChannel::eBroadcastBitUserInterrupt |
1476                                          IOChannel::eBroadcastBitThreadShouldExit |
1477                                          IOChannel::eBroadcastBitThreadDidStart |
1478                                          IOChannel::eBroadcastBitThreadDidExit);
1479
1480        if (m_io_channel_ap->Start ())
1481        {
1482            bool iochannel_thread_exited = false;
1483
1484            listener.StartListeningForEvents (sb_interpreter.GetBroadcaster(),
1485                                              SBCommandInterpreter::eBroadcastBitQuitCommandReceived |
1486                                              SBCommandInterpreter::eBroadcastBitAsynchronousOutputData |
1487                                              SBCommandInterpreter::eBroadcastBitAsynchronousErrorData);
1488
1489            // Before we handle any options from the command line, we parse the
1490            // .lldbinit file in the user's home directory.
1491            SBCommandReturnObject result;
1492            sb_interpreter.SourceInitFileInHomeDirectory(result);
1493            if (GetDebugMode())
1494            {
1495                result.PutError (m_debugger.GetErrorFileHandle());
1496                result.PutOutput (m_debugger.GetOutputFileHandle());
1497            }
1498
1499            // Now we handle options we got from the command line
1500            // First source in the commands specified to be run before the file arguments are processed.
1501            ExecuteInitialCommands(true);
1502
1503            // Was there a core file specified?
1504            std::string core_file_spec("");
1505            if (!m_option_data.m_core_file.empty())
1506                core_file_spec.append("--core ").append(m_option_data.m_core_file);
1507
1508            char command_string[PATH_MAX * 2];
1509            const size_t num_args = m_option_data.m_args.size();
1510            if (num_args > 0)
1511            {
1512                char arch_name[64];
1513                if (m_debugger.GetDefaultArchitecture (arch_name, sizeof (arch_name)))
1514                    ::snprintf (command_string,
1515                                sizeof (command_string),
1516                                "target create --arch=%s %s \"%s\"",
1517                                arch_name,
1518                                core_file_spec.c_str(),
1519                                m_option_data.m_args[0].c_str());
1520                else
1521                    ::snprintf (command_string,
1522                                sizeof(command_string),
1523                                "target create %s \"%s\"",
1524                                core_file_spec.c_str(),
1525                                m_option_data.m_args[0].c_str());
1526
1527                m_debugger.HandleCommand (command_string);
1528
1529                if (num_args > 1)
1530                {
1531                    m_debugger.HandleCommand ("settings clear target.run-args");
1532                    char arg_cstr[1024];
1533                    for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx)
1534                    {
1535                        ::snprintf (arg_cstr,
1536                                    sizeof(arg_cstr),
1537                                    "settings append target.run-args \"%s\"",
1538                                    m_option_data.m_args[arg_idx].c_str());
1539                        m_debugger.HandleCommand (arg_cstr);
1540                    }
1541                }
1542            }
1543            else if (!core_file_spec.empty())
1544            {
1545                ::snprintf (command_string,
1546                            sizeof(command_string),
1547                            "target create %s",
1548                            core_file_spec.c_str());
1549                m_debugger.HandleCommand (command_string);;
1550            }
1551
1552            // Now that all option parsing is done, we try and parse the .lldbinit
1553            // file in the current working directory
1554            sb_interpreter.SourceInitFileInCurrentWorkingDirectory (result);
1555            if (GetDebugMode())
1556            {
1557                result.PutError(m_debugger.GetErrorFileHandle());
1558                result.PutOutput(m_debugger.GetOutputFileHandle());
1559            }
1560
1561            // Now execute the commands specified for after the file arguments are processed.
1562            ExecuteInitialCommands(false);
1563
1564            SBEvent event;
1565
1566            // Make sure the IO channel is started up before we try to tell it we
1567            // are ready for input
1568            listener.WaitForEventForBroadcasterWithType (UINT32_MAX,
1569                                                         *m_io_channel_ap,
1570                                                         IOChannel::eBroadcastBitThreadDidStart,
1571                                                         event);
1572            // If we were asked to attach, then do that here:
1573            // I'm going to use the command string rather than directly
1574            // calling the API's because then I don't have to recode the
1575            // event handling here.
1576            if (!m_option_data.m_process_name.empty()
1577                || m_option_data.m_process_pid != LLDB_INVALID_PROCESS_ID)
1578            {
1579                std::string command_str("process attach ");
1580                if (m_option_data.m_process_pid != LLDB_INVALID_PROCESS_ID)
1581                {
1582                    command_str.append("-p ");
1583                    char pid_buffer[32];
1584                    ::snprintf (pid_buffer, sizeof(pid_buffer), "%" PRIu64, m_option_data.m_process_pid);
1585                    command_str.append(pid_buffer);
1586                }
1587                else
1588                {
1589                    command_str.append("-n \"");
1590                    command_str.append(m_option_data.m_process_name);
1591                    command_str.push_back('\"');
1592                    if (m_option_data.m_wait_for)
1593                        command_str.append(" -w");
1594                }
1595
1596                if (m_debugger.GetOutputFileHandle())
1597                    ::fprintf (m_debugger.GetOutputFileHandle(),
1598                               "Attaching to process with:\n    %s\n",
1599                               command_str.c_str());
1600
1601                // Force the attach to be synchronous:
1602                bool orig_async = m_debugger.GetAsync();
1603                m_debugger.SetAsync(true);
1604                m_debugger.HandleCommand(command_str.c_str());
1605                m_debugger.SetAsync(orig_async);
1606            }
1607
1608            ReadyForCommand ();
1609
1610            while (!GetIsDone())
1611            {
1612                listener.WaitForEvent (UINT32_MAX, event);
1613                if (event.IsValid())
1614                {
1615                    if (event.GetBroadcaster().IsValid())
1616                    {
1617                        uint32_t event_type = event.GetType();
1618                        if (event.BroadcasterMatchesRef (*m_io_channel_ap))
1619                        {
1620                            if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
1621                                (event_type & IOChannel::eBroadcastBitThreadDidExit))
1622                            {
1623                                SetIsDone();
1624                                if (event_type & IOChannel::eBroadcastBitThreadDidExit)
1625                                    iochannel_thread_exited = true;
1626                            }
1627                            else
1628                            {
1629                                if (HandleIOEvent (event))
1630                                    SetIsDone();
1631                            }
1632                        }
1633                        else if (SBProcess::EventIsProcessEvent (event))
1634                        {
1635                            HandleProcessEvent (event);
1636                        }
1637                        else if (SBBreakpoint::EventIsBreakpointEvent (event))
1638                        {
1639                            HandleBreakpointEvent (event);
1640                        }
1641                        else if (SBThread::EventIsThreadEvent (event))
1642                        {
1643                            HandleThreadEvent (event);
1644                        }
1645                        else if (event.BroadcasterMatchesRef (sb_interpreter.GetBroadcaster()))
1646                        {
1647                            // TODO: deprecate the eBroadcastBitQuitCommandReceived event
1648                            // now that we have SBCommandInterpreter::SetCommandOverrideCallback()
1649                            // that can take over a command
1650                            if (event_type & SBCommandInterpreter::eBroadcastBitQuitCommandReceived)
1651                            {
1652                                SetIsDone();
1653                            }
1654                            else if (event_type & SBCommandInterpreter::eBroadcastBitAsynchronousErrorData)
1655                            {
1656                                const char *data = SBEvent::GetCStringFromEvent (event);
1657                                m_io_channel_ap->ErrWrite (data, strlen(data), ASYNC);
1658                            }
1659                            else if (event_type & SBCommandInterpreter::eBroadcastBitAsynchronousOutputData)
1660                            {
1661                                const char *data = SBEvent::GetCStringFromEvent (event);
1662                                m_io_channel_ap->OutWrite (data, strlen(data), ASYNC);
1663                            }
1664                        }
1665                    }
1666                }
1667            }
1668
1669            master_out_comm.SetReadThreadBytesReceivedCallback(NULL, NULL);
1670            master_out_comm.Disconnect();
1671            master_out_comm.ReadThreadStop();
1672
1673#if !defined(_MSC_VER)
1674            out_comm_2.SetReadThreadBytesReceivedCallback(NULL, NULL);
1675            out_comm_2.Disconnect();
1676            out_comm_2.ReadThreadStop();
1677#endif
1678
1679            editline_output_pty.CloseMasterFileDescriptor();
1680            reset_stdin_termios();
1681            fclose (stdin);
1682
1683            CloseIOChannelFile ();
1684
1685            if (!iochannel_thread_exited)
1686            {
1687                event.Clear();
1688                listener.GetNextEventForBroadcasterWithType (*m_io_channel_ap,
1689                                                             IOChannel::eBroadcastBitThreadDidExit,
1690                                                             event);
1691                if (!event.IsValid())
1692                {
1693                    // Send end EOF to the driver file descriptor
1694                    m_io_channel_ap->Stop();
1695                }
1696            }
1697
1698            SBDebugger::Destroy (m_debugger);
1699        }
1700    }
1701}
1702
1703
1704void
1705Driver::ReadyForCommand ()
1706{
1707    if (m_waiting_for_command == false)
1708    {
1709        m_waiting_for_command = true;
1710        BroadcastEventByType (Driver::eBroadcastBitReadyForInput, true);
1711    }
1712}
1713
1714void
1715Driver::ResizeWindow (unsigned short col)
1716{
1717    GetDebugger().SetTerminalWidth (col);
1718    if (m_io_channel_ap.get() != NULL)
1719    {
1720        m_io_channel_ap->ElResize();
1721    }
1722}
1723
1724void
1725sigwinch_handler (int signo)
1726{
1727    struct winsize window_size;
1728    if (isatty (STDIN_FILENO)
1729        && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
1730    {
1731        if ((window_size.ws_col > 0) && g_driver != NULL)
1732        {
1733            g_driver->ResizeWindow (window_size.ws_col);
1734        }
1735    }
1736}
1737
1738void
1739sigint_handler (int signo)
1740{
1741	static bool g_interrupt_sent = false;
1742    if (g_driver)
1743	{
1744		if (!g_interrupt_sent)
1745		{
1746			g_interrupt_sent = true;
1747        	g_driver->GetDebugger().DispatchInputInterrupt();
1748			g_interrupt_sent = false;
1749			return;
1750		}
1751	}
1752
1753	exit (signo);
1754}
1755
1756void
1757sigtstp_handler (int signo)
1758{
1759    g_driver->GetDebugger().SaveInputTerminalState();
1760    signal (signo, SIG_DFL);
1761    kill (getpid(), signo);
1762    signal (signo, sigtstp_handler);
1763}
1764
1765void
1766sigcont_handler (int signo)
1767{
1768    g_driver->GetDebugger().RestoreInputTerminalState();
1769    signal (signo, SIG_DFL);
1770    kill (getpid(), signo);
1771    signal (signo, sigcont_handler);
1772}
1773
1774int
1775main (int argc, char const *argv[], const char *envp[])
1776{
1777    SBDebugger::Initialize();
1778
1779    SBHostOS::ThreadCreated ("<lldb.driver.main-thread>");
1780
1781    signal (SIGPIPE, SIG_IGN);
1782    signal (SIGWINCH, sigwinch_handler);
1783    signal (SIGINT, sigint_handler);
1784    signal (SIGTSTP, sigtstp_handler);
1785    signal (SIGCONT, sigcont_handler);
1786
1787    // Create a scope for driver so that the driver object will destroy itself
1788    // before SBDebugger::Terminate() is called.
1789    {
1790        Driver driver;
1791
1792        bool exiting = false;
1793        SBError error (driver.ParseArgs (argc, argv, stdout, exiting));
1794        if (error.Fail())
1795        {
1796            const char *error_cstr = error.GetCString ();
1797            if (error_cstr)
1798                ::fprintf (stderr, "error: %s\n", error_cstr);
1799        }
1800        else if (!exiting)
1801        {
1802            driver.MainLoop ();
1803        }
1804    }
1805
1806    SBDebugger::Terminate();
1807    return 0;
1808}
1809