blob: 7929390e446e033a4ad3e0b61a7ce8dd96bd8d98 [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 Ingham6ae25442011-08-16 23:15:02 +000067#define LLDB_2_TO_4 LLDB_OPT_SET_2|LLDB_OPT_SET_3|LLDB_OPT_SET_4
Greg Claytonb3448432011-03-24 21:19:54 +000068static OptionDefinition g_options[] =
69{
70 { LLDB_OPT_SET_1, true , "help" , 'h', no_argument , NULL, eArgTypeNone, "Prints out the usage information for the LLDB debugger." },
71 { LLDB_OPT_SET_2, true , "version" , 'v', no_argument , NULL, eArgTypeNone, "Prints out the current version number of the LLDB debugger." },
72 { 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." },
73 { 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." },
74 { 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." },
75 { 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." },
76 { 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." },
Jim Ingham6ae25442011-08-16 23:15:02 +000077 { LLDB_2_TO_4, false, "editor" , 'e', no_argument , NULL, eArgTypeNone, "Tells the debugger to open source files using the host's \"external editor\" mechanism." },
78 { LLDB_2_TO_4, false, "no-lldbinit" , 'n', no_argument , NULL, eArgTypeNone, "Do not automatically parse any '.lldbinit' files." },
Greg Claytonb3448432011-03-24 21:19:54 +000079 { 0, false, NULL , 0 , 0 , NULL, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +000080};
81
82
83Driver::Driver () :
84 SBBroadcaster ("Driver"),
Jim Ingham558dd5b2011-08-13 00:22:20 +000085 m_debugger (SBDebugger::Create(false)),
Chris Lattner24943d22010-06-08 16:52:24 +000086 m_editline_pty (),
87 m_editline_slave_fh (NULL),
88 m_editline_reader (),
89 m_io_channel_ap (),
90 m_option_data (),
91 m_waiting_for_command (false)
92{
Greg Clayton421ca502011-05-29 04:06:55 +000093 // We want to be able to handle CTRL+D in the terminal to have it terminate
94 // certain input
95 m_debugger.SetCloseInputOnEOF (false);
Caroline Ticeb8314fe2010-09-09 17:45:09 +000096 g_debugger_name = (char *) m_debugger.GetInstanceName();
97 if (g_debugger_name == NULL)
98 g_debugger_name = (char *) "";
Caroline Ticec4f55fe2010-11-19 20:47:54 +000099 g_driver = this;
Chris Lattner24943d22010-06-08 16:52:24 +0000100}
101
102Driver::~Driver ()
103{
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000104 g_driver = NULL;
105 g_debugger_name = NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000106}
107
108void
109Driver::CloseIOChannelFile ()
110{
111 // Write and End of File sequence to the file descriptor to ensure any
112 // read functions can exit.
113 char eof_str[] = "\x04";
114 ::write (m_editline_pty.GetMasterFileDescriptor(), eof_str, strlen(eof_str));
115
116 m_editline_pty.CloseMasterFileDescriptor();
117
118 if (m_editline_slave_fh)
119 {
120 ::fclose (m_editline_slave_fh);
121 m_editline_slave_fh = NULL;
122 }
123}
124
Greg Clayton54e7afa2010-07-09 20:39:50 +0000125// This function takes INDENT, which tells how many spaces to output at the front
126// of each line; TEXT, which is the text that is to be output. It outputs the
127// text, on multiple lines if necessary, to RESULT, with INDENT spaces at the
128// front of each line. It breaks lines on spaces, tabs or newlines, shortening
129// the line if necessary to not break in the middle of a word. It assumes that
130// each output line should contain a maximum of OUTPUT_MAX_COLUMNS characters.
Chris Lattner24943d22010-06-08 16:52:24 +0000131
132void
Greg Clayton54e7afa2010-07-09 20:39:50 +0000133OutputFormattedUsageText (FILE *out, int indent, const char *text, int output_max_columns)
Chris Lattner24943d22010-06-08 16:52:24 +0000134{
135 int len = strlen (text);
136 std::string text_string (text);
Chris Lattner24943d22010-06-08 16:52:24 +0000137
138 // Force indentation to be reasonable.
139 if (indent >= output_max_columns)
140 indent = 0;
141
142 // Will it all fit on one line?
143
144 if (len + indent < output_max_columns)
145 // Output as a single line
Greg Clayton54e7afa2010-07-09 20:39:50 +0000146 fprintf (out, "%*s%s\n", indent, "", text);
Chris Lattner24943d22010-06-08 16:52:24 +0000147 else
148 {
149 // We need to break it up into multiple lines.
150 int text_width = output_max_columns - indent - 1;
151 int start = 0;
152 int end = start;
153 int final_end = len;
154 int sub_len;
155
156 while (end < final_end)
157 {
158 // Dont start the 'text' on a space, since we're already outputting the indentation.
159 while ((start < final_end) && (text[start] == ' '))
160 start++;
161
162 end = start + text_width;
163 if (end > final_end)
164 end = final_end;
165 else
166 {
167 // If we're not at the end of the text, make sure we break the line on white space.
168 while (end > start
169 && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
170 end--;
171 }
172 sub_len = end - start;
173 std::string substring = text_string.substr (start, sub_len);
Greg Clayton54e7afa2010-07-09 20:39:50 +0000174 fprintf (out, "%*s%s\n", indent, "", substring.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000175 start = end + 1;
176 }
177 }
178}
179
180void
Greg Claytonb3448432011-03-24 21:19:54 +0000181ShowUsage (FILE *out, OptionDefinition *option_table, Driver::OptionData data)
Chris Lattner24943d22010-06-08 16:52:24 +0000182{
183 uint32_t screen_width = 80;
184 uint32_t indent_level = 0;
185 const char *name = "lldb";
Jim Ingham34e9a982010-06-15 18:47:14 +0000186
Chris Lattner24943d22010-06-08 16:52:24 +0000187 fprintf (out, "\nUsage:\n\n");
188
189 indent_level += 2;
190
191
192 // First, show each usage level set of options, e.g. <cmd> [options-for-level-0]
193 // <cmd> [options-for-level-1]
194 // etc.
195
Chris Lattner24943d22010-06-08 16:52:24 +0000196 uint32_t num_options;
Jim Ingham34e9a982010-06-15 18:47:14 +0000197 uint32_t num_option_sets = 0;
198
199 for (num_options = 0; option_table[num_options].long_option != NULL; ++num_options)
Chris Lattner24943d22010-06-08 16:52:24 +0000200 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000201 uint32_t this_usage_mask = option_table[num_options].usage_mask;
202 if (this_usage_mask == LLDB_OPT_SET_ALL)
Chris Lattner24943d22010-06-08 16:52:24 +0000203 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000204 if (num_option_sets == 0)
205 num_option_sets = 1;
Chris Lattner24943d22010-06-08 16:52:24 +0000206 }
207 else
208 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000209 for (uint32_t j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++)
Jim Ingham34e9a982010-06-15 18:47:14 +0000210 {
211 if (this_usage_mask & 1 << j)
212 {
213 if (num_option_sets <= j)
214 num_option_sets = j + 1;
215 }
216 }
217 }
218 }
219
220 for (uint32_t opt_set = 0; opt_set < num_option_sets; opt_set++)
221 {
222 uint32_t opt_set_mask;
223
224 opt_set_mask = 1 << opt_set;
225
226 if (opt_set > 0)
227 fprintf (out, "\n");
Greg Clayton54e7afa2010-07-09 20:39:50 +0000228 fprintf (out, "%*s%s", indent_level, "", name);
Jim Ingham6ae25442011-08-16 23:15:02 +0000229 bool is_help_line = false;
Jim Ingham34e9a982010-06-15 18:47:14 +0000230
231 for (uint32_t i = 0; i < num_options; ++i)
232 {
233 if (option_table[i].usage_mask & opt_set_mask)
234 {
Caroline Tice4d6675c2010-10-01 19:59:14 +0000235 CommandArgumentType arg_type = option_table[i].argument_type;
Greg Claytonaa378b12011-02-20 02:15:07 +0000236 const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type);
Jim Ingham6ae25442011-08-16 23:15:02 +0000237 // This is a bit of a hack, but there's no way to say certain options don't have arguments yet...
238 // so we do it by hand here.
239 if (option_table[i].short_option == 'h')
240 is_help_line = true;
241
Jim Ingham34e9a982010-06-15 18:47:14 +0000242 if (option_table[i].required)
243 {
244 if (option_table[i].option_has_arg == required_argument)
Greg Claytonaa378b12011-02-20 02:15:07 +0000245 fprintf (out, " -%c <%s>", option_table[i].short_option, arg_name);
Jim Ingham34e9a982010-06-15 18:47:14 +0000246 else if (option_table[i].option_has_arg == optional_argument)
Greg Claytonaa378b12011-02-20 02:15:07 +0000247 fprintf (out, " -%c [<%s>]", option_table[i].short_option, arg_name);
Jim Ingham34e9a982010-06-15 18:47:14 +0000248 else
249 fprintf (out, " -%c", option_table[i].short_option);
250 }
251 else
252 {
253 if (option_table[i].option_has_arg == required_argument)
Greg Claytonaa378b12011-02-20 02:15:07 +0000254 fprintf (out, " [-%c <%s>]", option_table[i].short_option, arg_name);
Jim Ingham34e9a982010-06-15 18:47:14 +0000255 else if (option_table[i].option_has_arg == optional_argument)
Greg Claytonaa378b12011-02-20 02:15:07 +0000256 fprintf (out, " [-%c [<%s>]]", option_table[i].short_option, arg_name);
Jim Ingham34e9a982010-06-15 18:47:14 +0000257 else
258 fprintf (out, " [-%c]", option_table[i].short_option);
259 }
260 }
Chris Lattner24943d22010-06-08 16:52:24 +0000261 }
Jim Ingham6ae25442011-08-16 23:15:02 +0000262 if (!is_help_line)
263 fprintf (out, " [[--] <PROGRAM-ARG-1> [<PROGRAM_ARG-2> ...]]");
Chris Lattner24943d22010-06-08 16:52:24 +0000264 }
265
266 fprintf (out, "\n\n");
267
268 // Now print out all the detailed information about the various options: long form, short form and help text:
269 // -- long_name <argument>
270 // - short <argument>
271 // help text
272
273 // This variable is used to keep track of which options' info we've printed out, because some options can be in
274 // more than one usage level, but we only want to print the long form of its information once.
275
276 Driver::OptionData::OptionSet options_seen;
277 Driver::OptionData::OptionSet::iterator pos;
278
279 indent_level += 5;
280
Jim Ingham34e9a982010-06-15 18:47:14 +0000281 for (uint32_t i = 0; i < num_options; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000282 {
283 // Only print this option if we haven't already seen it.
284 pos = options_seen.find (option_table[i].short_option);
285 if (pos == options_seen.end())
286 {
Caroline Tice4d6675c2010-10-01 19:59:14 +0000287 CommandArgumentType arg_type = option_table[i].argument_type;
Greg Claytonaa378b12011-02-20 02:15:07 +0000288 const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type);
Caroline Tice4d6675c2010-10-01 19:59:14 +0000289
Chris Lattner24943d22010-06-08 16:52:24 +0000290 options_seen.insert (option_table[i].short_option);
Greg Clayton54e7afa2010-07-09 20:39:50 +0000291 fprintf (out, "%*s-%c ", indent_level, "", option_table[i].short_option);
Caroline Tice4d6675c2010-10-01 19:59:14 +0000292 if (arg_type != eArgTypeNone)
Greg Claytonaa378b12011-02-20 02:15:07 +0000293 fprintf (out, "<%s>", arg_name);
Chris Lattner24943d22010-06-08 16:52:24 +0000294 fprintf (out, "\n");
Greg Clayton54e7afa2010-07-09 20:39:50 +0000295 fprintf (out, "%*s--%s ", indent_level, "", option_table[i].long_option);
Caroline Tice4d6675c2010-10-01 19:59:14 +0000296 if (arg_type != eArgTypeNone)
Greg Claytonaa378b12011-02-20 02:15:07 +0000297 fprintf (out, "<%s>", arg_name);
Chris Lattner24943d22010-06-08 16:52:24 +0000298 fprintf (out, "\n");
299 indent_level += 5;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000300 OutputFormattedUsageText (out, indent_level, option_table[i].usage_text, screen_width);
Chris Lattner24943d22010-06-08 16:52:24 +0000301 indent_level -= 5;
302 fprintf (out, "\n");
303 }
304 }
305
306 indent_level -= 5;
307
Jim Inghamcf0de262011-08-16 23:57:58 +0000308 fprintf (out, "\n%*s(If you don't provide -f then the first argument will be the file to be debugged"
309 "\n%*s so '%s -- <filename> [<ARG1> [<ARG2>]]' also works."
310 "\n%*s Remember to end the options with \"--\" if any of your arguments have a \"-\" in them.)\n\n",
311 indent_level, "",
312 indent_level, "",
313 name,
314 indent_level, "");
Chris Lattner24943d22010-06-08 16:52:24 +0000315}
316
317void
Greg Claytonb3448432011-03-24 21:19:54 +0000318BuildGetOptTable (OptionDefinition *expanded_option_table, std::vector<struct option> &getopt_table,
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000319 uint32_t num_options)
Chris Lattner24943d22010-06-08 16:52:24 +0000320{
321 if (num_options == 0)
322 return;
323
324 uint32_t i;
325 uint32_t j;
326 std::bitset<256> option_seen;
327
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000328 getopt_table.resize (num_options + 1);
329
Chris Lattner24943d22010-06-08 16:52:24 +0000330 for (i = 0, j = 0; i < num_options; ++i)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000331 {
Chris Lattner24943d22010-06-08 16:52:24 +0000332 char short_opt = expanded_option_table[i].short_option;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000333
Chris Lattner24943d22010-06-08 16:52:24 +0000334 if (option_seen.test(short_opt) == false)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000335 {
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000336 getopt_table[j].name = expanded_option_table[i].long_option;
337 getopt_table[j].has_arg = expanded_option_table[i].option_has_arg;
338 getopt_table[j].flag = NULL;
339 getopt_table[j].val = expanded_option_table[i].short_option;
Chris Lattner24943d22010-06-08 16:52:24 +0000340 option_seen.set(short_opt);
341 ++j;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000342 }
343 }
Chris Lattner24943d22010-06-08 16:52:24 +0000344
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000345 getopt_table[j].name = NULL;
346 getopt_table[j].has_arg = 0;
347 getopt_table[j].flag = NULL;
348 getopt_table[j].val = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000349
350}
351
Greg Clayton63094e02010-06-23 01:19:29 +0000352Driver::OptionData::OptionData () :
Greg Clayton4dc18922010-12-08 22:23:24 +0000353 m_args(),
Greg Clayton63094e02010-06-23 01:19:29 +0000354 m_script_lang (lldb::eScriptLanguageDefault),
Greg Clayton54e7afa2010-07-09 20:39:50 +0000355 m_crash_log (),
Greg Clayton63094e02010-06-23 01:19:29 +0000356 m_source_command_files (),
357 m_debug_mode (false),
Greg Clayton54e7afa2010-07-09 20:39:50 +0000358 m_print_version (false),
Greg Clayton63094e02010-06-23 01:19:29 +0000359 m_print_help (false),
Stephen Wilsondbeb3e12011-04-11 19:41:40 +0000360 m_use_external_editor(false),
361 m_seen_options()
Chris Lattner24943d22010-06-08 16:52:24 +0000362{
Greg Clayton63094e02010-06-23 01:19:29 +0000363}
364
365Driver::OptionData::~OptionData ()
366{
367}
368
369void
370Driver::OptionData::Clear ()
371{
Greg Clayton4dc18922010-12-08 22:23:24 +0000372 m_args.clear ();
Greg Clayton63094e02010-06-23 01:19:29 +0000373 m_script_lang = lldb::eScriptLanguageDefault;
374 m_source_command_files.clear ();
375 m_debug_mode = false;
376 m_print_help = false;
377 m_print_version = false;
Jim Ingham74989e82010-08-30 19:44:40 +0000378 m_use_external_editor = false;
Greg Clayton63094e02010-06-23 01:19:29 +0000379}
380
381void
382Driver::ResetOptionValues ()
383{
384 m_option_data.Clear ();
385}
386
387const char *
388Driver::GetFilename() const
389{
Greg Clayton4dc18922010-12-08 22:23:24 +0000390 if (m_option_data.m_args.empty())
Greg Clayton63094e02010-06-23 01:19:29 +0000391 return NULL;
Greg Clayton4dc18922010-12-08 22:23:24 +0000392 return m_option_data.m_args.front().c_str();
Greg Clayton63094e02010-06-23 01:19:29 +0000393}
394
395const char *
396Driver::GetCrashLogFilename() const
397{
398 if (m_option_data.m_crash_log.empty())
399 return NULL;
400 return m_option_data.m_crash_log.c_str();
401}
402
403lldb::ScriptLanguage
404Driver::GetScriptLanguage() const
405{
406 return m_option_data.m_script_lang;
407}
408
409size_t
410Driver::GetNumSourceCommandFiles () const
411{
412 return m_option_data.m_source_command_files.size();
413}
414
415const char *
416Driver::GetSourceCommandFileAtIndex (uint32_t idx) const
417{
418 if (idx < m_option_data.m_source_command_files.size())
419 return m_option_data.m_source_command_files[idx].c_str();
420 return NULL;
421}
422
423bool
424Driver::GetDebugMode() const
425{
426 return m_option_data.m_debug_mode;
427}
428
429
430// Check the arguments that were passed to this program to make sure they are valid and to get their
431// argument values (if any). Return a boolean value indicating whether or not to start up the full
432// debugger (i.e. the Command Interpreter) or not. Return FALSE if the arguments were invalid OR
433// if the user only wanted help or version information.
434
435SBError
436Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exit)
437{
438 ResetOptionValues ();
439
440 SBCommandReturnObject result;
441
Chris Lattner24943d22010-06-08 16:52:24 +0000442 SBError error;
443 std::string option_string;
444 struct option *long_options = NULL;
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000445 std::vector<struct option> long_options_vector;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000446 uint32_t num_options;
Chris Lattner24943d22010-06-08 16:52:24 +0000447
Greg Clayton54e7afa2010-07-09 20:39:50 +0000448 for (num_options = 0; g_options[num_options].long_option != NULL; ++num_options)
449 /* Do Nothing. */;
Chris Lattner24943d22010-06-08 16:52:24 +0000450
451 if (num_options == 0)
452 {
453 if (argc > 1)
454 error.SetErrorStringWithFormat ("invalid number of options");
455 return error;
456 }
457
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000458 BuildGetOptTable (g_options, long_options_vector, num_options);
Chris Lattner24943d22010-06-08 16:52:24 +0000459
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000460 if (long_options_vector.empty())
461 long_options = NULL;
462 else
463 long_options = &long_options_vector.front();
Chris Lattner24943d22010-06-08 16:52:24 +0000464
465 if (long_options == NULL)
466 {
467 error.SetErrorStringWithFormat ("invalid long options");
468 return error;
469 }
470
471 // Build the option_string argument for call to getopt_long.
472
473 for (int i = 0; long_options[i].name != NULL; ++i)
474 {
475 if (long_options[i].flag == NULL)
476 {
477 option_string.push_back ((char) long_options[i].val);
478 switch (long_options[i].has_arg)
479 {
480 default:
481 case no_argument:
482 break;
483 case required_argument:
484 option_string.push_back (':');
485 break;
486 case optional_argument:
487 option_string.append ("::");
488 break;
489 }
490 }
491 }
492
Jim Ingham558dd5b2011-08-13 00:22:20 +0000493 // This is kind of a pain, but since we make the debugger in the Driver's constructor, we can't
494 // know at that point whether we should read in init files yet. So we don't read them in in the
495 // Driver constructor, then set the flags back to "read them in" here, and then if we see the
496 // "-n" flag, we'll turn it off again. Finally we have to read them in by hand later in the
497 // main loop.
498
499 m_debugger.SkipLLDBInitFiles (false);
500 m_debugger.SkipAppInitFiles (false);
501
Chris Lattner24943d22010-06-08 16:52:24 +0000502 // Prepare for & make calls to getopt_long.
Eli Friedmanef2bc872010-06-13 19:18:49 +0000503#if __GLIBC__
504 optind = 0;
505#else
Chris Lattner24943d22010-06-08 16:52:24 +0000506 optreset = 1;
507 optind = 1;
Eli Friedmanef2bc872010-06-13 19:18:49 +0000508#endif
Chris Lattner24943d22010-06-08 16:52:24 +0000509 int val;
510 while (1)
511 {
512 int long_options_index = -1;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000513 val = ::getopt_long (argc, const_cast<char **>(argv), option_string.c_str(), long_options, &long_options_index);
Chris Lattner24943d22010-06-08 16:52:24 +0000514
515 if (val == -1)
516 break;
517 else if (val == '?')
518 {
Greg Clayton63094e02010-06-23 01:19:29 +0000519 m_option_data.m_print_help = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000520 error.SetErrorStringWithFormat ("unknown or ambiguous option");
521 break;
522 }
523 else if (val == 0)
524 continue;
525 else
526 {
Greg Clayton63094e02010-06-23 01:19:29 +0000527 m_option_data.m_seen_options.insert ((char) val);
Chris Lattner24943d22010-06-08 16:52:24 +0000528 if (long_options_index == -1)
529 {
530 for (int i = 0;
531 long_options[i].name || long_options[i].has_arg || long_options[i].flag || long_options[i].val;
532 ++i)
533 {
534 if (long_options[i].val == val)
535 {
536 long_options_index = i;
537 break;
538 }
539 }
540 }
541
542 if (long_options_index >= 0)
543 {
Greg Clayton63094e02010-06-23 01:19:29 +0000544 const char short_option = (char) g_options[long_options_index].short_option;
545
546 switch (short_option)
547 {
548 case 'h':
549 m_option_data.m_print_help = true;
550 break;
551
552 case 'v':
553 m_option_data.m_print_version = true;
554 break;
555
556 case 'c':
557 m_option_data.m_crash_log = optarg;
558 break;
Greg Clayton887aa282010-10-11 01:05:37 +0000559
Jim Ingham74989e82010-08-30 19:44:40 +0000560 case 'e':
561 m_option_data.m_use_external_editor = true;
562 break;
Greg Clayton887aa282010-10-11 01:05:37 +0000563
564 case 'n':
565 m_debugger.SkipLLDBInitFiles (true);
Jim Ingham558dd5b2011-08-13 00:22:20 +0000566 m_debugger.SkipAppInitFiles (true);
Greg Clayton887aa282010-10-11 01:05:37 +0000567 break;
568
Greg Clayton63094e02010-06-23 01:19:29 +0000569 case 'f':
570 {
571 SBFileSpec file(optarg);
572 if (file.Exists())
Greg Clayton4dc18922010-12-08 22:23:24 +0000573 {
574 m_option_data.m_args.push_back (optarg);
575 }
Caroline Ticeeddffe92010-09-10 04:48:55 +0000576 else if (file.ResolveExecutableLocation())
577 {
578 char path[PATH_MAX];
Johnny Chenee6e7902011-08-10 22:06:24 +0000579 file.GetPath (path, sizeof(path));
Greg Clayton4dc18922010-12-08 22:23:24 +0000580 m_option_data.m_args.push_back (path);
Caroline Ticeeddffe92010-09-10 04:48:55 +0000581 }
Greg Clayton63094e02010-06-23 01:19:29 +0000582 else
583 error.SetErrorStringWithFormat("file specified in --file (-f) option doesn't exist: '%s'", optarg);
584 }
585 break;
586
587 case 'a':
588 if (!m_debugger.SetDefaultArchitecture (optarg))
589 error.SetErrorStringWithFormat("invalid architecture in the -a or --arch option: '%s'", optarg);
590 break;
591
592 case 'l':
593 m_option_data.m_script_lang = m_debugger.GetScriptingLanguage (optarg);
594 break;
595
596 case 'd':
597 m_option_data.m_debug_mode = true;
598 break;
599
600 case 's':
601 {
602 SBFileSpec file(optarg);
603 if (file.Exists())
604 m_option_data.m_source_command_files.push_back (optarg);
Caroline Ticeeddffe92010-09-10 04:48:55 +0000605 else if (file.ResolveExecutableLocation())
606 {
607 char final_path[PATH_MAX];
Johnny Chenee6e7902011-08-10 22:06:24 +0000608 file.GetPath (final_path, sizeof(final_path));
Caroline Ticeeddffe92010-09-10 04:48:55 +0000609 std::string path_str (final_path);
610 m_option_data.m_source_command_files.push_back (path_str);
611 }
Greg Clayton63094e02010-06-23 01:19:29 +0000612 else
613 error.SetErrorStringWithFormat("file specified in --source (-s) option doesn't exist: '%s'", optarg);
614 }
615 break;
616
617 default:
618 m_option_data.m_print_help = true;
619 error.SetErrorStringWithFormat ("unrecognized option %c", short_option);
620 break;
621 }
Chris Lattner24943d22010-06-08 16:52:24 +0000622 }
623 else
624 {
625 error.SetErrorStringWithFormat ("invalid option with value %i", val);
626 }
627 if (error.Fail())
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000628 {
Greg Clayton63094e02010-06-23 01:19:29 +0000629 return error;
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000630 }
Chris Lattner24943d22010-06-08 16:52:24 +0000631 }
632 }
Jim Ingham34e9a982010-06-15 18:47:14 +0000633
Greg Clayton63094e02010-06-23 01:19:29 +0000634 if (error.Fail() || m_option_data.m_print_help)
Chris Lattner24943d22010-06-08 16:52:24 +0000635 {
636 ShowUsage (out_fh, g_options, m_option_data);
Greg Clayton9caa9462010-10-11 01:13:37 +0000637 exit = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000638 }
639 else if (m_option_data.m_print_version)
640 {
Greg Clayton63094e02010-06-23 01:19:29 +0000641 ::fprintf (out_fh, "%s\n", m_debugger.GetVersionString());
642 exit = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000643 }
644 else if (! m_option_data.m_crash_log.empty())
645 {
646 // Handle crash log stuff here.
647 }
648 else
649 {
Greg Clayton4dc18922010-12-08 22:23:24 +0000650 // Any arguments that are left over after option parsing are for
651 // the program. If a file was specified with -f then the filename
652 // is already in the m_option_data.m_args array, and any remaining args
653 // are arguments for the inferior program. If no file was specified with
654 // -f, then what is left is the program name followed by any arguments.
655
656 // Skip any options we consumed with getopt_long
657 argc -= optind;
658 argv += optind;
659
660 if (argc > 0)
661 {
662 for (int arg_idx=0; arg_idx<argc; ++arg_idx)
663 {
664 const char *arg = argv[arg_idx];
665 if (arg)
666 m_option_data.m_args.push_back (arg);
667 }
668 }
669
Chris Lattner24943d22010-06-08 16:52:24 +0000670 }
671
Greg Clayton63094e02010-06-23 01:19:29 +0000672 return error;
Chris Lattner24943d22010-06-08 16:52:24 +0000673}
674
Caroline Tice757500e2010-09-29 18:35:42 +0000675size_t
Chris Lattner24943d22010-06-08 16:52:24 +0000676Driver::GetProcessSTDOUT ()
677{
678 // The process has stuff waiting for stdout; get it and write it out to the appropriate place.
679 char stdio_buffer[1024];
680 size_t len;
Caroline Tice757500e2010-09-29 18:35:42 +0000681 size_t total_bytes = 0;
Jim Inghamc8332952010-08-26 21:32:51 +0000682 while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0)
Caroline Tice757500e2010-09-29 18:35:42 +0000683 {
Caroline Tice4a348082011-05-02 20:41:46 +0000684 m_io_channel_ap->OutWrite (stdio_buffer, len, ASYNC);
Caroline Tice757500e2010-09-29 18:35:42 +0000685 total_bytes += len;
686 }
687 return total_bytes;
Chris Lattner24943d22010-06-08 16:52:24 +0000688}
689
Caroline Tice757500e2010-09-29 18:35:42 +0000690size_t
Chris Lattner24943d22010-06-08 16:52:24 +0000691Driver::GetProcessSTDERR ()
692{
693 // The process has stuff waiting for stderr; get it and write it out to the appropriate place.
694 char stdio_buffer[1024];
695 size_t len;
Caroline Tice757500e2010-09-29 18:35:42 +0000696 size_t total_bytes = 0;
Jim Inghamc8332952010-08-26 21:32:51 +0000697 while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0)
Caroline Tice757500e2010-09-29 18:35:42 +0000698 {
Caroline Tice4a348082011-05-02 20:41:46 +0000699 m_io_channel_ap->ErrWrite (stdio_buffer, len, ASYNC);
Caroline Tice757500e2010-09-29 18:35:42 +0000700 total_bytes += len;
701 }
702 return total_bytes;
Chris Lattner24943d22010-06-08 16:52:24 +0000703}
704
705void
Jim Inghamc8332952010-08-26 21:32:51 +0000706Driver::UpdateSelectedThread ()
Chris Lattner24943d22010-06-08 16:52:24 +0000707{
708 using namespace lldb;
Jim Inghamc8332952010-08-26 21:32:51 +0000709 SBProcess process(m_debugger.GetSelectedTarget().GetProcess());
Chris Lattner24943d22010-06-08 16:52:24 +0000710 if (process.IsValid())
711 {
Jim Inghamc8332952010-08-26 21:32:51 +0000712 SBThread curr_thread (process.GetSelectedThread());
Chris Lattner24943d22010-06-08 16:52:24 +0000713 SBThread thread;
714 StopReason curr_thread_stop_reason = eStopReasonInvalid;
715 curr_thread_stop_reason = curr_thread.GetStopReason();
716
717 if (!curr_thread.IsValid() ||
718 curr_thread_stop_reason == eStopReasonInvalid ||
719 curr_thread_stop_reason == eStopReasonNone)
720 {
721 // Prefer a thread that has just completed its plan over another thread as current thread.
722 SBThread plan_thread;
723 SBThread other_thread;
724 const size_t num_threads = process.GetNumThreads();
725 size_t i;
726 for (i = 0; i < num_threads; ++i)
727 {
728 thread = process.GetThreadAtIndex(i);
729 StopReason thread_stop_reason = thread.GetStopReason();
730 switch (thread_stop_reason)
731 {
732 default:
733 case eStopReasonInvalid:
734 case eStopReasonNone:
735 break;
736
737 case eStopReasonTrace:
738 case eStopReasonBreakpoint:
739 case eStopReasonWatchpoint:
740 case eStopReasonSignal:
741 case eStopReasonException:
742 if (!other_thread.IsValid())
743 other_thread = thread;
744 break;
745 case eStopReasonPlanComplete:
746 if (!plan_thread.IsValid())
747 plan_thread = thread;
748 break;
749 }
750 }
751 if (plan_thread.IsValid())
Jim Inghamc8332952010-08-26 21:32:51 +0000752 process.SetSelectedThread (plan_thread);
Chris Lattner24943d22010-06-08 16:52:24 +0000753 else if (other_thread.IsValid())
Jim Inghamc8332952010-08-26 21:32:51 +0000754 process.SetSelectedThread (other_thread);
Chris Lattner24943d22010-06-08 16:52:24 +0000755 else
756 {
757 if (curr_thread.IsValid())
758 thread = curr_thread;
759 else
760 thread = process.GetThreadAtIndex(0);
761
762 if (thread.IsValid())
Jim Inghamc8332952010-08-26 21:32:51 +0000763 process.SetSelectedThread (thread);
Chris Lattner24943d22010-06-08 16:52:24 +0000764 }
765 }
766 }
767}
768
769
770// This function handles events that were broadcast by the process.
771void
772Driver::HandleProcessEvent (const SBEvent &event)
773{
774 using namespace lldb;
775 const uint32_t event_type = event.GetType();
776
777 if (event_type & SBProcess::eBroadcastBitSTDOUT)
778 {
779 // The process has stdout available, get it and write it out to the
780 // appropriate place.
Caroline Tice4a348082011-05-02 20:41:46 +0000781 GetProcessSTDOUT ();
Chris Lattner24943d22010-06-08 16:52:24 +0000782 }
783 else if (event_type & SBProcess::eBroadcastBitSTDERR)
784 {
785 // The process has stderr available, get it and write it out to the
786 // appropriate place.
Caroline Tice4a348082011-05-02 20:41:46 +0000787 GetProcessSTDERR ();
Chris Lattner24943d22010-06-08 16:52:24 +0000788 }
789 else if (event_type & SBProcess::eBroadcastBitStateChanged)
790 {
791 // Drain all stout and stderr so we don't see any output come after
792 // we print our prompts
Caroline Tice4a348082011-05-02 20:41:46 +0000793 GetProcessSTDOUT ();
794 GetProcessSTDERR ();
Chris Lattner24943d22010-06-08 16:52:24 +0000795 // Something changed in the process; get the event and report the process's current status and location to
796 // the user.
797 StateType event_state = SBProcess::GetStateFromEvent (event);
798 if (event_state == eStateInvalid)
799 return;
800
801 SBProcess process (SBProcess::GetProcessFromEvent (event));
802 assert (process.IsValid());
803
804 switch (event_state)
805 {
806 case eStateInvalid:
807 case eStateUnloaded:
Greg Claytone71e2582011-02-04 01:58:07 +0000808 case eStateConnected:
Chris Lattner24943d22010-06-08 16:52:24 +0000809 case eStateAttaching:
810 case eStateLaunching:
811 case eStateStepping:
812 case eStateDetached:
813 {
814 char message[1024];
815 int message_len = ::snprintf (message, sizeof(message), "Process %d %s\n", process.GetProcessID(),
Greg Clayton63094e02010-06-23 01:19:29 +0000816 m_debugger.StateAsCString (event_state));
Caroline Tice4a348082011-05-02 20:41:46 +0000817 m_io_channel_ap->OutWrite(message, message_len, ASYNC);
Chris Lattner24943d22010-06-08 16:52:24 +0000818 }
819 break;
820
821 case eStateRunning:
822 // Don't be chatty when we run...
823 break;
824
825 case eStateExited:
Caroline Tice757500e2010-09-29 18:35:42 +0000826 {
827 SBCommandReturnObject result;
828 m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
Caroline Tice4a348082011-05-02 20:41:46 +0000829 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize(), ASYNC);
830 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize(), ASYNC);
Caroline Tice757500e2010-09-29 18:35:42 +0000831 }
Chris Lattner24943d22010-06-08 16:52:24 +0000832 break;
833
834 case eStateStopped:
835 case eStateCrashed:
836 case eStateSuspended:
837 // Make sure the program hasn't been auto-restarted:
838 if (SBProcess::GetRestartedFromEvent (event))
839 {
840 // FIXME: Do we want to report this, or would that just be annoyingly chatty?
841 char message[1024];
842 int message_len = ::snprintf (message, sizeof(message), "Process %d stopped and was programmatically restarted.\n",
843 process.GetProcessID());
Caroline Tice4a348082011-05-02 20:41:46 +0000844 m_io_channel_ap->OutWrite(message, message_len, ASYNC);
Chris Lattner24943d22010-06-08 16:52:24 +0000845 }
846 else
847 {
Caroline Tice757500e2010-09-29 18:35:42 +0000848 SBCommandReturnObject result;
Jim Inghamc8332952010-08-26 21:32:51 +0000849 UpdateSelectedThread ();
Caroline Tice757500e2010-09-29 18:35:42 +0000850 m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
Caroline Tice4a348082011-05-02 20:41:46 +0000851 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize(), ASYNC);
852 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize(), ASYNC);
Chris Lattner24943d22010-06-08 16:52:24 +0000853 }
854 break;
855 }
856 }
857}
858
859// This function handles events broadcast by the IOChannel (HasInput, UserInterrupt, or ThreadShouldExit).
860
861bool
862Driver::HandleIOEvent (const SBEvent &event)
863{
864 bool quit = false;
865
866 const uint32_t event_type = event.GetType();
867
868 if (event_type & IOChannel::eBroadcastBitHasUserInput)
869 {
870 // We got some input (i.e. a command string) from the user; pass it off to the command interpreter for
871 // handling.
872
873 const char *command_string = SBEvent::GetCStringFromEvent(event);
874 if (command_string == NULL)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000875 command_string = "";
Chris Lattner24943d22010-06-08 16:52:24 +0000876 SBCommandReturnObject result;
Jim Ingham2e8cb8a2011-02-19 02:53:09 +0000877
Caroline Tice845d6da2011-05-16 19:20:50 +0000878 // We don't want the result to bypass the OutWrite function in IOChannel, as this can result in odd
879 // output orderings and problems with the prompt.
Jim Ingham2e8cb8a2011-02-19 02:53:09 +0000880 m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, true);
881
Caroline Tice845d6da2011-05-16 19:20:50 +0000882 if (result.GetOutputSize() > 0)
883 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize(), NO_ASYNC);
884
885 if (result.GetErrorSize() > 0)
886 m_io_channel_ap->OutWrite (result.GetError(), result.GetErrorSize(), NO_ASYNC);
887
Chris Lattner24943d22010-06-08 16:52:24 +0000888 // We are done getting and running our command, we can now clear the
889 // m_waiting_for_command so we can get another one.
890 m_waiting_for_command = false;
891
892 // If our editline input reader is active, it means another input reader
893 // got pushed onto the input reader and caused us to become deactivated.
894 // When the input reader above us gets popped, we will get re-activated
895 // and our prompt will refresh in our callback
896 if (m_editline_reader.IsActive())
897 {
898 ReadyForCommand ();
899 }
900 }
901 else if (event_type & IOChannel::eBroadcastBitUserInterrupt)
902 {
903 // This is here to handle control-c interrupts from the user. It has not yet really been implemented.
904 // TO BE DONE: PROPERLY HANDLE CONTROL-C FROM USER
905 //m_io_channel_ap->CancelInput();
906 // Anything else? Send Interrupt to process?
907 }
908 else if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
909 (event_type & IOChannel::eBroadcastBitThreadDidExit))
910 {
911 // If the IOChannel thread is trying to go away, then it is definitely
912 // time to end the debugging session.
913 quit = true;
914 }
915
916 return quit;
917}
918
Chris Lattner24943d22010-06-08 16:52:24 +0000919void
920Driver::MasterThreadBytesReceived (void *baton, const void *src, size_t src_len)
921{
922 Driver *driver = (Driver*)baton;
923 driver->GetFromMaster ((const char *)src, src_len);
924}
925
926void
927Driver::GetFromMaster (const char *src, size_t src_len)
928{
929 // Echo the characters back to the Debugger's stdout, that way if you
930 // type characters while a command is running, you'll see what you've typed.
Greg Clayton63094e02010-06-23 01:19:29 +0000931 FILE *out_fh = m_debugger.GetOutputFileHandle();
Chris Lattner24943d22010-06-08 16:52:24 +0000932 if (out_fh)
933 ::fwrite (src, 1, src_len, out_fh);
934}
935
936size_t
937Driver::EditLineInputReaderCallback
938(
939 void *baton,
940 SBInputReader *reader,
941 InputReaderAction notification,
942 const char *bytes,
943 size_t bytes_len
944)
945{
946 Driver *driver = (Driver *)baton;
947
948 switch (notification)
949 {
950 case eInputReaderActivate:
951 break;
952
953 case eInputReaderReactivate:
954 driver->ReadyForCommand();
955 break;
956
957 case eInputReaderDeactivate:
958 break;
Caroline Tice4a348082011-05-02 20:41:46 +0000959
960 case eInputReaderAsynchronousOutputWritten:
961 if (driver->m_io_channel_ap.get() != NULL)
962 driver->m_io_channel_ap->RefreshPrompt();
963 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000964
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000965 case eInputReaderInterrupt:
966 if (driver->m_io_channel_ap.get() != NULL)
967 {
Caroline Tice4a348082011-05-02 20:41:46 +0000968 driver->m_io_channel_ap->OutWrite ("^C\n", 3, NO_ASYNC);
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000969 driver->m_io_channel_ap->RefreshPrompt();
970 }
971 break;
972
973 case eInputReaderEndOfFile:
974 if (driver->m_io_channel_ap.get() != NULL)
975 {
Caroline Tice4a348082011-05-02 20:41:46 +0000976 driver->m_io_channel_ap->OutWrite ("^D\n", 3, NO_ASYNC);
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000977 driver->m_io_channel_ap->RefreshPrompt ();
978 }
979 write (driver->m_editline_pty.GetMasterFileDescriptor(), "quit\n", 5);
980 break;
981
Chris Lattner24943d22010-06-08 16:52:24 +0000982 case eInputReaderGotToken:
983 write (driver->m_editline_pty.GetMasterFileDescriptor(), bytes, bytes_len);
984 break;
985
986 case eInputReaderDone:
987 break;
988 }
989 return bytes_len;
990}
991
992void
993Driver::MainLoop ()
994{
995 char error_str[1024];
996 if (m_editline_pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, error_str, sizeof(error_str)) == false)
997 {
998 ::fprintf (stderr, "error: failed to open driver pseudo terminal : %s", error_str);
999 exit(1);
1000 }
1001 else
1002 {
1003 const char *driver_slave_name = m_editline_pty.GetSlaveName (error_str, sizeof(error_str));
1004 if (driver_slave_name == NULL)
1005 {
1006 ::fprintf (stderr, "error: failed to get slave name for driver pseudo terminal : %s", error_str);
1007 exit(2);
1008 }
1009 else
1010 {
1011 m_editline_slave_fh = ::fopen (driver_slave_name, "r+");
1012 if (m_editline_slave_fh == NULL)
1013 {
1014 SBError error;
1015 error.SetErrorToErrno();
1016 ::fprintf (stderr, "error: failed to get open slave for driver pseudo terminal : %s",
1017 error.GetCString());
1018 exit(3);
1019 }
1020
1021 ::setbuf (m_editline_slave_fh, NULL);
1022 }
1023 }
1024
Caroline Tice4a348082011-05-02 20:41:46 +00001025 lldb_utility::PseudoTerminal editline_output_pty;
1026 FILE *editline_output_slave_fh = NULL;
1027
1028 if (editline_output_pty.OpenFirstAvailableMaster (O_RDWR|O_NOCTTY, error_str, sizeof (error_str)) == false)
1029 {
1030 ::fprintf (stderr, "error: failed to open output pseudo terminal : %s", error_str);
1031 exit(1);
1032 }
1033 else
1034 {
1035 const char *output_slave_name = editline_output_pty.GetSlaveName (error_str, sizeof(error_str));
1036 if (output_slave_name == NULL)
1037 {
1038 ::fprintf (stderr, "error: failed to get slave name for output pseudo terminal : %s", error_str);
1039 exit(2);
1040 }
1041 else
1042 {
1043 editline_output_slave_fh = ::fopen (output_slave_name, "r+");
1044 if (editline_output_slave_fh == NULL)
1045 {
1046 SBError error;
1047 error.SetErrorToErrno();
1048 ::fprintf (stderr, "error: failed to get open slave for output pseudo terminal : %s",
1049 error.GetCString());
1050 exit(3);
1051 }
1052 ::setbuf (editline_output_slave_fh, NULL);
1053 }
1054 }
Chris Lattner24943d22010-06-08 16:52:24 +00001055
1056 // struct termios stdin_termios;
1057
1058 if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0)
1059 atexit (reset_stdin_termios);
1060
1061 ::setbuf (stdin, NULL);
1062 ::setbuf (stdout, NULL);
1063
Greg Clayton63094e02010-06-23 01:19:29 +00001064 m_debugger.SetErrorFileHandle (stderr, false);
1065 m_debugger.SetOutputFileHandle (stdout, false);
1066 m_debugger.SetInputFileHandle (stdin, true);
Jim Ingham74989e82010-08-30 19:44:40 +00001067
1068 m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor);
Chris Lattner24943d22010-06-08 16:52:24 +00001069
1070 // You have to drain anything that comes to the master side of the PTY. master_out_comm is
1071 // for that purpose. The reason you need to do this is a curious reason... editline will echo
1072 // characters to the PTY when it gets characters while el_gets is not running, and then when
1073 // you call el_gets (or el_getc) it will try to reset the terminal back to raw mode which blocks
1074 // if there are unconsumed characters in the out buffer.
1075 // However, you don't need to do anything with the characters, since editline will dump these
1076 // unconsumed characters after printing the prompt again in el_gets.
1077
Greg Claytoneecb0f32010-12-04 02:39:47 +00001078 SBCommunication master_out_comm("driver.editline");
1079 master_out_comm.SetCloseOnEOF (false);
Chris Lattner24943d22010-06-08 16:52:24 +00001080 master_out_comm.AdoptFileDesriptor(m_editline_pty.GetMasterFileDescriptor(), false);
1081 master_out_comm.SetReadThreadBytesReceivedCallback(Driver::MasterThreadBytesReceived, this);
1082
1083 if (master_out_comm.ReadThreadStart () == false)
1084 {
1085 ::fprintf (stderr, "error: failed to start master out read thread");
1086 exit(5);
1087 }
1088
Greg Clayton63094e02010-06-23 01:19:29 +00001089 SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter();
Chris Lattner24943d22010-06-08 16:52:24 +00001090
Caroline Tice4a348082011-05-02 20:41:46 +00001091 m_io_channel_ap.reset (new IOChannel(m_editline_slave_fh, editline_output_slave_fh, stdout, stderr, this));
1092
1093 SBCommunication out_comm_2("driver.editline_output");
1094 out_comm_2.SetCloseOnEOF (false);
1095 out_comm_2.AdoptFileDesriptor (editline_output_pty.GetMasterFileDescriptor(), false);
1096 out_comm_2.SetReadThreadBytesReceivedCallback (IOChannel::LibeditOutputBytesReceived, m_io_channel_ap.get());
1097
1098 if (out_comm_2.ReadThreadStart () == false)
1099 {
1100 ::fprintf (stderr, "error: failed to start libedit output read thread");
1101 exit (5);
1102 }
1103
Chris Lattner24943d22010-06-08 16:52:24 +00001104
1105 struct winsize window_size;
1106 if (isatty (STDIN_FILENO)
1107 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
1108 {
Caroline Tice6e4c5ce2010-09-04 00:03:46 +00001109 if (window_size.ws_col > 0)
Greg Clayton238c0a12010-09-18 01:14:36 +00001110 m_debugger.SetTerminalWidth (window_size.ws_col);
Chris Lattner24943d22010-06-08 16:52:24 +00001111 }
1112
1113 // Since input can be redirected by the debugger, we must insert our editline
1114 // input reader in the queue so we know when our reader should be active
1115 // and so we can receive bytes only when we are supposed to.
Greg Clayton63094e02010-06-23 01:19:29 +00001116 SBError err (m_editline_reader.Initialize (m_debugger,
1117 Driver::EditLineInputReaderCallback, // callback
Chris Lattner24943d22010-06-08 16:52:24 +00001118 this, // baton
1119 eInputReaderGranularityByte, // token_size
1120 NULL, // end token - NULL means never done
1121 NULL, // prompt - taken care of elsewhere
1122 false)); // echo input - don't need Debugger
1123 // to do this, we handle it elsewhere
1124
1125 if (err.Fail())
1126 {
1127 ::fprintf (stderr, "error: %s", err.GetCString());
1128 exit (6);
1129 }
1130
Greg Clayton63094e02010-06-23 01:19:29 +00001131 m_debugger.PushInputReader (m_editline_reader);
Chris Lattner24943d22010-06-08 16:52:24 +00001132
Greg Clayton63094e02010-06-23 01:19:29 +00001133 SBListener listener(m_debugger.GetListener());
Chris Lattner24943d22010-06-08 16:52:24 +00001134 if (listener.IsValid())
1135 {
1136
1137 listener.StartListeningForEvents (*m_io_channel_ap,
1138 IOChannel::eBroadcastBitHasUserInput |
1139 IOChannel::eBroadcastBitUserInterrupt |
1140 IOChannel::eBroadcastBitThreadShouldExit |
1141 IOChannel::eBroadcastBitThreadDidStart |
1142 IOChannel::eBroadcastBitThreadDidExit);
1143
1144 if (m_io_channel_ap->Start ())
1145 {
1146 bool iochannel_thread_exited = false;
1147
1148 listener.StartListeningForEvents (sb_interpreter.GetBroadcaster(),
Caroline Tice388ca8f2011-05-03 20:53:11 +00001149 SBCommandInterpreter::eBroadcastBitQuitCommandReceived |
1150 SBCommandInterpreter::eBroadcastBitAsynchronousOutputData |
1151 SBCommandInterpreter::eBroadcastBitAsynchronousErrorData);
Chris Lattner24943d22010-06-08 16:52:24 +00001152
1153 // Before we handle any options from the command line, we parse the
1154 // .lldbinit file in the user's home directory.
1155 SBCommandReturnObject result;
1156 sb_interpreter.SourceInitFileInHomeDirectory(result);
1157 if (GetDebugMode())
1158 {
Greg Clayton63094e02010-06-23 01:19:29 +00001159 result.PutError (m_debugger.GetErrorFileHandle());
1160 result.PutOutput (m_debugger.GetOutputFileHandle());
Chris Lattner24943d22010-06-08 16:52:24 +00001161 }
1162
1163 // Now we handle options we got from the command line
1164 char command_string[PATH_MAX * 2];
1165 const size_t num_source_command_files = GetNumSourceCommandFiles();
1166 if (num_source_command_files > 0)
1167 {
1168 for (size_t i=0; i < num_source_command_files; ++i)
1169 {
1170 const char *command_file = GetSourceCommandFileAtIndex(i);
Johnny Chen7c984242010-07-28 21:16:11 +00001171 ::snprintf (command_string, sizeof(command_string), "command source '%s'", command_file);
Greg Clayton63094e02010-06-23 01:19:29 +00001172 m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, false);
Chris Lattner24943d22010-06-08 16:52:24 +00001173 if (GetDebugMode())
1174 {
Greg Clayton63094e02010-06-23 01:19:29 +00001175 result.PutError (m_debugger.GetErrorFileHandle());
1176 result.PutOutput (m_debugger.GetOutputFileHandle());
Chris Lattner24943d22010-06-08 16:52:24 +00001177 }
1178 }
1179 }
1180
Greg Clayton4dc18922010-12-08 22:23:24 +00001181 const size_t num_args = m_option_data.m_args.size();
1182 if (num_args > 0)
Chris Lattner24943d22010-06-08 16:52:24 +00001183 {
1184 char arch_name[64];
Greg Clayton63094e02010-06-23 01:19:29 +00001185 if (m_debugger.GetDefaultArchitecture (arch_name, sizeof (arch_name)))
Greg Clayton4dc18922010-12-08 22:23:24 +00001186 ::snprintf (command_string,
1187 sizeof (command_string),
Greg Claytonabe0fed2011-04-18 08:33:37 +00001188 "target create --arch=%s '%s'",
Greg Clayton4dc18922010-12-08 22:23:24 +00001189 arch_name,
1190 m_option_data.m_args[0].c_str());
Chris Lattner24943d22010-06-08 16:52:24 +00001191 else
Greg Clayton4dc18922010-12-08 22:23:24 +00001192 ::snprintf (command_string,
1193 sizeof(command_string),
Greg Claytonabe0fed2011-04-18 08:33:37 +00001194 "target create '%s'",
Greg Clayton4dc18922010-12-08 22:23:24 +00001195 m_option_data.m_args[0].c_str());
Chris Lattner24943d22010-06-08 16:52:24 +00001196
Greg Clayton63094e02010-06-23 01:19:29 +00001197 m_debugger.HandleCommand (command_string);
Greg Clayton4dc18922010-12-08 22:23:24 +00001198
1199 if (num_args > 1)
1200 {
1201 m_debugger.HandleCommand ("settings clear target.process.run-args");
1202 char arg_cstr[1024];
1203 for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx)
1204 {
1205 ::snprintf (arg_cstr, sizeof(arg_cstr), "settings append target.process.run-args \"%s\"", m_option_data.m_args[arg_idx].c_str());
1206 m_debugger.HandleCommand (arg_cstr);
1207 }
1208 }
Chris Lattner24943d22010-06-08 16:52:24 +00001209 }
1210
1211 // Now that all option parsing is done, we try and parse the .lldbinit
1212 // file in the current working directory
1213 sb_interpreter.SourceInitFileInCurrentWorkingDirectory (result);
1214 if (GetDebugMode())
1215 {
Greg Clayton63094e02010-06-23 01:19:29 +00001216 result.PutError(m_debugger.GetErrorFileHandle());
1217 result.PutOutput(m_debugger.GetOutputFileHandle());
Chris Lattner24943d22010-06-08 16:52:24 +00001218 }
1219
1220 SBEvent event;
1221
1222 // Make sure the IO channel is started up before we try to tell it we
1223 // are ready for input
1224 listener.WaitForEventForBroadcasterWithType (UINT32_MAX,
1225 *m_io_channel_ap,
1226 IOChannel::eBroadcastBitThreadDidStart,
1227 event);
1228
1229 ReadyForCommand ();
1230
1231 bool done = false;
1232 while (!done)
1233 {
1234 listener.WaitForEvent (UINT32_MAX, event);
1235 if (event.IsValid())
1236 {
1237 if (event.GetBroadcaster().IsValid())
1238 {
1239 uint32_t event_type = event.GetType();
1240 if (event.BroadcasterMatchesRef (*m_io_channel_ap))
1241 {
1242 if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
1243 (event_type & IOChannel::eBroadcastBitThreadDidExit))
1244 {
1245 done = true;
1246 if (event_type & IOChannel::eBroadcastBitThreadDidExit)
1247 iochannel_thread_exited = true;
Chris Lattner24943d22010-06-08 16:52:24 +00001248 }
1249 else
1250 done = HandleIOEvent (event);
1251 }
Jim Inghamc8332952010-08-26 21:32:51 +00001252 else if (event.BroadcasterMatchesRef (m_debugger.GetSelectedTarget().GetProcess().GetBroadcaster()))
Chris Lattner24943d22010-06-08 16:52:24 +00001253 {
1254 HandleProcessEvent (event);
1255 }
1256 else if (event.BroadcasterMatchesRef (sb_interpreter.GetBroadcaster()))
1257 {
1258 if (event_type & SBCommandInterpreter::eBroadcastBitQuitCommandReceived)
1259 done = true;
Caroline Tice388ca8f2011-05-03 20:53:11 +00001260 else if (event_type & SBCommandInterpreter::eBroadcastBitAsynchronousErrorData)
1261 {
1262 const char *data = SBEvent::GetCStringFromEvent (event);
1263 m_io_channel_ap->ErrWrite (data, strlen(data), ASYNC);
1264 }
1265 else if (event_type & SBCommandInterpreter::eBroadcastBitAsynchronousOutputData)
1266 {
1267 const char *data = SBEvent::GetCStringFromEvent (event);
1268 m_io_channel_ap->OutWrite (data, strlen(data), ASYNC);
1269 }
Chris Lattner24943d22010-06-08 16:52:24 +00001270 }
1271 }
1272 }
1273 }
1274
1275 reset_stdin_termios ();
1276
1277 CloseIOChannelFile ();
1278
1279 if (!iochannel_thread_exited)
1280 {
Greg Claytonbef15832010-07-14 00:18:15 +00001281 event.Clear();
Chris Lattner24943d22010-06-08 16:52:24 +00001282 listener.GetNextEventForBroadcasterWithType (*m_io_channel_ap,
1283 IOChannel::eBroadcastBitThreadDidExit,
1284 event);
1285 if (!event.IsValid())
1286 {
1287 // Send end EOF to the driver file descriptor
1288 m_io_channel_ap->Stop();
1289 }
1290 }
1291
Jim Inghamc8332952010-08-26 21:32:51 +00001292 SBProcess process = m_debugger.GetSelectedTarget().GetProcess();
Chris Lattner24943d22010-06-08 16:52:24 +00001293 if (process.IsValid())
1294 process.Destroy();
1295 }
1296 }
1297}
1298
1299
1300void
1301Driver::ReadyForCommand ()
1302{
1303 if (m_waiting_for_command == false)
1304 {
1305 m_waiting_for_command = true;
1306 BroadcastEventByType (Driver::eBroadcastBitReadyForInput, true);
1307 }
1308}
1309
1310
Caroline Ticeb8314fe2010-09-09 17:45:09 +00001311void
1312sigwinch_handler (int signo)
1313{
1314 struct winsize window_size;
1315 if (isatty (STDIN_FILENO)
1316 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
1317 {
1318 if ((window_size.ws_col > 0) && (strlen (g_debugger_name) > 0))
1319 {
1320 char width_str_buffer[25];
1321 ::sprintf (width_str_buffer, "%d", window_size.ws_col);
1322 SBDebugger::SetInternalVariable ("term-width", width_str_buffer, g_debugger_name);
1323 }
1324 }
1325}
1326
Caroline Ticec4f55fe2010-11-19 20:47:54 +00001327void
1328sigint_handler (int signo)
1329{
1330 static bool g_interrupt_sent = false;
1331 if (g_driver)
1332 {
1333 if (!g_interrupt_sent)
1334 {
1335 g_interrupt_sent = true;
1336 g_driver->GetDebugger().DispatchInputInterrupt();
1337 g_interrupt_sent = false;
1338 return;
1339 }
1340 }
1341
1342 exit (signo);
1343}
1344
Chris Lattner24943d22010-06-08 16:52:24 +00001345int
Jim Inghamb2b604f2011-01-27 20:15:39 +00001346main (int argc, char const *argv[], const char *envp[])
Chris Lattner24943d22010-06-08 16:52:24 +00001347{
Chris Lattner24943d22010-06-08 16:52:24 +00001348 SBDebugger::Initialize();
1349
Greg Clayton95e33b72010-11-07 21:02:03 +00001350 SBHostOS::ThreadCreated ("<lldb.driver.main-thread>");
Chris Lattner24943d22010-06-08 16:52:24 +00001351
Greg Clayton36f63a92010-10-19 03:25:40 +00001352 signal (SIGPIPE, SIG_IGN);
Caroline Ticeb8314fe2010-09-09 17:45:09 +00001353 signal (SIGWINCH, sigwinch_handler);
Caroline Ticec4f55fe2010-11-19 20:47:54 +00001354 signal (SIGINT, sigint_handler);
Caroline Ticeb8314fe2010-09-09 17:45:09 +00001355
Greg Clayton63094e02010-06-23 01:19:29 +00001356 // Create a scope for driver so that the driver object will destroy itself
1357 // before SBDebugger::Terminate() is called.
Chris Lattner24943d22010-06-08 16:52:24 +00001358 {
Greg Clayton63094e02010-06-23 01:19:29 +00001359 Driver driver;
1360
1361 bool exit = false;
1362 SBError error (driver.ParseArgs (argc, argv, stdout, exit));
1363 if (error.Fail())
1364 {
1365 const char *error_cstr = error.GetCString ();
1366 if (error_cstr)
1367 ::fprintf (stderr, "error: %s\n", error_cstr);
1368 }
1369 else if (!exit)
1370 {
1371 driver.MainLoop ();
1372 }
Chris Lattner24943d22010-06-08 16:52:24 +00001373 }
1374
1375 SBDebugger::Terminate();
1376 return 0;
1377}