blob: 77c6fc2955c9365540d1d424ec94dc23053c7a7a [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- Driver.cpp ----------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "Driver.h"
11
12#include <getopt.h>
13#include <libgen.h>
14#include <sys/ioctl.h>
15#include <termios.h>
16#include <unistd.h>
Eli Friedmanf2f321d2010-06-09 09:50:17 +000017#include <string.h>
18#include <stdlib.h>
19#include <limits.h>
Eli Friedmand6e167d2010-06-09 19:11:30 +000020#include <fcntl.h>
Chris Lattner24943d22010-06-08 16:52:24 +000021
22#include <string>
23
24#include "IOChannel.h"
Eli Friedmanf2f321d2010-06-09 09:50:17 +000025#include "lldb/API/SBCommandInterpreter.h"
26#include "lldb/API/SBCommandReturnObject.h"
27#include "lldb/API/SBCommunication.h"
28#include "lldb/API/SBDebugger.h"
29#include "lldb/API/SBEvent.h"
30#include "lldb/API/SBHostOS.h"
31#include "lldb/API/SBListener.h"
32#include "lldb/API/SBSourceManager.h"
Jim Ingham2e8cb8a2011-02-19 02:53:09 +000033#include "lldb/API/SBStream.h"
Eli Friedmanf2f321d2010-06-09 09:50:17 +000034#include "lldb/API/SBTarget.h"
35#include "lldb/API/SBThread.h"
36#include "lldb/API/SBProcess.h"
Chris Lattner24943d22010-06-08 16:52:24 +000037
38using namespace lldb;
39
40static void reset_stdin_termios ();
41static struct termios g_old_stdin_termios;
42
Caroline Ticeb8314fe2010-09-09 17:45:09 +000043static char *g_debugger_name = (char *) "";
Caroline Ticec4f55fe2010-11-19 20:47:54 +000044static Driver *g_driver = NULL;
Caroline Ticeb8314fe2010-09-09 17:45:09 +000045
Chris Lattner24943d22010-06-08 16:52:24 +000046// In the Driver::MainLoop, we change the terminal settings. This function is
47// added as an atexit handler to make sure we clean them up.
48static void
49reset_stdin_termios ()
50{
51 ::tcsetattr (STDIN_FILENO, TCSANOW, &g_old_stdin_termios);
52}
53
Greg Claytonb3448432011-03-24 21:19:54 +000054typedef struct
Chris Lattner24943d22010-06-08 16:52:24 +000055{
Greg Claytonb3448432011-03-24 21:19:54 +000056 uint32_t usage_mask; // Used to mark options that can be used together. If (1 << n & usage_mask) != 0
57 // then this option belongs to option set n.
58 bool required; // This option is required (in the current usage level)
59 const char * long_option; // Full name for this option.
60 char short_option; // Single character for this option.
61 int option_has_arg; // no_argument, required_argument or optional_argument
62 uint32_t completionType; // Cookie the option class can use to do define the argument completion.
63 lldb::CommandArgumentType argument_type; // Type of argument this option takes
64 const char * usage_text; // Full text explaining what this options does and what (if any) argument to
65 // pass it.
66} OptionDefinition;
Chris Lattner24943d22010-06-08 16:52:24 +000067
Chris Lattner24943d22010-06-08 16:52:24 +000068
Greg Claytonb3448432011-03-24 21:19:54 +000069static OptionDefinition g_options[] =
70{
71 { LLDB_OPT_SET_1, true , "help" , 'h', no_argument , NULL, eArgTypeNone, "Prints out the usage information for the LLDB debugger." },
72 { LLDB_OPT_SET_2, true , "version" , 'v', no_argument , NULL, eArgTypeNone, "Prints out the current version number of the LLDB debugger." },
73 { LLDB_OPT_SET_3, true , "arch" , 'a', required_argument, NULL, eArgTypeArchitecture,"Tells the debugger to use the specified architecture when starting and running the program. <architecture> must be one of the architectures for which the program was compiled." },
74 { LLDB_OPT_SET_3 | LLDB_OPT_SET_4, false, "script-language", 'l', required_argument, NULL, eArgTypeScriptLang,"Tells the debugger to use the specified scripting language for user-defined scripts, rather than the default. Valid scripting languages that can be specified include Python, Perl, Ruby and Tcl. Currently only the Python extensions have been implemented." },
75 { LLDB_OPT_SET_3 | LLDB_OPT_SET_4, false, "debug" , 'd', no_argument , NULL, eArgTypeNone,"Tells the debugger to print out extra information for debugging itself." },
76 { LLDB_OPT_SET_3 | LLDB_OPT_SET_4, false, "source" , 's', required_argument, NULL, eArgTypeFilename, "Tells the debugger to read in and execute the file <file>, which should contain lldb commands." },
77 { LLDB_OPT_SET_3, true , "file" , 'f', required_argument, NULL, eArgTypeFilename, "Tells the debugger to use the file <filename> as the program to be debugged." },
78 { LLDB_OPT_SET_ALL, false, "editor" , 'e', no_argument , NULL, eArgTypeNone, "Tells the debugger to open source files using the host's \"external editor\" mechanism." },
79 { LLDB_OPT_SET_ALL, false, "no-lldbinit" , 'n', no_argument , NULL, eArgTypeNone, "Do not automatically parse any '.lldbinit' files." },
80 { 0, false, NULL , 0 , 0 , NULL, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +000081};
82
83
84Driver::Driver () :
85 SBBroadcaster ("Driver"),
Greg Clayton63094e02010-06-23 01:19:29 +000086 m_debugger (SBDebugger::Create()),
Chris Lattner24943d22010-06-08 16:52:24 +000087 m_editline_pty (),
88 m_editline_slave_fh (NULL),
89 m_editline_reader (),
90 m_io_channel_ap (),
91 m_option_data (),
92 m_waiting_for_command (false)
93{
Caroline Ticeb8314fe2010-09-09 17:45:09 +000094 g_debugger_name = (char *) m_debugger.GetInstanceName();
95 if (g_debugger_name == NULL)
96 g_debugger_name = (char *) "";
Caroline Ticec4f55fe2010-11-19 20:47:54 +000097 g_driver = this;
Chris Lattner24943d22010-06-08 16:52:24 +000098}
99
100Driver::~Driver ()
101{
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000102 g_driver = NULL;
103 g_debugger_name = NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000104}
105
106void
107Driver::CloseIOChannelFile ()
108{
109 // Write and End of File sequence to the file descriptor to ensure any
110 // read functions can exit.
111 char eof_str[] = "\x04";
112 ::write (m_editline_pty.GetMasterFileDescriptor(), eof_str, strlen(eof_str));
113
114 m_editline_pty.CloseMasterFileDescriptor();
115
116 if (m_editline_slave_fh)
117 {
118 ::fclose (m_editline_slave_fh);
119 m_editline_slave_fh = NULL;
120 }
121}
122
Greg Clayton54e7afa2010-07-09 20:39:50 +0000123// This function takes INDENT, which tells how many spaces to output at the front
124// of each line; TEXT, which is the text that is to be output. It outputs the
125// text, on multiple lines if necessary, to RESULT, with INDENT spaces at the
126// front of each line. It breaks lines on spaces, tabs or newlines, shortening
127// the line if necessary to not break in the middle of a word. It assumes that
128// each output line should contain a maximum of OUTPUT_MAX_COLUMNS characters.
Chris Lattner24943d22010-06-08 16:52:24 +0000129
130void
Greg Clayton54e7afa2010-07-09 20:39:50 +0000131OutputFormattedUsageText (FILE *out, int indent, const char *text, int output_max_columns)
Chris Lattner24943d22010-06-08 16:52:24 +0000132{
133 int len = strlen (text);
134 std::string text_string (text);
Chris Lattner24943d22010-06-08 16:52:24 +0000135
136 // Force indentation to be reasonable.
137 if (indent >= output_max_columns)
138 indent = 0;
139
140 // Will it all fit on one line?
141
142 if (len + indent < output_max_columns)
143 // Output as a single line
Greg Clayton54e7afa2010-07-09 20:39:50 +0000144 fprintf (out, "%*s%s\n", indent, "", text);
Chris Lattner24943d22010-06-08 16:52:24 +0000145 else
146 {
147 // We need to break it up into multiple lines.
148 int text_width = output_max_columns - indent - 1;
149 int start = 0;
150 int end = start;
151 int final_end = len;
152 int sub_len;
153
154 while (end < final_end)
155 {
156 // Dont start the 'text' on a space, since we're already outputting the indentation.
157 while ((start < final_end) && (text[start] == ' '))
158 start++;
159
160 end = start + text_width;
161 if (end > final_end)
162 end = final_end;
163 else
164 {
165 // If we're not at the end of the text, make sure we break the line on white space.
166 while (end > start
167 && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
168 end--;
169 }
170 sub_len = end - start;
171 std::string substring = text_string.substr (start, sub_len);
Greg Clayton54e7afa2010-07-09 20:39:50 +0000172 fprintf (out, "%*s%s\n", indent, "", substring.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000173 start = end + 1;
174 }
175 }
176}
177
178void
Greg Claytonb3448432011-03-24 21:19:54 +0000179ShowUsage (FILE *out, OptionDefinition *option_table, Driver::OptionData data)
Chris Lattner24943d22010-06-08 16:52:24 +0000180{
181 uint32_t screen_width = 80;
182 uint32_t indent_level = 0;
183 const char *name = "lldb";
Jim Ingham34e9a982010-06-15 18:47:14 +0000184
Chris Lattner24943d22010-06-08 16:52:24 +0000185 fprintf (out, "\nUsage:\n\n");
186
187 indent_level += 2;
188
189
190 // First, show each usage level set of options, e.g. <cmd> [options-for-level-0]
191 // <cmd> [options-for-level-1]
192 // etc.
193
Chris Lattner24943d22010-06-08 16:52:24 +0000194 uint32_t num_options;
Jim Ingham34e9a982010-06-15 18:47:14 +0000195 uint32_t num_option_sets = 0;
196
197 for (num_options = 0; option_table[num_options].long_option != NULL; ++num_options)
Chris Lattner24943d22010-06-08 16:52:24 +0000198 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000199 uint32_t this_usage_mask = option_table[num_options].usage_mask;
200 if (this_usage_mask == LLDB_OPT_SET_ALL)
Chris Lattner24943d22010-06-08 16:52:24 +0000201 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000202 if (num_option_sets == 0)
203 num_option_sets = 1;
Chris Lattner24943d22010-06-08 16:52:24 +0000204 }
205 else
206 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000207 for (uint32_t j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++)
Jim Ingham34e9a982010-06-15 18:47:14 +0000208 {
209 if (this_usage_mask & 1 << j)
210 {
211 if (num_option_sets <= j)
212 num_option_sets = j + 1;
213 }
214 }
215 }
216 }
217
218 for (uint32_t opt_set = 0; opt_set < num_option_sets; opt_set++)
219 {
220 uint32_t opt_set_mask;
221
222 opt_set_mask = 1 << opt_set;
223
224 if (opt_set > 0)
225 fprintf (out, "\n");
Greg Clayton54e7afa2010-07-09 20:39:50 +0000226 fprintf (out, "%*s%s", indent_level, "", name);
Jim Ingham34e9a982010-06-15 18:47:14 +0000227
228 for (uint32_t i = 0; i < num_options; ++i)
229 {
230 if (option_table[i].usage_mask & opt_set_mask)
231 {
Caroline Tice4d6675c2010-10-01 19:59:14 +0000232 CommandArgumentType arg_type = option_table[i].argument_type;
Greg Claytonaa378b12011-02-20 02:15:07 +0000233 const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type);
Jim Ingham34e9a982010-06-15 18:47:14 +0000234 if (option_table[i].required)
235 {
236 if (option_table[i].option_has_arg == required_argument)
Greg Claytonaa378b12011-02-20 02:15:07 +0000237 fprintf (out, " -%c <%s>", option_table[i].short_option, arg_name);
Jim Ingham34e9a982010-06-15 18:47:14 +0000238 else if (option_table[i].option_has_arg == optional_argument)
Greg Claytonaa378b12011-02-20 02:15:07 +0000239 fprintf (out, " -%c [<%s>]", option_table[i].short_option, arg_name);
Jim Ingham34e9a982010-06-15 18:47:14 +0000240 else
241 fprintf (out, " -%c", option_table[i].short_option);
242 }
243 else
244 {
245 if (option_table[i].option_has_arg == required_argument)
Greg Claytonaa378b12011-02-20 02:15:07 +0000246 fprintf (out, " [-%c <%s>]", option_table[i].short_option, arg_name);
Jim Ingham34e9a982010-06-15 18:47:14 +0000247 else if (option_table[i].option_has_arg == optional_argument)
Greg Claytonaa378b12011-02-20 02:15:07 +0000248 fprintf (out, " [-%c [<%s>]]", option_table[i].short_option, arg_name);
Jim Ingham34e9a982010-06-15 18:47:14 +0000249 else
250 fprintf (out, " [-%c]", option_table[i].short_option);
251 }
252 }
Chris Lattner24943d22010-06-08 16:52:24 +0000253 }
254 }
255
256 fprintf (out, "\n\n");
257
258 // Now print out all the detailed information about the various options: long form, short form and help text:
259 // -- long_name <argument>
260 // - short <argument>
261 // help text
262
263 // This variable is used to keep track of which options' info we've printed out, because some options can be in
264 // more than one usage level, but we only want to print the long form of its information once.
265
266 Driver::OptionData::OptionSet options_seen;
267 Driver::OptionData::OptionSet::iterator pos;
268
269 indent_level += 5;
270
Jim Ingham34e9a982010-06-15 18:47:14 +0000271 for (uint32_t i = 0; i < num_options; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000272 {
273 // Only print this option if we haven't already seen it.
274 pos = options_seen.find (option_table[i].short_option);
275 if (pos == options_seen.end())
276 {
Caroline Tice4d6675c2010-10-01 19:59:14 +0000277 CommandArgumentType arg_type = option_table[i].argument_type;
Greg Claytonaa378b12011-02-20 02:15:07 +0000278 const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type);
Caroline Tice4d6675c2010-10-01 19:59:14 +0000279
Chris Lattner24943d22010-06-08 16:52:24 +0000280 options_seen.insert (option_table[i].short_option);
Greg Clayton54e7afa2010-07-09 20:39:50 +0000281 fprintf (out, "%*s-%c ", indent_level, "", option_table[i].short_option);
Caroline Tice4d6675c2010-10-01 19:59:14 +0000282 if (arg_type != eArgTypeNone)
Greg Claytonaa378b12011-02-20 02:15:07 +0000283 fprintf (out, "<%s>", arg_name);
Chris Lattner24943d22010-06-08 16:52:24 +0000284 fprintf (out, "\n");
Greg Clayton54e7afa2010-07-09 20:39:50 +0000285 fprintf (out, "%*s--%s ", indent_level, "", option_table[i].long_option);
Caroline Tice4d6675c2010-10-01 19:59:14 +0000286 if (arg_type != eArgTypeNone)
Greg Claytonaa378b12011-02-20 02:15:07 +0000287 fprintf (out, "<%s>", arg_name);
Chris Lattner24943d22010-06-08 16:52:24 +0000288 fprintf (out, "\n");
289 indent_level += 5;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000290 OutputFormattedUsageText (out, indent_level, option_table[i].usage_text, screen_width);
Chris Lattner24943d22010-06-08 16:52:24 +0000291 indent_level -= 5;
292 fprintf (out, "\n");
293 }
294 }
295
296 indent_level -= 5;
297
Greg Clayton54e7afa2010-07-09 20:39:50 +0000298 fprintf (out, "\n%*s('%s <filename>' also works, to specify the file to be debugged.)\n\n",
299 indent_level, "", name);
Chris Lattner24943d22010-06-08 16:52:24 +0000300}
301
302void
Greg Claytonb3448432011-03-24 21:19:54 +0000303BuildGetOptTable (OptionDefinition *expanded_option_table, std::vector<struct option> &getopt_table,
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000304 uint32_t num_options)
Chris Lattner24943d22010-06-08 16:52:24 +0000305{
306 if (num_options == 0)
307 return;
308
309 uint32_t i;
310 uint32_t j;
311 std::bitset<256> option_seen;
312
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000313 getopt_table.resize (num_options + 1);
314
Chris Lattner24943d22010-06-08 16:52:24 +0000315 for (i = 0, j = 0; i < num_options; ++i)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000316 {
Chris Lattner24943d22010-06-08 16:52:24 +0000317 char short_opt = expanded_option_table[i].short_option;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000318
Chris Lattner24943d22010-06-08 16:52:24 +0000319 if (option_seen.test(short_opt) == false)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000320 {
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000321 getopt_table[j].name = expanded_option_table[i].long_option;
322 getopt_table[j].has_arg = expanded_option_table[i].option_has_arg;
323 getopt_table[j].flag = NULL;
324 getopt_table[j].val = expanded_option_table[i].short_option;
Chris Lattner24943d22010-06-08 16:52:24 +0000325 option_seen.set(short_opt);
326 ++j;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000327 }
328 }
Chris Lattner24943d22010-06-08 16:52:24 +0000329
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000330 getopt_table[j].name = NULL;
331 getopt_table[j].has_arg = 0;
332 getopt_table[j].flag = NULL;
333 getopt_table[j].val = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000334
335}
336
Greg Clayton63094e02010-06-23 01:19:29 +0000337Driver::OptionData::OptionData () :
Greg Clayton4dc18922010-12-08 22:23:24 +0000338 m_args(),
Greg Clayton63094e02010-06-23 01:19:29 +0000339 m_script_lang (lldb::eScriptLanguageDefault),
Greg Clayton54e7afa2010-07-09 20:39:50 +0000340 m_crash_log (),
Greg Clayton63094e02010-06-23 01:19:29 +0000341 m_source_command_files (),
342 m_debug_mode (false),
Greg Clayton54e7afa2010-07-09 20:39:50 +0000343 m_print_version (false),
Greg Clayton63094e02010-06-23 01:19:29 +0000344 m_print_help (false),
Jim Ingham74989e82010-08-30 19:44:40 +0000345 m_seen_options(),
346 m_use_external_editor(false)
Chris Lattner24943d22010-06-08 16:52:24 +0000347{
Greg Clayton63094e02010-06-23 01:19:29 +0000348}
349
350Driver::OptionData::~OptionData ()
351{
352}
353
354void
355Driver::OptionData::Clear ()
356{
Greg Clayton4dc18922010-12-08 22:23:24 +0000357 m_args.clear ();
Greg Clayton63094e02010-06-23 01:19:29 +0000358 m_script_lang = lldb::eScriptLanguageDefault;
359 m_source_command_files.clear ();
360 m_debug_mode = false;
361 m_print_help = false;
362 m_print_version = false;
Jim Ingham74989e82010-08-30 19:44:40 +0000363 m_use_external_editor = false;
Greg Clayton63094e02010-06-23 01:19:29 +0000364}
365
366void
367Driver::ResetOptionValues ()
368{
369 m_option_data.Clear ();
370}
371
372const char *
373Driver::GetFilename() const
374{
Greg Clayton4dc18922010-12-08 22:23:24 +0000375 if (m_option_data.m_args.empty())
Greg Clayton63094e02010-06-23 01:19:29 +0000376 return NULL;
Greg Clayton4dc18922010-12-08 22:23:24 +0000377 return m_option_data.m_args.front().c_str();
Greg Clayton63094e02010-06-23 01:19:29 +0000378}
379
380const char *
381Driver::GetCrashLogFilename() const
382{
383 if (m_option_data.m_crash_log.empty())
384 return NULL;
385 return m_option_data.m_crash_log.c_str();
386}
387
388lldb::ScriptLanguage
389Driver::GetScriptLanguage() const
390{
391 return m_option_data.m_script_lang;
392}
393
394size_t
395Driver::GetNumSourceCommandFiles () const
396{
397 return m_option_data.m_source_command_files.size();
398}
399
400const char *
401Driver::GetSourceCommandFileAtIndex (uint32_t idx) const
402{
403 if (idx < m_option_data.m_source_command_files.size())
404 return m_option_data.m_source_command_files[idx].c_str();
405 return NULL;
406}
407
408bool
409Driver::GetDebugMode() const
410{
411 return m_option_data.m_debug_mode;
412}
413
414
415// Check the arguments that were passed to this program to make sure they are valid and to get their
416// argument values (if any). Return a boolean value indicating whether or not to start up the full
417// debugger (i.e. the Command Interpreter) or not. Return FALSE if the arguments were invalid OR
418// if the user only wanted help or version information.
419
420SBError
421Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exit)
422{
423 ResetOptionValues ();
424
425 SBCommandReturnObject result;
426
Chris Lattner24943d22010-06-08 16:52:24 +0000427 SBError error;
428 std::string option_string;
429 struct option *long_options = NULL;
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000430 std::vector<struct option> long_options_vector;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000431 uint32_t num_options;
Chris Lattner24943d22010-06-08 16:52:24 +0000432
Greg Clayton54e7afa2010-07-09 20:39:50 +0000433 for (num_options = 0; g_options[num_options].long_option != NULL; ++num_options)
434 /* Do Nothing. */;
Chris Lattner24943d22010-06-08 16:52:24 +0000435
436 if (num_options == 0)
437 {
438 if (argc > 1)
439 error.SetErrorStringWithFormat ("invalid number of options");
440 return error;
441 }
442
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000443 BuildGetOptTable (g_options, long_options_vector, num_options);
Chris Lattner24943d22010-06-08 16:52:24 +0000444
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000445 if (long_options_vector.empty())
446 long_options = NULL;
447 else
448 long_options = &long_options_vector.front();
Chris Lattner24943d22010-06-08 16:52:24 +0000449
450 if (long_options == NULL)
451 {
452 error.SetErrorStringWithFormat ("invalid long options");
453 return error;
454 }
455
456 // Build the option_string argument for call to getopt_long.
457
458 for (int i = 0; long_options[i].name != NULL; ++i)
459 {
460 if (long_options[i].flag == NULL)
461 {
462 option_string.push_back ((char) long_options[i].val);
463 switch (long_options[i].has_arg)
464 {
465 default:
466 case no_argument:
467 break;
468 case required_argument:
469 option_string.push_back (':');
470 break;
471 case optional_argument:
472 option_string.append ("::");
473 break;
474 }
475 }
476 }
477
478 // Prepare for & make calls to getopt_long.
Eli Friedmanef2bc872010-06-13 19:18:49 +0000479#if __GLIBC__
480 optind = 0;
481#else
Chris Lattner24943d22010-06-08 16:52:24 +0000482 optreset = 1;
483 optind = 1;
Eli Friedmanef2bc872010-06-13 19:18:49 +0000484#endif
Chris Lattner24943d22010-06-08 16:52:24 +0000485 int val;
486 while (1)
487 {
488 int long_options_index = -1;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000489 val = ::getopt_long (argc, const_cast<char **>(argv), option_string.c_str(), long_options, &long_options_index);
Chris Lattner24943d22010-06-08 16:52:24 +0000490
491 if (val == -1)
492 break;
493 else if (val == '?')
494 {
Greg Clayton63094e02010-06-23 01:19:29 +0000495 m_option_data.m_print_help = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000496 error.SetErrorStringWithFormat ("unknown or ambiguous option");
497 break;
498 }
499 else if (val == 0)
500 continue;
501 else
502 {
Greg Clayton63094e02010-06-23 01:19:29 +0000503 m_option_data.m_seen_options.insert ((char) val);
Chris Lattner24943d22010-06-08 16:52:24 +0000504 if (long_options_index == -1)
505 {
506 for (int i = 0;
507 long_options[i].name || long_options[i].has_arg || long_options[i].flag || long_options[i].val;
508 ++i)
509 {
510 if (long_options[i].val == val)
511 {
512 long_options_index = i;
513 break;
514 }
515 }
516 }
517
518 if (long_options_index >= 0)
519 {
Greg Clayton63094e02010-06-23 01:19:29 +0000520 const char short_option = (char) g_options[long_options_index].short_option;
521
522 switch (short_option)
523 {
524 case 'h':
525 m_option_data.m_print_help = true;
526 break;
527
528 case 'v':
529 m_option_data.m_print_version = true;
530 break;
531
532 case 'c':
533 m_option_data.m_crash_log = optarg;
534 break;
Greg Clayton887aa282010-10-11 01:05:37 +0000535
Jim Ingham74989e82010-08-30 19:44:40 +0000536 case 'e':
537 m_option_data.m_use_external_editor = true;
538 break;
Greg Clayton887aa282010-10-11 01:05:37 +0000539
540 case 'n':
541 m_debugger.SkipLLDBInitFiles (true);
542 break;
543
Greg Clayton63094e02010-06-23 01:19:29 +0000544 case 'f':
545 {
546 SBFileSpec file(optarg);
547 if (file.Exists())
Greg Clayton4dc18922010-12-08 22:23:24 +0000548 {
549 m_option_data.m_args.push_back (optarg);
550 }
Caroline Ticeeddffe92010-09-10 04:48:55 +0000551 else if (file.ResolveExecutableLocation())
552 {
553 char path[PATH_MAX];
554 int path_len;
555 file.GetPath (path, path_len);
Greg Clayton4dc18922010-12-08 22:23:24 +0000556 m_option_data.m_args.push_back (path);
Caroline Ticeeddffe92010-09-10 04:48:55 +0000557 }
Greg Clayton63094e02010-06-23 01:19:29 +0000558 else
559 error.SetErrorStringWithFormat("file specified in --file (-f) option doesn't exist: '%s'", optarg);
560 }
561 break;
562
563 case 'a':
564 if (!m_debugger.SetDefaultArchitecture (optarg))
565 error.SetErrorStringWithFormat("invalid architecture in the -a or --arch option: '%s'", optarg);
566 break;
567
568 case 'l':
569 m_option_data.m_script_lang = m_debugger.GetScriptingLanguage (optarg);
570 break;
571
572 case 'd':
573 m_option_data.m_debug_mode = true;
574 break;
575
576 case 's':
577 {
578 SBFileSpec file(optarg);
579 if (file.Exists())
580 m_option_data.m_source_command_files.push_back (optarg);
Caroline Ticeeddffe92010-09-10 04:48:55 +0000581 else if (file.ResolveExecutableLocation())
582 {
583 char final_path[PATH_MAX];
584 size_t path_len;
585 file.GetPath (final_path, path_len);
586 std::string path_str (final_path);
587 m_option_data.m_source_command_files.push_back (path_str);
588 }
Greg Clayton63094e02010-06-23 01:19:29 +0000589 else
590 error.SetErrorStringWithFormat("file specified in --source (-s) option doesn't exist: '%s'", optarg);
591 }
592 break;
593
594 default:
595 m_option_data.m_print_help = true;
596 error.SetErrorStringWithFormat ("unrecognized option %c", short_option);
597 break;
598 }
Chris Lattner24943d22010-06-08 16:52:24 +0000599 }
600 else
601 {
602 error.SetErrorStringWithFormat ("invalid option with value %i", val);
603 }
604 if (error.Fail())
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000605 {
Greg Clayton63094e02010-06-23 01:19:29 +0000606 return error;
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000607 }
Chris Lattner24943d22010-06-08 16:52:24 +0000608 }
609 }
Jim Ingham34e9a982010-06-15 18:47:14 +0000610
Greg Clayton63094e02010-06-23 01:19:29 +0000611 if (error.Fail() || m_option_data.m_print_help)
Chris Lattner24943d22010-06-08 16:52:24 +0000612 {
613 ShowUsage (out_fh, g_options, m_option_data);
Greg Clayton9caa9462010-10-11 01:13:37 +0000614 exit = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000615 }
616 else if (m_option_data.m_print_version)
617 {
Greg Clayton63094e02010-06-23 01:19:29 +0000618 ::fprintf (out_fh, "%s\n", m_debugger.GetVersionString());
619 exit = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000620 }
621 else if (! m_option_data.m_crash_log.empty())
622 {
623 // Handle crash log stuff here.
624 }
625 else
626 {
Greg Clayton4dc18922010-12-08 22:23:24 +0000627 // Any arguments that are left over after option parsing are for
628 // the program. If a file was specified with -f then the filename
629 // is already in the m_option_data.m_args array, and any remaining args
630 // are arguments for the inferior program. If no file was specified with
631 // -f, then what is left is the program name followed by any arguments.
632
633 // Skip any options we consumed with getopt_long
634 argc -= optind;
635 argv += optind;
636
637 if (argc > 0)
638 {
639 for (int arg_idx=0; arg_idx<argc; ++arg_idx)
640 {
641 const char *arg = argv[arg_idx];
642 if (arg)
643 m_option_data.m_args.push_back (arg);
644 }
645 }
646
Chris Lattner24943d22010-06-08 16:52:24 +0000647 }
648
Greg Clayton63094e02010-06-23 01:19:29 +0000649 return error;
Chris Lattner24943d22010-06-08 16:52:24 +0000650}
651
Caroline Tice757500e2010-09-29 18:35:42 +0000652size_t
Chris Lattner24943d22010-06-08 16:52:24 +0000653Driver::GetProcessSTDOUT ()
654{
655 // The process has stuff waiting for stdout; get it and write it out to the appropriate place.
656 char stdio_buffer[1024];
657 size_t len;
Caroline Tice757500e2010-09-29 18:35:42 +0000658 size_t total_bytes = 0;
Jim Inghamc8332952010-08-26 21:32:51 +0000659 while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0)
Caroline Tice757500e2010-09-29 18:35:42 +0000660 {
Chris Lattner24943d22010-06-08 16:52:24 +0000661 m_io_channel_ap->OutWrite (stdio_buffer, len);
Caroline Tice757500e2010-09-29 18:35:42 +0000662 total_bytes += len;
663 }
664 return total_bytes;
Chris Lattner24943d22010-06-08 16:52:24 +0000665}
666
Caroline Tice757500e2010-09-29 18:35:42 +0000667size_t
Chris Lattner24943d22010-06-08 16:52:24 +0000668Driver::GetProcessSTDERR ()
669{
670 // The process has stuff waiting for stderr; get it and write it out to the appropriate place.
671 char stdio_buffer[1024];
672 size_t len;
Caroline Tice757500e2010-09-29 18:35:42 +0000673 size_t total_bytes = 0;
Jim Inghamc8332952010-08-26 21:32:51 +0000674 while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0)
Caroline Tice757500e2010-09-29 18:35:42 +0000675 {
Chris Lattner24943d22010-06-08 16:52:24 +0000676 m_io_channel_ap->ErrWrite (stdio_buffer, len);
Caroline Tice757500e2010-09-29 18:35:42 +0000677 total_bytes += len;
678 }
679 return total_bytes;
Chris Lattner24943d22010-06-08 16:52:24 +0000680}
681
682void
Jim Inghamc8332952010-08-26 21:32:51 +0000683Driver::UpdateSelectedThread ()
Chris Lattner24943d22010-06-08 16:52:24 +0000684{
685 using namespace lldb;
Jim Inghamc8332952010-08-26 21:32:51 +0000686 SBProcess process(m_debugger.GetSelectedTarget().GetProcess());
Chris Lattner24943d22010-06-08 16:52:24 +0000687 if (process.IsValid())
688 {
Jim Inghamc8332952010-08-26 21:32:51 +0000689 SBThread curr_thread (process.GetSelectedThread());
Chris Lattner24943d22010-06-08 16:52:24 +0000690 SBThread thread;
691 StopReason curr_thread_stop_reason = eStopReasonInvalid;
692 curr_thread_stop_reason = curr_thread.GetStopReason();
693
694 if (!curr_thread.IsValid() ||
695 curr_thread_stop_reason == eStopReasonInvalid ||
696 curr_thread_stop_reason == eStopReasonNone)
697 {
698 // Prefer a thread that has just completed its plan over another thread as current thread.
699 SBThread plan_thread;
700 SBThread other_thread;
701 const size_t num_threads = process.GetNumThreads();
702 size_t i;
703 for (i = 0; i < num_threads; ++i)
704 {
705 thread = process.GetThreadAtIndex(i);
706 StopReason thread_stop_reason = thread.GetStopReason();
707 switch (thread_stop_reason)
708 {
709 default:
710 case eStopReasonInvalid:
711 case eStopReasonNone:
712 break;
713
714 case eStopReasonTrace:
715 case eStopReasonBreakpoint:
716 case eStopReasonWatchpoint:
717 case eStopReasonSignal:
718 case eStopReasonException:
719 if (!other_thread.IsValid())
720 other_thread = thread;
721 break;
722 case eStopReasonPlanComplete:
723 if (!plan_thread.IsValid())
724 plan_thread = thread;
725 break;
726 }
727 }
728 if (plan_thread.IsValid())
Jim Inghamc8332952010-08-26 21:32:51 +0000729 process.SetSelectedThread (plan_thread);
Chris Lattner24943d22010-06-08 16:52:24 +0000730 else if (other_thread.IsValid())
Jim Inghamc8332952010-08-26 21:32:51 +0000731 process.SetSelectedThread (other_thread);
Chris Lattner24943d22010-06-08 16:52:24 +0000732 else
733 {
734 if (curr_thread.IsValid())
735 thread = curr_thread;
736 else
737 thread = process.GetThreadAtIndex(0);
738
739 if (thread.IsValid())
Jim Inghamc8332952010-08-26 21:32:51 +0000740 process.SetSelectedThread (thread);
Chris Lattner24943d22010-06-08 16:52:24 +0000741 }
742 }
743 }
744}
745
746
747// This function handles events that were broadcast by the process.
748void
749Driver::HandleProcessEvent (const SBEvent &event)
750{
751 using namespace lldb;
752 const uint32_t event_type = event.GetType();
753
754 if (event_type & SBProcess::eBroadcastBitSTDOUT)
755 {
756 // The process has stdout available, get it and write it out to the
757 // appropriate place.
Caroline Tice757500e2010-09-29 18:35:42 +0000758 if (GetProcessSTDOUT ())
759 m_io_channel_ap->RefreshPrompt();
Chris Lattner24943d22010-06-08 16:52:24 +0000760 }
761 else if (event_type & SBProcess::eBroadcastBitSTDERR)
762 {
763 // The process has stderr available, get it and write it out to the
764 // appropriate place.
Caroline Tice757500e2010-09-29 18:35:42 +0000765 if (GetProcessSTDERR ())
766 m_io_channel_ap->RefreshPrompt();
Chris Lattner24943d22010-06-08 16:52:24 +0000767 }
768 else if (event_type & SBProcess::eBroadcastBitStateChanged)
769 {
770 // Drain all stout and stderr so we don't see any output come after
771 // we print our prompts
Caroline Tice757500e2010-09-29 18:35:42 +0000772 if (GetProcessSTDOUT ()
773 || GetProcessSTDERR ())
774 m_io_channel_ap->RefreshPrompt();
Chris Lattner24943d22010-06-08 16:52:24 +0000775
776 // Something changed in the process; get the event and report the process's current status and location to
777 // the user.
778 StateType event_state = SBProcess::GetStateFromEvent (event);
779 if (event_state == eStateInvalid)
780 return;
781
782 SBProcess process (SBProcess::GetProcessFromEvent (event));
783 assert (process.IsValid());
784
785 switch (event_state)
786 {
787 case eStateInvalid:
788 case eStateUnloaded:
Greg Claytone71e2582011-02-04 01:58:07 +0000789 case eStateConnected:
Chris Lattner24943d22010-06-08 16:52:24 +0000790 case eStateAttaching:
791 case eStateLaunching:
792 case eStateStepping:
793 case eStateDetached:
794 {
795 char message[1024];
796 int message_len = ::snprintf (message, sizeof(message), "Process %d %s\n", process.GetProcessID(),
Greg Clayton63094e02010-06-23 01:19:29 +0000797 m_debugger.StateAsCString (event_state));
Chris Lattner24943d22010-06-08 16:52:24 +0000798 m_io_channel_ap->OutWrite(message, message_len);
799 }
800 break;
801
802 case eStateRunning:
803 // Don't be chatty when we run...
804 break;
805
806 case eStateExited:
Caroline Tice757500e2010-09-29 18:35:42 +0000807 {
808 SBCommandReturnObject result;
809 m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
810 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize());
811 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize());
812 m_io_channel_ap->RefreshPrompt();
813 }
Chris Lattner24943d22010-06-08 16:52:24 +0000814 break;
815
816 case eStateStopped:
817 case eStateCrashed:
818 case eStateSuspended:
819 // Make sure the program hasn't been auto-restarted:
820 if (SBProcess::GetRestartedFromEvent (event))
821 {
822 // FIXME: Do we want to report this, or would that just be annoyingly chatty?
823 char message[1024];
824 int message_len = ::snprintf (message, sizeof(message), "Process %d stopped and was programmatically restarted.\n",
825 process.GetProcessID());
826 m_io_channel_ap->OutWrite(message, message_len);
Caroline Tice757500e2010-09-29 18:35:42 +0000827 m_io_channel_ap->RefreshPrompt ();
Chris Lattner24943d22010-06-08 16:52:24 +0000828 }
829 else
830 {
Caroline Tice757500e2010-09-29 18:35:42 +0000831 SBCommandReturnObject result;
Jim Inghamc8332952010-08-26 21:32:51 +0000832 UpdateSelectedThread ();
Caroline Tice757500e2010-09-29 18:35:42 +0000833 m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
834 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize());
835 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize());
836 m_io_channel_ap->RefreshPrompt ();
Chris Lattner24943d22010-06-08 16:52:24 +0000837 }
838 break;
839 }
840 }
841}
842
843// This function handles events broadcast by the IOChannel (HasInput, UserInterrupt, or ThreadShouldExit).
844
845bool
846Driver::HandleIOEvent (const SBEvent &event)
847{
848 bool quit = false;
849
850 const uint32_t event_type = event.GetType();
851
852 if (event_type & IOChannel::eBroadcastBitHasUserInput)
853 {
854 // We got some input (i.e. a command string) from the user; pass it off to the command interpreter for
855 // handling.
856
857 const char *command_string = SBEvent::GetCStringFromEvent(event);
858 if (command_string == NULL)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000859 command_string = "";
Chris Lattner24943d22010-06-08 16:52:24 +0000860 SBCommandReturnObject result;
Jim Ingham2e8cb8a2011-02-19 02:53:09 +0000861 result.SetImmediateOutputFile (m_debugger.GetOutputFileHandle());
862 result.SetImmediateErrorFile (m_debugger.GetErrorFileHandle());
863
864 // We've set the result to dump immediately.
865 m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, true);
866
Chris Lattner24943d22010-06-08 16:52:24 +0000867 // We are done getting and running our command, we can now clear the
868 // m_waiting_for_command so we can get another one.
869 m_waiting_for_command = false;
870
871 // If our editline input reader is active, it means another input reader
872 // got pushed onto the input reader and caused us to become deactivated.
873 // When the input reader above us gets popped, we will get re-activated
874 // and our prompt will refresh in our callback
875 if (m_editline_reader.IsActive())
876 {
877 ReadyForCommand ();
878 }
879 }
880 else if (event_type & IOChannel::eBroadcastBitUserInterrupt)
881 {
882 // This is here to handle control-c interrupts from the user. It has not yet really been implemented.
883 // TO BE DONE: PROPERLY HANDLE CONTROL-C FROM USER
884 //m_io_channel_ap->CancelInput();
885 // Anything else? Send Interrupt to process?
886 }
887 else if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
888 (event_type & IOChannel::eBroadcastBitThreadDidExit))
889 {
890 // If the IOChannel thread is trying to go away, then it is definitely
891 // time to end the debugging session.
892 quit = true;
893 }
894
895 return quit;
896}
897
Chris Lattner24943d22010-06-08 16:52:24 +0000898void
899Driver::MasterThreadBytesReceived (void *baton, const void *src, size_t src_len)
900{
901 Driver *driver = (Driver*)baton;
902 driver->GetFromMaster ((const char *)src, src_len);
903}
904
905void
906Driver::GetFromMaster (const char *src, size_t src_len)
907{
908 // Echo the characters back to the Debugger's stdout, that way if you
909 // type characters while a command is running, you'll see what you've typed.
Greg Clayton63094e02010-06-23 01:19:29 +0000910 FILE *out_fh = m_debugger.GetOutputFileHandle();
Chris Lattner24943d22010-06-08 16:52:24 +0000911 if (out_fh)
912 ::fwrite (src, 1, src_len, out_fh);
913}
914
915size_t
916Driver::EditLineInputReaderCallback
917(
918 void *baton,
919 SBInputReader *reader,
920 InputReaderAction notification,
921 const char *bytes,
922 size_t bytes_len
923)
924{
925 Driver *driver = (Driver *)baton;
926
927 switch (notification)
928 {
929 case eInputReaderActivate:
930 break;
931
932 case eInputReaderReactivate:
933 driver->ReadyForCommand();
934 break;
935
936 case eInputReaderDeactivate:
937 break;
938
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000939 case eInputReaderInterrupt:
940 if (driver->m_io_channel_ap.get() != NULL)
941 {
942 driver->m_io_channel_ap->OutWrite ("^C\n", 3);
943 driver->m_io_channel_ap->RefreshPrompt();
944 }
945 break;
946
947 case eInputReaderEndOfFile:
948 if (driver->m_io_channel_ap.get() != NULL)
949 {
950 driver->m_io_channel_ap->OutWrite ("^D\n", 3);
951 driver->m_io_channel_ap->RefreshPrompt ();
952 }
953 write (driver->m_editline_pty.GetMasterFileDescriptor(), "quit\n", 5);
954 break;
955
Chris Lattner24943d22010-06-08 16:52:24 +0000956 case eInputReaderGotToken:
957 write (driver->m_editline_pty.GetMasterFileDescriptor(), bytes, bytes_len);
958 break;
959
960 case eInputReaderDone:
961 break;
962 }
963 return bytes_len;
964}
965
966void
967Driver::MainLoop ()
968{
969 char error_str[1024];
970 if (m_editline_pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, error_str, sizeof(error_str)) == false)
971 {
972 ::fprintf (stderr, "error: failed to open driver pseudo terminal : %s", error_str);
973 exit(1);
974 }
975 else
976 {
977 const char *driver_slave_name = m_editline_pty.GetSlaveName (error_str, sizeof(error_str));
978 if (driver_slave_name == NULL)
979 {
980 ::fprintf (stderr, "error: failed to get slave name for driver pseudo terminal : %s", error_str);
981 exit(2);
982 }
983 else
984 {
985 m_editline_slave_fh = ::fopen (driver_slave_name, "r+");
986 if (m_editline_slave_fh == NULL)
987 {
988 SBError error;
989 error.SetErrorToErrno();
990 ::fprintf (stderr, "error: failed to get open slave for driver pseudo terminal : %s",
991 error.GetCString());
992 exit(3);
993 }
994
995 ::setbuf (m_editline_slave_fh, NULL);
996 }
997 }
998
999
1000 // struct termios stdin_termios;
1001
1002 if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0)
1003 atexit (reset_stdin_termios);
1004
1005 ::setbuf (stdin, NULL);
1006 ::setbuf (stdout, NULL);
1007
Greg Clayton63094e02010-06-23 01:19:29 +00001008 m_debugger.SetErrorFileHandle (stderr, false);
1009 m_debugger.SetOutputFileHandle (stdout, false);
1010 m_debugger.SetInputFileHandle (stdin, true);
Jim Ingham74989e82010-08-30 19:44:40 +00001011
1012 m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor);
Chris Lattner24943d22010-06-08 16:52:24 +00001013
1014 // You have to drain anything that comes to the master side of the PTY. master_out_comm is
1015 // for that purpose. The reason you need to do this is a curious reason... editline will echo
1016 // characters to the PTY when it gets characters while el_gets is not running, and then when
1017 // you call el_gets (or el_getc) it will try to reset the terminal back to raw mode which blocks
1018 // if there are unconsumed characters in the out buffer.
1019 // However, you don't need to do anything with the characters, since editline will dump these
1020 // unconsumed characters after printing the prompt again in el_gets.
1021
Greg Claytoneecb0f32010-12-04 02:39:47 +00001022 SBCommunication master_out_comm("driver.editline");
1023 master_out_comm.SetCloseOnEOF (false);
Chris Lattner24943d22010-06-08 16:52:24 +00001024 master_out_comm.AdoptFileDesriptor(m_editline_pty.GetMasterFileDescriptor(), false);
1025 master_out_comm.SetReadThreadBytesReceivedCallback(Driver::MasterThreadBytesReceived, this);
1026
1027 if (master_out_comm.ReadThreadStart () == false)
1028 {
1029 ::fprintf (stderr, "error: failed to start master out read thread");
1030 exit(5);
1031 }
1032
1033// const char *crash_log = GetCrashLogFilename();
1034// if (crash_log)
1035// {
1036// ParseCrashLog (crash_log);
1037// }
1038//
Greg Clayton63094e02010-06-23 01:19:29 +00001039 SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter();
Chris Lattner24943d22010-06-08 16:52:24 +00001040
1041 m_io_channel_ap.reset (new IOChannel(m_editline_slave_fh, stdout, stderr, this));
1042
1043 struct winsize window_size;
1044 if (isatty (STDIN_FILENO)
1045 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
1046 {
Caroline Tice6e4c5ce2010-09-04 00:03:46 +00001047 if (window_size.ws_col > 0)
Greg Clayton238c0a12010-09-18 01:14:36 +00001048 m_debugger.SetTerminalWidth (window_size.ws_col);
Chris Lattner24943d22010-06-08 16:52:24 +00001049 }
1050
1051 // Since input can be redirected by the debugger, we must insert our editline
1052 // input reader in the queue so we know when our reader should be active
1053 // and so we can receive bytes only when we are supposed to.
Greg Clayton63094e02010-06-23 01:19:29 +00001054 SBError err (m_editline_reader.Initialize (m_debugger,
1055 Driver::EditLineInputReaderCallback, // callback
Chris Lattner24943d22010-06-08 16:52:24 +00001056 this, // baton
1057 eInputReaderGranularityByte, // token_size
1058 NULL, // end token - NULL means never done
1059 NULL, // prompt - taken care of elsewhere
1060 false)); // echo input - don't need Debugger
1061 // to do this, we handle it elsewhere
1062
1063 if (err.Fail())
1064 {
1065 ::fprintf (stderr, "error: %s", err.GetCString());
1066 exit (6);
1067 }
1068
Greg Clayton63094e02010-06-23 01:19:29 +00001069 m_debugger.PushInputReader (m_editline_reader);
Chris Lattner24943d22010-06-08 16:52:24 +00001070
Greg Clayton63094e02010-06-23 01:19:29 +00001071 SBListener listener(m_debugger.GetListener());
Chris Lattner24943d22010-06-08 16:52:24 +00001072 if (listener.IsValid())
1073 {
1074
1075 listener.StartListeningForEvents (*m_io_channel_ap,
1076 IOChannel::eBroadcastBitHasUserInput |
1077 IOChannel::eBroadcastBitUserInterrupt |
1078 IOChannel::eBroadcastBitThreadShouldExit |
1079 IOChannel::eBroadcastBitThreadDidStart |
1080 IOChannel::eBroadcastBitThreadDidExit);
1081
1082 if (m_io_channel_ap->Start ())
1083 {
1084 bool iochannel_thread_exited = false;
1085
1086 listener.StartListeningForEvents (sb_interpreter.GetBroadcaster(),
1087 SBCommandInterpreter::eBroadcastBitQuitCommandReceived);
1088
1089 // Before we handle any options from the command line, we parse the
1090 // .lldbinit file in the user's home directory.
1091 SBCommandReturnObject result;
1092 sb_interpreter.SourceInitFileInHomeDirectory(result);
1093 if (GetDebugMode())
1094 {
Greg Clayton63094e02010-06-23 01:19:29 +00001095 result.PutError (m_debugger.GetErrorFileHandle());
1096 result.PutOutput (m_debugger.GetOutputFileHandle());
Chris Lattner24943d22010-06-08 16:52:24 +00001097 }
1098
1099 // Now we handle options we got from the command line
1100 char command_string[PATH_MAX * 2];
1101 const size_t num_source_command_files = GetNumSourceCommandFiles();
1102 if (num_source_command_files > 0)
1103 {
1104 for (size_t i=0; i < num_source_command_files; ++i)
1105 {
1106 const char *command_file = GetSourceCommandFileAtIndex(i);
Johnny Chen7c984242010-07-28 21:16:11 +00001107 ::snprintf (command_string, sizeof(command_string), "command source '%s'", command_file);
Greg Clayton63094e02010-06-23 01:19:29 +00001108 m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, false);
Chris Lattner24943d22010-06-08 16:52:24 +00001109 if (GetDebugMode())
1110 {
Greg Clayton63094e02010-06-23 01:19:29 +00001111 result.PutError (m_debugger.GetErrorFileHandle());
1112 result.PutOutput (m_debugger.GetOutputFileHandle());
Chris Lattner24943d22010-06-08 16:52:24 +00001113 }
1114 }
1115 }
1116
Greg Clayton4dc18922010-12-08 22:23:24 +00001117 const size_t num_args = m_option_data.m_args.size();
1118 if (num_args > 0)
Chris Lattner24943d22010-06-08 16:52:24 +00001119 {
1120 char arch_name[64];
Greg Clayton63094e02010-06-23 01:19:29 +00001121 if (m_debugger.GetDefaultArchitecture (arch_name, sizeof (arch_name)))
Greg Clayton4dc18922010-12-08 22:23:24 +00001122 ::snprintf (command_string,
1123 sizeof (command_string),
1124 "file --arch=%s '%s'",
1125 arch_name,
1126 m_option_data.m_args[0].c_str());
Chris Lattner24943d22010-06-08 16:52:24 +00001127 else
Greg Clayton4dc18922010-12-08 22:23:24 +00001128 ::snprintf (command_string,
1129 sizeof(command_string),
1130 "file '%s'",
1131 m_option_data.m_args[0].c_str());
Chris Lattner24943d22010-06-08 16:52:24 +00001132
Greg Clayton63094e02010-06-23 01:19:29 +00001133 m_debugger.HandleCommand (command_string);
Greg Clayton4dc18922010-12-08 22:23:24 +00001134
1135 if (num_args > 1)
1136 {
1137 m_debugger.HandleCommand ("settings clear target.process.run-args");
1138 char arg_cstr[1024];
1139 for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx)
1140 {
1141 ::snprintf (arg_cstr, sizeof(arg_cstr), "settings append target.process.run-args \"%s\"", m_option_data.m_args[arg_idx].c_str());
1142 m_debugger.HandleCommand (arg_cstr);
1143 }
1144 }
Chris Lattner24943d22010-06-08 16:52:24 +00001145 }
1146
1147 // Now that all option parsing is done, we try and parse the .lldbinit
1148 // file in the current working directory
1149 sb_interpreter.SourceInitFileInCurrentWorkingDirectory (result);
1150 if (GetDebugMode())
1151 {
Greg Clayton63094e02010-06-23 01:19:29 +00001152 result.PutError(m_debugger.GetErrorFileHandle());
1153 result.PutOutput(m_debugger.GetOutputFileHandle());
Chris Lattner24943d22010-06-08 16:52:24 +00001154 }
1155
1156 SBEvent event;
1157
1158 // Make sure the IO channel is started up before we try to tell it we
1159 // are ready for input
1160 listener.WaitForEventForBroadcasterWithType (UINT32_MAX,
1161 *m_io_channel_ap,
1162 IOChannel::eBroadcastBitThreadDidStart,
1163 event);
1164
1165 ReadyForCommand ();
1166
1167 bool done = false;
1168 while (!done)
1169 {
1170 listener.WaitForEvent (UINT32_MAX, event);
1171 if (event.IsValid())
1172 {
1173 if (event.GetBroadcaster().IsValid())
1174 {
1175 uint32_t event_type = event.GetType();
1176 if (event.BroadcasterMatchesRef (*m_io_channel_ap))
1177 {
1178 if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
1179 (event_type & IOChannel::eBroadcastBitThreadDidExit))
1180 {
1181 done = true;
1182 if (event_type & IOChannel::eBroadcastBitThreadDidExit)
1183 iochannel_thread_exited = true;
1184 break;
1185 }
1186 else
1187 done = HandleIOEvent (event);
1188 }
Jim Inghamc8332952010-08-26 21:32:51 +00001189 else if (event.BroadcasterMatchesRef (m_debugger.GetSelectedTarget().GetProcess().GetBroadcaster()))
Chris Lattner24943d22010-06-08 16:52:24 +00001190 {
1191 HandleProcessEvent (event);
1192 }
1193 else if (event.BroadcasterMatchesRef (sb_interpreter.GetBroadcaster()))
1194 {
1195 if (event_type & SBCommandInterpreter::eBroadcastBitQuitCommandReceived)
1196 done = true;
1197 }
1198 }
1199 }
1200 }
1201
1202 reset_stdin_termios ();
1203
1204 CloseIOChannelFile ();
1205
1206 if (!iochannel_thread_exited)
1207 {
Greg Claytonbef15832010-07-14 00:18:15 +00001208 event.Clear();
Chris Lattner24943d22010-06-08 16:52:24 +00001209 listener.GetNextEventForBroadcasterWithType (*m_io_channel_ap,
1210 IOChannel::eBroadcastBitThreadDidExit,
1211 event);
1212 if (!event.IsValid())
1213 {
1214 // Send end EOF to the driver file descriptor
1215 m_io_channel_ap->Stop();
1216 }
1217 }
1218
Jim Inghamc8332952010-08-26 21:32:51 +00001219 SBProcess process = m_debugger.GetSelectedTarget().GetProcess();
Chris Lattner24943d22010-06-08 16:52:24 +00001220 if (process.IsValid())
1221 process.Destroy();
1222 }
1223 }
1224}
1225
1226
1227void
1228Driver::ReadyForCommand ()
1229{
1230 if (m_waiting_for_command == false)
1231 {
1232 m_waiting_for_command = true;
1233 BroadcastEventByType (Driver::eBroadcastBitReadyForInput, true);
1234 }
1235}
1236
1237
Caroline Ticeb8314fe2010-09-09 17:45:09 +00001238void
1239sigwinch_handler (int signo)
1240{
1241 struct winsize window_size;
1242 if (isatty (STDIN_FILENO)
1243 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
1244 {
1245 if ((window_size.ws_col > 0) && (strlen (g_debugger_name) > 0))
1246 {
1247 char width_str_buffer[25];
1248 ::sprintf (width_str_buffer, "%d", window_size.ws_col);
1249 SBDebugger::SetInternalVariable ("term-width", width_str_buffer, g_debugger_name);
1250 }
1251 }
1252}
1253
Caroline Ticec4f55fe2010-11-19 20:47:54 +00001254void
1255sigint_handler (int signo)
1256{
1257 static bool g_interrupt_sent = false;
1258 if (g_driver)
1259 {
1260 if (!g_interrupt_sent)
1261 {
1262 g_interrupt_sent = true;
1263 g_driver->GetDebugger().DispatchInputInterrupt();
1264 g_interrupt_sent = false;
1265 return;
1266 }
1267 }
1268
1269 exit (signo);
1270}
1271
Chris Lattner24943d22010-06-08 16:52:24 +00001272int
Jim Inghamb2b604f2011-01-27 20:15:39 +00001273main (int argc, char const *argv[], const char *envp[])
Chris Lattner24943d22010-06-08 16:52:24 +00001274{
Chris Lattner24943d22010-06-08 16:52:24 +00001275 SBDebugger::Initialize();
1276
Greg Clayton95e33b72010-11-07 21:02:03 +00001277 SBHostOS::ThreadCreated ("<lldb.driver.main-thread>");
Chris Lattner24943d22010-06-08 16:52:24 +00001278
Greg Clayton36f63a92010-10-19 03:25:40 +00001279 signal (SIGPIPE, SIG_IGN);
Caroline Ticeb8314fe2010-09-09 17:45:09 +00001280 signal (SIGWINCH, sigwinch_handler);
Caroline Ticec4f55fe2010-11-19 20:47:54 +00001281 signal (SIGINT, sigint_handler);
Caroline Ticeb8314fe2010-09-09 17:45:09 +00001282
Greg Clayton63094e02010-06-23 01:19:29 +00001283 // Create a scope for driver so that the driver object will destroy itself
1284 // before SBDebugger::Terminate() is called.
Chris Lattner24943d22010-06-08 16:52:24 +00001285 {
Greg Clayton63094e02010-06-23 01:19:29 +00001286 Driver driver;
1287
1288 bool exit = false;
1289 SBError error (driver.ParseArgs (argc, argv, stdout, exit));
1290 if (error.Fail())
1291 {
1292 const char *error_cstr = error.GetCString ();
1293 if (error_cstr)
1294 ::fprintf (stderr, "error: %s\n", error_cstr);
1295 }
1296 else if (!exit)
1297 {
1298 driver.MainLoop ();
1299 }
Chris Lattner24943d22010-06-08 16:52:24 +00001300 }
1301
1302 SBDebugger::Terminate();
1303 return 0;
1304}