blob: 1e0630e2d3ea3ced3072e45c43f629a0732eca75 [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 Ingham83dd2032011-09-13 23:25:31 +000072 { LLDB_OPT_SET_1, true , "help" , 'h', no_argument , NULL, eArgTypeNone, "Prints out the usage information for the LLDB debugger." },
73 { LLDB_OPT_SET_2, true , "version" , 'v', no_argument , NULL, eArgTypeNone, "Prints out the current version number of the LLDB debugger." },
74 { 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." },
75 { 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." },
76 { LLDB_OPT_SET_4, true , "attach-name" , 'n', required_argument, NULL, eArgTypeProcessName, "Tells the debugger to attach to a process with the given name." },
77 { LLDB_OPT_SET_4, true , "wait-for" , 'w', no_argument , NULL, eArgTypeNone, "Tells the debugger to wait for a process with the given pid or name to launch before attaching." },
78 { LLDB_OPT_SET_5, true , "attach-pid" , 'p', required_argument, NULL, eArgTypePid, "Tells the debugger to attach to a process with the given pid." },
79 { LLDB_3_TO_5, 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." },
80 { LLDB_3_TO_5, false, "debug" , 'd', no_argument , NULL, eArgTypeNone, "Tells the debugger to print out extra information for debugging itself." },
81 { LLDB_3_TO_5, false, "source" , 's', required_argument, NULL, eArgTypeFilename, "Tells the debugger to read in and execute the file <file>, which should contain lldb commands." },
82 { LLDB_3_TO_5, false, "editor" , 'e', no_argument , NULL, eArgTypeNone, "Tells the debugger to open source files using the host's \"external editor\" mechanism." },
83 { LLDB_3_TO_5, false, "no-lldbinit" , 'x', no_argument , NULL, eArgTypeNone, "Do not automatically parse any '.lldbinit' files." },
84 { 0, false, NULL , 0 , 0 , NULL, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +000085};
86
Jim Ingham83dd2032011-09-13 23:25:31 +000087static const uint32_t last_option_set_with_args = 2;
Chris Lattner24943d22010-06-08 16:52:24 +000088
89Driver::Driver () :
90 SBBroadcaster ("Driver"),
Jim Ingham558dd5b2011-08-13 00:22:20 +000091 m_debugger (SBDebugger::Create(false)),
Chris Lattner24943d22010-06-08 16:52:24 +000092 m_editline_pty (),
93 m_editline_slave_fh (NULL),
94 m_editline_reader (),
95 m_io_channel_ap (),
96 m_option_data (),
97 m_waiting_for_command (false)
98{
Greg Clayton421ca502011-05-29 04:06:55 +000099 // We want to be able to handle CTRL+D in the terminal to have it terminate
100 // certain input
101 m_debugger.SetCloseInputOnEOF (false);
Caroline Ticeb8314fe2010-09-09 17:45:09 +0000102 g_debugger_name = (char *) m_debugger.GetInstanceName();
103 if (g_debugger_name == NULL)
104 g_debugger_name = (char *) "";
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000105 g_driver = this;
Chris Lattner24943d22010-06-08 16:52:24 +0000106}
107
108Driver::~Driver ()
109{
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000110 g_driver = NULL;
111 g_debugger_name = NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000112}
113
114void
115Driver::CloseIOChannelFile ()
116{
117 // Write and End of File sequence to the file descriptor to ensure any
118 // read functions can exit.
119 char eof_str[] = "\x04";
120 ::write (m_editline_pty.GetMasterFileDescriptor(), eof_str, strlen(eof_str));
121
122 m_editline_pty.CloseMasterFileDescriptor();
123
124 if (m_editline_slave_fh)
125 {
126 ::fclose (m_editline_slave_fh);
127 m_editline_slave_fh = NULL;
128 }
129}
130
Greg Clayton54e7afa2010-07-09 20:39:50 +0000131// This function takes INDENT, which tells how many spaces to output at the front
132// of each line; TEXT, which is the text that is to be output. It outputs the
133// text, on multiple lines if necessary, to RESULT, with INDENT spaces at the
134// front of each line. It breaks lines on spaces, tabs or newlines, shortening
135// the line if necessary to not break in the middle of a word. It assumes that
136// each output line should contain a maximum of OUTPUT_MAX_COLUMNS characters.
Chris Lattner24943d22010-06-08 16:52:24 +0000137
138void
Greg Clayton54e7afa2010-07-09 20:39:50 +0000139OutputFormattedUsageText (FILE *out, int indent, const char *text, int output_max_columns)
Chris Lattner24943d22010-06-08 16:52:24 +0000140{
141 int len = strlen (text);
142 std::string text_string (text);
Chris Lattner24943d22010-06-08 16:52:24 +0000143
144 // Force indentation to be reasonable.
145 if (indent >= output_max_columns)
146 indent = 0;
147
148 // Will it all fit on one line?
149
150 if (len + indent < output_max_columns)
151 // Output as a single line
Greg Clayton54e7afa2010-07-09 20:39:50 +0000152 fprintf (out, "%*s%s\n", indent, "", text);
Chris Lattner24943d22010-06-08 16:52:24 +0000153 else
154 {
155 // We need to break it up into multiple lines.
156 int text_width = output_max_columns - indent - 1;
157 int start = 0;
158 int end = start;
159 int final_end = len;
160 int sub_len;
161
162 while (end < final_end)
163 {
164 // Dont start the 'text' on a space, since we're already outputting the indentation.
165 while ((start < final_end) && (text[start] == ' '))
166 start++;
167
168 end = start + text_width;
169 if (end > final_end)
170 end = final_end;
171 else
172 {
173 // If we're not at the end of the text, make sure we break the line on white space.
174 while (end > start
175 && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
176 end--;
177 }
178 sub_len = end - start;
179 std::string substring = text_string.substr (start, sub_len);
Greg Clayton54e7afa2010-07-09 20:39:50 +0000180 fprintf (out, "%*s%s\n", indent, "", substring.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000181 start = end + 1;
182 }
183 }
184}
185
186void
Greg Claytonb3448432011-03-24 21:19:54 +0000187ShowUsage (FILE *out, OptionDefinition *option_table, Driver::OptionData data)
Chris Lattner24943d22010-06-08 16:52:24 +0000188{
189 uint32_t screen_width = 80;
190 uint32_t indent_level = 0;
191 const char *name = "lldb";
Jim Ingham34e9a982010-06-15 18:47:14 +0000192
Chris Lattner24943d22010-06-08 16:52:24 +0000193 fprintf (out, "\nUsage:\n\n");
194
195 indent_level += 2;
196
197
198 // First, show each usage level set of options, e.g. <cmd> [options-for-level-0]
199 // <cmd> [options-for-level-1]
200 // etc.
201
Chris Lattner24943d22010-06-08 16:52:24 +0000202 uint32_t num_options;
Jim Ingham34e9a982010-06-15 18:47:14 +0000203 uint32_t num_option_sets = 0;
204
205 for (num_options = 0; option_table[num_options].long_option != NULL; ++num_options)
Chris Lattner24943d22010-06-08 16:52:24 +0000206 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000207 uint32_t this_usage_mask = option_table[num_options].usage_mask;
208 if (this_usage_mask == LLDB_OPT_SET_ALL)
Chris Lattner24943d22010-06-08 16:52:24 +0000209 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000210 if (num_option_sets == 0)
211 num_option_sets = 1;
Chris Lattner24943d22010-06-08 16:52:24 +0000212 }
213 else
214 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000215 for (uint32_t j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++)
Jim Ingham34e9a982010-06-15 18:47:14 +0000216 {
217 if (this_usage_mask & 1 << j)
218 {
219 if (num_option_sets <= j)
220 num_option_sets = j + 1;
221 }
222 }
223 }
224 }
225
226 for (uint32_t opt_set = 0; opt_set < num_option_sets; opt_set++)
227 {
228 uint32_t opt_set_mask;
229
230 opt_set_mask = 1 << opt_set;
231
232 if (opt_set > 0)
233 fprintf (out, "\n");
Greg Clayton54e7afa2010-07-09 20:39:50 +0000234 fprintf (out, "%*s%s", indent_level, "", name);
Jim Ingham6ae25442011-08-16 23:15:02 +0000235 bool is_help_line = false;
Jim Ingham34e9a982010-06-15 18:47:14 +0000236
237 for (uint32_t i = 0; i < num_options; ++i)
238 {
239 if (option_table[i].usage_mask & opt_set_mask)
240 {
Caroline Tice4d6675c2010-10-01 19:59:14 +0000241 CommandArgumentType arg_type = option_table[i].argument_type;
Greg Claytonaa378b12011-02-20 02:15:07 +0000242 const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type);
Jim Ingham6ae25442011-08-16 23:15:02 +0000243 // This is a bit of a hack, but there's no way to say certain options don't have arguments yet...
244 // so we do it by hand here.
245 if (option_table[i].short_option == 'h')
246 is_help_line = true;
247
Jim Ingham34e9a982010-06-15 18:47:14 +0000248 if (option_table[i].required)
249 {
250 if (option_table[i].option_has_arg == required_argument)
Greg Claytonaa378b12011-02-20 02:15:07 +0000251 fprintf (out, " -%c <%s>", option_table[i].short_option, arg_name);
Jim Ingham34e9a982010-06-15 18:47:14 +0000252 else if (option_table[i].option_has_arg == optional_argument)
Greg Claytonaa378b12011-02-20 02:15:07 +0000253 fprintf (out, " -%c [<%s>]", option_table[i].short_option, arg_name);
Jim Ingham34e9a982010-06-15 18:47:14 +0000254 else
255 fprintf (out, " -%c", option_table[i].short_option);
256 }
257 else
258 {
259 if (option_table[i].option_has_arg == required_argument)
Greg Claytonaa378b12011-02-20 02:15:07 +0000260 fprintf (out, " [-%c <%s>]", option_table[i].short_option, arg_name);
Jim Ingham34e9a982010-06-15 18:47:14 +0000261 else if (option_table[i].option_has_arg == optional_argument)
Greg Claytonaa378b12011-02-20 02:15:07 +0000262 fprintf (out, " [-%c [<%s>]]", option_table[i].short_option, arg_name);
Jim Ingham34e9a982010-06-15 18:47:14 +0000263 else
264 fprintf (out, " [-%c]", option_table[i].short_option);
265 }
266 }
Chris Lattner24943d22010-06-08 16:52:24 +0000267 }
Jim Ingham83dd2032011-09-13 23:25:31 +0000268 if (!is_help_line && (opt_set <= last_option_set_with_args))
Jim Ingham6ae25442011-08-16 23:15:02 +0000269 fprintf (out, " [[--] <PROGRAM-ARG-1> [<PROGRAM_ARG-2> ...]]");
Chris Lattner24943d22010-06-08 16:52:24 +0000270 }
271
272 fprintf (out, "\n\n");
273
274 // Now print out all the detailed information about the various options: long form, short form and help text:
275 // -- long_name <argument>
276 // - short <argument>
277 // help text
278
279 // This variable is used to keep track of which options' info we've printed out, because some options can be in
280 // more than one usage level, but we only want to print the long form of its information once.
281
282 Driver::OptionData::OptionSet options_seen;
283 Driver::OptionData::OptionSet::iterator pos;
284
285 indent_level += 5;
286
Jim Ingham34e9a982010-06-15 18:47:14 +0000287 for (uint32_t i = 0; i < num_options; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000288 {
289 // Only print this option if we haven't already seen it.
290 pos = options_seen.find (option_table[i].short_option);
291 if (pos == options_seen.end())
292 {
Caroline Tice4d6675c2010-10-01 19:59:14 +0000293 CommandArgumentType arg_type = option_table[i].argument_type;
Greg Claytonaa378b12011-02-20 02:15:07 +0000294 const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type);
Caroline Tice4d6675c2010-10-01 19:59:14 +0000295
Chris Lattner24943d22010-06-08 16:52:24 +0000296 options_seen.insert (option_table[i].short_option);
Greg Clayton54e7afa2010-07-09 20:39:50 +0000297 fprintf (out, "%*s-%c ", indent_level, "", option_table[i].short_option);
Caroline Tice4d6675c2010-10-01 19:59:14 +0000298 if (arg_type != eArgTypeNone)
Greg Claytonaa378b12011-02-20 02:15:07 +0000299 fprintf (out, "<%s>", arg_name);
Chris Lattner24943d22010-06-08 16:52:24 +0000300 fprintf (out, "\n");
Greg Clayton54e7afa2010-07-09 20:39:50 +0000301 fprintf (out, "%*s--%s ", indent_level, "", option_table[i].long_option);
Caroline Tice4d6675c2010-10-01 19:59:14 +0000302 if (arg_type != eArgTypeNone)
Greg Claytonaa378b12011-02-20 02:15:07 +0000303 fprintf (out, "<%s>", arg_name);
Chris Lattner24943d22010-06-08 16:52:24 +0000304 fprintf (out, "\n");
305 indent_level += 5;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000306 OutputFormattedUsageText (out, indent_level, option_table[i].usage_text, screen_width);
Chris Lattner24943d22010-06-08 16:52:24 +0000307 indent_level -= 5;
308 fprintf (out, "\n");
309 }
310 }
311
312 indent_level -= 5;
313
Jim Inghamcf0de262011-08-16 23:57:58 +0000314 fprintf (out, "\n%*s(If you don't provide -f then the first argument will be the file to be debugged"
315 "\n%*s so '%s -- <filename> [<ARG1> [<ARG2>]]' also works."
316 "\n%*s Remember to end the options with \"--\" if any of your arguments have a \"-\" in them.)\n\n",
317 indent_level, "",
318 indent_level, "",
319 name,
320 indent_level, "");
Chris Lattner24943d22010-06-08 16:52:24 +0000321}
322
323void
Greg Claytonb3448432011-03-24 21:19:54 +0000324BuildGetOptTable (OptionDefinition *expanded_option_table, std::vector<struct option> &getopt_table,
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000325 uint32_t num_options)
Chris Lattner24943d22010-06-08 16:52:24 +0000326{
327 if (num_options == 0)
328 return;
329
330 uint32_t i;
331 uint32_t j;
332 std::bitset<256> option_seen;
333
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000334 getopt_table.resize (num_options + 1);
335
Chris Lattner24943d22010-06-08 16:52:24 +0000336 for (i = 0, j = 0; i < num_options; ++i)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000337 {
Chris Lattner24943d22010-06-08 16:52:24 +0000338 char short_opt = expanded_option_table[i].short_option;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000339
Chris Lattner24943d22010-06-08 16:52:24 +0000340 if (option_seen.test(short_opt) == false)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000341 {
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000342 getopt_table[j].name = expanded_option_table[i].long_option;
343 getopt_table[j].has_arg = expanded_option_table[i].option_has_arg;
344 getopt_table[j].flag = NULL;
345 getopt_table[j].val = expanded_option_table[i].short_option;
Chris Lattner24943d22010-06-08 16:52:24 +0000346 option_seen.set(short_opt);
347 ++j;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000348 }
349 }
Chris Lattner24943d22010-06-08 16:52:24 +0000350
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000351 getopt_table[j].name = NULL;
352 getopt_table[j].has_arg = 0;
353 getopt_table[j].flag = NULL;
354 getopt_table[j].val = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000355
356}
357
Greg Clayton63094e02010-06-23 01:19:29 +0000358Driver::OptionData::OptionData () :
Greg Clayton4dc18922010-12-08 22:23:24 +0000359 m_args(),
Greg Clayton63094e02010-06-23 01:19:29 +0000360 m_script_lang (lldb::eScriptLanguageDefault),
Greg Clayton54e7afa2010-07-09 20:39:50 +0000361 m_crash_log (),
Greg Clayton63094e02010-06-23 01:19:29 +0000362 m_source_command_files (),
363 m_debug_mode (false),
Greg Clayton54e7afa2010-07-09 20:39:50 +0000364 m_print_version (false),
Greg Clayton63094e02010-06-23 01:19:29 +0000365 m_print_help (false),
Stephen Wilsondbeb3e12011-04-11 19:41:40 +0000366 m_use_external_editor(false),
Jim Ingham83dd2032011-09-13 23:25:31 +0000367 m_wait_for(false),
368 m_process_name(),
369 m_process_pid(LLDB_INVALID_PROCESS_ID),
Stephen Wilsondbeb3e12011-04-11 19:41:40 +0000370 m_seen_options()
Chris Lattner24943d22010-06-08 16:52:24 +0000371{
Greg Clayton63094e02010-06-23 01:19:29 +0000372}
373
374Driver::OptionData::~OptionData ()
375{
376}
377
378void
379Driver::OptionData::Clear ()
380{
Greg Clayton4dc18922010-12-08 22:23:24 +0000381 m_args.clear ();
Greg Clayton63094e02010-06-23 01:19:29 +0000382 m_script_lang = lldb::eScriptLanguageDefault;
383 m_source_command_files.clear ();
384 m_debug_mode = false;
385 m_print_help = false;
386 m_print_version = false;
Jim Ingham74989e82010-08-30 19:44:40 +0000387 m_use_external_editor = false;
Jim Ingham83dd2032011-09-13 23:25:31 +0000388 m_wait_for = false;
389 m_process_name.erase();
390 m_process_pid = LLDB_INVALID_PROCESS_ID;
Greg Clayton63094e02010-06-23 01:19:29 +0000391}
392
393void
394Driver::ResetOptionValues ()
395{
396 m_option_data.Clear ();
397}
398
399const char *
400Driver::GetFilename() const
401{
Greg Clayton4dc18922010-12-08 22:23:24 +0000402 if (m_option_data.m_args.empty())
Greg Clayton63094e02010-06-23 01:19:29 +0000403 return NULL;
Greg Clayton4dc18922010-12-08 22:23:24 +0000404 return m_option_data.m_args.front().c_str();
Greg Clayton63094e02010-06-23 01:19:29 +0000405}
406
407const char *
408Driver::GetCrashLogFilename() const
409{
410 if (m_option_data.m_crash_log.empty())
411 return NULL;
412 return m_option_data.m_crash_log.c_str();
413}
414
415lldb::ScriptLanguage
416Driver::GetScriptLanguage() const
417{
418 return m_option_data.m_script_lang;
419}
420
421size_t
422Driver::GetNumSourceCommandFiles () const
423{
424 return m_option_data.m_source_command_files.size();
425}
426
427const char *
428Driver::GetSourceCommandFileAtIndex (uint32_t idx) const
429{
430 if (idx < m_option_data.m_source_command_files.size())
431 return m_option_data.m_source_command_files[idx].c_str();
432 return NULL;
433}
434
435bool
436Driver::GetDebugMode() const
437{
438 return m_option_data.m_debug_mode;
439}
440
441
442// Check the arguments that were passed to this program to make sure they are valid and to get their
443// argument values (if any). Return a boolean value indicating whether or not to start up the full
444// debugger (i.e. the Command Interpreter) or not. Return FALSE if the arguments were invalid OR
445// if the user only wanted help or version information.
446
447SBError
448Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exit)
449{
450 ResetOptionValues ();
451
452 SBCommandReturnObject result;
453
Chris Lattner24943d22010-06-08 16:52:24 +0000454 SBError error;
455 std::string option_string;
456 struct option *long_options = NULL;
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000457 std::vector<struct option> long_options_vector;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000458 uint32_t num_options;
Chris Lattner24943d22010-06-08 16:52:24 +0000459
Greg Clayton54e7afa2010-07-09 20:39:50 +0000460 for (num_options = 0; g_options[num_options].long_option != NULL; ++num_options)
461 /* Do Nothing. */;
Chris Lattner24943d22010-06-08 16:52:24 +0000462
463 if (num_options == 0)
464 {
465 if (argc > 1)
466 error.SetErrorStringWithFormat ("invalid number of options");
467 return error;
468 }
469
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000470 BuildGetOptTable (g_options, long_options_vector, num_options);
Chris Lattner24943d22010-06-08 16:52:24 +0000471
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000472 if (long_options_vector.empty())
473 long_options = NULL;
474 else
475 long_options = &long_options_vector.front();
Chris Lattner24943d22010-06-08 16:52:24 +0000476
477 if (long_options == NULL)
478 {
479 error.SetErrorStringWithFormat ("invalid long options");
480 return error;
481 }
482
483 // Build the option_string argument for call to getopt_long.
484
485 for (int i = 0; long_options[i].name != NULL; ++i)
486 {
487 if (long_options[i].flag == NULL)
488 {
489 option_string.push_back ((char) long_options[i].val);
490 switch (long_options[i].has_arg)
491 {
492 default:
493 case no_argument:
494 break;
495 case required_argument:
496 option_string.push_back (':');
497 break;
498 case optional_argument:
499 option_string.append ("::");
500 break;
501 }
502 }
503 }
504
Jim Ingham558dd5b2011-08-13 00:22:20 +0000505 // This is kind of a pain, but since we make the debugger in the Driver's constructor, we can't
506 // know at that point whether we should read in init files yet. So we don't read them in in the
507 // Driver constructor, then set the flags back to "read them in" here, and then if we see the
508 // "-n" flag, we'll turn it off again. Finally we have to read them in by hand later in the
509 // main loop.
510
511 m_debugger.SkipLLDBInitFiles (false);
512 m_debugger.SkipAppInitFiles (false);
513
Chris Lattner24943d22010-06-08 16:52:24 +0000514 // Prepare for & make calls to getopt_long.
Eli Friedmanef2bc872010-06-13 19:18:49 +0000515#if __GLIBC__
516 optind = 0;
517#else
Chris Lattner24943d22010-06-08 16:52:24 +0000518 optreset = 1;
519 optind = 1;
Eli Friedmanef2bc872010-06-13 19:18:49 +0000520#endif
Chris Lattner24943d22010-06-08 16:52:24 +0000521 int val;
522 while (1)
523 {
524 int long_options_index = -1;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000525 val = ::getopt_long (argc, const_cast<char **>(argv), option_string.c_str(), long_options, &long_options_index);
Chris Lattner24943d22010-06-08 16:52:24 +0000526
527 if (val == -1)
528 break;
529 else if (val == '?')
530 {
Greg Clayton63094e02010-06-23 01:19:29 +0000531 m_option_data.m_print_help = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000532 error.SetErrorStringWithFormat ("unknown or ambiguous option");
533 break;
534 }
535 else if (val == 0)
536 continue;
537 else
538 {
Greg Clayton63094e02010-06-23 01:19:29 +0000539 m_option_data.m_seen_options.insert ((char) val);
Chris Lattner24943d22010-06-08 16:52:24 +0000540 if (long_options_index == -1)
541 {
542 for (int i = 0;
543 long_options[i].name || long_options[i].has_arg || long_options[i].flag || long_options[i].val;
544 ++i)
545 {
546 if (long_options[i].val == val)
547 {
548 long_options_index = i;
549 break;
550 }
551 }
552 }
553
554 if (long_options_index >= 0)
555 {
Greg Clayton63094e02010-06-23 01:19:29 +0000556 const char short_option = (char) g_options[long_options_index].short_option;
557
558 switch (short_option)
559 {
560 case 'h':
561 m_option_data.m_print_help = true;
562 break;
563
564 case 'v':
565 m_option_data.m_print_version = true;
566 break;
567
568 case 'c':
569 m_option_data.m_crash_log = optarg;
570 break;
Greg Clayton887aa282010-10-11 01:05:37 +0000571
Jim Ingham74989e82010-08-30 19:44:40 +0000572 case 'e':
573 m_option_data.m_use_external_editor = true;
574 break;
Greg Clayton887aa282010-10-11 01:05:37 +0000575
Jim Ingham83dd2032011-09-13 23:25:31 +0000576 case 'x':
Greg Clayton887aa282010-10-11 01:05:37 +0000577 m_debugger.SkipLLDBInitFiles (true);
Jim Ingham558dd5b2011-08-13 00:22:20 +0000578 m_debugger.SkipAppInitFiles (true);
Greg Clayton887aa282010-10-11 01:05:37 +0000579 break;
580
Greg Clayton63094e02010-06-23 01:19:29 +0000581 case 'f':
582 {
583 SBFileSpec file(optarg);
584 if (file.Exists())
Greg Clayton4dc18922010-12-08 22:23:24 +0000585 {
586 m_option_data.m_args.push_back (optarg);
587 }
Caroline Ticeeddffe92010-09-10 04:48:55 +0000588 else if (file.ResolveExecutableLocation())
589 {
590 char path[PATH_MAX];
Johnny Chenee6e7902011-08-10 22:06:24 +0000591 file.GetPath (path, sizeof(path));
Greg Clayton4dc18922010-12-08 22:23:24 +0000592 m_option_data.m_args.push_back (path);
Caroline Ticeeddffe92010-09-10 04:48:55 +0000593 }
Greg Clayton63094e02010-06-23 01:19:29 +0000594 else
595 error.SetErrorStringWithFormat("file specified in --file (-f) option doesn't exist: '%s'", optarg);
596 }
597 break;
598
599 case 'a':
600 if (!m_debugger.SetDefaultArchitecture (optarg))
601 error.SetErrorStringWithFormat("invalid architecture in the -a or --arch option: '%s'", optarg);
602 break;
603
604 case 'l':
605 m_option_data.m_script_lang = m_debugger.GetScriptingLanguage (optarg);
606 break;
607
608 case 'd':
609 m_option_data.m_debug_mode = true;
610 break;
611
Jim Ingham83dd2032011-09-13 23:25:31 +0000612 case 'n':
613 m_option_data.m_process_name = optarg;
614 break;
615
616 case 'w':
617 m_option_data.m_wait_for = true;
618 break;
619
620 case 'p':
621 {
622 char *remainder;
623 m_option_data.m_process_pid = strtol (optarg, &remainder, 0);
624 if (remainder == optarg || *remainder != '\0')
625 error.SetErrorStringWithFormat ("Could not convert process PID: \"%s\" into a pid.",
626 optarg);
627 }
628 break;
Greg Clayton63094e02010-06-23 01:19:29 +0000629 case 's':
630 {
631 SBFileSpec file(optarg);
632 if (file.Exists())
633 m_option_data.m_source_command_files.push_back (optarg);
Caroline Ticeeddffe92010-09-10 04:48:55 +0000634 else if (file.ResolveExecutableLocation())
635 {
636 char final_path[PATH_MAX];
Johnny Chenee6e7902011-08-10 22:06:24 +0000637 file.GetPath (final_path, sizeof(final_path));
Caroline Ticeeddffe92010-09-10 04:48:55 +0000638 std::string path_str (final_path);
639 m_option_data.m_source_command_files.push_back (path_str);
640 }
Greg Clayton63094e02010-06-23 01:19:29 +0000641 else
642 error.SetErrorStringWithFormat("file specified in --source (-s) option doesn't exist: '%s'", optarg);
643 }
644 break;
645
646 default:
647 m_option_data.m_print_help = true;
648 error.SetErrorStringWithFormat ("unrecognized option %c", short_option);
649 break;
650 }
Chris Lattner24943d22010-06-08 16:52:24 +0000651 }
652 else
653 {
654 error.SetErrorStringWithFormat ("invalid option with value %i", val);
655 }
656 if (error.Fail())
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000657 {
Greg Clayton63094e02010-06-23 01:19:29 +0000658 return error;
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000659 }
Chris Lattner24943d22010-06-08 16:52:24 +0000660 }
661 }
Jim Ingham34e9a982010-06-15 18:47:14 +0000662
Greg Clayton63094e02010-06-23 01:19:29 +0000663 if (error.Fail() || m_option_data.m_print_help)
Chris Lattner24943d22010-06-08 16:52:24 +0000664 {
665 ShowUsage (out_fh, g_options, m_option_data);
Greg Clayton9caa9462010-10-11 01:13:37 +0000666 exit = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000667 }
668 else if (m_option_data.m_print_version)
669 {
Greg Clayton63094e02010-06-23 01:19:29 +0000670 ::fprintf (out_fh, "%s\n", m_debugger.GetVersionString());
671 exit = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000672 }
673 else if (! m_option_data.m_crash_log.empty())
674 {
675 // Handle crash log stuff here.
676 }
Jim Ingham83dd2032011-09-13 23:25:31 +0000677 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 +0000678 {
Greg Clayton4dc18922010-12-08 22:23:24 +0000679 // Any arguments that are left over after option parsing are for
680 // the program. If a file was specified with -f then the filename
681 // is already in the m_option_data.m_args array, and any remaining args
682 // are arguments for the inferior program. If no file was specified with
683 // -f, then what is left is the program name followed by any arguments.
684
685 // Skip any options we consumed with getopt_long
686 argc -= optind;
687 argv += optind;
688
689 if (argc > 0)
690 {
691 for (int arg_idx=0; arg_idx<argc; ++arg_idx)
692 {
693 const char *arg = argv[arg_idx];
694 if (arg)
695 m_option_data.m_args.push_back (arg);
696 }
697 }
698
Chris Lattner24943d22010-06-08 16:52:24 +0000699 }
Jim Ingham83dd2032011-09-13 23:25:31 +0000700 else
701 {
702 // Skip any options we consumed with getopt_long
703 argc -= optind;
704 argv += optind;
705
706 if (argc > 0)
707 ::fprintf (out_fh, "Warning: program arguments are ignored when attaching.\n");
708 }
Chris Lattner24943d22010-06-08 16:52:24 +0000709
Greg Clayton63094e02010-06-23 01:19:29 +0000710 return error;
Chris Lattner24943d22010-06-08 16:52:24 +0000711}
712
Caroline Tice757500e2010-09-29 18:35:42 +0000713size_t
Chris Lattner24943d22010-06-08 16:52:24 +0000714Driver::GetProcessSTDOUT ()
715{
716 // The process has stuff waiting for stdout; get it and write it out to the appropriate place.
717 char stdio_buffer[1024];
718 size_t len;
Caroline Tice757500e2010-09-29 18:35:42 +0000719 size_t total_bytes = 0;
Jim Inghamc8332952010-08-26 21:32:51 +0000720 while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0)
Caroline Tice757500e2010-09-29 18:35:42 +0000721 {
Caroline Tice4a348082011-05-02 20:41:46 +0000722 m_io_channel_ap->OutWrite (stdio_buffer, len, ASYNC);
Caroline Tice757500e2010-09-29 18:35:42 +0000723 total_bytes += len;
724 }
725 return total_bytes;
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::GetProcessSTDERR ()
730{
731 // The process has stuff waiting for stderr; 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().GetSTDERR (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->ErrWrite (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
743void
Jim Inghamc8332952010-08-26 21:32:51 +0000744Driver::UpdateSelectedThread ()
Chris Lattner24943d22010-06-08 16:52:24 +0000745{
746 using namespace lldb;
Jim Inghamc8332952010-08-26 21:32:51 +0000747 SBProcess process(m_debugger.GetSelectedTarget().GetProcess());
Chris Lattner24943d22010-06-08 16:52:24 +0000748 if (process.IsValid())
749 {
Jim Inghamc8332952010-08-26 21:32:51 +0000750 SBThread curr_thread (process.GetSelectedThread());
Chris Lattner24943d22010-06-08 16:52:24 +0000751 SBThread thread;
752 StopReason curr_thread_stop_reason = eStopReasonInvalid;
753 curr_thread_stop_reason = curr_thread.GetStopReason();
754
755 if (!curr_thread.IsValid() ||
756 curr_thread_stop_reason == eStopReasonInvalid ||
757 curr_thread_stop_reason == eStopReasonNone)
758 {
759 // Prefer a thread that has just completed its plan over another thread as current thread.
760 SBThread plan_thread;
761 SBThread other_thread;
762 const size_t num_threads = process.GetNumThreads();
763 size_t i;
764 for (i = 0; i < num_threads; ++i)
765 {
766 thread = process.GetThreadAtIndex(i);
767 StopReason thread_stop_reason = thread.GetStopReason();
768 switch (thread_stop_reason)
769 {
770 default:
771 case eStopReasonInvalid:
772 case eStopReasonNone:
773 break;
774
775 case eStopReasonTrace:
776 case eStopReasonBreakpoint:
777 case eStopReasonWatchpoint:
778 case eStopReasonSignal:
779 case eStopReasonException:
780 if (!other_thread.IsValid())
781 other_thread = thread;
782 break;
783 case eStopReasonPlanComplete:
784 if (!plan_thread.IsValid())
785 plan_thread = thread;
786 break;
787 }
788 }
789 if (plan_thread.IsValid())
Jim Inghamc8332952010-08-26 21:32:51 +0000790 process.SetSelectedThread (plan_thread);
Chris Lattner24943d22010-06-08 16:52:24 +0000791 else if (other_thread.IsValid())
Jim Inghamc8332952010-08-26 21:32:51 +0000792 process.SetSelectedThread (other_thread);
Chris Lattner24943d22010-06-08 16:52:24 +0000793 else
794 {
795 if (curr_thread.IsValid())
796 thread = curr_thread;
797 else
798 thread = process.GetThreadAtIndex(0);
799
800 if (thread.IsValid())
Jim Inghamc8332952010-08-26 21:32:51 +0000801 process.SetSelectedThread (thread);
Chris Lattner24943d22010-06-08 16:52:24 +0000802 }
803 }
804 }
805}
806
807
808// This function handles events that were broadcast by the process.
809void
810Driver::HandleProcessEvent (const SBEvent &event)
811{
812 using namespace lldb;
813 const uint32_t event_type = event.GetType();
814
815 if (event_type & SBProcess::eBroadcastBitSTDOUT)
816 {
817 // The process has stdout available, get it and write it out to the
818 // appropriate place.
Caroline Tice4a348082011-05-02 20:41:46 +0000819 GetProcessSTDOUT ();
Chris Lattner24943d22010-06-08 16:52:24 +0000820 }
821 else if (event_type & SBProcess::eBroadcastBitSTDERR)
822 {
823 // The process has stderr available, get it and write it out to the
824 // appropriate place.
Caroline Tice4a348082011-05-02 20:41:46 +0000825 GetProcessSTDERR ();
Chris Lattner24943d22010-06-08 16:52:24 +0000826 }
827 else if (event_type & SBProcess::eBroadcastBitStateChanged)
828 {
829 // Drain all stout and stderr so we don't see any output come after
830 // we print our prompts
Caroline Tice4a348082011-05-02 20:41:46 +0000831 GetProcessSTDOUT ();
832 GetProcessSTDERR ();
Chris Lattner24943d22010-06-08 16:52:24 +0000833 // Something changed in the process; get the event and report the process's current status and location to
834 // the user.
835 StateType event_state = SBProcess::GetStateFromEvent (event);
836 if (event_state == eStateInvalid)
837 return;
838
839 SBProcess process (SBProcess::GetProcessFromEvent (event));
840 assert (process.IsValid());
841
842 switch (event_state)
843 {
844 case eStateInvalid:
845 case eStateUnloaded:
Greg Claytone71e2582011-02-04 01:58:07 +0000846 case eStateConnected:
Chris Lattner24943d22010-06-08 16:52:24 +0000847 case eStateAttaching:
848 case eStateLaunching:
849 case eStateStepping:
850 case eStateDetached:
851 {
852 char message[1024];
853 int message_len = ::snprintf (message, sizeof(message), "Process %d %s\n", process.GetProcessID(),
Greg Clayton63094e02010-06-23 01:19:29 +0000854 m_debugger.StateAsCString (event_state));
Caroline Tice4a348082011-05-02 20:41:46 +0000855 m_io_channel_ap->OutWrite(message, message_len, ASYNC);
Chris Lattner24943d22010-06-08 16:52:24 +0000856 }
857 break;
858
859 case eStateRunning:
860 // Don't be chatty when we run...
861 break;
862
863 case eStateExited:
Caroline Tice757500e2010-09-29 18:35:42 +0000864 {
865 SBCommandReturnObject result;
866 m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
Caroline Tice4a348082011-05-02 20:41:46 +0000867 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize(), ASYNC);
868 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize(), ASYNC);
Caroline Tice757500e2010-09-29 18:35:42 +0000869 }
Chris Lattner24943d22010-06-08 16:52:24 +0000870 break;
871
872 case eStateStopped:
873 case eStateCrashed:
874 case eStateSuspended:
875 // Make sure the program hasn't been auto-restarted:
876 if (SBProcess::GetRestartedFromEvent (event))
877 {
878 // FIXME: Do we want to report this, or would that just be annoyingly chatty?
879 char message[1024];
880 int message_len = ::snprintf (message, sizeof(message), "Process %d stopped and was programmatically restarted.\n",
881 process.GetProcessID());
Caroline Tice4a348082011-05-02 20:41:46 +0000882 m_io_channel_ap->OutWrite(message, message_len, ASYNC);
Chris Lattner24943d22010-06-08 16:52:24 +0000883 }
884 else
885 {
Caroline Tice757500e2010-09-29 18:35:42 +0000886 SBCommandReturnObject result;
Jim Inghamc8332952010-08-26 21:32:51 +0000887 UpdateSelectedThread ();
Caroline Tice757500e2010-09-29 18:35:42 +0000888 m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
Caroline Tice4a348082011-05-02 20:41:46 +0000889 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize(), ASYNC);
890 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize(), ASYNC);
Chris Lattner24943d22010-06-08 16:52:24 +0000891 }
892 break;
893 }
894 }
895}
896
897// This function handles events broadcast by the IOChannel (HasInput, UserInterrupt, or ThreadShouldExit).
898
899bool
900Driver::HandleIOEvent (const SBEvent &event)
901{
902 bool quit = false;
903
904 const uint32_t event_type = event.GetType();
905
906 if (event_type & IOChannel::eBroadcastBitHasUserInput)
907 {
908 // We got some input (i.e. a command string) from the user; pass it off to the command interpreter for
909 // handling.
910
911 const char *command_string = SBEvent::GetCStringFromEvent(event);
912 if (command_string == NULL)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000913 command_string = "";
Chris Lattner24943d22010-06-08 16:52:24 +0000914 SBCommandReturnObject result;
Jim Ingham2e8cb8a2011-02-19 02:53:09 +0000915
Caroline Tice845d6da2011-05-16 19:20:50 +0000916 // We don't want the result to bypass the OutWrite function in IOChannel, as this can result in odd
917 // output orderings and problems with the prompt.
Jim Ingham2e8cb8a2011-02-19 02:53:09 +0000918 m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, true);
919
Caroline Tice845d6da2011-05-16 19:20:50 +0000920 if (result.GetOutputSize() > 0)
921 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize(), NO_ASYNC);
922
923 if (result.GetErrorSize() > 0)
924 m_io_channel_ap->OutWrite (result.GetError(), result.GetErrorSize(), NO_ASYNC);
925
Chris Lattner24943d22010-06-08 16:52:24 +0000926 // We are done getting and running our command, we can now clear the
927 // m_waiting_for_command so we can get another one.
928 m_waiting_for_command = false;
929
930 // If our editline input reader is active, it means another input reader
931 // got pushed onto the input reader and caused us to become deactivated.
932 // When the input reader above us gets popped, we will get re-activated
933 // and our prompt will refresh in our callback
934 if (m_editline_reader.IsActive())
935 {
936 ReadyForCommand ();
937 }
938 }
939 else if (event_type & IOChannel::eBroadcastBitUserInterrupt)
940 {
941 // This is here to handle control-c interrupts from the user. It has not yet really been implemented.
942 // TO BE DONE: PROPERLY HANDLE CONTROL-C FROM USER
943 //m_io_channel_ap->CancelInput();
944 // Anything else? Send Interrupt to process?
945 }
946 else if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
947 (event_type & IOChannel::eBroadcastBitThreadDidExit))
948 {
949 // If the IOChannel thread is trying to go away, then it is definitely
950 // time to end the debugging session.
951 quit = true;
952 }
953
954 return quit;
955}
956
Chris Lattner24943d22010-06-08 16:52:24 +0000957void
958Driver::MasterThreadBytesReceived (void *baton, const void *src, size_t src_len)
959{
960 Driver *driver = (Driver*)baton;
961 driver->GetFromMaster ((const char *)src, src_len);
962}
963
964void
965Driver::GetFromMaster (const char *src, size_t src_len)
966{
967 // Echo the characters back to the Debugger's stdout, that way if you
968 // type characters while a command is running, you'll see what you've typed.
Greg Clayton63094e02010-06-23 01:19:29 +0000969 FILE *out_fh = m_debugger.GetOutputFileHandle();
Chris Lattner24943d22010-06-08 16:52:24 +0000970 if (out_fh)
971 ::fwrite (src, 1, src_len, out_fh);
972}
973
974size_t
975Driver::EditLineInputReaderCallback
976(
977 void *baton,
978 SBInputReader *reader,
979 InputReaderAction notification,
980 const char *bytes,
981 size_t bytes_len
982)
983{
984 Driver *driver = (Driver *)baton;
985
986 switch (notification)
987 {
988 case eInputReaderActivate:
989 break;
990
991 case eInputReaderReactivate:
992 driver->ReadyForCommand();
993 break;
994
995 case eInputReaderDeactivate:
996 break;
Caroline Tice4a348082011-05-02 20:41:46 +0000997
998 case eInputReaderAsynchronousOutputWritten:
999 if (driver->m_io_channel_ap.get() != NULL)
1000 driver->m_io_channel_ap->RefreshPrompt();
1001 break;
Chris Lattner24943d22010-06-08 16:52:24 +00001002
Caroline Ticec4f55fe2010-11-19 20:47:54 +00001003 case eInputReaderInterrupt:
1004 if (driver->m_io_channel_ap.get() != NULL)
1005 {
Caroline Tice4a348082011-05-02 20:41:46 +00001006 driver->m_io_channel_ap->OutWrite ("^C\n", 3, NO_ASYNC);
Caroline Ticec4f55fe2010-11-19 20:47:54 +00001007 driver->m_io_channel_ap->RefreshPrompt();
1008 }
1009 break;
1010
1011 case eInputReaderEndOfFile:
1012 if (driver->m_io_channel_ap.get() != NULL)
1013 {
Caroline Tice4a348082011-05-02 20:41:46 +00001014 driver->m_io_channel_ap->OutWrite ("^D\n", 3, NO_ASYNC);
Caroline Ticec4f55fe2010-11-19 20:47:54 +00001015 driver->m_io_channel_ap->RefreshPrompt ();
1016 }
1017 write (driver->m_editline_pty.GetMasterFileDescriptor(), "quit\n", 5);
1018 break;
1019
Chris Lattner24943d22010-06-08 16:52:24 +00001020 case eInputReaderGotToken:
1021 write (driver->m_editline_pty.GetMasterFileDescriptor(), bytes, bytes_len);
1022 break;
1023
1024 case eInputReaderDone:
1025 break;
1026 }
1027 return bytes_len;
1028}
1029
1030void
1031Driver::MainLoop ()
1032{
1033 char error_str[1024];
1034 if (m_editline_pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, error_str, sizeof(error_str)) == false)
1035 {
1036 ::fprintf (stderr, "error: failed to open driver pseudo terminal : %s", error_str);
1037 exit(1);
1038 }
1039 else
1040 {
1041 const char *driver_slave_name = m_editline_pty.GetSlaveName (error_str, sizeof(error_str));
1042 if (driver_slave_name == NULL)
1043 {
1044 ::fprintf (stderr, "error: failed to get slave name for driver pseudo terminal : %s", error_str);
1045 exit(2);
1046 }
1047 else
1048 {
1049 m_editline_slave_fh = ::fopen (driver_slave_name, "r+");
1050 if (m_editline_slave_fh == NULL)
1051 {
1052 SBError error;
1053 error.SetErrorToErrno();
1054 ::fprintf (stderr, "error: failed to get open slave for driver pseudo terminal : %s",
1055 error.GetCString());
1056 exit(3);
1057 }
1058
1059 ::setbuf (m_editline_slave_fh, NULL);
1060 }
1061 }
1062
Caroline Tice4a348082011-05-02 20:41:46 +00001063 lldb_utility::PseudoTerminal editline_output_pty;
1064 FILE *editline_output_slave_fh = NULL;
1065
1066 if (editline_output_pty.OpenFirstAvailableMaster (O_RDWR|O_NOCTTY, error_str, sizeof (error_str)) == false)
1067 {
1068 ::fprintf (stderr, "error: failed to open output pseudo terminal : %s", error_str);
1069 exit(1);
1070 }
1071 else
1072 {
1073 const char *output_slave_name = editline_output_pty.GetSlaveName (error_str, sizeof(error_str));
1074 if (output_slave_name == NULL)
1075 {
1076 ::fprintf (stderr, "error: failed to get slave name for output pseudo terminal : %s", error_str);
1077 exit(2);
1078 }
1079 else
1080 {
1081 editline_output_slave_fh = ::fopen (output_slave_name, "r+");
1082 if (editline_output_slave_fh == NULL)
1083 {
1084 SBError error;
1085 error.SetErrorToErrno();
1086 ::fprintf (stderr, "error: failed to get open slave for output pseudo terminal : %s",
1087 error.GetCString());
1088 exit(3);
1089 }
1090 ::setbuf (editline_output_slave_fh, NULL);
1091 }
1092 }
Chris Lattner24943d22010-06-08 16:52:24 +00001093
1094 // struct termios stdin_termios;
1095
1096 if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0)
1097 atexit (reset_stdin_termios);
1098
1099 ::setbuf (stdin, NULL);
1100 ::setbuf (stdout, NULL);
1101
Greg Clayton63094e02010-06-23 01:19:29 +00001102 m_debugger.SetErrorFileHandle (stderr, false);
1103 m_debugger.SetOutputFileHandle (stdout, false);
1104 m_debugger.SetInputFileHandle (stdin, true);
Jim Ingham74989e82010-08-30 19:44:40 +00001105
1106 m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor);
Chris Lattner24943d22010-06-08 16:52:24 +00001107
1108 // You have to drain anything that comes to the master side of the PTY. master_out_comm is
1109 // for that purpose. The reason you need to do this is a curious reason... editline will echo
1110 // characters to the PTY when it gets characters while el_gets is not running, and then when
1111 // you call el_gets (or el_getc) it will try to reset the terminal back to raw mode which blocks
1112 // if there are unconsumed characters in the out buffer.
1113 // However, you don't need to do anything with the characters, since editline will dump these
1114 // unconsumed characters after printing the prompt again in el_gets.
1115
Greg Claytoneecb0f32010-12-04 02:39:47 +00001116 SBCommunication master_out_comm("driver.editline");
1117 master_out_comm.SetCloseOnEOF (false);
Chris Lattner24943d22010-06-08 16:52:24 +00001118 master_out_comm.AdoptFileDesriptor(m_editline_pty.GetMasterFileDescriptor(), false);
1119 master_out_comm.SetReadThreadBytesReceivedCallback(Driver::MasterThreadBytesReceived, this);
1120
1121 if (master_out_comm.ReadThreadStart () == false)
1122 {
1123 ::fprintf (stderr, "error: failed to start master out read thread");
1124 exit(5);
1125 }
1126
Greg Clayton63094e02010-06-23 01:19:29 +00001127 SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter();
Chris Lattner24943d22010-06-08 16:52:24 +00001128
Caroline Tice4a348082011-05-02 20:41:46 +00001129 m_io_channel_ap.reset (new IOChannel(m_editline_slave_fh, editline_output_slave_fh, stdout, stderr, this));
1130
1131 SBCommunication out_comm_2("driver.editline_output");
1132 out_comm_2.SetCloseOnEOF (false);
1133 out_comm_2.AdoptFileDesriptor (editline_output_pty.GetMasterFileDescriptor(), false);
1134 out_comm_2.SetReadThreadBytesReceivedCallback (IOChannel::LibeditOutputBytesReceived, m_io_channel_ap.get());
1135
1136 if (out_comm_2.ReadThreadStart () == false)
1137 {
1138 ::fprintf (stderr, "error: failed to start libedit output read thread");
1139 exit (5);
1140 }
1141
Chris Lattner24943d22010-06-08 16:52:24 +00001142
1143 struct winsize window_size;
1144 if (isatty (STDIN_FILENO)
1145 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
1146 {
Caroline Tice6e4c5ce2010-09-04 00:03:46 +00001147 if (window_size.ws_col > 0)
Greg Clayton238c0a12010-09-18 01:14:36 +00001148 m_debugger.SetTerminalWidth (window_size.ws_col);
Chris Lattner24943d22010-06-08 16:52:24 +00001149 }
1150
1151 // Since input can be redirected by the debugger, we must insert our editline
1152 // input reader in the queue so we know when our reader should be active
1153 // and so we can receive bytes only when we are supposed to.
Greg Clayton63094e02010-06-23 01:19:29 +00001154 SBError err (m_editline_reader.Initialize (m_debugger,
1155 Driver::EditLineInputReaderCallback, // callback
Chris Lattner24943d22010-06-08 16:52:24 +00001156 this, // baton
1157 eInputReaderGranularityByte, // token_size
1158 NULL, // end token - NULL means never done
1159 NULL, // prompt - taken care of elsewhere
1160 false)); // echo input - don't need Debugger
1161 // to do this, we handle it elsewhere
1162
1163 if (err.Fail())
1164 {
1165 ::fprintf (stderr, "error: %s", err.GetCString());
1166 exit (6);
1167 }
1168
Greg Clayton63094e02010-06-23 01:19:29 +00001169 m_debugger.PushInputReader (m_editline_reader);
Chris Lattner24943d22010-06-08 16:52:24 +00001170
Greg Clayton63094e02010-06-23 01:19:29 +00001171 SBListener listener(m_debugger.GetListener());
Chris Lattner24943d22010-06-08 16:52:24 +00001172 if (listener.IsValid())
1173 {
1174
1175 listener.StartListeningForEvents (*m_io_channel_ap,
1176 IOChannel::eBroadcastBitHasUserInput |
1177 IOChannel::eBroadcastBitUserInterrupt |
1178 IOChannel::eBroadcastBitThreadShouldExit |
1179 IOChannel::eBroadcastBitThreadDidStart |
1180 IOChannel::eBroadcastBitThreadDidExit);
1181
1182 if (m_io_channel_ap->Start ())
1183 {
1184 bool iochannel_thread_exited = false;
1185
1186 listener.StartListeningForEvents (sb_interpreter.GetBroadcaster(),
Caroline Tice388ca8f2011-05-03 20:53:11 +00001187 SBCommandInterpreter::eBroadcastBitQuitCommandReceived |
1188 SBCommandInterpreter::eBroadcastBitAsynchronousOutputData |
1189 SBCommandInterpreter::eBroadcastBitAsynchronousErrorData);
Chris Lattner24943d22010-06-08 16:52:24 +00001190
1191 // Before we handle any options from the command line, we parse the
1192 // .lldbinit file in the user's home directory.
1193 SBCommandReturnObject result;
1194 sb_interpreter.SourceInitFileInHomeDirectory(result);
1195 if (GetDebugMode())
1196 {
Greg Clayton63094e02010-06-23 01:19:29 +00001197 result.PutError (m_debugger.GetErrorFileHandle());
1198 result.PutOutput (m_debugger.GetOutputFileHandle());
Chris Lattner24943d22010-06-08 16:52:24 +00001199 }
1200
1201 // Now we handle options we got from the command line
1202 char command_string[PATH_MAX * 2];
1203 const size_t num_source_command_files = GetNumSourceCommandFiles();
1204 if (num_source_command_files > 0)
1205 {
1206 for (size_t i=0; i < num_source_command_files; ++i)
1207 {
1208 const char *command_file = GetSourceCommandFileAtIndex(i);
Johnny Chen7c984242010-07-28 21:16:11 +00001209 ::snprintf (command_string, sizeof(command_string), "command source '%s'", command_file);
Greg Clayton63094e02010-06-23 01:19:29 +00001210 m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, false);
Chris Lattner24943d22010-06-08 16:52:24 +00001211 if (GetDebugMode())
1212 {
Greg Clayton63094e02010-06-23 01:19:29 +00001213 result.PutError (m_debugger.GetErrorFileHandle());
1214 result.PutOutput (m_debugger.GetOutputFileHandle());
Chris Lattner24943d22010-06-08 16:52:24 +00001215 }
1216 }
1217 }
1218
Greg Clayton4dc18922010-12-08 22:23:24 +00001219 const size_t num_args = m_option_data.m_args.size();
1220 if (num_args > 0)
Chris Lattner24943d22010-06-08 16:52:24 +00001221 {
1222 char arch_name[64];
Greg Clayton63094e02010-06-23 01:19:29 +00001223 if (m_debugger.GetDefaultArchitecture (arch_name, sizeof (arch_name)))
Greg Clayton4dc18922010-12-08 22:23:24 +00001224 ::snprintf (command_string,
1225 sizeof (command_string),
Greg Claytonabe0fed2011-04-18 08:33:37 +00001226 "target create --arch=%s '%s'",
Greg Clayton4dc18922010-12-08 22:23:24 +00001227 arch_name,
1228 m_option_data.m_args[0].c_str());
Chris Lattner24943d22010-06-08 16:52:24 +00001229 else
Greg Clayton4dc18922010-12-08 22:23:24 +00001230 ::snprintf (command_string,
1231 sizeof(command_string),
Greg Claytonabe0fed2011-04-18 08:33:37 +00001232 "target create '%s'",
Greg Clayton4dc18922010-12-08 22:23:24 +00001233 m_option_data.m_args[0].c_str());
Chris Lattner24943d22010-06-08 16:52:24 +00001234
Greg Clayton63094e02010-06-23 01:19:29 +00001235 m_debugger.HandleCommand (command_string);
Greg Clayton4dc18922010-12-08 22:23:24 +00001236
1237 if (num_args > 1)
1238 {
1239 m_debugger.HandleCommand ("settings clear target.process.run-args");
1240 char arg_cstr[1024];
1241 for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx)
1242 {
Jim Ingham83dd2032011-09-13 23:25:31 +00001243 ::snprintf (arg_cstr,
1244 sizeof(arg_cstr),
1245 "settings append target.process.run-args \"%s\"",
1246 m_option_data.m_args[arg_idx].c_str());
Greg Clayton4dc18922010-12-08 22:23:24 +00001247 m_debugger.HandleCommand (arg_cstr);
1248 }
1249 }
Chris Lattner24943d22010-06-08 16:52:24 +00001250 }
1251
1252 // Now that all option parsing is done, we try and parse the .lldbinit
1253 // file in the current working directory
1254 sb_interpreter.SourceInitFileInCurrentWorkingDirectory (result);
1255 if (GetDebugMode())
1256 {
Greg Clayton63094e02010-06-23 01:19:29 +00001257 result.PutError(m_debugger.GetErrorFileHandle());
1258 result.PutOutput(m_debugger.GetOutputFileHandle());
Chris Lattner24943d22010-06-08 16:52:24 +00001259 }
1260
1261 SBEvent event;
1262
1263 // Make sure the IO channel is started up before we try to tell it we
1264 // are ready for input
1265 listener.WaitForEventForBroadcasterWithType (UINT32_MAX,
1266 *m_io_channel_ap,
1267 IOChannel::eBroadcastBitThreadDidStart,
1268 event);
Jim Ingham83dd2032011-09-13 23:25:31 +00001269 // If we were asked to attach, then do that here:
1270 // I'm going to use the command string rather than directly
1271 // calling the API's because then I don't have to recode the
1272 // event handling here.
1273 if (!m_option_data.m_process_name.empty()
1274 || m_option_data.m_process_pid != LLDB_INVALID_PROCESS_ID)
1275 {
1276 std::string command_str("process attach ");
1277 if (m_option_data.m_process_pid != LLDB_INVALID_PROCESS_ID)
1278 {
1279 command_str.append("-p ");
1280 char pid_buffer[32];
1281 ::snprintf (pid_buffer, sizeof(pid_buffer), "%d", m_option_data.m_process_pid);
1282 command_str.append(pid_buffer);
1283 }
1284 else
1285 {
1286 command_str.append("-n \"");
1287 command_str.append(m_option_data.m_process_name);
1288 command_str.push_back('\"');
1289 if (m_option_data.m_wait_for)
1290 command_str.append(" -w");
1291 }
1292
1293 if (m_debugger.GetOutputFileHandle())
1294 ::fprintf (m_debugger.GetOutputFileHandle(),
1295 "Attaching to process with:\n %s\n",
1296 command_str.c_str());
1297
1298 // Force the attach to be synchronous:
1299 bool orig_async = m_debugger.GetAsync();
1300 m_debugger.SetAsync(true);
1301 m_debugger.HandleCommand(command_str.c_str());
1302 m_debugger.SetAsync(orig_async);
1303 }
1304
Chris Lattner24943d22010-06-08 16:52:24 +00001305 ReadyForCommand ();
1306
1307 bool done = false;
1308 while (!done)
1309 {
1310 listener.WaitForEvent (UINT32_MAX, event);
1311 if (event.IsValid())
1312 {
1313 if (event.GetBroadcaster().IsValid())
1314 {
1315 uint32_t event_type = event.GetType();
1316 if (event.BroadcasterMatchesRef (*m_io_channel_ap))
1317 {
1318 if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
1319 (event_type & IOChannel::eBroadcastBitThreadDidExit))
1320 {
1321 done = true;
1322 if (event_type & IOChannel::eBroadcastBitThreadDidExit)
1323 iochannel_thread_exited = true;
Chris Lattner24943d22010-06-08 16:52:24 +00001324 }
1325 else
1326 done = HandleIOEvent (event);
1327 }
Jim Inghamc8332952010-08-26 21:32:51 +00001328 else if (event.BroadcasterMatchesRef (m_debugger.GetSelectedTarget().GetProcess().GetBroadcaster()))
Chris Lattner24943d22010-06-08 16:52:24 +00001329 {
1330 HandleProcessEvent (event);
1331 }
1332 else if (event.BroadcasterMatchesRef (sb_interpreter.GetBroadcaster()))
1333 {
1334 if (event_type & SBCommandInterpreter::eBroadcastBitQuitCommandReceived)
1335 done = true;
Caroline Tice388ca8f2011-05-03 20:53:11 +00001336 else if (event_type & SBCommandInterpreter::eBroadcastBitAsynchronousErrorData)
1337 {
1338 const char *data = SBEvent::GetCStringFromEvent (event);
1339 m_io_channel_ap->ErrWrite (data, strlen(data), ASYNC);
1340 }
1341 else if (event_type & SBCommandInterpreter::eBroadcastBitAsynchronousOutputData)
1342 {
1343 const char *data = SBEvent::GetCStringFromEvent (event);
1344 m_io_channel_ap->OutWrite (data, strlen(data), ASYNC);
1345 }
Chris Lattner24943d22010-06-08 16:52:24 +00001346 }
1347 }
1348 }
1349 }
1350
1351 reset_stdin_termios ();
1352
1353 CloseIOChannelFile ();
1354
1355 if (!iochannel_thread_exited)
1356 {
Greg Claytonbef15832010-07-14 00:18:15 +00001357 event.Clear();
Chris Lattner24943d22010-06-08 16:52:24 +00001358 listener.GetNextEventForBroadcasterWithType (*m_io_channel_ap,
1359 IOChannel::eBroadcastBitThreadDidExit,
1360 event);
1361 if (!event.IsValid())
1362 {
1363 // Send end EOF to the driver file descriptor
1364 m_io_channel_ap->Stop();
1365 }
1366 }
1367
Jim Inghamc8332952010-08-26 21:32:51 +00001368 SBProcess process = m_debugger.GetSelectedTarget().GetProcess();
Chris Lattner24943d22010-06-08 16:52:24 +00001369 if (process.IsValid())
1370 process.Destroy();
1371 }
1372 }
1373}
1374
1375
1376void
1377Driver::ReadyForCommand ()
1378{
1379 if (m_waiting_for_command == false)
1380 {
1381 m_waiting_for_command = true;
1382 BroadcastEventByType (Driver::eBroadcastBitReadyForInput, true);
1383 }
1384}
1385
1386
Caroline Ticeb8314fe2010-09-09 17:45:09 +00001387void
1388sigwinch_handler (int signo)
1389{
1390 struct winsize window_size;
1391 if (isatty (STDIN_FILENO)
1392 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
1393 {
1394 if ((window_size.ws_col > 0) && (strlen (g_debugger_name) > 0))
1395 {
1396 char width_str_buffer[25];
1397 ::sprintf (width_str_buffer, "%d", window_size.ws_col);
1398 SBDebugger::SetInternalVariable ("term-width", width_str_buffer, g_debugger_name);
1399 }
1400 }
1401}
1402
Caroline Ticec4f55fe2010-11-19 20:47:54 +00001403void
1404sigint_handler (int signo)
1405{
1406 static bool g_interrupt_sent = false;
1407 if (g_driver)
1408 {
1409 if (!g_interrupt_sent)
1410 {
1411 g_interrupt_sent = true;
1412 g_driver->GetDebugger().DispatchInputInterrupt();
1413 g_interrupt_sent = false;
1414 return;
1415 }
1416 }
1417
1418 exit (signo);
1419}
1420
Chris Lattner24943d22010-06-08 16:52:24 +00001421int
Jim Inghamb2b604f2011-01-27 20:15:39 +00001422main (int argc, char const *argv[], const char *envp[])
Chris Lattner24943d22010-06-08 16:52:24 +00001423{
Chris Lattner24943d22010-06-08 16:52:24 +00001424 SBDebugger::Initialize();
1425
Greg Clayton95e33b72010-11-07 21:02:03 +00001426 SBHostOS::ThreadCreated ("<lldb.driver.main-thread>");
Chris Lattner24943d22010-06-08 16:52:24 +00001427
Greg Clayton36f63a92010-10-19 03:25:40 +00001428 signal (SIGPIPE, SIG_IGN);
Caroline Ticeb8314fe2010-09-09 17:45:09 +00001429 signal (SIGWINCH, sigwinch_handler);
Caroline Ticec4f55fe2010-11-19 20:47:54 +00001430 signal (SIGINT, sigint_handler);
Caroline Ticeb8314fe2010-09-09 17:45:09 +00001431
Greg Clayton63094e02010-06-23 01:19:29 +00001432 // Create a scope for driver so that the driver object will destroy itself
1433 // before SBDebugger::Terminate() is called.
Chris Lattner24943d22010-06-08 16:52:24 +00001434 {
Greg Clayton63094e02010-06-23 01:19:29 +00001435 Driver driver;
1436
1437 bool exit = false;
1438 SBError error (driver.ParseArgs (argc, argv, stdout, exit));
1439 if (error.Fail())
1440 {
1441 const char *error_cstr = error.GetCString ();
1442 if (error_cstr)
1443 ::fprintf (stderr, "error: %s\n", error_cstr);
1444 }
1445 else if (!exit)
1446 {
1447 driver.MainLoop ();
1448 }
Chris Lattner24943d22010-06-08 16:52:24 +00001449 }
1450
1451 SBDebugger::Terminate();
1452 return 0;
1453}