blob: 8ce6da95ecce08ed6001de7eb4aa6d0ed657a646 [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"
Jim Ingham2e8cb8a2011-02-19 02:53:09 +000032#include "lldb/API/SBStream.h"
Eli Friedmanf2f321d2010-06-09 09:50:17 +000033#include "lldb/API/SBTarget.h"
34#include "lldb/API/SBThread.h"
35#include "lldb/API/SBProcess.h"
Chris Lattner24943d22010-06-08 16:52:24 +000036
37using namespace lldb;
38
39static void reset_stdin_termios ();
40static struct termios g_old_stdin_termios;
41
Caroline Ticeb8314fe2010-09-09 17:45:09 +000042static char *g_debugger_name = (char *) "";
Caroline Ticec4f55fe2010-11-19 20:47:54 +000043static Driver *g_driver = NULL;
Caroline Ticeb8314fe2010-09-09 17:45:09 +000044
Chris Lattner24943d22010-06-08 16:52:24 +000045// In the Driver::MainLoop, we change the terminal settings. This function is
46// added as an atexit handler to make sure we clean them up.
47static void
48reset_stdin_termios ()
49{
50 ::tcsetattr (STDIN_FILENO, TCSANOW, &g_old_stdin_termios);
51}
52
Greg Claytonb3448432011-03-24 21:19:54 +000053typedef struct
Chris Lattner24943d22010-06-08 16:52:24 +000054{
Greg Claytonb3448432011-03-24 21:19:54 +000055 uint32_t usage_mask; // Used to mark options that can be used together. If (1 << n & usage_mask) != 0
56 // then this option belongs to option set n.
57 bool required; // This option is required (in the current usage level)
58 const char * long_option; // Full name for this option.
59 char short_option; // Single character for this option.
60 int option_has_arg; // no_argument, required_argument or optional_argument
Greg Clayton5e342f52011-04-13 22:47:15 +000061 uint32_t completion_type; // Cookie the option class can use to do define the argument completion.
Greg Claytonb3448432011-03-24 21:19:54 +000062 lldb::CommandArgumentType argument_type; // Type of argument this option takes
63 const char * usage_text; // Full text explaining what this options does and what (if any) argument to
64 // pass it.
65} OptionDefinition;
Chris Lattner24943d22010-06-08 16:52:24 +000066
Jim Ingham83dd2032011-09-13 23:25:31 +000067#define LLDB_3_TO_5 LLDB_OPT_SET_3|LLDB_OPT_SET_4|LLDB_OPT_SET_5
68#define LLDB_4_TO_5 LLDB_OPT_SET_4|LLDB_OPT_SET_5
69
Greg Claytonb3448432011-03-24 21:19:54 +000070static OptionDefinition g_options[] =
71{
Jim Inghamdbcf98c2011-09-15 21:30:02 +000072 { LLDB_OPT_SET_1, true , "help" , 'h', no_argument , NULL, eArgTypeNone,
73 "Prints out the usage information for the LLDB debugger." },
74 { LLDB_OPT_SET_2, true , "version" , 'v', no_argument , NULL, eArgTypeNone,
75 "Prints out the current version number of the LLDB debugger." },
76 { LLDB_OPT_SET_3, true , "arch" , 'a', required_argument, NULL, eArgTypeArchitecture,
77 "Tells the debugger to use the specified architecture when starting and running the program. <architecture> must "
78 "be one of the architectures for which the program was compiled." },
79 { LLDB_OPT_SET_3, true , "file" , 'f', required_argument, NULL, eArgTypeFilename,
80 "Tells the debugger to use the file <filename> as the program to be debugged." },
81 { LLDB_OPT_SET_4, true , "attach-name" , 'n', required_argument, NULL, eArgTypeProcessName,
82 "Tells the debugger to attach to a process with the given name." },
83 { LLDB_OPT_SET_4, true , "wait-for" , 'w', no_argument , NULL, eArgTypeNone,
84 "Tells the debugger to wait for a process with the given pid or name to launch before attaching." },
85 { LLDB_OPT_SET_5, true , "attach-pid" , 'p', required_argument, NULL, eArgTypePid,
86 "Tells the debugger to attach to a process with the given pid." },
87 { LLDB_3_TO_5, false, "script-language", 'l', required_argument, NULL, eArgTypeScriptLang,
88 "Tells the debugger to use the specified scripting language for user-defined scripts, rather than the default. "
89 "Valid scripting languages that can be specified include Python, Perl, Ruby and Tcl. Currently only the Python "
90 "extensions have been implemented." },
91 { LLDB_3_TO_5, false, "debug" , 'd', no_argument , NULL, eArgTypeNone,
92 "Tells the debugger to print out extra information for debugging itself." },
93 { LLDB_3_TO_5, false, "source" , 's', required_argument, NULL, eArgTypeFilename,
94 "Tells the debugger to read in and execute the file <file>, which should contain lldb commands." },
95 { LLDB_3_TO_5, false, "editor" , 'e', no_argument , NULL, eArgTypeNone,
96 "Tells the debugger to open source files using the host's \"external editor\" mechanism." },
97 { LLDB_3_TO_5, false, "no-lldbinit" , 'x', no_argument , NULL, eArgTypeNone,
98 "Do not automatically parse any '.lldbinit' files." },
Jim Ingham83dd2032011-09-13 23:25:31 +000099 { 0, false, NULL , 0 , 0 , NULL, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +0000100};
101
Jim Ingham83dd2032011-09-13 23:25:31 +0000102static const uint32_t last_option_set_with_args = 2;
Chris Lattner24943d22010-06-08 16:52:24 +0000103
104Driver::Driver () :
105 SBBroadcaster ("Driver"),
Jim Ingham558dd5b2011-08-13 00:22:20 +0000106 m_debugger (SBDebugger::Create(false)),
Chris Lattner24943d22010-06-08 16:52:24 +0000107 m_editline_pty (),
108 m_editline_slave_fh (NULL),
109 m_editline_reader (),
110 m_io_channel_ap (),
111 m_option_data (),
112 m_waiting_for_command (false)
113{
Greg Clayton421ca502011-05-29 04:06:55 +0000114 // We want to be able to handle CTRL+D in the terminal to have it terminate
115 // certain input
116 m_debugger.SetCloseInputOnEOF (false);
Caroline Ticeb8314fe2010-09-09 17:45:09 +0000117 g_debugger_name = (char *) m_debugger.GetInstanceName();
118 if (g_debugger_name == NULL)
119 g_debugger_name = (char *) "";
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000120 g_driver = this;
Chris Lattner24943d22010-06-08 16:52:24 +0000121}
122
123Driver::~Driver ()
124{
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000125 g_driver = NULL;
126 g_debugger_name = NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000127}
128
129void
130Driver::CloseIOChannelFile ()
131{
132 // Write and End of File sequence to the file descriptor to ensure any
133 // read functions can exit.
134 char eof_str[] = "\x04";
135 ::write (m_editline_pty.GetMasterFileDescriptor(), eof_str, strlen(eof_str));
136
137 m_editline_pty.CloseMasterFileDescriptor();
138
139 if (m_editline_slave_fh)
140 {
141 ::fclose (m_editline_slave_fh);
142 m_editline_slave_fh = NULL;
143 }
144}
145
Greg Clayton54e7afa2010-07-09 20:39:50 +0000146// This function takes INDENT, which tells how many spaces to output at the front
147// of each line; TEXT, which is the text that is to be output. It outputs the
148// text, on multiple lines if necessary, to RESULT, with INDENT spaces at the
149// front of each line. It breaks lines on spaces, tabs or newlines, shortening
150// the line if necessary to not break in the middle of a word. It assumes that
151// each output line should contain a maximum of OUTPUT_MAX_COLUMNS characters.
Chris Lattner24943d22010-06-08 16:52:24 +0000152
153void
Greg Clayton54e7afa2010-07-09 20:39:50 +0000154OutputFormattedUsageText (FILE *out, int indent, const char *text, int output_max_columns)
Chris Lattner24943d22010-06-08 16:52:24 +0000155{
156 int len = strlen (text);
157 std::string text_string (text);
Chris Lattner24943d22010-06-08 16:52:24 +0000158
159 // Force indentation to be reasonable.
160 if (indent >= output_max_columns)
161 indent = 0;
162
163 // Will it all fit on one line?
164
165 if (len + indent < output_max_columns)
166 // Output as a single line
Greg Clayton54e7afa2010-07-09 20:39:50 +0000167 fprintf (out, "%*s%s\n", indent, "", text);
Chris Lattner24943d22010-06-08 16:52:24 +0000168 else
169 {
170 // We need to break it up into multiple lines.
171 int text_width = output_max_columns - indent - 1;
172 int start = 0;
173 int end = start;
174 int final_end = len;
175 int sub_len;
176
177 while (end < final_end)
178 {
179 // Dont start the 'text' on a space, since we're already outputting the indentation.
180 while ((start < final_end) && (text[start] == ' '))
181 start++;
182
183 end = start + text_width;
184 if (end > final_end)
185 end = final_end;
186 else
187 {
188 // If we're not at the end of the text, make sure we break the line on white space.
189 while (end > start
190 && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
191 end--;
192 }
193 sub_len = end - start;
194 std::string substring = text_string.substr (start, sub_len);
Greg Clayton54e7afa2010-07-09 20:39:50 +0000195 fprintf (out, "%*s%s\n", indent, "", substring.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000196 start = end + 1;
197 }
198 }
199}
200
201void
Greg Claytonb3448432011-03-24 21:19:54 +0000202ShowUsage (FILE *out, OptionDefinition *option_table, Driver::OptionData data)
Chris Lattner24943d22010-06-08 16:52:24 +0000203{
204 uint32_t screen_width = 80;
205 uint32_t indent_level = 0;
206 const char *name = "lldb";
Jim Ingham34e9a982010-06-15 18:47:14 +0000207
Chris Lattner24943d22010-06-08 16:52:24 +0000208 fprintf (out, "\nUsage:\n\n");
209
210 indent_level += 2;
211
212
213 // First, show each usage level set of options, e.g. <cmd> [options-for-level-0]
214 // <cmd> [options-for-level-1]
215 // etc.
216
Chris Lattner24943d22010-06-08 16:52:24 +0000217 uint32_t num_options;
Jim Ingham34e9a982010-06-15 18:47:14 +0000218 uint32_t num_option_sets = 0;
219
220 for (num_options = 0; option_table[num_options].long_option != NULL; ++num_options)
Chris Lattner24943d22010-06-08 16:52:24 +0000221 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000222 uint32_t this_usage_mask = option_table[num_options].usage_mask;
223 if (this_usage_mask == LLDB_OPT_SET_ALL)
Chris Lattner24943d22010-06-08 16:52:24 +0000224 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000225 if (num_option_sets == 0)
226 num_option_sets = 1;
Chris Lattner24943d22010-06-08 16:52:24 +0000227 }
228 else
229 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000230 for (uint32_t j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++)
Jim Ingham34e9a982010-06-15 18:47:14 +0000231 {
232 if (this_usage_mask & 1 << j)
233 {
234 if (num_option_sets <= j)
235 num_option_sets = j + 1;
236 }
237 }
238 }
239 }
240
241 for (uint32_t opt_set = 0; opt_set < num_option_sets; opt_set++)
242 {
243 uint32_t opt_set_mask;
244
245 opt_set_mask = 1 << opt_set;
246
247 if (opt_set > 0)
248 fprintf (out, "\n");
Greg Clayton54e7afa2010-07-09 20:39:50 +0000249 fprintf (out, "%*s%s", indent_level, "", name);
Jim Ingham6ae25442011-08-16 23:15:02 +0000250 bool is_help_line = false;
Jim Ingham34e9a982010-06-15 18:47:14 +0000251
252 for (uint32_t i = 0; i < num_options; ++i)
253 {
254 if (option_table[i].usage_mask & opt_set_mask)
255 {
Caroline Tice4d6675c2010-10-01 19:59:14 +0000256 CommandArgumentType arg_type = option_table[i].argument_type;
Greg Claytonaa378b12011-02-20 02:15:07 +0000257 const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type);
Jim Ingham6ae25442011-08-16 23:15:02 +0000258 // This is a bit of a hack, but there's no way to say certain options don't have arguments yet...
259 // so we do it by hand here.
260 if (option_table[i].short_option == 'h')
261 is_help_line = true;
262
Jim Ingham34e9a982010-06-15 18:47:14 +0000263 if (option_table[i].required)
264 {
265 if (option_table[i].option_has_arg == required_argument)
Greg Claytonaa378b12011-02-20 02:15:07 +0000266 fprintf (out, " -%c <%s>", option_table[i].short_option, arg_name);
Jim Ingham34e9a982010-06-15 18:47:14 +0000267 else if (option_table[i].option_has_arg == optional_argument)
Greg Claytonaa378b12011-02-20 02:15:07 +0000268 fprintf (out, " -%c [<%s>]", option_table[i].short_option, arg_name);
Jim Ingham34e9a982010-06-15 18:47:14 +0000269 else
270 fprintf (out, " -%c", option_table[i].short_option);
271 }
272 else
273 {
274 if (option_table[i].option_has_arg == required_argument)
Greg Claytonaa378b12011-02-20 02:15:07 +0000275 fprintf (out, " [-%c <%s>]", option_table[i].short_option, arg_name);
Jim Ingham34e9a982010-06-15 18:47:14 +0000276 else if (option_table[i].option_has_arg == optional_argument)
Greg Claytonaa378b12011-02-20 02:15:07 +0000277 fprintf (out, " [-%c [<%s>]]", option_table[i].short_option, arg_name);
Jim Ingham34e9a982010-06-15 18:47:14 +0000278 else
279 fprintf (out, " [-%c]", option_table[i].short_option);
280 }
281 }
Chris Lattner24943d22010-06-08 16:52:24 +0000282 }
Jim Ingham83dd2032011-09-13 23:25:31 +0000283 if (!is_help_line && (opt_set <= last_option_set_with_args))
Jim Ingham6ae25442011-08-16 23:15:02 +0000284 fprintf (out, " [[--] <PROGRAM-ARG-1> [<PROGRAM_ARG-2> ...]]");
Chris Lattner24943d22010-06-08 16:52:24 +0000285 }
286
287 fprintf (out, "\n\n");
288
289 // Now print out all the detailed information about the various options: long form, short form and help text:
290 // -- long_name <argument>
291 // - short <argument>
292 // help text
293
294 // This variable is used to keep track of which options' info we've printed out, because some options can be in
295 // more than one usage level, but we only want to print the long form of its information once.
296
297 Driver::OptionData::OptionSet options_seen;
298 Driver::OptionData::OptionSet::iterator pos;
299
300 indent_level += 5;
301
Jim Ingham34e9a982010-06-15 18:47:14 +0000302 for (uint32_t i = 0; i < num_options; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000303 {
304 // Only print this option if we haven't already seen it.
305 pos = options_seen.find (option_table[i].short_option);
306 if (pos == options_seen.end())
307 {
Caroline Tice4d6675c2010-10-01 19:59:14 +0000308 CommandArgumentType arg_type = option_table[i].argument_type;
Greg Claytonaa378b12011-02-20 02:15:07 +0000309 const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type);
Caroline Tice4d6675c2010-10-01 19:59:14 +0000310
Chris Lattner24943d22010-06-08 16:52:24 +0000311 options_seen.insert (option_table[i].short_option);
Greg Clayton54e7afa2010-07-09 20:39:50 +0000312 fprintf (out, "%*s-%c ", indent_level, "", option_table[i].short_option);
Caroline Tice4d6675c2010-10-01 19:59:14 +0000313 if (arg_type != eArgTypeNone)
Greg Claytonaa378b12011-02-20 02:15:07 +0000314 fprintf (out, "<%s>", arg_name);
Chris Lattner24943d22010-06-08 16:52:24 +0000315 fprintf (out, "\n");
Greg Clayton54e7afa2010-07-09 20:39:50 +0000316 fprintf (out, "%*s--%s ", indent_level, "", option_table[i].long_option);
Caroline Tice4d6675c2010-10-01 19:59:14 +0000317 if (arg_type != eArgTypeNone)
Greg Claytonaa378b12011-02-20 02:15:07 +0000318 fprintf (out, "<%s>", arg_name);
Chris Lattner24943d22010-06-08 16:52:24 +0000319 fprintf (out, "\n");
320 indent_level += 5;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000321 OutputFormattedUsageText (out, indent_level, option_table[i].usage_text, screen_width);
Chris Lattner24943d22010-06-08 16:52:24 +0000322 indent_level -= 5;
323 fprintf (out, "\n");
324 }
325 }
326
327 indent_level -= 5;
328
Jim Inghamcf0de262011-08-16 23:57:58 +0000329 fprintf (out, "\n%*s(If you don't provide -f then the first argument will be the file to be debugged"
330 "\n%*s so '%s -- <filename> [<ARG1> [<ARG2>]]' also works."
331 "\n%*s Remember to end the options with \"--\" if any of your arguments have a \"-\" in them.)\n\n",
332 indent_level, "",
333 indent_level, "",
334 name,
335 indent_level, "");
Chris Lattner24943d22010-06-08 16:52:24 +0000336}
337
338void
Greg Claytonb3448432011-03-24 21:19:54 +0000339BuildGetOptTable (OptionDefinition *expanded_option_table, std::vector<struct option> &getopt_table,
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000340 uint32_t num_options)
Chris Lattner24943d22010-06-08 16:52:24 +0000341{
342 if (num_options == 0)
343 return;
344
345 uint32_t i;
346 uint32_t j;
347 std::bitset<256> option_seen;
348
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000349 getopt_table.resize (num_options + 1);
350
Chris Lattner24943d22010-06-08 16:52:24 +0000351 for (i = 0, j = 0; i < num_options; ++i)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000352 {
Chris Lattner24943d22010-06-08 16:52:24 +0000353 char short_opt = expanded_option_table[i].short_option;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000354
Chris Lattner24943d22010-06-08 16:52:24 +0000355 if (option_seen.test(short_opt) == false)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000356 {
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000357 getopt_table[j].name = expanded_option_table[i].long_option;
358 getopt_table[j].has_arg = expanded_option_table[i].option_has_arg;
359 getopt_table[j].flag = NULL;
360 getopt_table[j].val = expanded_option_table[i].short_option;
Chris Lattner24943d22010-06-08 16:52:24 +0000361 option_seen.set(short_opt);
362 ++j;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000363 }
364 }
Chris Lattner24943d22010-06-08 16:52:24 +0000365
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000366 getopt_table[j].name = NULL;
367 getopt_table[j].has_arg = 0;
368 getopt_table[j].flag = NULL;
369 getopt_table[j].val = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000370
371}
372
Greg Clayton63094e02010-06-23 01:19:29 +0000373Driver::OptionData::OptionData () :
Greg Clayton4dc18922010-12-08 22:23:24 +0000374 m_args(),
Greg Clayton63094e02010-06-23 01:19:29 +0000375 m_script_lang (lldb::eScriptLanguageDefault),
Greg Clayton54e7afa2010-07-09 20:39:50 +0000376 m_crash_log (),
Greg Clayton63094e02010-06-23 01:19:29 +0000377 m_source_command_files (),
378 m_debug_mode (false),
Greg Clayton54e7afa2010-07-09 20:39:50 +0000379 m_print_version (false),
Greg Clayton63094e02010-06-23 01:19:29 +0000380 m_print_help (false),
Jim Ingham83dd2032011-09-13 23:25:31 +0000381 m_wait_for(false),
382 m_process_name(),
383 m_process_pid(LLDB_INVALID_PROCESS_ID),
Daniel Dunbar97c89572011-10-31 22:50:49 +0000384 m_use_external_editor(false),
Stephen Wilsondbeb3e12011-04-11 19:41:40 +0000385 m_seen_options()
Chris Lattner24943d22010-06-08 16:52:24 +0000386{
Greg Clayton63094e02010-06-23 01:19:29 +0000387}
388
389Driver::OptionData::~OptionData ()
390{
391}
392
393void
394Driver::OptionData::Clear ()
395{
Greg Clayton4dc18922010-12-08 22:23:24 +0000396 m_args.clear ();
Greg Clayton63094e02010-06-23 01:19:29 +0000397 m_script_lang = lldb::eScriptLanguageDefault;
398 m_source_command_files.clear ();
399 m_debug_mode = false;
400 m_print_help = false;
401 m_print_version = false;
Jim Ingham74989e82010-08-30 19:44:40 +0000402 m_use_external_editor = false;
Jim Ingham83dd2032011-09-13 23:25:31 +0000403 m_wait_for = false;
404 m_process_name.erase();
405 m_process_pid = LLDB_INVALID_PROCESS_ID;
Greg Clayton63094e02010-06-23 01:19:29 +0000406}
407
408void
409Driver::ResetOptionValues ()
410{
411 m_option_data.Clear ();
412}
413
414const char *
415Driver::GetFilename() const
416{
Greg Clayton4dc18922010-12-08 22:23:24 +0000417 if (m_option_data.m_args.empty())
Greg Clayton63094e02010-06-23 01:19:29 +0000418 return NULL;
Greg Clayton4dc18922010-12-08 22:23:24 +0000419 return m_option_data.m_args.front().c_str();
Greg Clayton63094e02010-06-23 01:19:29 +0000420}
421
422const char *
423Driver::GetCrashLogFilename() const
424{
425 if (m_option_data.m_crash_log.empty())
426 return NULL;
427 return m_option_data.m_crash_log.c_str();
428}
429
430lldb::ScriptLanguage
431Driver::GetScriptLanguage() const
432{
433 return m_option_data.m_script_lang;
434}
435
436size_t
437Driver::GetNumSourceCommandFiles () const
438{
439 return m_option_data.m_source_command_files.size();
440}
441
442const char *
443Driver::GetSourceCommandFileAtIndex (uint32_t idx) const
444{
445 if (idx < m_option_data.m_source_command_files.size())
446 return m_option_data.m_source_command_files[idx].c_str();
447 return NULL;
448}
449
450bool
451Driver::GetDebugMode() const
452{
453 return m_option_data.m_debug_mode;
454}
455
456
457// Check the arguments that were passed to this program to make sure they are valid and to get their
458// argument values (if any). Return a boolean value indicating whether or not to start up the full
459// debugger (i.e. the Command Interpreter) or not. Return FALSE if the arguments were invalid OR
460// if the user only wanted help or version information.
461
462SBError
463Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exit)
464{
465 ResetOptionValues ();
466
467 SBCommandReturnObject result;
468
Chris Lattner24943d22010-06-08 16:52:24 +0000469 SBError error;
470 std::string option_string;
471 struct option *long_options = NULL;
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000472 std::vector<struct option> long_options_vector;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000473 uint32_t num_options;
Chris Lattner24943d22010-06-08 16:52:24 +0000474
Greg Clayton54e7afa2010-07-09 20:39:50 +0000475 for (num_options = 0; g_options[num_options].long_option != NULL; ++num_options)
476 /* Do Nothing. */;
Chris Lattner24943d22010-06-08 16:52:24 +0000477
478 if (num_options == 0)
479 {
480 if (argc > 1)
481 error.SetErrorStringWithFormat ("invalid number of options");
482 return error;
483 }
484
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000485 BuildGetOptTable (g_options, long_options_vector, num_options);
Chris Lattner24943d22010-06-08 16:52:24 +0000486
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000487 if (long_options_vector.empty())
488 long_options = NULL;
489 else
490 long_options = &long_options_vector.front();
Chris Lattner24943d22010-06-08 16:52:24 +0000491
492 if (long_options == NULL)
493 {
494 error.SetErrorStringWithFormat ("invalid long options");
495 return error;
496 }
497
498 // Build the option_string argument for call to getopt_long.
499
500 for (int i = 0; long_options[i].name != NULL; ++i)
501 {
502 if (long_options[i].flag == NULL)
503 {
504 option_string.push_back ((char) long_options[i].val);
505 switch (long_options[i].has_arg)
506 {
507 default:
508 case no_argument:
509 break;
510 case required_argument:
511 option_string.push_back (':');
512 break;
513 case optional_argument:
514 option_string.append ("::");
515 break;
516 }
517 }
518 }
519
Jim Ingham558dd5b2011-08-13 00:22:20 +0000520 // This is kind of a pain, but since we make the debugger in the Driver's constructor, we can't
521 // know at that point whether we should read in init files yet. So we don't read them in in the
522 // Driver constructor, then set the flags back to "read them in" here, and then if we see the
523 // "-n" flag, we'll turn it off again. Finally we have to read them in by hand later in the
524 // main loop.
525
526 m_debugger.SkipLLDBInitFiles (false);
527 m_debugger.SkipAppInitFiles (false);
528
Chris Lattner24943d22010-06-08 16:52:24 +0000529 // Prepare for & make calls to getopt_long.
Eli Friedmanef2bc872010-06-13 19:18:49 +0000530#if __GLIBC__
531 optind = 0;
532#else
Chris Lattner24943d22010-06-08 16:52:24 +0000533 optreset = 1;
534 optind = 1;
Eli Friedmanef2bc872010-06-13 19:18:49 +0000535#endif
Chris Lattner24943d22010-06-08 16:52:24 +0000536 int val;
537 while (1)
538 {
539 int long_options_index = -1;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000540 val = ::getopt_long (argc, const_cast<char **>(argv), option_string.c_str(), long_options, &long_options_index);
Chris Lattner24943d22010-06-08 16:52:24 +0000541
542 if (val == -1)
543 break;
544 else if (val == '?')
545 {
Greg Clayton63094e02010-06-23 01:19:29 +0000546 m_option_data.m_print_help = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000547 error.SetErrorStringWithFormat ("unknown or ambiguous option");
548 break;
549 }
550 else if (val == 0)
551 continue;
552 else
553 {
Greg Clayton63094e02010-06-23 01:19:29 +0000554 m_option_data.m_seen_options.insert ((char) val);
Chris Lattner24943d22010-06-08 16:52:24 +0000555 if (long_options_index == -1)
556 {
557 for (int i = 0;
558 long_options[i].name || long_options[i].has_arg || long_options[i].flag || long_options[i].val;
559 ++i)
560 {
561 if (long_options[i].val == val)
562 {
563 long_options_index = i;
564 break;
565 }
566 }
567 }
568
569 if (long_options_index >= 0)
570 {
Greg Clayton63094e02010-06-23 01:19:29 +0000571 const char short_option = (char) g_options[long_options_index].short_option;
572
573 switch (short_option)
574 {
575 case 'h':
576 m_option_data.m_print_help = true;
577 break;
578
579 case 'v':
580 m_option_data.m_print_version = true;
581 break;
582
583 case 'c':
584 m_option_data.m_crash_log = optarg;
585 break;
Greg Clayton887aa282010-10-11 01:05:37 +0000586
Jim Ingham74989e82010-08-30 19:44:40 +0000587 case 'e':
588 m_option_data.m_use_external_editor = true;
589 break;
Greg Clayton887aa282010-10-11 01:05:37 +0000590
Jim Ingham83dd2032011-09-13 23:25:31 +0000591 case 'x':
Greg Clayton887aa282010-10-11 01:05:37 +0000592 m_debugger.SkipLLDBInitFiles (true);
Jim Ingham558dd5b2011-08-13 00:22:20 +0000593 m_debugger.SkipAppInitFiles (true);
Greg Clayton887aa282010-10-11 01:05:37 +0000594 break;
595
Greg Clayton63094e02010-06-23 01:19:29 +0000596 case 'f':
597 {
598 SBFileSpec file(optarg);
599 if (file.Exists())
Greg Clayton4dc18922010-12-08 22:23:24 +0000600 {
601 m_option_data.m_args.push_back (optarg);
602 }
Caroline Ticeeddffe92010-09-10 04:48:55 +0000603 else if (file.ResolveExecutableLocation())
604 {
605 char path[PATH_MAX];
Johnny Chenee6e7902011-08-10 22:06:24 +0000606 file.GetPath (path, sizeof(path));
Greg Clayton4dc18922010-12-08 22:23:24 +0000607 m_option_data.m_args.push_back (path);
Caroline Ticeeddffe92010-09-10 04:48:55 +0000608 }
Greg Clayton63094e02010-06-23 01:19:29 +0000609 else
610 error.SetErrorStringWithFormat("file specified in --file (-f) option doesn't exist: '%s'", optarg);
611 }
612 break;
613
614 case 'a':
615 if (!m_debugger.SetDefaultArchitecture (optarg))
616 error.SetErrorStringWithFormat("invalid architecture in the -a or --arch option: '%s'", optarg);
617 break;
618
619 case 'l':
620 m_option_data.m_script_lang = m_debugger.GetScriptingLanguage (optarg);
621 break;
622
623 case 'd':
624 m_option_data.m_debug_mode = true;
625 break;
626
Jim Ingham83dd2032011-09-13 23:25:31 +0000627 case 'n':
628 m_option_data.m_process_name = optarg;
629 break;
630
631 case 'w':
632 m_option_data.m_wait_for = true;
633 break;
634
635 case 'p':
636 {
637 char *remainder;
638 m_option_data.m_process_pid = strtol (optarg, &remainder, 0);
639 if (remainder == optarg || *remainder != '\0')
640 error.SetErrorStringWithFormat ("Could not convert process PID: \"%s\" into a pid.",
641 optarg);
642 }
643 break;
Greg Clayton63094e02010-06-23 01:19:29 +0000644 case 's':
645 {
646 SBFileSpec file(optarg);
647 if (file.Exists())
648 m_option_data.m_source_command_files.push_back (optarg);
Caroline Ticeeddffe92010-09-10 04:48:55 +0000649 else if (file.ResolveExecutableLocation())
650 {
651 char final_path[PATH_MAX];
Johnny Chenee6e7902011-08-10 22:06:24 +0000652 file.GetPath (final_path, sizeof(final_path));
Caroline Ticeeddffe92010-09-10 04:48:55 +0000653 std::string path_str (final_path);
654 m_option_data.m_source_command_files.push_back (path_str);
655 }
Greg Clayton63094e02010-06-23 01:19:29 +0000656 else
657 error.SetErrorStringWithFormat("file specified in --source (-s) option doesn't exist: '%s'", optarg);
658 }
659 break;
660
661 default:
662 m_option_data.m_print_help = true;
663 error.SetErrorStringWithFormat ("unrecognized option %c", short_option);
664 break;
665 }
Chris Lattner24943d22010-06-08 16:52:24 +0000666 }
667 else
668 {
669 error.SetErrorStringWithFormat ("invalid option with value %i", val);
670 }
671 if (error.Fail())
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000672 {
Greg Clayton63094e02010-06-23 01:19:29 +0000673 return error;
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000674 }
Chris Lattner24943d22010-06-08 16:52:24 +0000675 }
676 }
Jim Ingham34e9a982010-06-15 18:47:14 +0000677
Greg Clayton63094e02010-06-23 01:19:29 +0000678 if (error.Fail() || m_option_data.m_print_help)
Chris Lattner24943d22010-06-08 16:52:24 +0000679 {
680 ShowUsage (out_fh, g_options, m_option_data);
Greg Clayton9caa9462010-10-11 01:13:37 +0000681 exit = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000682 }
683 else if (m_option_data.m_print_version)
684 {
Greg Clayton63094e02010-06-23 01:19:29 +0000685 ::fprintf (out_fh, "%s\n", m_debugger.GetVersionString());
686 exit = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000687 }
688 else if (! m_option_data.m_crash_log.empty())
689 {
690 // Handle crash log stuff here.
691 }
Jim Ingham83dd2032011-09-13 23:25:31 +0000692 else if (m_option_data.m_process_name.empty() && m_option_data.m_process_pid == LLDB_INVALID_PROCESS_ID)
Chris Lattner24943d22010-06-08 16:52:24 +0000693 {
Greg Clayton4dc18922010-12-08 22:23:24 +0000694 // Any arguments that are left over after option parsing are for
695 // the program. If a file was specified with -f then the filename
696 // is already in the m_option_data.m_args array, and any remaining args
697 // are arguments for the inferior program. If no file was specified with
698 // -f, then what is left is the program name followed by any arguments.
699
700 // Skip any options we consumed with getopt_long
701 argc -= optind;
702 argv += optind;
703
704 if (argc > 0)
705 {
706 for (int arg_idx=0; arg_idx<argc; ++arg_idx)
707 {
708 const char *arg = argv[arg_idx];
709 if (arg)
710 m_option_data.m_args.push_back (arg);
711 }
712 }
713
Chris Lattner24943d22010-06-08 16:52:24 +0000714 }
Jim Ingham83dd2032011-09-13 23:25:31 +0000715 else
716 {
717 // Skip any options we consumed with getopt_long
718 argc -= optind;
719 argv += optind;
720
721 if (argc > 0)
722 ::fprintf (out_fh, "Warning: program arguments are ignored when attaching.\n");
723 }
Chris Lattner24943d22010-06-08 16:52:24 +0000724
Greg Clayton63094e02010-06-23 01:19:29 +0000725 return error;
Chris Lattner24943d22010-06-08 16:52:24 +0000726}
727
Caroline Tice757500e2010-09-29 18:35:42 +0000728size_t
Chris Lattner24943d22010-06-08 16:52:24 +0000729Driver::GetProcessSTDOUT ()
730{
731 // The process has stuff waiting for stdout; get it and write it out to the appropriate place.
732 char stdio_buffer[1024];
733 size_t len;
Caroline Tice757500e2010-09-29 18:35:42 +0000734 size_t total_bytes = 0;
Jim Inghamc8332952010-08-26 21:32:51 +0000735 while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0)
Caroline Tice757500e2010-09-29 18:35:42 +0000736 {
Caroline Tice4a348082011-05-02 20:41:46 +0000737 m_io_channel_ap->OutWrite (stdio_buffer, len, ASYNC);
Caroline Tice757500e2010-09-29 18:35:42 +0000738 total_bytes += len;
739 }
740 return total_bytes;
Chris Lattner24943d22010-06-08 16:52:24 +0000741}
742
Caroline Tice757500e2010-09-29 18:35:42 +0000743size_t
Chris Lattner24943d22010-06-08 16:52:24 +0000744Driver::GetProcessSTDERR ()
745{
746 // The process has stuff waiting for stderr; get it and write it out to the appropriate place.
747 char stdio_buffer[1024];
748 size_t len;
Caroline Tice757500e2010-09-29 18:35:42 +0000749 size_t total_bytes = 0;
Jim Inghamc8332952010-08-26 21:32:51 +0000750 while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0)
Caroline Tice757500e2010-09-29 18:35:42 +0000751 {
Caroline Tice4a348082011-05-02 20:41:46 +0000752 m_io_channel_ap->ErrWrite (stdio_buffer, len, ASYNC);
Caroline Tice757500e2010-09-29 18:35:42 +0000753 total_bytes += len;
754 }
755 return total_bytes;
Chris Lattner24943d22010-06-08 16:52:24 +0000756}
757
758void
Jim Inghamc8332952010-08-26 21:32:51 +0000759Driver::UpdateSelectedThread ()
Chris Lattner24943d22010-06-08 16:52:24 +0000760{
761 using namespace lldb;
Jim Inghamc8332952010-08-26 21:32:51 +0000762 SBProcess process(m_debugger.GetSelectedTarget().GetProcess());
Chris Lattner24943d22010-06-08 16:52:24 +0000763 if (process.IsValid())
764 {
Jim Inghamc8332952010-08-26 21:32:51 +0000765 SBThread curr_thread (process.GetSelectedThread());
Chris Lattner24943d22010-06-08 16:52:24 +0000766 SBThread thread;
767 StopReason curr_thread_stop_reason = eStopReasonInvalid;
768 curr_thread_stop_reason = curr_thread.GetStopReason();
769
770 if (!curr_thread.IsValid() ||
771 curr_thread_stop_reason == eStopReasonInvalid ||
772 curr_thread_stop_reason == eStopReasonNone)
773 {
774 // Prefer a thread that has just completed its plan over another thread as current thread.
775 SBThread plan_thread;
776 SBThread other_thread;
777 const size_t num_threads = process.GetNumThreads();
778 size_t i;
779 for (i = 0; i < num_threads; ++i)
780 {
781 thread = process.GetThreadAtIndex(i);
782 StopReason thread_stop_reason = thread.GetStopReason();
783 switch (thread_stop_reason)
784 {
785 default:
786 case eStopReasonInvalid:
787 case eStopReasonNone:
788 break;
789
790 case eStopReasonTrace:
791 case eStopReasonBreakpoint:
792 case eStopReasonWatchpoint:
793 case eStopReasonSignal:
794 case eStopReasonException:
795 if (!other_thread.IsValid())
796 other_thread = thread;
797 break;
798 case eStopReasonPlanComplete:
799 if (!plan_thread.IsValid())
800 plan_thread = thread;
801 break;
802 }
803 }
804 if (plan_thread.IsValid())
Jim Inghamc8332952010-08-26 21:32:51 +0000805 process.SetSelectedThread (plan_thread);
Chris Lattner24943d22010-06-08 16:52:24 +0000806 else if (other_thread.IsValid())
Jim Inghamc8332952010-08-26 21:32:51 +0000807 process.SetSelectedThread (other_thread);
Chris Lattner24943d22010-06-08 16:52:24 +0000808 else
809 {
810 if (curr_thread.IsValid())
811 thread = curr_thread;
812 else
813 thread = process.GetThreadAtIndex(0);
814
815 if (thread.IsValid())
Jim Inghamc8332952010-08-26 21:32:51 +0000816 process.SetSelectedThread (thread);
Chris Lattner24943d22010-06-08 16:52:24 +0000817 }
818 }
819 }
820}
821
822
823// This function handles events that were broadcast by the process.
824void
825Driver::HandleProcessEvent (const SBEvent &event)
826{
827 using namespace lldb;
828 const uint32_t event_type = event.GetType();
829
830 if (event_type & SBProcess::eBroadcastBitSTDOUT)
831 {
832 // The process has stdout available, get it and write it out to the
833 // appropriate place.
Caroline Tice4a348082011-05-02 20:41:46 +0000834 GetProcessSTDOUT ();
Chris Lattner24943d22010-06-08 16:52:24 +0000835 }
836 else if (event_type & SBProcess::eBroadcastBitSTDERR)
837 {
838 // The process has stderr available, get it and write it out to the
839 // appropriate place.
Caroline Tice4a348082011-05-02 20:41:46 +0000840 GetProcessSTDERR ();
Chris Lattner24943d22010-06-08 16:52:24 +0000841 }
842 else if (event_type & SBProcess::eBroadcastBitStateChanged)
843 {
844 // Drain all stout and stderr so we don't see any output come after
845 // we print our prompts
Caroline Tice4a348082011-05-02 20:41:46 +0000846 GetProcessSTDOUT ();
847 GetProcessSTDERR ();
Chris Lattner24943d22010-06-08 16:52:24 +0000848 // Something changed in the process; get the event and report the process's current status and location to
849 // the user.
850 StateType event_state = SBProcess::GetStateFromEvent (event);
851 if (event_state == eStateInvalid)
852 return;
853
854 SBProcess process (SBProcess::GetProcessFromEvent (event));
855 assert (process.IsValid());
856
857 switch (event_state)
858 {
859 case eStateInvalid:
860 case eStateUnloaded:
Greg Claytone71e2582011-02-04 01:58:07 +0000861 case eStateConnected:
Chris Lattner24943d22010-06-08 16:52:24 +0000862 case eStateAttaching:
863 case eStateLaunching:
864 case eStateStepping:
865 case eStateDetached:
866 {
867 char message[1024];
868 int message_len = ::snprintf (message, sizeof(message), "Process %d %s\n", process.GetProcessID(),
Greg Clayton63094e02010-06-23 01:19:29 +0000869 m_debugger.StateAsCString (event_state));
Caroline Tice4a348082011-05-02 20:41:46 +0000870 m_io_channel_ap->OutWrite(message, message_len, ASYNC);
Chris Lattner24943d22010-06-08 16:52:24 +0000871 }
872 break;
873
874 case eStateRunning:
875 // Don't be chatty when we run...
876 break;
877
878 case eStateExited:
Caroline Tice757500e2010-09-29 18:35:42 +0000879 {
880 SBCommandReturnObject result;
881 m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
Caroline Tice4a348082011-05-02 20:41:46 +0000882 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize(), ASYNC);
883 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize(), ASYNC);
Caroline Tice757500e2010-09-29 18:35:42 +0000884 }
Chris Lattner24943d22010-06-08 16:52:24 +0000885 break;
886
887 case eStateStopped:
888 case eStateCrashed:
889 case eStateSuspended:
890 // Make sure the program hasn't been auto-restarted:
891 if (SBProcess::GetRestartedFromEvent (event))
892 {
893 // FIXME: Do we want to report this, or would that just be annoyingly chatty?
894 char message[1024];
895 int message_len = ::snprintf (message, sizeof(message), "Process %d stopped and was programmatically restarted.\n",
896 process.GetProcessID());
Caroline Tice4a348082011-05-02 20:41:46 +0000897 m_io_channel_ap->OutWrite(message, message_len, ASYNC);
Chris Lattner24943d22010-06-08 16:52:24 +0000898 }
899 else
900 {
Caroline Tice757500e2010-09-29 18:35:42 +0000901 SBCommandReturnObject result;
Jim Inghamc8332952010-08-26 21:32:51 +0000902 UpdateSelectedThread ();
Caroline Tice757500e2010-09-29 18:35:42 +0000903 m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
Caroline Tice4a348082011-05-02 20:41:46 +0000904 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize(), ASYNC);
905 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize(), ASYNC);
Chris Lattner24943d22010-06-08 16:52:24 +0000906 }
907 break;
908 }
909 }
910}
911
912// This function handles events broadcast by the IOChannel (HasInput, UserInterrupt, or ThreadShouldExit).
913
914bool
915Driver::HandleIOEvent (const SBEvent &event)
916{
917 bool quit = false;
918
919 const uint32_t event_type = event.GetType();
920
921 if (event_type & IOChannel::eBroadcastBitHasUserInput)
922 {
923 // We got some input (i.e. a command string) from the user; pass it off to the command interpreter for
924 // handling.
925
926 const char *command_string = SBEvent::GetCStringFromEvent(event);
927 if (command_string == NULL)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000928 command_string = "";
Chris Lattner24943d22010-06-08 16:52:24 +0000929 SBCommandReturnObject result;
Jim Ingham2e8cb8a2011-02-19 02:53:09 +0000930
Caroline Tice845d6da2011-05-16 19:20:50 +0000931 // We don't want the result to bypass the OutWrite function in IOChannel, as this can result in odd
932 // output orderings and problems with the prompt.
Jim Ingham2e8cb8a2011-02-19 02:53:09 +0000933 m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, true);
934
Caroline Tice845d6da2011-05-16 19:20:50 +0000935 if (result.GetOutputSize() > 0)
936 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize(), NO_ASYNC);
937
938 if (result.GetErrorSize() > 0)
939 m_io_channel_ap->OutWrite (result.GetError(), result.GetErrorSize(), NO_ASYNC);
940
Chris Lattner24943d22010-06-08 16:52:24 +0000941 // We are done getting and running our command, we can now clear the
942 // m_waiting_for_command so we can get another one.
943 m_waiting_for_command = false;
944
945 // If our editline input reader is active, it means another input reader
946 // got pushed onto the input reader and caused us to become deactivated.
947 // When the input reader above us gets popped, we will get re-activated
948 // and our prompt will refresh in our callback
949 if (m_editline_reader.IsActive())
950 {
951 ReadyForCommand ();
952 }
953 }
954 else if (event_type & IOChannel::eBroadcastBitUserInterrupt)
955 {
956 // This is here to handle control-c interrupts from the user. It has not yet really been implemented.
957 // TO BE DONE: PROPERLY HANDLE CONTROL-C FROM USER
958 //m_io_channel_ap->CancelInput();
959 // Anything else? Send Interrupt to process?
960 }
961 else if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
962 (event_type & IOChannel::eBroadcastBitThreadDidExit))
963 {
964 // If the IOChannel thread is trying to go away, then it is definitely
965 // time to end the debugging session.
966 quit = true;
967 }
968
969 return quit;
970}
971
Chris Lattner24943d22010-06-08 16:52:24 +0000972void
973Driver::MasterThreadBytesReceived (void *baton, const void *src, size_t src_len)
974{
975 Driver *driver = (Driver*)baton;
976 driver->GetFromMaster ((const char *)src, src_len);
977}
978
979void
980Driver::GetFromMaster (const char *src, size_t src_len)
981{
982 // Echo the characters back to the Debugger's stdout, that way if you
983 // type characters while a command is running, you'll see what you've typed.
Greg Clayton63094e02010-06-23 01:19:29 +0000984 FILE *out_fh = m_debugger.GetOutputFileHandle();
Chris Lattner24943d22010-06-08 16:52:24 +0000985 if (out_fh)
986 ::fwrite (src, 1, src_len, out_fh);
987}
988
989size_t
990Driver::EditLineInputReaderCallback
991(
992 void *baton,
993 SBInputReader *reader,
994 InputReaderAction notification,
995 const char *bytes,
996 size_t bytes_len
997)
998{
999 Driver *driver = (Driver *)baton;
1000
1001 switch (notification)
1002 {
1003 case eInputReaderActivate:
1004 break;
1005
1006 case eInputReaderReactivate:
1007 driver->ReadyForCommand();
1008 break;
1009
1010 case eInputReaderDeactivate:
1011 break;
Caroline Tice4a348082011-05-02 20:41:46 +00001012
1013 case eInputReaderAsynchronousOutputWritten:
1014 if (driver->m_io_channel_ap.get() != NULL)
1015 driver->m_io_channel_ap->RefreshPrompt();
1016 break;
Chris Lattner24943d22010-06-08 16:52:24 +00001017
Caroline Ticec4f55fe2010-11-19 20:47:54 +00001018 case eInputReaderInterrupt:
1019 if (driver->m_io_channel_ap.get() != NULL)
1020 {
Caroline Tice4a348082011-05-02 20:41:46 +00001021 driver->m_io_channel_ap->OutWrite ("^C\n", 3, NO_ASYNC);
Caroline Ticec4f55fe2010-11-19 20:47:54 +00001022 driver->m_io_channel_ap->RefreshPrompt();
1023 }
1024 break;
1025
1026 case eInputReaderEndOfFile:
1027 if (driver->m_io_channel_ap.get() != NULL)
1028 {
Caroline Tice4a348082011-05-02 20:41:46 +00001029 driver->m_io_channel_ap->OutWrite ("^D\n", 3, NO_ASYNC);
Caroline Ticec4f55fe2010-11-19 20:47:54 +00001030 driver->m_io_channel_ap->RefreshPrompt ();
1031 }
1032 write (driver->m_editline_pty.GetMasterFileDescriptor(), "quit\n", 5);
1033 break;
1034
Chris Lattner24943d22010-06-08 16:52:24 +00001035 case eInputReaderGotToken:
1036 write (driver->m_editline_pty.GetMasterFileDescriptor(), bytes, bytes_len);
1037 break;
1038
1039 case eInputReaderDone:
1040 break;
1041 }
1042 return bytes_len;
1043}
1044
1045void
1046Driver::MainLoop ()
1047{
1048 char error_str[1024];
1049 if (m_editline_pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, error_str, sizeof(error_str)) == false)
1050 {
1051 ::fprintf (stderr, "error: failed to open driver pseudo terminal : %s", error_str);
1052 exit(1);
1053 }
1054 else
1055 {
1056 const char *driver_slave_name = m_editline_pty.GetSlaveName (error_str, sizeof(error_str));
1057 if (driver_slave_name == NULL)
1058 {
1059 ::fprintf (stderr, "error: failed to get slave name for driver pseudo terminal : %s", error_str);
1060 exit(2);
1061 }
1062 else
1063 {
1064 m_editline_slave_fh = ::fopen (driver_slave_name, "r+");
1065 if (m_editline_slave_fh == NULL)
1066 {
1067 SBError error;
1068 error.SetErrorToErrno();
1069 ::fprintf (stderr, "error: failed to get open slave for driver pseudo terminal : %s",
1070 error.GetCString());
1071 exit(3);
1072 }
1073
1074 ::setbuf (m_editline_slave_fh, NULL);
1075 }
1076 }
1077
Caroline Tice4a348082011-05-02 20:41:46 +00001078 lldb_utility::PseudoTerminal editline_output_pty;
1079 FILE *editline_output_slave_fh = NULL;
1080
1081 if (editline_output_pty.OpenFirstAvailableMaster (O_RDWR|O_NOCTTY, error_str, sizeof (error_str)) == false)
1082 {
1083 ::fprintf (stderr, "error: failed to open output pseudo terminal : %s", error_str);
1084 exit(1);
1085 }
1086 else
1087 {
1088 const char *output_slave_name = editline_output_pty.GetSlaveName (error_str, sizeof(error_str));
1089 if (output_slave_name == NULL)
1090 {
1091 ::fprintf (stderr, "error: failed to get slave name for output pseudo terminal : %s", error_str);
1092 exit(2);
1093 }
1094 else
1095 {
1096 editline_output_slave_fh = ::fopen (output_slave_name, "r+");
1097 if (editline_output_slave_fh == NULL)
1098 {
1099 SBError error;
1100 error.SetErrorToErrno();
1101 ::fprintf (stderr, "error: failed to get open slave for output pseudo terminal : %s",
1102 error.GetCString());
1103 exit(3);
1104 }
1105 ::setbuf (editline_output_slave_fh, NULL);
1106 }
1107 }
Chris Lattner24943d22010-06-08 16:52:24 +00001108
1109 // struct termios stdin_termios;
1110
1111 if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0)
1112 atexit (reset_stdin_termios);
1113
1114 ::setbuf (stdin, NULL);
1115 ::setbuf (stdout, NULL);
1116
Greg Clayton63094e02010-06-23 01:19:29 +00001117 m_debugger.SetErrorFileHandle (stderr, false);
1118 m_debugger.SetOutputFileHandle (stdout, false);
1119 m_debugger.SetInputFileHandle (stdin, true);
Jim Ingham74989e82010-08-30 19:44:40 +00001120
1121 m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor);
Chris Lattner24943d22010-06-08 16:52:24 +00001122
1123 // You have to drain anything that comes to the master side of the PTY. master_out_comm is
1124 // for that purpose. The reason you need to do this is a curious reason... editline will echo
1125 // characters to the PTY when it gets characters while el_gets is not running, and then when
1126 // you call el_gets (or el_getc) it will try to reset the terminal back to raw mode which blocks
1127 // if there are unconsumed characters in the out buffer.
1128 // However, you don't need to do anything with the characters, since editline will dump these
1129 // unconsumed characters after printing the prompt again in el_gets.
1130
Greg Claytoneecb0f32010-12-04 02:39:47 +00001131 SBCommunication master_out_comm("driver.editline");
1132 master_out_comm.SetCloseOnEOF (false);
Chris Lattner24943d22010-06-08 16:52:24 +00001133 master_out_comm.AdoptFileDesriptor(m_editline_pty.GetMasterFileDescriptor(), false);
1134 master_out_comm.SetReadThreadBytesReceivedCallback(Driver::MasterThreadBytesReceived, this);
1135
1136 if (master_out_comm.ReadThreadStart () == false)
1137 {
1138 ::fprintf (stderr, "error: failed to start master out read thread");
1139 exit(5);
1140 }
1141
Greg Clayton63094e02010-06-23 01:19:29 +00001142 SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter();
Chris Lattner24943d22010-06-08 16:52:24 +00001143
Caroline Tice4a348082011-05-02 20:41:46 +00001144 m_io_channel_ap.reset (new IOChannel(m_editline_slave_fh, editline_output_slave_fh, stdout, stderr, this));
1145
1146 SBCommunication out_comm_2("driver.editline_output");
1147 out_comm_2.SetCloseOnEOF (false);
1148 out_comm_2.AdoptFileDesriptor (editline_output_pty.GetMasterFileDescriptor(), false);
1149 out_comm_2.SetReadThreadBytesReceivedCallback (IOChannel::LibeditOutputBytesReceived, m_io_channel_ap.get());
1150
1151 if (out_comm_2.ReadThreadStart () == false)
1152 {
1153 ::fprintf (stderr, "error: failed to start libedit output read thread");
1154 exit (5);
1155 }
1156
Chris Lattner24943d22010-06-08 16:52:24 +00001157
1158 struct winsize window_size;
1159 if (isatty (STDIN_FILENO)
1160 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
1161 {
Caroline Tice6e4c5ce2010-09-04 00:03:46 +00001162 if (window_size.ws_col > 0)
Greg Clayton238c0a12010-09-18 01:14:36 +00001163 m_debugger.SetTerminalWidth (window_size.ws_col);
Chris Lattner24943d22010-06-08 16:52:24 +00001164 }
1165
1166 // Since input can be redirected by the debugger, we must insert our editline
1167 // input reader in the queue so we know when our reader should be active
1168 // and so we can receive bytes only when we are supposed to.
Greg Clayton63094e02010-06-23 01:19:29 +00001169 SBError err (m_editline_reader.Initialize (m_debugger,
1170 Driver::EditLineInputReaderCallback, // callback
Chris Lattner24943d22010-06-08 16:52:24 +00001171 this, // baton
1172 eInputReaderGranularityByte, // token_size
1173 NULL, // end token - NULL means never done
1174 NULL, // prompt - taken care of elsewhere
1175 false)); // echo input - don't need Debugger
1176 // to do this, we handle it elsewhere
1177
1178 if (err.Fail())
1179 {
1180 ::fprintf (stderr, "error: %s", err.GetCString());
1181 exit (6);
1182 }
1183
Greg Clayton63094e02010-06-23 01:19:29 +00001184 m_debugger.PushInputReader (m_editline_reader);
Chris Lattner24943d22010-06-08 16:52:24 +00001185
Greg Clayton63094e02010-06-23 01:19:29 +00001186 SBListener listener(m_debugger.GetListener());
Chris Lattner24943d22010-06-08 16:52:24 +00001187 if (listener.IsValid())
1188 {
1189
1190 listener.StartListeningForEvents (*m_io_channel_ap,
1191 IOChannel::eBroadcastBitHasUserInput |
1192 IOChannel::eBroadcastBitUserInterrupt |
1193 IOChannel::eBroadcastBitThreadShouldExit |
1194 IOChannel::eBroadcastBitThreadDidStart |
1195 IOChannel::eBroadcastBitThreadDidExit);
1196
1197 if (m_io_channel_ap->Start ())
1198 {
1199 bool iochannel_thread_exited = false;
1200
1201 listener.StartListeningForEvents (sb_interpreter.GetBroadcaster(),
Caroline Tice388ca8f2011-05-03 20:53:11 +00001202 SBCommandInterpreter::eBroadcastBitQuitCommandReceived |
1203 SBCommandInterpreter::eBroadcastBitAsynchronousOutputData |
1204 SBCommandInterpreter::eBroadcastBitAsynchronousErrorData);
Chris Lattner24943d22010-06-08 16:52:24 +00001205
1206 // Before we handle any options from the command line, we parse the
1207 // .lldbinit file in the user's home directory.
1208 SBCommandReturnObject result;
1209 sb_interpreter.SourceInitFileInHomeDirectory(result);
1210 if (GetDebugMode())
1211 {
Greg Clayton63094e02010-06-23 01:19:29 +00001212 result.PutError (m_debugger.GetErrorFileHandle());
1213 result.PutOutput (m_debugger.GetOutputFileHandle());
Chris Lattner24943d22010-06-08 16:52:24 +00001214 }
1215
1216 // Now we handle options we got from the command line
1217 char command_string[PATH_MAX * 2];
1218 const size_t num_source_command_files = GetNumSourceCommandFiles();
1219 if (num_source_command_files > 0)
1220 {
1221 for (size_t i=0; i < num_source_command_files; ++i)
1222 {
1223 const char *command_file = GetSourceCommandFileAtIndex(i);
Johnny Chen7c984242010-07-28 21:16:11 +00001224 ::snprintf (command_string, sizeof(command_string), "command source '%s'", command_file);
Greg Clayton63094e02010-06-23 01:19:29 +00001225 m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, false);
Chris Lattner24943d22010-06-08 16:52:24 +00001226 if (GetDebugMode())
1227 {
Greg Clayton63094e02010-06-23 01:19:29 +00001228 result.PutError (m_debugger.GetErrorFileHandle());
1229 result.PutOutput (m_debugger.GetOutputFileHandle());
Chris Lattner24943d22010-06-08 16:52:24 +00001230 }
1231 }
1232 }
1233
Greg Clayton4dc18922010-12-08 22:23:24 +00001234 const size_t num_args = m_option_data.m_args.size();
1235 if (num_args > 0)
Chris Lattner24943d22010-06-08 16:52:24 +00001236 {
1237 char arch_name[64];
Greg Clayton63094e02010-06-23 01:19:29 +00001238 if (m_debugger.GetDefaultArchitecture (arch_name, sizeof (arch_name)))
Greg Clayton4dc18922010-12-08 22:23:24 +00001239 ::snprintf (command_string,
1240 sizeof (command_string),
Greg Claytonabe0fed2011-04-18 08:33:37 +00001241 "target create --arch=%s '%s'",
Greg Clayton4dc18922010-12-08 22:23:24 +00001242 arch_name,
1243 m_option_data.m_args[0].c_str());
Chris Lattner24943d22010-06-08 16:52:24 +00001244 else
Greg Clayton4dc18922010-12-08 22:23:24 +00001245 ::snprintf (command_string,
1246 sizeof(command_string),
Greg Claytonabe0fed2011-04-18 08:33:37 +00001247 "target create '%s'",
Greg Clayton4dc18922010-12-08 22:23:24 +00001248 m_option_data.m_args[0].c_str());
Chris Lattner24943d22010-06-08 16:52:24 +00001249
Greg Clayton63094e02010-06-23 01:19:29 +00001250 m_debugger.HandleCommand (command_string);
Greg Clayton4dc18922010-12-08 22:23:24 +00001251
1252 if (num_args > 1)
1253 {
Greg Claytonabb33022011-11-08 02:43:13 +00001254 m_debugger.HandleCommand ("settings clear target.run-args");
Greg Clayton4dc18922010-12-08 22:23:24 +00001255 char arg_cstr[1024];
1256 for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx)
1257 {
Jim Ingham83dd2032011-09-13 23:25:31 +00001258 ::snprintf (arg_cstr,
1259 sizeof(arg_cstr),
Greg Claytonabb33022011-11-08 02:43:13 +00001260 "settings append target.run-args \"%s\"",
Jim Ingham83dd2032011-09-13 23:25:31 +00001261 m_option_data.m_args[arg_idx].c_str());
Greg Clayton4dc18922010-12-08 22:23:24 +00001262 m_debugger.HandleCommand (arg_cstr);
1263 }
1264 }
Chris Lattner24943d22010-06-08 16:52:24 +00001265 }
1266
1267 // Now that all option parsing is done, we try and parse the .lldbinit
1268 // file in the current working directory
1269 sb_interpreter.SourceInitFileInCurrentWorkingDirectory (result);
1270 if (GetDebugMode())
1271 {
Greg Clayton63094e02010-06-23 01:19:29 +00001272 result.PutError(m_debugger.GetErrorFileHandle());
1273 result.PutOutput(m_debugger.GetOutputFileHandle());
Chris Lattner24943d22010-06-08 16:52:24 +00001274 }
1275
1276 SBEvent event;
1277
1278 // Make sure the IO channel is started up before we try to tell it we
1279 // are ready for input
1280 listener.WaitForEventForBroadcasterWithType (UINT32_MAX,
1281 *m_io_channel_ap,
1282 IOChannel::eBroadcastBitThreadDidStart,
1283 event);
Jim Ingham83dd2032011-09-13 23:25:31 +00001284 // If we were asked to attach, then do that here:
1285 // I'm going to use the command string rather than directly
1286 // calling the API's because then I don't have to recode the
1287 // event handling here.
1288 if (!m_option_data.m_process_name.empty()
1289 || m_option_data.m_process_pid != LLDB_INVALID_PROCESS_ID)
1290 {
1291 std::string command_str("process attach ");
1292 if (m_option_data.m_process_pid != LLDB_INVALID_PROCESS_ID)
1293 {
1294 command_str.append("-p ");
1295 char pid_buffer[32];
1296 ::snprintf (pid_buffer, sizeof(pid_buffer), "%d", m_option_data.m_process_pid);
1297 command_str.append(pid_buffer);
1298 }
1299 else
1300 {
1301 command_str.append("-n \"");
1302 command_str.append(m_option_data.m_process_name);
1303 command_str.push_back('\"');
1304 if (m_option_data.m_wait_for)
1305 command_str.append(" -w");
1306 }
1307
1308 if (m_debugger.GetOutputFileHandle())
1309 ::fprintf (m_debugger.GetOutputFileHandle(),
1310 "Attaching to process with:\n %s\n",
1311 command_str.c_str());
1312
1313 // Force the attach to be synchronous:
1314 bool orig_async = m_debugger.GetAsync();
1315 m_debugger.SetAsync(true);
1316 m_debugger.HandleCommand(command_str.c_str());
1317 m_debugger.SetAsync(orig_async);
1318 }
1319
Chris Lattner24943d22010-06-08 16:52:24 +00001320 ReadyForCommand ();
1321
1322 bool done = false;
1323 while (!done)
1324 {
1325 listener.WaitForEvent (UINT32_MAX, event);
1326 if (event.IsValid())
1327 {
1328 if (event.GetBroadcaster().IsValid())
1329 {
1330 uint32_t event_type = event.GetType();
1331 if (event.BroadcasterMatchesRef (*m_io_channel_ap))
1332 {
1333 if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
1334 (event_type & IOChannel::eBroadcastBitThreadDidExit))
1335 {
1336 done = true;
1337 if (event_type & IOChannel::eBroadcastBitThreadDidExit)
1338 iochannel_thread_exited = true;
Chris Lattner24943d22010-06-08 16:52:24 +00001339 }
1340 else
1341 done = HandleIOEvent (event);
1342 }
Jim Inghamc8332952010-08-26 21:32:51 +00001343 else if (event.BroadcasterMatchesRef (m_debugger.GetSelectedTarget().GetProcess().GetBroadcaster()))
Chris Lattner24943d22010-06-08 16:52:24 +00001344 {
1345 HandleProcessEvent (event);
1346 }
1347 else if (event.BroadcasterMatchesRef (sb_interpreter.GetBroadcaster()))
1348 {
1349 if (event_type & SBCommandInterpreter::eBroadcastBitQuitCommandReceived)
1350 done = true;
Caroline Tice388ca8f2011-05-03 20:53:11 +00001351 else if (event_type & SBCommandInterpreter::eBroadcastBitAsynchronousErrorData)
1352 {
1353 const char *data = SBEvent::GetCStringFromEvent (event);
1354 m_io_channel_ap->ErrWrite (data, strlen(data), ASYNC);
1355 }
1356 else if (event_type & SBCommandInterpreter::eBroadcastBitAsynchronousOutputData)
1357 {
1358 const char *data = SBEvent::GetCStringFromEvent (event);
1359 m_io_channel_ap->OutWrite (data, strlen(data), ASYNC);
1360 }
Chris Lattner24943d22010-06-08 16:52:24 +00001361 }
1362 }
1363 }
1364 }
1365
1366 reset_stdin_termios ();
1367
1368 CloseIOChannelFile ();
1369
1370 if (!iochannel_thread_exited)
1371 {
Greg Claytonbef15832010-07-14 00:18:15 +00001372 event.Clear();
Chris Lattner24943d22010-06-08 16:52:24 +00001373 listener.GetNextEventForBroadcasterWithType (*m_io_channel_ap,
1374 IOChannel::eBroadcastBitThreadDidExit,
1375 event);
1376 if (!event.IsValid())
1377 {
1378 // Send end EOF to the driver file descriptor
1379 m_io_channel_ap->Stop();
1380 }
1381 }
1382
Jim Inghamdbcf98c2011-09-15 21:30:02 +00001383 SBDebugger::Destroy (m_debugger);
Chris Lattner24943d22010-06-08 16:52:24 +00001384 }
1385 }
1386}
1387
1388
1389void
1390Driver::ReadyForCommand ()
1391{
1392 if (m_waiting_for_command == false)
1393 {
1394 m_waiting_for_command = true;
1395 BroadcastEventByType (Driver::eBroadcastBitReadyForInput, true);
1396 }
1397}
1398
1399
Caroline Ticeb8314fe2010-09-09 17:45:09 +00001400void
1401sigwinch_handler (int signo)
1402{
1403 struct winsize window_size;
1404 if (isatty (STDIN_FILENO)
1405 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
1406 {
1407 if ((window_size.ws_col > 0) && (strlen (g_debugger_name) > 0))
1408 {
1409 char width_str_buffer[25];
1410 ::sprintf (width_str_buffer, "%d", window_size.ws_col);
1411 SBDebugger::SetInternalVariable ("term-width", width_str_buffer, g_debugger_name);
1412 }
1413 }
1414}
1415
Caroline Ticec4f55fe2010-11-19 20:47:54 +00001416void
1417sigint_handler (int signo)
1418{
1419 static bool g_interrupt_sent = false;
1420 if (g_driver)
1421 {
1422 if (!g_interrupt_sent)
1423 {
1424 g_interrupt_sent = true;
1425 g_driver->GetDebugger().DispatchInputInterrupt();
1426 g_interrupt_sent = false;
1427 return;
1428 }
1429 }
1430
1431 exit (signo);
1432}
1433
Chris Lattner24943d22010-06-08 16:52:24 +00001434int
Jim Inghamb2b604f2011-01-27 20:15:39 +00001435main (int argc, char const *argv[], const char *envp[])
Chris Lattner24943d22010-06-08 16:52:24 +00001436{
Chris Lattner24943d22010-06-08 16:52:24 +00001437 SBDebugger::Initialize();
1438
Greg Clayton95e33b72010-11-07 21:02:03 +00001439 SBHostOS::ThreadCreated ("<lldb.driver.main-thread>");
Chris Lattner24943d22010-06-08 16:52:24 +00001440
Greg Clayton36f63a92010-10-19 03:25:40 +00001441 signal (SIGPIPE, SIG_IGN);
Caroline Ticeb8314fe2010-09-09 17:45:09 +00001442 signal (SIGWINCH, sigwinch_handler);
Caroline Ticec4f55fe2010-11-19 20:47:54 +00001443 signal (SIGINT, sigint_handler);
Caroline Ticeb8314fe2010-09-09 17:45:09 +00001444
Greg Clayton63094e02010-06-23 01:19:29 +00001445 // Create a scope for driver so that the driver object will destroy itself
1446 // before SBDebugger::Terminate() is called.
Chris Lattner24943d22010-06-08 16:52:24 +00001447 {
Greg Clayton63094e02010-06-23 01:19:29 +00001448 Driver driver;
1449
1450 bool exit = false;
1451 SBError error (driver.ParseArgs (argc, argv, stdout, exit));
1452 if (error.Fail())
1453 {
1454 const char *error_cstr = error.GetCString ();
1455 if (error_cstr)
1456 ::fprintf (stderr, "error: %s\n", error_cstr);
1457 }
1458 else if (!exit)
1459 {
1460 driver.MainLoop ();
1461 }
Chris Lattner24943d22010-06-08 16:52:24 +00001462 }
1463
1464 SBDebugger::Terminate();
1465 return 0;
1466}