blob: 6b59b612f24502ecbbb22383c0c68b81497e9b42 [file] [log] [blame]
Chris Lattner30fdc8d2010-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 Friedmana382d472010-06-09 09:50:17 +000017#include <string.h>
18#include <stdlib.h>
19#include <limits.h>
Eli Friedman07b16272010-06-09 19:11:30 +000020#include <fcntl.h>
Daniel Malead01b2952012-11-29 21:49:15 +000021#include <inttypes.h>
Chris Lattner30fdc8d2010-06-08 16:52:24 +000022
23#include <string>
24
25#include "IOChannel.h"
Jim Inghame6bc6cb2012-02-08 05:23:15 +000026#include "lldb/API/SBBreakpoint.h"
Eli Friedmana382d472010-06-09 09:50:17 +000027#include "lldb/API/SBCommandInterpreter.h"
28#include "lldb/API/SBCommandReturnObject.h"
29#include "lldb/API/SBCommunication.h"
30#include "lldb/API/SBDebugger.h"
31#include "lldb/API/SBEvent.h"
32#include "lldb/API/SBHostOS.h"
33#include "lldb/API/SBListener.h"
Jim Ingham85e8b812011-02-19 02:53:09 +000034#include "lldb/API/SBStream.h"
Eli Friedmana382d472010-06-09 09:50:17 +000035#include "lldb/API/SBTarget.h"
36#include "lldb/API/SBThread.h"
37#include "lldb/API/SBProcess.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000038
39using namespace lldb;
40
41static void reset_stdin_termios ();
Greg Claytonf571b892012-02-02 19:28:31 +000042static bool g_old_stdin_termios_is_valid = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000043static struct termios g_old_stdin_termios;
44
Caroline Ticedd759852010-09-09 17:45:09 +000045static char *g_debugger_name = (char *) "";
Caroline Ticeefed6132010-11-19 20:47:54 +000046static Driver *g_driver = NULL;
Caroline Ticedd759852010-09-09 17:45:09 +000047
Chris Lattner30fdc8d2010-06-08 16:52:24 +000048// In the Driver::MainLoop, we change the terminal settings. This function is
49// added as an atexit handler to make sure we clean them up.
50static void
51reset_stdin_termios ()
52{
Greg Claytonf571b892012-02-02 19:28:31 +000053 if (g_old_stdin_termios_is_valid)
54 {
55 g_old_stdin_termios_is_valid = false;
56 ::tcsetattr (STDIN_FILENO, TCSANOW, &g_old_stdin_termios);
57 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +000058}
59
Greg Claytone0d378b2011-03-24 21:19:54 +000060typedef struct
Chris Lattner30fdc8d2010-06-08 16:52:24 +000061{
Greg Claytone0d378b2011-03-24 21:19:54 +000062 uint32_t usage_mask; // Used to mark options that can be used together. If (1 << n & usage_mask) != 0
63 // then this option belongs to option set n.
64 bool required; // This option is required (in the current usage level)
65 const char * long_option; // Full name for this option.
Greg Clayton3bcdfc02012-12-04 00:32:51 +000066 int short_option; // Single character for this option.
Greg Claytone0d378b2011-03-24 21:19:54 +000067 int option_has_arg; // no_argument, required_argument or optional_argument
Greg Claytonab65b342011-04-13 22:47:15 +000068 uint32_t completion_type; // Cookie the option class can use to do define the argument completion.
Greg Claytone0d378b2011-03-24 21:19:54 +000069 lldb::CommandArgumentType argument_type; // Type of argument this option takes
70 const char * usage_text; // Full text explaining what this options does and what (if any) argument to
71 // pass it.
72} OptionDefinition;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000073
Jim Inghame64f0dc2011-09-13 23:25:31 +000074#define LLDB_3_TO_5 LLDB_OPT_SET_3|LLDB_OPT_SET_4|LLDB_OPT_SET_5
75#define LLDB_4_TO_5 LLDB_OPT_SET_4|LLDB_OPT_SET_5
76
Greg Claytone0d378b2011-03-24 21:19:54 +000077static OptionDefinition g_options[] =
78{
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +000079 { LLDB_OPT_SET_1, true , "help" , 'h', no_argument , 0, eArgTypeNone,
Jim Ingham12e9a202011-09-15 21:30:02 +000080 "Prints out the usage information for the LLDB debugger." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +000081 { LLDB_OPT_SET_2, true , "version" , 'v', no_argument , 0, eArgTypeNone,
Jim Ingham12e9a202011-09-15 21:30:02 +000082 "Prints out the current version number of the LLDB debugger." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +000083 { LLDB_OPT_SET_3, true , "arch" , 'a', required_argument, 0, eArgTypeArchitecture,
Jim Ingham12e9a202011-09-15 21:30:02 +000084 "Tells the debugger to use the specified architecture when starting and running the program. <architecture> must "
85 "be one of the architectures for which the program was compiled." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +000086 { LLDB_OPT_SET_3, true , "file" , 'f', required_argument, 0, eArgTypeFilename,
Jim Ingham12e9a202011-09-15 21:30:02 +000087 "Tells the debugger to use the file <filename> as the program to be debugged." },
Jason Molenda67c3cf52012-10-24 03:29:40 +000088 { LLDB_OPT_SET_3, false, "core" , 'c', required_argument, 0, eArgTypeFilename,
Johnny Cheneb46f782012-08-15 22:10:42 +000089 "Tells the debugger to use the fullpath to <path> as the core file." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +000090 { LLDB_OPT_SET_4, true , "attach-name" , 'n', required_argument, 0, eArgTypeProcessName,
Jim Ingham12e9a202011-09-15 21:30:02 +000091 "Tells the debugger to attach to a process with the given name." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +000092 { LLDB_OPT_SET_4, true , "wait-for" , 'w', no_argument , 0, eArgTypeNone,
Jim Ingham12e9a202011-09-15 21:30:02 +000093 "Tells the debugger to wait for a process with the given pid or name to launch before attaching." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +000094 { LLDB_OPT_SET_5, true , "attach-pid" , 'p', required_argument, 0, eArgTypePid,
Jim Ingham12e9a202011-09-15 21:30:02 +000095 "Tells the debugger to attach to a process with the given pid." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +000096 { LLDB_3_TO_5, false, "script-language", 'l', required_argument, 0, eArgTypeScriptLang,
Jim Ingham12e9a202011-09-15 21:30:02 +000097 "Tells the debugger to use the specified scripting language for user-defined scripts, rather than the default. "
98 "Valid scripting languages that can be specified include Python, Perl, Ruby and Tcl. Currently only the Python "
99 "extensions have been implemented." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +0000100 { LLDB_3_TO_5, false, "debug" , 'd', no_argument , 0, eArgTypeNone,
Jim Ingham12e9a202011-09-15 21:30:02 +0000101 "Tells the debugger to print out extra information for debugging itself." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +0000102 { LLDB_3_TO_5, false, "source" , 's', required_argument, 0, eArgTypeFilename,
Jim Ingham12e9a202011-09-15 21:30:02 +0000103 "Tells the debugger to read in and execute the file <file>, which should contain lldb commands." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +0000104 { LLDB_3_TO_5, false, "editor" , 'e', no_argument , 0, eArgTypeNone,
Jim Ingham12e9a202011-09-15 21:30:02 +0000105 "Tells the debugger to open source files using the host's \"external editor\" mechanism." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +0000106 { LLDB_3_TO_5, false, "no-lldbinit" , 'x', no_argument , 0, eArgTypeNone,
Jim Ingham12e9a202011-09-15 21:30:02 +0000107 "Do not automatically parse any '.lldbinit' files." },
Jim Inghame2231ac2012-12-21 22:22:26 +0000108 { LLDB_OPT_SET_6, true , "python-path" , 'P', no_argument , 0, eArgTypeNone,
109 "Prints out the path to the lldb.py file for this version of lldb." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +0000110 { 0, false, NULL , 0 , 0 , 0, eArgTypeNone, NULL }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000111};
112
Jim Inghame64f0dc2011-09-13 23:25:31 +0000113static const uint32_t last_option_set_with_args = 2;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000114
115Driver::Driver () :
116 SBBroadcaster ("Driver"),
Jim Ingham06942692011-08-13 00:22:20 +0000117 m_debugger (SBDebugger::Create(false)),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000118 m_editline_pty (),
119 m_editline_slave_fh (NULL),
120 m_editline_reader (),
121 m_io_channel_ap (),
122 m_option_data (),
Daniel Malea926758b2012-12-17 17:40:07 +0000123 m_waiting_for_command (false),
124 m_done(false)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000125{
Greg Claytonfc3f0272011-05-29 04:06:55 +0000126 // We want to be able to handle CTRL+D in the terminal to have it terminate
127 // certain input
128 m_debugger.SetCloseInputOnEOF (false);
Caroline Ticedd759852010-09-09 17:45:09 +0000129 g_debugger_name = (char *) m_debugger.GetInstanceName();
130 if (g_debugger_name == NULL)
131 g_debugger_name = (char *) "";
Caroline Ticeefed6132010-11-19 20:47:54 +0000132 g_driver = this;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000133}
134
135Driver::~Driver ()
136{
Caroline Ticeefed6132010-11-19 20:47:54 +0000137 g_driver = NULL;
138 g_debugger_name = NULL;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000139}
140
141void
142Driver::CloseIOChannelFile ()
143{
Johnny Chene26c7212012-05-16 22:01:10 +0000144 // Write an End of File sequence to the file descriptor to ensure any
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000145 // read functions can exit.
146 char eof_str[] = "\x04";
147 ::write (m_editline_pty.GetMasterFileDescriptor(), eof_str, strlen(eof_str));
148
149 m_editline_pty.CloseMasterFileDescriptor();
150
151 if (m_editline_slave_fh)
152 {
153 ::fclose (m_editline_slave_fh);
154 m_editline_slave_fh = NULL;
155 }
156}
157
Greg Claytonc982c762010-07-09 20:39:50 +0000158// This function takes INDENT, which tells how many spaces to output at the front
159// of each line; TEXT, which is the text that is to be output. It outputs the
160// text, on multiple lines if necessary, to RESULT, with INDENT spaces at the
161// front of each line. It breaks lines on spaces, tabs or newlines, shortening
162// the line if necessary to not break in the middle of a word. It assumes that
163// each output line should contain a maximum of OUTPUT_MAX_COLUMNS characters.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000164
165void
Greg Claytonc982c762010-07-09 20:39:50 +0000166OutputFormattedUsageText (FILE *out, int indent, const char *text, int output_max_columns)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000167{
168 int len = strlen (text);
169 std::string text_string (text);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000170
171 // Force indentation to be reasonable.
172 if (indent >= output_max_columns)
173 indent = 0;
174
175 // Will it all fit on one line?
176
177 if (len + indent < output_max_columns)
178 // Output as a single line
Greg Claytonc982c762010-07-09 20:39:50 +0000179 fprintf (out, "%*s%s\n", indent, "", text);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000180 else
181 {
182 // We need to break it up into multiple lines.
183 int text_width = output_max_columns - indent - 1;
184 int start = 0;
185 int end = start;
186 int final_end = len;
187 int sub_len;
188
189 while (end < final_end)
190 {
191 // Dont start the 'text' on a space, since we're already outputting the indentation.
192 while ((start < final_end) && (text[start] == ' '))
193 start++;
194
195 end = start + text_width;
196 if (end > final_end)
197 end = final_end;
198 else
199 {
200 // If we're not at the end of the text, make sure we break the line on white space.
201 while (end > start
202 && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
203 end--;
204 }
205 sub_len = end - start;
206 std::string substring = text_string.substr (start, sub_len);
Greg Claytonc982c762010-07-09 20:39:50 +0000207 fprintf (out, "%*s%s\n", indent, "", substring.c_str());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000208 start = end + 1;
209 }
210 }
211}
212
213void
Greg Claytone0d378b2011-03-24 21:19:54 +0000214ShowUsage (FILE *out, OptionDefinition *option_table, Driver::OptionData data)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000215{
216 uint32_t screen_width = 80;
217 uint32_t indent_level = 0;
218 const char *name = "lldb";
Jim Ingham86511212010-06-15 18:47:14 +0000219
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000220 fprintf (out, "\nUsage:\n\n");
221
222 indent_level += 2;
223
224
225 // First, show each usage level set of options, e.g. <cmd> [options-for-level-0]
226 // <cmd> [options-for-level-1]
227 // etc.
228
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000229 uint32_t num_options;
Jim Ingham86511212010-06-15 18:47:14 +0000230 uint32_t num_option_sets = 0;
231
232 for (num_options = 0; option_table[num_options].long_option != NULL; ++num_options)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000233 {
Jim Ingham86511212010-06-15 18:47:14 +0000234 uint32_t this_usage_mask = option_table[num_options].usage_mask;
235 if (this_usage_mask == LLDB_OPT_SET_ALL)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000236 {
Jim Ingham86511212010-06-15 18:47:14 +0000237 if (num_option_sets == 0)
238 num_option_sets = 1;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000239 }
240 else
241 {
Greg Claytonc982c762010-07-09 20:39:50 +0000242 for (uint32_t j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++)
Jim Ingham86511212010-06-15 18:47:14 +0000243 {
244 if (this_usage_mask & 1 << j)
245 {
246 if (num_option_sets <= j)
247 num_option_sets = j + 1;
248 }
249 }
250 }
251 }
252
253 for (uint32_t opt_set = 0; opt_set < num_option_sets; opt_set++)
254 {
255 uint32_t opt_set_mask;
256
257 opt_set_mask = 1 << opt_set;
258
259 if (opt_set > 0)
260 fprintf (out, "\n");
Greg Claytonc982c762010-07-09 20:39:50 +0000261 fprintf (out, "%*s%s", indent_level, "", name);
Jim Ingham556e6532011-08-16 23:15:02 +0000262 bool is_help_line = false;
Jim Ingham86511212010-06-15 18:47:14 +0000263
264 for (uint32_t i = 0; i < num_options; ++i)
265 {
266 if (option_table[i].usage_mask & opt_set_mask)
267 {
Caroline Ticedeaab222010-10-01 19:59:14 +0000268 CommandArgumentType arg_type = option_table[i].argument_type;
Greg Clayton9d0402b2011-02-20 02:15:07 +0000269 const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type);
Jim Ingham556e6532011-08-16 23:15:02 +0000270 // This is a bit of a hack, but there's no way to say certain options don't have arguments yet...
271 // so we do it by hand here.
272 if (option_table[i].short_option == 'h')
273 is_help_line = true;
274
Jim Ingham86511212010-06-15 18:47:14 +0000275 if (option_table[i].required)
276 {
277 if (option_table[i].option_has_arg == required_argument)
Greg Clayton9d0402b2011-02-20 02:15:07 +0000278 fprintf (out, " -%c <%s>", option_table[i].short_option, arg_name);
Jim Ingham86511212010-06-15 18:47:14 +0000279 else if (option_table[i].option_has_arg == optional_argument)
Greg Clayton9d0402b2011-02-20 02:15:07 +0000280 fprintf (out, " -%c [<%s>]", option_table[i].short_option, arg_name);
Jim Ingham86511212010-06-15 18:47:14 +0000281 else
282 fprintf (out, " -%c", option_table[i].short_option);
283 }
284 else
285 {
286 if (option_table[i].option_has_arg == required_argument)
Greg Clayton9d0402b2011-02-20 02:15:07 +0000287 fprintf (out, " [-%c <%s>]", option_table[i].short_option, arg_name);
Jim Ingham86511212010-06-15 18:47:14 +0000288 else if (option_table[i].option_has_arg == optional_argument)
Greg Clayton9d0402b2011-02-20 02:15:07 +0000289 fprintf (out, " [-%c [<%s>]]", option_table[i].short_option, arg_name);
Jim Ingham86511212010-06-15 18:47:14 +0000290 else
291 fprintf (out, " [-%c]", option_table[i].short_option);
292 }
293 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000294 }
Jim Inghame64f0dc2011-09-13 23:25:31 +0000295 if (!is_help_line && (opt_set <= last_option_set_with_args))
Jim Ingham556e6532011-08-16 23:15:02 +0000296 fprintf (out, " [[--] <PROGRAM-ARG-1> [<PROGRAM_ARG-2> ...]]");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000297 }
298
299 fprintf (out, "\n\n");
300
301 // Now print out all the detailed information about the various options: long form, short form and help text:
302 // -- long_name <argument>
303 // - short <argument>
304 // help text
305
306 // This variable is used to keep track of which options' info we've printed out, because some options can be in
307 // more than one usage level, but we only want to print the long form of its information once.
308
309 Driver::OptionData::OptionSet options_seen;
310 Driver::OptionData::OptionSet::iterator pos;
311
312 indent_level += 5;
313
Jim Ingham86511212010-06-15 18:47:14 +0000314 for (uint32_t i = 0; i < num_options; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000315 {
316 // Only print this option if we haven't already seen it.
317 pos = options_seen.find (option_table[i].short_option);
318 if (pos == options_seen.end())
319 {
Caroline Ticedeaab222010-10-01 19:59:14 +0000320 CommandArgumentType arg_type = option_table[i].argument_type;
Greg Clayton9d0402b2011-02-20 02:15:07 +0000321 const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type);
Caroline Ticedeaab222010-10-01 19:59:14 +0000322
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000323 options_seen.insert (option_table[i].short_option);
Greg Claytonc982c762010-07-09 20:39:50 +0000324 fprintf (out, "%*s-%c ", indent_level, "", option_table[i].short_option);
Caroline Ticedeaab222010-10-01 19:59:14 +0000325 if (arg_type != eArgTypeNone)
Greg Clayton9d0402b2011-02-20 02:15:07 +0000326 fprintf (out, "<%s>", arg_name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000327 fprintf (out, "\n");
Greg Claytonc982c762010-07-09 20:39:50 +0000328 fprintf (out, "%*s--%s ", indent_level, "", option_table[i].long_option);
Caroline Ticedeaab222010-10-01 19:59:14 +0000329 if (arg_type != eArgTypeNone)
Greg Clayton9d0402b2011-02-20 02:15:07 +0000330 fprintf (out, "<%s>", arg_name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000331 fprintf (out, "\n");
332 indent_level += 5;
Greg Claytonc982c762010-07-09 20:39:50 +0000333 OutputFormattedUsageText (out, indent_level, option_table[i].usage_text, screen_width);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000334 indent_level -= 5;
335 fprintf (out, "\n");
336 }
337 }
338
339 indent_level -= 5;
340
Jim Inghama9deaf92011-08-16 23:57:58 +0000341 fprintf (out, "\n%*s(If you don't provide -f then the first argument will be the file to be debugged"
342 "\n%*s so '%s -- <filename> [<ARG1> [<ARG2>]]' also works."
343 "\n%*s Remember to end the options with \"--\" if any of your arguments have a \"-\" in them.)\n\n",
344 indent_level, "",
345 indent_level, "",
346 name,
347 indent_level, "");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000348}
349
350void
Greg Claytone0d378b2011-03-24 21:19:54 +0000351BuildGetOptTable (OptionDefinition *expanded_option_table, std::vector<struct option> &getopt_table,
Caroline Tice4ab31c92010-10-12 21:57:09 +0000352 uint32_t num_options)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000353{
354 if (num_options == 0)
355 return;
356
357 uint32_t i;
358 uint32_t j;
359 std::bitset<256> option_seen;
360
Caroline Tice4ab31c92010-10-12 21:57:09 +0000361 getopt_table.resize (num_options + 1);
362
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000363 for (i = 0, j = 0; i < num_options; ++i)
Greg Claytonc982c762010-07-09 20:39:50 +0000364 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000365 char short_opt = expanded_option_table[i].short_option;
Greg Claytonc982c762010-07-09 20:39:50 +0000366
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000367 if (option_seen.test(short_opt) == false)
Greg Claytonc982c762010-07-09 20:39:50 +0000368 {
Caroline Tice4ab31c92010-10-12 21:57:09 +0000369 getopt_table[j].name = expanded_option_table[i].long_option;
370 getopt_table[j].has_arg = expanded_option_table[i].option_has_arg;
371 getopt_table[j].flag = NULL;
372 getopt_table[j].val = expanded_option_table[i].short_option;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000373 option_seen.set(short_opt);
374 ++j;
Greg Claytonc982c762010-07-09 20:39:50 +0000375 }
376 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000377
Caroline Tice4ab31c92010-10-12 21:57:09 +0000378 getopt_table[j].name = NULL;
379 getopt_table[j].has_arg = 0;
380 getopt_table[j].flag = NULL;
381 getopt_table[j].val = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000382
383}
384
Greg Clayton66111032010-06-23 01:19:29 +0000385Driver::OptionData::OptionData () :
Greg Clayton8d846da2010-12-08 22:23:24 +0000386 m_args(),
Greg Clayton66111032010-06-23 01:19:29 +0000387 m_script_lang (lldb::eScriptLanguageDefault),
Johnny Cheneb46f782012-08-15 22:10:42 +0000388 m_core_file (),
Greg Claytonc982c762010-07-09 20:39:50 +0000389 m_crash_log (),
Greg Clayton66111032010-06-23 01:19:29 +0000390 m_source_command_files (),
391 m_debug_mode (false),
Greg Claytonc982c762010-07-09 20:39:50 +0000392 m_print_version (false),
Jim Inghame2231ac2012-12-21 22:22:26 +0000393 m_print_python_path (false),
Greg Clayton66111032010-06-23 01:19:29 +0000394 m_print_help (false),
Jim Inghame64f0dc2011-09-13 23:25:31 +0000395 m_wait_for(false),
396 m_process_name(),
397 m_process_pid(LLDB_INVALID_PROCESS_ID),
Daniel Dunbara08823f2011-10-31 22:50:49 +0000398 m_use_external_editor(false),
Stephen Wilson71c21d12011-04-11 19:41:40 +0000399 m_seen_options()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000400{
Greg Clayton66111032010-06-23 01:19:29 +0000401}
402
403Driver::OptionData::~OptionData ()
404{
405}
406
407void
408Driver::OptionData::Clear ()
409{
Greg Clayton8d846da2010-12-08 22:23:24 +0000410 m_args.clear ();
Greg Clayton66111032010-06-23 01:19:29 +0000411 m_script_lang = lldb::eScriptLanguageDefault;
412 m_source_command_files.clear ();
413 m_debug_mode = false;
414 m_print_help = false;
415 m_print_version = false;
Jim Inghame2231ac2012-12-21 22:22:26 +0000416 m_print_python_path = false;
Jim Inghame40e4212010-08-30 19:44:40 +0000417 m_use_external_editor = false;
Jim Inghame64f0dc2011-09-13 23:25:31 +0000418 m_wait_for = false;
419 m_process_name.erase();
420 m_process_pid = LLDB_INVALID_PROCESS_ID;
Greg Clayton66111032010-06-23 01:19:29 +0000421}
422
423void
424Driver::ResetOptionValues ()
425{
426 m_option_data.Clear ();
427}
428
429const char *
430Driver::GetFilename() const
431{
Greg Clayton8d846da2010-12-08 22:23:24 +0000432 if (m_option_data.m_args.empty())
Greg Clayton66111032010-06-23 01:19:29 +0000433 return NULL;
Greg Clayton8d846da2010-12-08 22:23:24 +0000434 return m_option_data.m_args.front().c_str();
Greg Clayton66111032010-06-23 01:19:29 +0000435}
436
437const char *
438Driver::GetCrashLogFilename() const
439{
440 if (m_option_data.m_crash_log.empty())
441 return NULL;
442 return m_option_data.m_crash_log.c_str();
443}
444
445lldb::ScriptLanguage
446Driver::GetScriptLanguage() const
447{
448 return m_option_data.m_script_lang;
449}
450
451size_t
452Driver::GetNumSourceCommandFiles () const
453{
454 return m_option_data.m_source_command_files.size();
455}
456
457const char *
458Driver::GetSourceCommandFileAtIndex (uint32_t idx) const
459{
460 if (idx < m_option_data.m_source_command_files.size())
461 return m_option_data.m_source_command_files[idx].c_str();
462 return NULL;
463}
464
465bool
466Driver::GetDebugMode() const
467{
468 return m_option_data.m_debug_mode;
469}
470
471
472// Check the arguments that were passed to this program to make sure they are valid and to get their
473// argument values (if any). Return a boolean value indicating whether or not to start up the full
474// debugger (i.e. the Command Interpreter) or not. Return FALSE if the arguments were invalid OR
475// if the user only wanted help or version information.
476
477SBError
478Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exit)
479{
480 ResetOptionValues ();
481
482 SBCommandReturnObject result;
483
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000484 SBError error;
485 std::string option_string;
486 struct option *long_options = NULL;
Caroline Tice4ab31c92010-10-12 21:57:09 +0000487 std::vector<struct option> long_options_vector;
Greg Claytonc982c762010-07-09 20:39:50 +0000488 uint32_t num_options;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000489
Greg Claytonc982c762010-07-09 20:39:50 +0000490 for (num_options = 0; g_options[num_options].long_option != NULL; ++num_options)
491 /* Do Nothing. */;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000492
493 if (num_options == 0)
494 {
495 if (argc > 1)
496 error.SetErrorStringWithFormat ("invalid number of options");
497 return error;
498 }
499
Caroline Tice4ab31c92010-10-12 21:57:09 +0000500 BuildGetOptTable (g_options, long_options_vector, num_options);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000501
Caroline Tice4ab31c92010-10-12 21:57:09 +0000502 if (long_options_vector.empty())
503 long_options = NULL;
504 else
505 long_options = &long_options_vector.front();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000506
507 if (long_options == NULL)
508 {
509 error.SetErrorStringWithFormat ("invalid long options");
510 return error;
511 }
512
513 // Build the option_string argument for call to getopt_long.
514
515 for (int i = 0; long_options[i].name != NULL; ++i)
516 {
517 if (long_options[i].flag == NULL)
518 {
519 option_string.push_back ((char) long_options[i].val);
520 switch (long_options[i].has_arg)
521 {
522 default:
523 case no_argument:
524 break;
525 case required_argument:
526 option_string.push_back (':');
527 break;
528 case optional_argument:
529 option_string.append ("::");
530 break;
531 }
532 }
533 }
534
Jim Ingham06942692011-08-13 00:22:20 +0000535 // This is kind of a pain, but since we make the debugger in the Driver's constructor, we can't
536 // know at that point whether we should read in init files yet. So we don't read them in in the
537 // Driver constructor, then set the flags back to "read them in" here, and then if we see the
538 // "-n" flag, we'll turn it off again. Finally we have to read them in by hand later in the
539 // main loop.
540
541 m_debugger.SkipLLDBInitFiles (false);
542 m_debugger.SkipAppInitFiles (false);
543
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000544 // Prepare for & make calls to getopt_long.
Eli Friedmanadb35022010-06-13 19:18:49 +0000545#if __GLIBC__
546 optind = 0;
547#else
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000548 optreset = 1;
549 optind = 1;
Eli Friedmanadb35022010-06-13 19:18:49 +0000550#endif
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000551 int val;
552 while (1)
553 {
554 int long_options_index = -1;
Greg Claytonc982c762010-07-09 20:39:50 +0000555 val = ::getopt_long (argc, const_cast<char **>(argv), option_string.c_str(), long_options, &long_options_index);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000556
557 if (val == -1)
558 break;
559 else if (val == '?')
560 {
Greg Clayton66111032010-06-23 01:19:29 +0000561 m_option_data.m_print_help = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000562 error.SetErrorStringWithFormat ("unknown or ambiguous option");
563 break;
564 }
565 else if (val == 0)
566 continue;
567 else
568 {
Greg Clayton66111032010-06-23 01:19:29 +0000569 m_option_data.m_seen_options.insert ((char) val);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000570 if (long_options_index == -1)
571 {
572 for (int i = 0;
573 long_options[i].name || long_options[i].has_arg || long_options[i].flag || long_options[i].val;
574 ++i)
575 {
576 if (long_options[i].val == val)
577 {
578 long_options_index = i;
579 break;
580 }
581 }
582 }
583
584 if (long_options_index >= 0)
585 {
Greg Clayton3bcdfc02012-12-04 00:32:51 +0000586 const int short_option = g_options[long_options_index].short_option;
Greg Clayton66111032010-06-23 01:19:29 +0000587
588 switch (short_option)
589 {
590 case 'h':
591 m_option_data.m_print_help = true;
592 break;
593
594 case 'v':
595 m_option_data.m_print_version = true;
596 break;
597
Jim Inghame2231ac2012-12-21 22:22:26 +0000598 case 'P':
599 m_option_data.m_print_python_path = true;
600 break;
601
Greg Clayton66111032010-06-23 01:19:29 +0000602 case 'c':
Johnny Cheneb46f782012-08-15 22:10:42 +0000603 {
604 SBFileSpec file(optarg);
605 if (file.Exists())
606 {
607 m_option_data.m_core_file = optarg;
608 }
609 else
610 error.SetErrorStringWithFormat("file specified in --core (-c) option doesn't exist: '%s'", optarg);
611 }
Greg Clayton66111032010-06-23 01:19:29 +0000612 break;
Johnny Cheneb46f782012-08-15 22:10:42 +0000613
Jim Inghame40e4212010-08-30 19:44:40 +0000614 case 'e':
615 m_option_data.m_use_external_editor = true;
616 break;
Greg Clayton6eee5aa2010-10-11 01:05:37 +0000617
Jim Inghame64f0dc2011-09-13 23:25:31 +0000618 case 'x':
Greg Clayton6eee5aa2010-10-11 01:05:37 +0000619 m_debugger.SkipLLDBInitFiles (true);
Jim Ingham06942692011-08-13 00:22:20 +0000620 m_debugger.SkipAppInitFiles (true);
Greg Clayton6eee5aa2010-10-11 01:05:37 +0000621 break;
622
Greg Clayton66111032010-06-23 01:19:29 +0000623 case 'f':
624 {
625 SBFileSpec file(optarg);
626 if (file.Exists())
Greg Clayton8d846da2010-12-08 22:23:24 +0000627 {
628 m_option_data.m_args.push_back (optarg);
629 }
Caroline Tice428a9a52010-09-10 04:48:55 +0000630 else if (file.ResolveExecutableLocation())
631 {
632 char path[PATH_MAX];
Johnny Chen25f3a3c2011-08-10 22:06:24 +0000633 file.GetPath (path, sizeof(path));
Greg Clayton8d846da2010-12-08 22:23:24 +0000634 m_option_data.m_args.push_back (path);
Caroline Tice428a9a52010-09-10 04:48:55 +0000635 }
Greg Clayton66111032010-06-23 01:19:29 +0000636 else
637 error.SetErrorStringWithFormat("file specified in --file (-f) option doesn't exist: '%s'", optarg);
638 }
639 break;
640
641 case 'a':
642 if (!m_debugger.SetDefaultArchitecture (optarg))
643 error.SetErrorStringWithFormat("invalid architecture in the -a or --arch option: '%s'", optarg);
644 break;
645
646 case 'l':
647 m_option_data.m_script_lang = m_debugger.GetScriptingLanguage (optarg);
648 break;
649
650 case 'd':
651 m_option_data.m_debug_mode = true;
652 break;
653
Jim Inghame64f0dc2011-09-13 23:25:31 +0000654 case 'n':
655 m_option_data.m_process_name = optarg;
656 break;
657
658 case 'w':
659 m_option_data.m_wait_for = true;
660 break;
661
662 case 'p':
663 {
664 char *remainder;
665 m_option_data.m_process_pid = strtol (optarg, &remainder, 0);
666 if (remainder == optarg || *remainder != '\0')
667 error.SetErrorStringWithFormat ("Could not convert process PID: \"%s\" into a pid.",
668 optarg);
669 }
670 break;
Greg Clayton66111032010-06-23 01:19:29 +0000671 case 's':
672 {
673 SBFileSpec file(optarg);
674 if (file.Exists())
675 m_option_data.m_source_command_files.push_back (optarg);
Caroline Tice428a9a52010-09-10 04:48:55 +0000676 else if (file.ResolveExecutableLocation())
677 {
678 char final_path[PATH_MAX];
Johnny Chen25f3a3c2011-08-10 22:06:24 +0000679 file.GetPath (final_path, sizeof(final_path));
Caroline Tice428a9a52010-09-10 04:48:55 +0000680 std::string path_str (final_path);
681 m_option_data.m_source_command_files.push_back (path_str);
682 }
Greg Clayton66111032010-06-23 01:19:29 +0000683 else
684 error.SetErrorStringWithFormat("file specified in --source (-s) option doesn't exist: '%s'", optarg);
685 }
686 break;
687
688 default:
689 m_option_data.m_print_help = true;
690 error.SetErrorStringWithFormat ("unrecognized option %c", short_option);
691 break;
692 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000693 }
694 else
695 {
696 error.SetErrorStringWithFormat ("invalid option with value %i", val);
697 }
698 if (error.Fail())
Caroline Tice4ab31c92010-10-12 21:57:09 +0000699 {
Greg Clayton66111032010-06-23 01:19:29 +0000700 return error;
Caroline Tice4ab31c92010-10-12 21:57:09 +0000701 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000702 }
703 }
Jim Ingham86511212010-06-15 18:47:14 +0000704
Greg Clayton66111032010-06-23 01:19:29 +0000705 if (error.Fail() || m_option_data.m_print_help)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000706 {
707 ShowUsage (out_fh, g_options, m_option_data);
Greg Claytone46dd322010-10-11 01:13:37 +0000708 exit = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000709 }
710 else if (m_option_data.m_print_version)
711 {
Greg Clayton66111032010-06-23 01:19:29 +0000712 ::fprintf (out_fh, "%s\n", m_debugger.GetVersionString());
713 exit = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000714 }
Jim Inghame2231ac2012-12-21 22:22:26 +0000715 else if (m_option_data.m_print_python_path)
716 {
717 SBFileSpec python_file_spec = SBHostOS::GetLLDBPythonPath();
718 if (python_file_spec.IsValid())
719 {
720 char python_path[PATH_MAX];
721 size_t num_chars = python_file_spec.GetPath(python_path, PATH_MAX);
722 if (num_chars < PATH_MAX)
723 {
724 ::fprintf (out_fh, "%s\n", python_path);
725 }
726 else
727 ::fprintf (out_fh, "<PATH TOO LONG>\n");
728 }
729 else
730 ::fprintf (out_fh, "<COULD NOT FIND PATH>\n");
731 exit = true;
732 }
Jim Inghame64f0dc2011-09-13 23:25:31 +0000733 else if (m_option_data.m_process_name.empty() && m_option_data.m_process_pid == LLDB_INVALID_PROCESS_ID)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000734 {
Greg Clayton8d846da2010-12-08 22:23:24 +0000735 // Any arguments that are left over after option parsing are for
736 // the program. If a file was specified with -f then the filename
737 // is already in the m_option_data.m_args array, and any remaining args
738 // are arguments for the inferior program. If no file was specified with
739 // -f, then what is left is the program name followed by any arguments.
740
741 // Skip any options we consumed with getopt_long
742 argc -= optind;
743 argv += optind;
744
745 if (argc > 0)
746 {
747 for (int arg_idx=0; arg_idx<argc; ++arg_idx)
748 {
749 const char *arg = argv[arg_idx];
750 if (arg)
751 m_option_data.m_args.push_back (arg);
752 }
753 }
754
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000755 }
Jim Inghame64f0dc2011-09-13 23:25:31 +0000756 else
757 {
758 // Skip any options we consumed with getopt_long
759 argc -= optind;
Greg Clayton23f59502012-07-17 03:23:13 +0000760 //argv += optind; // Commented out to keep static analyzer happy
Jim Inghame64f0dc2011-09-13 23:25:31 +0000761
762 if (argc > 0)
763 ::fprintf (out_fh, "Warning: program arguments are ignored when attaching.\n");
764 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000765
Greg Clayton66111032010-06-23 01:19:29 +0000766 return error;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000767}
768
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000769size_t
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000770Driver::GetProcessSTDOUT ()
771{
772 // The process has stuff waiting for stdout; get it and write it out to the appropriate place.
773 char stdio_buffer[1024];
774 size_t len;
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000775 size_t total_bytes = 0;
Jim Ingham2976d002010-08-26 21:32:51 +0000776 while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0)
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000777 {
Caroline Tice969ed3d2011-05-02 20:41:46 +0000778 m_io_channel_ap->OutWrite (stdio_buffer, len, ASYNC);
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000779 total_bytes += len;
780 }
781 return total_bytes;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000782}
783
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000784size_t
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000785Driver::GetProcessSTDERR ()
786{
787 // The process has stuff waiting for stderr; get it and write it out to the appropriate place.
788 char stdio_buffer[1024];
789 size_t len;
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000790 size_t total_bytes = 0;
Jim Ingham2976d002010-08-26 21:32:51 +0000791 while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0)
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000792 {
Caroline Tice969ed3d2011-05-02 20:41:46 +0000793 m_io_channel_ap->ErrWrite (stdio_buffer, len, ASYNC);
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000794 total_bytes += len;
795 }
796 return total_bytes;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000797}
798
799void
Jim Ingham2976d002010-08-26 21:32:51 +0000800Driver::UpdateSelectedThread ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000801{
802 using namespace lldb;
Jim Ingham2976d002010-08-26 21:32:51 +0000803 SBProcess process(m_debugger.GetSelectedTarget().GetProcess());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000804 if (process.IsValid())
805 {
Jim Ingham2976d002010-08-26 21:32:51 +0000806 SBThread curr_thread (process.GetSelectedThread());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000807 SBThread thread;
808 StopReason curr_thread_stop_reason = eStopReasonInvalid;
809 curr_thread_stop_reason = curr_thread.GetStopReason();
810
811 if (!curr_thread.IsValid() ||
812 curr_thread_stop_reason == eStopReasonInvalid ||
813 curr_thread_stop_reason == eStopReasonNone)
814 {
815 // Prefer a thread that has just completed its plan over another thread as current thread.
816 SBThread plan_thread;
817 SBThread other_thread;
818 const size_t num_threads = process.GetNumThreads();
819 size_t i;
820 for (i = 0; i < num_threads; ++i)
821 {
822 thread = process.GetThreadAtIndex(i);
823 StopReason thread_stop_reason = thread.GetStopReason();
824 switch (thread_stop_reason)
825 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000826 case eStopReasonInvalid:
827 case eStopReasonNone:
828 break;
829
830 case eStopReasonTrace:
831 case eStopReasonBreakpoint:
832 case eStopReasonWatchpoint:
833 case eStopReasonSignal:
834 case eStopReasonException:
Greg Clayton90ba8112012-12-05 00:16:59 +0000835 case eStopReasonExec:
Andrew Kaylorf85defa2012-12-20 23:08:03 +0000836 case eStopReasonThreadExiting:
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000837 if (!other_thread.IsValid())
838 other_thread = thread;
839 break;
840 case eStopReasonPlanComplete:
841 if (!plan_thread.IsValid())
842 plan_thread = thread;
843 break;
844 }
845 }
846 if (plan_thread.IsValid())
Jim Ingham2976d002010-08-26 21:32:51 +0000847 process.SetSelectedThread (plan_thread);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000848 else if (other_thread.IsValid())
Jim Ingham2976d002010-08-26 21:32:51 +0000849 process.SetSelectedThread (other_thread);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000850 else
851 {
852 if (curr_thread.IsValid())
853 thread = curr_thread;
854 else
855 thread = process.GetThreadAtIndex(0);
856
857 if (thread.IsValid())
Jim Ingham2976d002010-08-26 21:32:51 +0000858 process.SetSelectedThread (thread);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000859 }
860 }
861 }
862}
863
Jim Inghame6bc6cb2012-02-08 05:23:15 +0000864// This function handles events that were broadcast by the process.
865void
866Driver::HandleBreakpointEvent (const SBEvent &event)
867{
868 using namespace lldb;
869 const uint32_t event_type = SBBreakpoint::GetBreakpointEventTypeFromEvent (event);
870
871 if (event_type & eBreakpointEventTypeAdded
872 || event_type & eBreakpointEventTypeRemoved
873 || event_type & eBreakpointEventTypeEnabled
874 || event_type & eBreakpointEventTypeDisabled
875 || event_type & eBreakpointEventTypeCommandChanged
876 || event_type & eBreakpointEventTypeConditionChanged
877 || event_type & eBreakpointEventTypeIgnoreChanged
878 || event_type & eBreakpointEventTypeLocationsResolved)
879 {
880 // Don't do anything about these events, since the breakpoint commands already echo these actions.
881 }
882 else if (event_type & eBreakpointEventTypeLocationsAdded)
883 {
884 char message[256];
885 uint32_t num_new_locations = SBBreakpoint::GetNumBreakpointLocationsFromEvent(event);
886 if (num_new_locations > 0)
887 {
888 SBBreakpoint breakpoint = SBBreakpoint::GetBreakpointFromEvent(event);
Jim Inghamfab10e82012-03-06 00:37:27 +0000889 int message_len = ::snprintf (message, sizeof(message), "%d location%s added to breakpoint %d\n",
Jim Inghame6bc6cb2012-02-08 05:23:15 +0000890 num_new_locations,
Jason Molenda65c28cb2012-09-28 01:50:47 +0000891 num_new_locations == 1 ? "" : "s",
Jim Inghame6bc6cb2012-02-08 05:23:15 +0000892 breakpoint.GetID());
893 m_io_channel_ap->OutWrite(message, message_len, ASYNC);
894 }
895 }
896 else if (event_type & eBreakpointEventTypeLocationsRemoved)
897 {
898 // These locations just get disabled, not sure it is worth spamming folks about this on the command line.
899 }
900 else if (event_type & eBreakpointEventTypeLocationsResolved)
901 {
902 // This might be an interesting thing to note, but I'm going to leave it quiet for now, it just looked noisy.
903 }
904}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000905
906// This function handles events that were broadcast by the process.
907void
908Driver::HandleProcessEvent (const SBEvent &event)
909{
910 using namespace lldb;
911 const uint32_t event_type = event.GetType();
912
913 if (event_type & SBProcess::eBroadcastBitSTDOUT)
914 {
915 // The process has stdout available, get it and write it out to the
916 // appropriate place.
Caroline Tice969ed3d2011-05-02 20:41:46 +0000917 GetProcessSTDOUT ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000918 }
919 else if (event_type & SBProcess::eBroadcastBitSTDERR)
920 {
921 // The process has stderr available, get it and write it out to the
922 // appropriate place.
Caroline Tice969ed3d2011-05-02 20:41:46 +0000923 GetProcessSTDERR ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000924 }
925 else if (event_type & SBProcess::eBroadcastBitStateChanged)
926 {
927 // Drain all stout and stderr so we don't see any output come after
928 // we print our prompts
Caroline Tice969ed3d2011-05-02 20:41:46 +0000929 GetProcessSTDOUT ();
930 GetProcessSTDERR ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000931 // Something changed in the process; get the event and report the process's current status and location to
932 // the user.
933 StateType event_state = SBProcess::GetStateFromEvent (event);
934 if (event_state == eStateInvalid)
935 return;
936
937 SBProcess process (SBProcess::GetProcessFromEvent (event));
938 assert (process.IsValid());
939
940 switch (event_state)
941 {
942 case eStateInvalid:
943 case eStateUnloaded:
Greg Claytonb766a732011-02-04 01:58:07 +0000944 case eStateConnected:
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000945 case eStateAttaching:
946 case eStateLaunching:
947 case eStateStepping:
948 case eStateDetached:
949 {
950 char message[1024];
Daniel Malead01b2952012-11-29 21:49:15 +0000951 int message_len = ::snprintf (message, sizeof(message), "Process %" PRIu64 " %s\n", process.GetProcessID(),
Greg Clayton66111032010-06-23 01:19:29 +0000952 m_debugger.StateAsCString (event_state));
Caroline Tice969ed3d2011-05-02 20:41:46 +0000953 m_io_channel_ap->OutWrite(message, message_len, ASYNC);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000954 }
955 break;
956
957 case eStateRunning:
958 // Don't be chatty when we run...
959 break;
960
961 case eStateExited:
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000962 {
963 SBCommandReturnObject result;
964 m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
Caroline Tice969ed3d2011-05-02 20:41:46 +0000965 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize(), ASYNC);
966 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize(), ASYNC);
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000967 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000968 break;
969
970 case eStateStopped:
971 case eStateCrashed:
972 case eStateSuspended:
973 // Make sure the program hasn't been auto-restarted:
974 if (SBProcess::GetRestartedFromEvent (event))
975 {
Jim Ingham0161b492013-02-09 01:29:05 +0000976 size_t num_reasons = SBProcess::GetNumRestartedReasonsFromEvent(event);
977 if (num_reasons > 0)
978 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000979 // FIXME: Do we want to report this, or would that just be annoyingly chatty?
Jim Ingham0161b492013-02-09 01:29:05 +0000980 if (num_reasons == 1)
981 {
982 char message[1024];
983 const char *reason = SBProcess::GetRestartedReasonAtIndexFromEvent (event, 0);
984 int message_len = ::snprintf (message, sizeof(message), "Process %" PRIu64 " stopped and restarted: %s\n",
985 process.GetProcessID(), reason ? reason : "<UNKNOWN REASON>");
986 m_io_channel_ap->OutWrite(message, message_len, ASYNC);
987 }
988 else
989 {
990 char message[1024];
991 int message_len = ::snprintf (message, sizeof(message), "Process %" PRIu64 " stopped and restarted, reasons:\n",
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000992 process.GetProcessID());
Jim Ingham0161b492013-02-09 01:29:05 +0000993 m_io_channel_ap->OutWrite(message, message_len, ASYNC);
994 for (size_t i = 0; i < num_reasons; i++)
995 {
996 const char *reason = SBProcess::GetRestartedReasonAtIndexFromEvent (event, i);
997 int message_len = ::snprintf(message, sizeof(message), "\t%s\n", reason ? reason : "<UNKNOWN REASON>");
998 m_io_channel_ap->OutWrite(message, message_len, ASYNC);
999 }
1000 }
1001 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001002 }
1003 else
1004 {
Jim Ingham8499e1a2012-05-08 23:06:07 +00001005 if (GetDebugger().GetSelectedTarget() == process.GetTarget())
1006 {
1007 SBCommandReturnObject result;
1008 UpdateSelectedThread ();
1009 m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
1010 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize(), ASYNC);
1011 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize(), ASYNC);
1012 }
1013 else
1014 {
1015 SBStream out_stream;
1016 uint32_t target_idx = GetDebugger().GetIndexOfTarget(process.GetTarget());
1017 if (target_idx != UINT32_MAX)
1018 out_stream.Printf ("Target %d: (", target_idx);
1019 else
1020 out_stream.Printf ("Target <unknown index>: (");
1021 process.GetTarget().GetDescription (out_stream, eDescriptionLevelBrief);
1022 out_stream.Printf (") stopped.\n");
1023 m_io_channel_ap->OutWrite (out_stream.GetData(), out_stream.GetSize(), ASYNC);
1024 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001025 }
1026 break;
1027 }
1028 }
1029}
1030
Jim Ingham4f465cf2012-10-10 18:32:14 +00001031void
1032Driver::HandleThreadEvent (const SBEvent &event)
1033{
1034 // At present the only thread event we handle is the Frame Changed event, and all we do for that is just
1035 // reprint the thread status for that thread.
1036 using namespace lldb;
1037 const uint32_t event_type = event.GetType();
Jim Inghamc3faa192012-12-11 02:31:48 +00001038 if (event_type == SBThread::eBroadcastBitStackChanged
1039 || event_type == SBThread::eBroadcastBitThreadSelected)
Jim Ingham4f465cf2012-10-10 18:32:14 +00001040 {
1041 SBThread thread = SBThread::GetThreadFromEvent (event);
1042 if (thread.IsValid())
1043 {
1044 SBStream out_stream;
1045 thread.GetStatus(out_stream);
1046 m_io_channel_ap->OutWrite (out_stream.GetData (), out_stream.GetSize (), ASYNC);
1047 }
1048 }
1049}
1050
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001051// This function handles events broadcast by the IOChannel (HasInput, UserInterrupt, or ThreadShouldExit).
1052
1053bool
1054Driver::HandleIOEvent (const SBEvent &event)
1055{
1056 bool quit = false;
1057
1058 const uint32_t event_type = event.GetType();
1059
1060 if (event_type & IOChannel::eBroadcastBitHasUserInput)
1061 {
1062 // We got some input (i.e. a command string) from the user; pass it off to the command interpreter for
1063 // handling.
1064
1065 const char *command_string = SBEvent::GetCStringFromEvent(event);
1066 if (command_string == NULL)
Greg Claytonc982c762010-07-09 20:39:50 +00001067 command_string = "";
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001068 SBCommandReturnObject result;
Jim Ingham85e8b812011-02-19 02:53:09 +00001069
Caroline Ticeb5059ac2011-05-16 19:20:50 +00001070 // We don't want the result to bypass the OutWrite function in IOChannel, as this can result in odd
1071 // output orderings and problems with the prompt.
Jim Ingham85e8b812011-02-19 02:53:09 +00001072 m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, true);
1073
Enrico Granatacd4d24d2012-10-16 20:57:12 +00001074 const bool only_if_no_immediate = true;
1075
Enrico Granata430e5402012-10-16 21:11:14 +00001076 const size_t output_size = result.GetOutputSize();
Enrico Granatacd4d24d2012-10-16 20:57:12 +00001077
1078 if (output_size > 0)
1079 m_io_channel_ap->OutWrite (result.GetOutput(only_if_no_immediate), output_size, NO_ASYNC);
1080
Enrico Granata430e5402012-10-16 21:11:14 +00001081 const size_t error_size = result.GetErrorSize();
Enrico Granatacd4d24d2012-10-16 20:57:12 +00001082
1083 if (error_size > 0)
1084 m_io_channel_ap->OutWrite (result.GetError(only_if_no_immediate), error_size, NO_ASYNC);
Caroline Ticeb5059ac2011-05-16 19:20:50 +00001085
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001086 // We are done getting and running our command, we can now clear the
1087 // m_waiting_for_command so we can get another one.
1088 m_waiting_for_command = false;
1089
1090 // If our editline input reader is active, it means another input reader
1091 // got pushed onto the input reader and caused us to become deactivated.
1092 // When the input reader above us gets popped, we will get re-activated
1093 // and our prompt will refresh in our callback
1094 if (m_editline_reader.IsActive())
1095 {
1096 ReadyForCommand ();
1097 }
1098 }
1099 else if (event_type & IOChannel::eBroadcastBitUserInterrupt)
1100 {
1101 // This is here to handle control-c interrupts from the user. It has not yet really been implemented.
1102 // TO BE DONE: PROPERLY HANDLE CONTROL-C FROM USER
1103 //m_io_channel_ap->CancelInput();
1104 // Anything else? Send Interrupt to process?
1105 }
1106 else if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
1107 (event_type & IOChannel::eBroadcastBitThreadDidExit))
1108 {
1109 // If the IOChannel thread is trying to go away, then it is definitely
1110 // time to end the debugging session.
1111 quit = true;
1112 }
1113
1114 return quit;
1115}
1116
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001117void
1118Driver::MasterThreadBytesReceived (void *baton, const void *src, size_t src_len)
1119{
1120 Driver *driver = (Driver*)baton;
1121 driver->GetFromMaster ((const char *)src, src_len);
1122}
1123
1124void
1125Driver::GetFromMaster (const char *src, size_t src_len)
1126{
1127 // Echo the characters back to the Debugger's stdout, that way if you
1128 // type characters while a command is running, you'll see what you've typed.
Greg Clayton66111032010-06-23 01:19:29 +00001129 FILE *out_fh = m_debugger.GetOutputFileHandle();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001130 if (out_fh)
1131 ::fwrite (src, 1, src_len, out_fh);
1132}
1133
1134size_t
1135Driver::EditLineInputReaderCallback
1136(
1137 void *baton,
1138 SBInputReader *reader,
1139 InputReaderAction notification,
1140 const char *bytes,
1141 size_t bytes_len
1142)
1143{
1144 Driver *driver = (Driver *)baton;
1145
1146 switch (notification)
1147 {
1148 case eInputReaderActivate:
1149 break;
1150
1151 case eInputReaderReactivate:
1152 driver->ReadyForCommand();
1153 break;
1154
1155 case eInputReaderDeactivate:
1156 break;
Caroline Tice969ed3d2011-05-02 20:41:46 +00001157
1158 case eInputReaderAsynchronousOutputWritten:
1159 if (driver->m_io_channel_ap.get() != NULL)
1160 driver->m_io_channel_ap->RefreshPrompt();
1161 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001162
Caroline Ticeefed6132010-11-19 20:47:54 +00001163 case eInputReaderInterrupt:
1164 if (driver->m_io_channel_ap.get() != NULL)
1165 {
Jim Inghamcfc09352012-07-27 23:57:19 +00001166 SBProcess process(driver->GetDebugger().GetSelectedTarget().GetProcess());
Jim Inghamd242f1c2012-06-01 01:07:02 +00001167 if (!driver->m_io_channel_ap->EditLineHasCharacters()
Jim Inghamcfc09352012-07-27 23:57:19 +00001168 && process.IsValid()
1169 && (process.GetState() == lldb::eStateRunning || process.GetState() == lldb::eStateAttaching))
Jim Inghamd242f1c2012-06-01 01:07:02 +00001170 {
Jim Inghamcfc09352012-07-27 23:57:19 +00001171 process.SendAsyncInterrupt ();
Jim Inghamd242f1c2012-06-01 01:07:02 +00001172 }
1173 else
1174 {
1175 driver->m_io_channel_ap->OutWrite ("^C\n", 3, NO_ASYNC);
1176 // I wish I could erase the entire input line, but there's no public API for that.
1177 driver->m_io_channel_ap->EraseCharsBeforeCursor();
1178 driver->m_io_channel_ap->RefreshPrompt();
1179 }
Caroline Ticeefed6132010-11-19 20:47:54 +00001180 }
1181 break;
1182
1183 case eInputReaderEndOfFile:
1184 if (driver->m_io_channel_ap.get() != NULL)
1185 {
Caroline Tice969ed3d2011-05-02 20:41:46 +00001186 driver->m_io_channel_ap->OutWrite ("^D\n", 3, NO_ASYNC);
Caroline Ticeefed6132010-11-19 20:47:54 +00001187 driver->m_io_channel_ap->RefreshPrompt ();
1188 }
1189 write (driver->m_editline_pty.GetMasterFileDescriptor(), "quit\n", 5);
1190 break;
1191
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001192 case eInputReaderGotToken:
1193 write (driver->m_editline_pty.GetMasterFileDescriptor(), bytes, bytes_len);
1194 break;
1195
1196 case eInputReaderDone:
1197 break;
1198 }
1199 return bytes_len;
1200}
1201
1202void
1203Driver::MainLoop ()
1204{
1205 char error_str[1024];
1206 if (m_editline_pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, error_str, sizeof(error_str)) == false)
1207 {
1208 ::fprintf (stderr, "error: failed to open driver pseudo terminal : %s", error_str);
1209 exit(1);
1210 }
1211 else
1212 {
1213 const char *driver_slave_name = m_editline_pty.GetSlaveName (error_str, sizeof(error_str));
1214 if (driver_slave_name == NULL)
1215 {
1216 ::fprintf (stderr, "error: failed to get slave name for driver pseudo terminal : %s", error_str);
1217 exit(2);
1218 }
1219 else
1220 {
1221 m_editline_slave_fh = ::fopen (driver_slave_name, "r+");
1222 if (m_editline_slave_fh == NULL)
1223 {
1224 SBError error;
1225 error.SetErrorToErrno();
1226 ::fprintf (stderr, "error: failed to get open slave for driver pseudo terminal : %s",
1227 error.GetCString());
1228 exit(3);
1229 }
1230
1231 ::setbuf (m_editline_slave_fh, NULL);
1232 }
1233 }
1234
Caroline Tice969ed3d2011-05-02 20:41:46 +00001235 lldb_utility::PseudoTerminal editline_output_pty;
1236 FILE *editline_output_slave_fh = NULL;
1237
1238 if (editline_output_pty.OpenFirstAvailableMaster (O_RDWR|O_NOCTTY, error_str, sizeof (error_str)) == false)
1239 {
1240 ::fprintf (stderr, "error: failed to open output pseudo terminal : %s", error_str);
1241 exit(1);
1242 }
1243 else
1244 {
1245 const char *output_slave_name = editline_output_pty.GetSlaveName (error_str, sizeof(error_str));
1246 if (output_slave_name == NULL)
1247 {
1248 ::fprintf (stderr, "error: failed to get slave name for output pseudo terminal : %s", error_str);
1249 exit(2);
1250 }
1251 else
1252 {
1253 editline_output_slave_fh = ::fopen (output_slave_name, "r+");
1254 if (editline_output_slave_fh == NULL)
1255 {
1256 SBError error;
1257 error.SetErrorToErrno();
1258 ::fprintf (stderr, "error: failed to get open slave for output pseudo terminal : %s",
1259 error.GetCString());
1260 exit(3);
1261 }
1262 ::setbuf (editline_output_slave_fh, NULL);
1263 }
1264 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001265
1266 // struct termios stdin_termios;
1267
1268 if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0)
Greg Claytonf571b892012-02-02 19:28:31 +00001269 {
1270 g_old_stdin_termios_is_valid = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001271 atexit (reset_stdin_termios);
Greg Claytonf571b892012-02-02 19:28:31 +00001272 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001273
1274 ::setbuf (stdin, NULL);
1275 ::setbuf (stdout, NULL);
1276
Greg Clayton66111032010-06-23 01:19:29 +00001277 m_debugger.SetErrorFileHandle (stderr, false);
1278 m_debugger.SetOutputFileHandle (stdout, false);
1279 m_debugger.SetInputFileHandle (stdin, true);
Jim Inghame40e4212010-08-30 19:44:40 +00001280
1281 m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001282
1283 // You have to drain anything that comes to the master side of the PTY. master_out_comm is
1284 // for that purpose. The reason you need to do this is a curious reason... editline will echo
1285 // characters to the PTY when it gets characters while el_gets is not running, and then when
1286 // you call el_gets (or el_getc) it will try to reset the terminal back to raw mode which blocks
1287 // if there are unconsumed characters in the out buffer.
1288 // However, you don't need to do anything with the characters, since editline will dump these
1289 // unconsumed characters after printing the prompt again in el_gets.
1290
Greg Claytond46c87a2010-12-04 02:39:47 +00001291 SBCommunication master_out_comm("driver.editline");
1292 master_out_comm.SetCloseOnEOF (false);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001293 master_out_comm.AdoptFileDesriptor(m_editline_pty.GetMasterFileDescriptor(), false);
1294 master_out_comm.SetReadThreadBytesReceivedCallback(Driver::MasterThreadBytesReceived, this);
1295
1296 if (master_out_comm.ReadThreadStart () == false)
1297 {
1298 ::fprintf (stderr, "error: failed to start master out read thread");
1299 exit(5);
1300 }
1301
Greg Clayton66111032010-06-23 01:19:29 +00001302 SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001303
Caroline Tice969ed3d2011-05-02 20:41:46 +00001304 m_io_channel_ap.reset (new IOChannel(m_editline_slave_fh, editline_output_slave_fh, stdout, stderr, this));
1305
1306 SBCommunication out_comm_2("driver.editline_output");
1307 out_comm_2.SetCloseOnEOF (false);
1308 out_comm_2.AdoptFileDesriptor (editline_output_pty.GetMasterFileDescriptor(), false);
1309 out_comm_2.SetReadThreadBytesReceivedCallback (IOChannel::LibeditOutputBytesReceived, m_io_channel_ap.get());
1310
1311 if (out_comm_2.ReadThreadStart () == false)
1312 {
1313 ::fprintf (stderr, "error: failed to start libedit output read thread");
1314 exit (5);
1315 }
1316
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001317
1318 struct winsize window_size;
1319 if (isatty (STDIN_FILENO)
1320 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
1321 {
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001322 if (window_size.ws_col > 0)
Greg Claytona7015092010-09-18 01:14:36 +00001323 m_debugger.SetTerminalWidth (window_size.ws_col);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001324 }
1325
1326 // Since input can be redirected by the debugger, we must insert our editline
1327 // input reader in the queue so we know when our reader should be active
1328 // and so we can receive bytes only when we are supposed to.
Greg Clayton66111032010-06-23 01:19:29 +00001329 SBError err (m_editline_reader.Initialize (m_debugger,
1330 Driver::EditLineInputReaderCallback, // callback
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001331 this, // baton
1332 eInputReaderGranularityByte, // token_size
1333 NULL, // end token - NULL means never done
1334 NULL, // prompt - taken care of elsewhere
1335 false)); // echo input - don't need Debugger
1336 // to do this, we handle it elsewhere
1337
1338 if (err.Fail())
1339 {
1340 ::fprintf (stderr, "error: %s", err.GetCString());
1341 exit (6);
1342 }
1343
Greg Clayton66111032010-06-23 01:19:29 +00001344 m_debugger.PushInputReader (m_editline_reader);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001345
Greg Clayton66111032010-06-23 01:19:29 +00001346 SBListener listener(m_debugger.GetListener());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001347 if (listener.IsValid())
1348 {
1349
Jim Ingham4f465cf2012-10-10 18:32:14 +00001350 listener.StartListeningForEventClass(m_debugger,
1351 SBTarget::GetBroadcasterClassName(),
1352 SBTarget::eBroadcastBitBreakpointChanged);
1353 listener.StartListeningForEventClass(m_debugger,
1354 SBThread::GetBroadcasterClassName(),
Jim Inghamc3faa192012-12-11 02:31:48 +00001355 SBThread::eBroadcastBitStackChanged |
1356 SBThread::eBroadcastBitThreadSelected);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001357 listener.StartListeningForEvents (*m_io_channel_ap,
1358 IOChannel::eBroadcastBitHasUserInput |
1359 IOChannel::eBroadcastBitUserInterrupt |
1360 IOChannel::eBroadcastBitThreadShouldExit |
1361 IOChannel::eBroadcastBitThreadDidStart |
1362 IOChannel::eBroadcastBitThreadDidExit);
1363
1364 if (m_io_channel_ap->Start ())
1365 {
1366 bool iochannel_thread_exited = false;
1367
1368 listener.StartListeningForEvents (sb_interpreter.GetBroadcaster(),
Caroline Tice86a73f92011-05-03 20:53:11 +00001369 SBCommandInterpreter::eBroadcastBitQuitCommandReceived |
1370 SBCommandInterpreter::eBroadcastBitAsynchronousOutputData |
1371 SBCommandInterpreter::eBroadcastBitAsynchronousErrorData);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001372
1373 // Before we handle any options from the command line, we parse the
1374 // .lldbinit file in the user's home directory.
1375 SBCommandReturnObject result;
1376 sb_interpreter.SourceInitFileInHomeDirectory(result);
1377 if (GetDebugMode())
1378 {
Greg Clayton66111032010-06-23 01:19:29 +00001379 result.PutError (m_debugger.GetErrorFileHandle());
1380 result.PutOutput (m_debugger.GetOutputFileHandle());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001381 }
1382
1383 // Now we handle options we got from the command line
1384 char command_string[PATH_MAX * 2];
1385 const size_t num_source_command_files = GetNumSourceCommandFiles();
Enrico Granataaa0c8ff2012-12-13 20:20:11 +00001386 const bool dump_stream_only_if_no_immediate = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001387 if (num_source_command_files > 0)
1388 {
1389 for (size_t i=0; i < num_source_command_files; ++i)
1390 {
1391 const char *command_file = GetSourceCommandFileAtIndex(i);
Johnny Chen85ffddc2010-07-28 21:16:11 +00001392 ::snprintf (command_string, sizeof(command_string), "command source '%s'", command_file);
Greg Clayton66111032010-06-23 01:19:29 +00001393 m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, false);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001394 if (GetDebugMode())
1395 {
Greg Clayton66111032010-06-23 01:19:29 +00001396 result.PutError (m_debugger.GetErrorFileHandle());
1397 result.PutOutput (m_debugger.GetOutputFileHandle());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001398 }
Enrico Granataaa0c8ff2012-12-13 20:20:11 +00001399
1400 // if the command sourcing generated an error - dump the result object
Enrico Granatadc3f4f92012-12-14 00:52:54 +00001401 if (result.Succeeded() == false)
Enrico Granataaa0c8ff2012-12-13 20:20:11 +00001402 {
1403 const size_t output_size = result.GetOutputSize();
1404 if (output_size > 0)
1405 m_io_channel_ap->OutWrite (result.GetOutput(dump_stream_only_if_no_immediate), output_size, NO_ASYNC);
Enrico Granatadc3f4f92012-12-14 00:52:54 +00001406 const size_t error_size = result.GetErrorSize();
1407 if (error_size > 0)
1408 m_io_channel_ap->OutWrite (result.GetError(dump_stream_only_if_no_immediate), error_size, NO_ASYNC);
Enrico Granataaa0c8ff2012-12-13 20:20:11 +00001409 }
1410
1411 result.Clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001412 }
1413 }
1414
Johnny Cheneb46f782012-08-15 22:10:42 +00001415 // Was there a core file specified?
1416 std::string core_file_spec("");
1417 if (!m_option_data.m_core_file.empty())
1418 core_file_spec.append("--core ").append(m_option_data.m_core_file);
1419
Greg Clayton8d846da2010-12-08 22:23:24 +00001420 const size_t num_args = m_option_data.m_args.size();
1421 if (num_args > 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001422 {
1423 char arch_name[64];
Greg Clayton66111032010-06-23 01:19:29 +00001424 if (m_debugger.GetDefaultArchitecture (arch_name, sizeof (arch_name)))
Greg Clayton8d846da2010-12-08 22:23:24 +00001425 ::snprintf (command_string,
1426 sizeof (command_string),
Johnny Cheneb46f782012-08-15 22:10:42 +00001427 "target create --arch=%s %s \"%s\"",
Greg Clayton8d846da2010-12-08 22:23:24 +00001428 arch_name,
Johnny Cheneb46f782012-08-15 22:10:42 +00001429 core_file_spec.c_str(),
Greg Clayton8d846da2010-12-08 22:23:24 +00001430 m_option_data.m_args[0].c_str());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001431 else
Greg Clayton8d846da2010-12-08 22:23:24 +00001432 ::snprintf (command_string,
1433 sizeof(command_string),
Johnny Cheneb46f782012-08-15 22:10:42 +00001434 "target create %s \"%s\"",
1435 core_file_spec.c_str(),
Greg Clayton8d846da2010-12-08 22:23:24 +00001436 m_option_data.m_args[0].c_str());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001437
Greg Clayton66111032010-06-23 01:19:29 +00001438 m_debugger.HandleCommand (command_string);
Greg Clayton8d846da2010-12-08 22:23:24 +00001439
1440 if (num_args > 1)
1441 {
Greg Clayton1d885962011-11-08 02:43:13 +00001442 m_debugger.HandleCommand ("settings clear target.run-args");
Greg Clayton8d846da2010-12-08 22:23:24 +00001443 char arg_cstr[1024];
1444 for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx)
1445 {
Jim Inghame64f0dc2011-09-13 23:25:31 +00001446 ::snprintf (arg_cstr,
1447 sizeof(arg_cstr),
Greg Clayton1d885962011-11-08 02:43:13 +00001448 "settings append target.run-args \"%s\"",
Jim Inghame64f0dc2011-09-13 23:25:31 +00001449 m_option_data.m_args[arg_idx].c_str());
Greg Clayton8d846da2010-12-08 22:23:24 +00001450 m_debugger.HandleCommand (arg_cstr);
1451 }
1452 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001453 }
Johnny Cheneb46f782012-08-15 22:10:42 +00001454 else if (!core_file_spec.empty())
1455 {
1456 ::snprintf (command_string,
1457 sizeof(command_string),
1458 "target create %s",
1459 core_file_spec.c_str());
1460 m_debugger.HandleCommand (command_string);;
1461 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001462
1463 // Now that all option parsing is done, we try and parse the .lldbinit
1464 // file in the current working directory
1465 sb_interpreter.SourceInitFileInCurrentWorkingDirectory (result);
1466 if (GetDebugMode())
1467 {
Greg Clayton66111032010-06-23 01:19:29 +00001468 result.PutError(m_debugger.GetErrorFileHandle());
1469 result.PutOutput(m_debugger.GetOutputFileHandle());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001470 }
1471
1472 SBEvent event;
1473
1474 // Make sure the IO channel is started up before we try to tell it we
1475 // are ready for input
1476 listener.WaitForEventForBroadcasterWithType (UINT32_MAX,
1477 *m_io_channel_ap,
1478 IOChannel::eBroadcastBitThreadDidStart,
1479 event);
Jim Inghame64f0dc2011-09-13 23:25:31 +00001480 // If we were asked to attach, then do that here:
1481 // I'm going to use the command string rather than directly
1482 // calling the API's because then I don't have to recode the
1483 // event handling here.
1484 if (!m_option_data.m_process_name.empty()
1485 || m_option_data.m_process_pid != LLDB_INVALID_PROCESS_ID)
1486 {
1487 std::string command_str("process attach ");
1488 if (m_option_data.m_process_pid != LLDB_INVALID_PROCESS_ID)
1489 {
1490 command_str.append("-p ");
1491 char pid_buffer[32];
Daniel Malead01b2952012-11-29 21:49:15 +00001492 ::snprintf (pid_buffer, sizeof(pid_buffer), "%" PRIu64, m_option_data.m_process_pid);
Jim Inghame64f0dc2011-09-13 23:25:31 +00001493 command_str.append(pid_buffer);
1494 }
1495 else
1496 {
1497 command_str.append("-n \"");
1498 command_str.append(m_option_data.m_process_name);
1499 command_str.push_back('\"');
1500 if (m_option_data.m_wait_for)
1501 command_str.append(" -w");
1502 }
1503
1504 if (m_debugger.GetOutputFileHandle())
1505 ::fprintf (m_debugger.GetOutputFileHandle(),
1506 "Attaching to process with:\n %s\n",
1507 command_str.c_str());
1508
1509 // Force the attach to be synchronous:
1510 bool orig_async = m_debugger.GetAsync();
1511 m_debugger.SetAsync(true);
1512 m_debugger.HandleCommand(command_str.c_str());
1513 m_debugger.SetAsync(orig_async);
1514 }
1515
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001516 ReadyForCommand ();
1517
Greg Claytona9f7b792012-02-29 04:21:24 +00001518 while (!GetIsDone())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001519 {
1520 listener.WaitForEvent (UINT32_MAX, event);
1521 if (event.IsValid())
1522 {
1523 if (event.GetBroadcaster().IsValid())
1524 {
1525 uint32_t event_type = event.GetType();
1526 if (event.BroadcasterMatchesRef (*m_io_channel_ap))
1527 {
1528 if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
1529 (event_type & IOChannel::eBroadcastBitThreadDidExit))
1530 {
Greg Claytona9f7b792012-02-29 04:21:24 +00001531 SetIsDone();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001532 if (event_type & IOChannel::eBroadcastBitThreadDidExit)
1533 iochannel_thread_exited = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001534 }
1535 else
Greg Claytona9f7b792012-02-29 04:21:24 +00001536 {
1537 if (HandleIOEvent (event))
1538 SetIsDone();
1539 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001540 }
Jim Inghame6bc6cb2012-02-08 05:23:15 +00001541 else if (SBProcess::EventIsProcessEvent (event))
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001542 {
1543 HandleProcessEvent (event);
1544 }
Jim Inghame6bc6cb2012-02-08 05:23:15 +00001545 else if (SBBreakpoint::EventIsBreakpointEvent (event))
1546 {
1547 HandleBreakpointEvent (event);
1548 }
Jim Ingham4f465cf2012-10-10 18:32:14 +00001549 else if (SBThread::EventIsThreadEvent (event))
1550 {
1551 HandleThreadEvent (event);
1552 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001553 else if (event.BroadcasterMatchesRef (sb_interpreter.GetBroadcaster()))
1554 {
Greg Claytona9f7b792012-02-29 04:21:24 +00001555 // TODO: deprecate the eBroadcastBitQuitCommandReceived event
1556 // now that we have SBCommandInterpreter::SetCommandOverrideCallback()
1557 // that can take over a command
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001558 if (event_type & SBCommandInterpreter::eBroadcastBitQuitCommandReceived)
Greg Clayton74d41932012-01-31 04:56:17 +00001559 {
Greg Claytona9f7b792012-02-29 04:21:24 +00001560 SetIsDone();
Greg Clayton74d41932012-01-31 04:56:17 +00001561 }
Caroline Tice86a73f92011-05-03 20:53:11 +00001562 else if (event_type & SBCommandInterpreter::eBroadcastBitAsynchronousErrorData)
1563 {
1564 const char *data = SBEvent::GetCStringFromEvent (event);
1565 m_io_channel_ap->ErrWrite (data, strlen(data), ASYNC);
1566 }
1567 else if (event_type & SBCommandInterpreter::eBroadcastBitAsynchronousOutputData)
1568 {
1569 const char *data = SBEvent::GetCStringFromEvent (event);
1570 m_io_channel_ap->OutWrite (data, strlen(data), ASYNC);
1571 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001572 }
1573 }
1574 }
1575 }
1576
Greg Claytonf571b892012-02-02 19:28:31 +00001577 editline_output_pty.CloseMasterFileDescriptor();
1578 master_out_comm.Disconnect();
1579 out_comm_2.Disconnect();
1580 reset_stdin_termios();
1581 fclose (stdin);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001582
1583 CloseIOChannelFile ();
1584
1585 if (!iochannel_thread_exited)
1586 {
Greg Claytonb1320972010-07-14 00:18:15 +00001587 event.Clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001588 listener.GetNextEventForBroadcasterWithType (*m_io_channel_ap,
1589 IOChannel::eBroadcastBitThreadDidExit,
1590 event);
1591 if (!event.IsValid())
1592 {
1593 // Send end EOF to the driver file descriptor
1594 m_io_channel_ap->Stop();
1595 }
1596 }
1597
Jim Ingham12e9a202011-09-15 21:30:02 +00001598 SBDebugger::Destroy (m_debugger);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001599 }
1600 }
1601}
1602
1603
1604void
1605Driver::ReadyForCommand ()
1606{
1607 if (m_waiting_for_command == false)
1608 {
1609 m_waiting_for_command = true;
1610 BroadcastEventByType (Driver::eBroadcastBitReadyForInput, true);
1611 }
1612}
1613
1614
Caroline Ticedd759852010-09-09 17:45:09 +00001615void
1616sigwinch_handler (int signo)
1617{
1618 struct winsize window_size;
1619 if (isatty (STDIN_FILENO)
1620 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
1621 {
Jim Ingham57190ba2012-04-26 21:39:32 +00001622 if ((window_size.ws_col > 0) && g_driver != NULL)
Caroline Ticedd759852010-09-09 17:45:09 +00001623 {
Jim Ingham57190ba2012-04-26 21:39:32 +00001624 g_driver->GetDebugger().SetTerminalWidth (window_size.ws_col);
Caroline Ticedd759852010-09-09 17:45:09 +00001625 }
1626 }
1627}
1628
Caroline Ticeefed6132010-11-19 20:47:54 +00001629void
1630sigint_handler (int signo)
1631{
1632 static bool g_interrupt_sent = false;
1633 if (g_driver)
1634 {
1635 if (!g_interrupt_sent)
1636 {
1637 g_interrupt_sent = true;
1638 g_driver->GetDebugger().DispatchInputInterrupt();
1639 g_interrupt_sent = false;
1640 return;
1641 }
1642 }
1643
1644 exit (signo);
1645}
1646
Jim Inghamc5917d92012-11-30 20:23:19 +00001647void
1648sigtstp_handler (int signo)
1649{
1650 g_driver->GetDebugger().SaveInputTerminalState();
1651 signal (signo, SIG_DFL);
1652 kill (getpid(), signo);
1653 signal (signo, sigtstp_handler);
1654}
1655
1656void
1657sigcont_handler (int signo)
1658{
1659 g_driver->GetDebugger().RestoreInputTerminalState();
1660 signal (signo, SIG_DFL);
1661 kill (getpid(), signo);
1662 signal (signo, sigcont_handler);
1663}
1664
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001665int
Jim Inghama462f5c2011-01-27 20:15:39 +00001666main (int argc, char const *argv[], const char *envp[])
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001667{
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001668 SBDebugger::Initialize();
1669
Greg Clayton2ccf8cf2010-11-07 21:02:03 +00001670 SBHostOS::ThreadCreated ("<lldb.driver.main-thread>");
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001671
Greg Clayton3fcbed62010-10-19 03:25:40 +00001672 signal (SIGPIPE, SIG_IGN);
Caroline Ticedd759852010-09-09 17:45:09 +00001673 signal (SIGWINCH, sigwinch_handler);
Caroline Ticeefed6132010-11-19 20:47:54 +00001674 signal (SIGINT, sigint_handler);
Jim Inghamc5917d92012-11-30 20:23:19 +00001675 signal (SIGTSTP, sigtstp_handler);
1676 signal (SIGCONT, sigcont_handler);
Caroline Ticedd759852010-09-09 17:45:09 +00001677
Greg Clayton66111032010-06-23 01:19:29 +00001678 // Create a scope for driver so that the driver object will destroy itself
1679 // before SBDebugger::Terminate() is called.
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001680 {
Greg Clayton66111032010-06-23 01:19:29 +00001681 Driver driver;
1682
1683 bool exit = false;
1684 SBError error (driver.ParseArgs (argc, argv, stdout, exit));
1685 if (error.Fail())
1686 {
1687 const char *error_cstr = error.GetCString ();
1688 if (error_cstr)
1689 ::fprintf (stderr, "error: %s\n", error_cstr);
1690 }
1691 else if (!exit)
1692 {
1693 driver.MainLoop ();
1694 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001695 }
1696
1697 SBDebugger::Terminate();
1698 return 0;
1699}