blob: 36e5651461c036f732f95a3bef4e286b406a065f [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." },
Jim Inghamed3252f2013-09-14 00:20:24 +0000102 { LLDB_3_TO_5, false, "source-quietly" , 'b', no_argument , 0, eArgTypeNone,
103 "Tells the debugger to print out extra information for debugging itself." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +0000104 { LLDB_3_TO_5, false, "source" , 's', required_argument, 0, eArgTypeFilename,
Jim Ingham12e9a202011-09-15 21:30:02 +0000105 "Tells the debugger to read in and execute the file <file>, which should contain lldb commands." },
Jim Inghamed3252f2013-09-14 00:20:24 +0000106 { LLDB_3_TO_5, false, "one-line" , 'o', required_argument, 0, eArgTypeNone,
107 "Tells the debugger to execute this one-line lldb command." },
108 { LLDB_3_TO_5, false, "source-before-file" , 'S', required_argument, 0, eArgTypeFilename,
109 "Tells the debugger to read in and execute the file <file>, which should contain lldb commands." },
110 { LLDB_3_TO_5, false, "one-line-before-file" , 'O', required_argument, 0, eArgTypeNone,
111 "Tells the debugger to execute this one-line lldb command." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +0000112 { LLDB_3_TO_5, false, "editor" , 'e', no_argument , 0, eArgTypeNone,
Jim Ingham12e9a202011-09-15 21:30:02 +0000113 "Tells the debugger to open source files using the host's \"external editor\" mechanism." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +0000114 { LLDB_3_TO_5, false, "no-lldbinit" , 'x', no_argument , 0, eArgTypeNone,
Jim Ingham12e9a202011-09-15 21:30:02 +0000115 "Do not automatically parse any '.lldbinit' files." },
Jim Inghamed3252f2013-09-14 00:20:24 +0000116 { LLDB_3_TO_5, false, "no-use-colors" , 'X', no_argument , 0, eArgTypeNone,
Michael Sartainc3ce7f272013-05-23 20:47:45 +0000117 "Do not use colors." },
118 { LLDB_OPT_SET_6, true , "python-path" , 'P', no_argument , 0, eArgTypeNone,
Jim Inghame2231ac2012-12-21 22:22:26 +0000119 "Prints out the path to the lldb.py file for this version of lldb." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +0000120 { 0, false, NULL , 0 , 0 , 0, eArgTypeNone, NULL }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000121};
122
Jim Inghame64f0dc2011-09-13 23:25:31 +0000123static const uint32_t last_option_set_with_args = 2;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000124
125Driver::Driver () :
126 SBBroadcaster ("Driver"),
Jim Ingham06942692011-08-13 00:22:20 +0000127 m_debugger (SBDebugger::Create(false)),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000128 m_editline_pty (),
129 m_editline_slave_fh (NULL),
130 m_editline_reader (),
131 m_io_channel_ap (),
132 m_option_data (),
Greg Claytoneea37ee2013-05-14 17:36:51 +0000133 m_executing_user_command (false),
Daniel Malea926758b2012-12-17 17:40:07 +0000134 m_waiting_for_command (false),
135 m_done(false)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000136{
Greg Claytonfc3f0272011-05-29 04:06:55 +0000137 // We want to be able to handle CTRL+D in the terminal to have it terminate
138 // certain input
139 m_debugger.SetCloseInputOnEOF (false);
Caroline Ticedd759852010-09-09 17:45:09 +0000140 g_debugger_name = (char *) m_debugger.GetInstanceName();
141 if (g_debugger_name == NULL)
142 g_debugger_name = (char *) "";
Caroline Ticeefed6132010-11-19 20:47:54 +0000143 g_driver = this;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000144}
145
146Driver::~Driver ()
147{
Caroline Ticeefed6132010-11-19 20:47:54 +0000148 g_driver = NULL;
149 g_debugger_name = NULL;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000150}
151
152void
153Driver::CloseIOChannelFile ()
154{
Johnny Chene26c7212012-05-16 22:01:10 +0000155 // Write an End of File sequence to the file descriptor to ensure any
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000156 // read functions can exit.
157 char eof_str[] = "\x04";
158 ::write (m_editline_pty.GetMasterFileDescriptor(), eof_str, strlen(eof_str));
159
160 m_editline_pty.CloseMasterFileDescriptor();
161
162 if (m_editline_slave_fh)
163 {
164 ::fclose (m_editline_slave_fh);
165 m_editline_slave_fh = NULL;
166 }
167}
168
Greg Claytonc982c762010-07-09 20:39:50 +0000169// This function takes INDENT, which tells how many spaces to output at the front
170// of each line; TEXT, which is the text that is to be output. It outputs the
171// text, on multiple lines if necessary, to RESULT, with INDENT spaces at the
172// front of each line. It breaks lines on spaces, tabs or newlines, shortening
173// the line if necessary to not break in the middle of a word. It assumes that
174// each output line should contain a maximum of OUTPUT_MAX_COLUMNS characters.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000175
176void
Greg Claytonc982c762010-07-09 20:39:50 +0000177OutputFormattedUsageText (FILE *out, int indent, const char *text, int output_max_columns)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000178{
179 int len = strlen (text);
180 std::string text_string (text);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000181
182 // Force indentation to be reasonable.
183 if (indent >= output_max_columns)
184 indent = 0;
185
186 // Will it all fit on one line?
187
188 if (len + indent < output_max_columns)
189 // Output as a single line
Greg Claytonc982c762010-07-09 20:39:50 +0000190 fprintf (out, "%*s%s\n", indent, "", text);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000191 else
192 {
193 // We need to break it up into multiple lines.
194 int text_width = output_max_columns - indent - 1;
195 int start = 0;
196 int end = start;
197 int final_end = len;
198 int sub_len;
199
200 while (end < final_end)
201 {
202 // Dont start the 'text' on a space, since we're already outputting the indentation.
203 while ((start < final_end) && (text[start] == ' '))
204 start++;
205
206 end = start + text_width;
207 if (end > final_end)
208 end = final_end;
209 else
210 {
211 // If we're not at the end of the text, make sure we break the line on white space.
212 while (end > start
213 && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
214 end--;
215 }
216 sub_len = end - start;
217 std::string substring = text_string.substr (start, sub_len);
Greg Claytonc982c762010-07-09 20:39:50 +0000218 fprintf (out, "%*s%s\n", indent, "", substring.c_str());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000219 start = end + 1;
220 }
221 }
222}
223
224void
Greg Claytone0d378b2011-03-24 21:19:54 +0000225ShowUsage (FILE *out, OptionDefinition *option_table, Driver::OptionData data)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000226{
227 uint32_t screen_width = 80;
228 uint32_t indent_level = 0;
229 const char *name = "lldb";
Jim Ingham86511212010-06-15 18:47:14 +0000230
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000231 fprintf (out, "\nUsage:\n\n");
232
233 indent_level += 2;
234
235
236 // First, show each usage level set of options, e.g. <cmd> [options-for-level-0]
237 // <cmd> [options-for-level-1]
238 // etc.
239
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000240 uint32_t num_options;
Jim Ingham86511212010-06-15 18:47:14 +0000241 uint32_t num_option_sets = 0;
242
243 for (num_options = 0; option_table[num_options].long_option != NULL; ++num_options)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000244 {
Jim Ingham86511212010-06-15 18:47:14 +0000245 uint32_t this_usage_mask = option_table[num_options].usage_mask;
246 if (this_usage_mask == LLDB_OPT_SET_ALL)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000247 {
Jim Ingham86511212010-06-15 18:47:14 +0000248 if (num_option_sets == 0)
249 num_option_sets = 1;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000250 }
251 else
252 {
Greg Claytonc982c762010-07-09 20:39:50 +0000253 for (uint32_t j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++)
Jim Ingham86511212010-06-15 18:47:14 +0000254 {
255 if (this_usage_mask & 1 << j)
256 {
257 if (num_option_sets <= j)
258 num_option_sets = j + 1;
259 }
260 }
261 }
262 }
263
264 for (uint32_t opt_set = 0; opt_set < num_option_sets; opt_set++)
265 {
266 uint32_t opt_set_mask;
267
268 opt_set_mask = 1 << opt_set;
269
270 if (opt_set > 0)
271 fprintf (out, "\n");
Greg Claytonc982c762010-07-09 20:39:50 +0000272 fprintf (out, "%*s%s", indent_level, "", name);
Jim Ingham556e6532011-08-16 23:15:02 +0000273 bool is_help_line = false;
Jim Ingham86511212010-06-15 18:47:14 +0000274
275 for (uint32_t i = 0; i < num_options; ++i)
276 {
277 if (option_table[i].usage_mask & opt_set_mask)
278 {
Caroline Ticedeaab222010-10-01 19:59:14 +0000279 CommandArgumentType arg_type = option_table[i].argument_type;
Greg Clayton9d0402b2011-02-20 02:15:07 +0000280 const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type);
Jim Ingham556e6532011-08-16 23:15:02 +0000281 // This is a bit of a hack, but there's no way to say certain options don't have arguments yet...
282 // so we do it by hand here.
283 if (option_table[i].short_option == 'h')
284 is_help_line = true;
285
Jim Ingham86511212010-06-15 18:47:14 +0000286 if (option_table[i].required)
287 {
288 if (option_table[i].option_has_arg == required_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 if (option_table[i].option_has_arg == optional_argument)
Greg Clayton9d0402b2011-02-20 02:15:07 +0000291 fprintf (out, " -%c [<%s>]", option_table[i].short_option, arg_name);
Jim Ingham86511212010-06-15 18:47:14 +0000292 else
293 fprintf (out, " -%c", option_table[i].short_option);
294 }
295 else
296 {
297 if (option_table[i].option_has_arg == required_argument)
Greg Clayton9d0402b2011-02-20 02:15:07 +0000298 fprintf (out, " [-%c <%s>]", option_table[i].short_option, arg_name);
Jim Ingham86511212010-06-15 18:47:14 +0000299 else if (option_table[i].option_has_arg == optional_argument)
Greg Clayton9d0402b2011-02-20 02:15:07 +0000300 fprintf (out, " [-%c [<%s>]]", option_table[i].short_option, arg_name);
Jim Ingham86511212010-06-15 18:47:14 +0000301 else
302 fprintf (out, " [-%c]", option_table[i].short_option);
303 }
304 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000305 }
Jim Inghame64f0dc2011-09-13 23:25:31 +0000306 if (!is_help_line && (opt_set <= last_option_set_with_args))
Jim Ingham556e6532011-08-16 23:15:02 +0000307 fprintf (out, " [[--] <PROGRAM-ARG-1> [<PROGRAM_ARG-2> ...]]");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000308 }
309
310 fprintf (out, "\n\n");
311
312 // Now print out all the detailed information about the various options: long form, short form and help text:
313 // -- long_name <argument>
314 // - short <argument>
315 // help text
316
317 // This variable is used to keep track of which options' info we've printed out, because some options can be in
318 // more than one usage level, but we only want to print the long form of its information once.
319
320 Driver::OptionData::OptionSet options_seen;
321 Driver::OptionData::OptionSet::iterator pos;
322
323 indent_level += 5;
324
Jim Ingham86511212010-06-15 18:47:14 +0000325 for (uint32_t i = 0; i < num_options; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000326 {
327 // Only print this option if we haven't already seen it.
328 pos = options_seen.find (option_table[i].short_option);
329 if (pos == options_seen.end())
330 {
Caroline Ticedeaab222010-10-01 19:59:14 +0000331 CommandArgumentType arg_type = option_table[i].argument_type;
Greg Clayton9d0402b2011-02-20 02:15:07 +0000332 const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type);
Caroline Ticedeaab222010-10-01 19:59:14 +0000333
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000334 options_seen.insert (option_table[i].short_option);
Greg Claytonc982c762010-07-09 20:39:50 +0000335 fprintf (out, "%*s-%c ", indent_level, "", option_table[i].short_option);
Caroline Ticedeaab222010-10-01 19:59:14 +0000336 if (arg_type != eArgTypeNone)
Greg Clayton9d0402b2011-02-20 02:15:07 +0000337 fprintf (out, "<%s>", arg_name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000338 fprintf (out, "\n");
Greg Claytonc982c762010-07-09 20:39:50 +0000339 fprintf (out, "%*s--%s ", indent_level, "", option_table[i].long_option);
Caroline Ticedeaab222010-10-01 19:59:14 +0000340 if (arg_type != eArgTypeNone)
Greg Clayton9d0402b2011-02-20 02:15:07 +0000341 fprintf (out, "<%s>", arg_name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000342 fprintf (out, "\n");
343 indent_level += 5;
Greg Claytonc982c762010-07-09 20:39:50 +0000344 OutputFormattedUsageText (out, indent_level, option_table[i].usage_text, screen_width);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000345 indent_level -= 5;
346 fprintf (out, "\n");
347 }
348 }
349
350 indent_level -= 5;
351
Jim Inghama9deaf92011-08-16 23:57:58 +0000352 fprintf (out, "\n%*s(If you don't provide -f then the first argument will be the file to be debugged"
353 "\n%*s so '%s -- <filename> [<ARG1> [<ARG2>]]' also works."
354 "\n%*s Remember to end the options with \"--\" if any of your arguments have a \"-\" in them.)\n\n",
355 indent_level, "",
356 indent_level, "",
357 name,
358 indent_level, "");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000359}
360
361void
Greg Claytone0d378b2011-03-24 21:19:54 +0000362BuildGetOptTable (OptionDefinition *expanded_option_table, std::vector<struct option> &getopt_table,
Caroline Tice4ab31c92010-10-12 21:57:09 +0000363 uint32_t num_options)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000364{
365 if (num_options == 0)
366 return;
367
368 uint32_t i;
369 uint32_t j;
370 std::bitset<256> option_seen;
371
Caroline Tice4ab31c92010-10-12 21:57:09 +0000372 getopt_table.resize (num_options + 1);
373
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000374 for (i = 0, j = 0; i < num_options; ++i)
Greg Claytonc982c762010-07-09 20:39:50 +0000375 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000376 char short_opt = expanded_option_table[i].short_option;
Greg Claytonc982c762010-07-09 20:39:50 +0000377
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000378 if (option_seen.test(short_opt) == false)
Greg Claytonc982c762010-07-09 20:39:50 +0000379 {
Caroline Tice4ab31c92010-10-12 21:57:09 +0000380 getopt_table[j].name = expanded_option_table[i].long_option;
381 getopt_table[j].has_arg = expanded_option_table[i].option_has_arg;
382 getopt_table[j].flag = NULL;
383 getopt_table[j].val = expanded_option_table[i].short_option;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000384 option_seen.set(short_opt);
385 ++j;
Greg Claytonc982c762010-07-09 20:39:50 +0000386 }
387 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000388
Caroline Tice4ab31c92010-10-12 21:57:09 +0000389 getopt_table[j].name = NULL;
390 getopt_table[j].has_arg = 0;
391 getopt_table[j].flag = NULL;
392 getopt_table[j].val = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000393
394}
395
Greg Clayton66111032010-06-23 01:19:29 +0000396Driver::OptionData::OptionData () :
Greg Clayton8d846da2010-12-08 22:23:24 +0000397 m_args(),
Greg Clayton66111032010-06-23 01:19:29 +0000398 m_script_lang (lldb::eScriptLanguageDefault),
Johnny Cheneb46f782012-08-15 22:10:42 +0000399 m_core_file (),
Greg Claytonc982c762010-07-09 20:39:50 +0000400 m_crash_log (),
Jim Inghamed3252f2013-09-14 00:20:24 +0000401 m_initial_commands (),
402 m_after_file_commands (),
Greg Clayton66111032010-06-23 01:19:29 +0000403 m_debug_mode (false),
Jim Inghamed3252f2013-09-14 00:20:24 +0000404 m_source_quietly(false),
Greg Claytonc982c762010-07-09 20:39:50 +0000405 m_print_version (false),
Jim Inghame2231ac2012-12-21 22:22:26 +0000406 m_print_python_path (false),
Greg Clayton66111032010-06-23 01:19:29 +0000407 m_print_help (false),
Jim Inghame64f0dc2011-09-13 23:25:31 +0000408 m_wait_for(false),
409 m_process_name(),
410 m_process_pid(LLDB_INVALID_PROCESS_ID),
Daniel Dunbara08823f2011-10-31 22:50:49 +0000411 m_use_external_editor(false),
Stephen Wilson71c21d12011-04-11 19:41:40 +0000412 m_seen_options()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000413{
Greg Clayton66111032010-06-23 01:19:29 +0000414}
415
416Driver::OptionData::~OptionData ()
417{
418}
419
420void
421Driver::OptionData::Clear ()
422{
Greg Clayton8d846da2010-12-08 22:23:24 +0000423 m_args.clear ();
Greg Clayton66111032010-06-23 01:19:29 +0000424 m_script_lang = lldb::eScriptLanguageDefault;
Jim Inghamed3252f2013-09-14 00:20:24 +0000425 m_initial_commands.clear ();
426 m_after_file_commands.clear ();
Greg Clayton66111032010-06-23 01:19:29 +0000427 m_debug_mode = false;
Jim Inghamed3252f2013-09-14 00:20:24 +0000428 m_source_quietly = false;
Greg Clayton66111032010-06-23 01:19:29 +0000429 m_print_help = false;
430 m_print_version = false;
Jim Inghame2231ac2012-12-21 22:22:26 +0000431 m_print_python_path = false;
Jim Inghame40e4212010-08-30 19:44:40 +0000432 m_use_external_editor = false;
Jim Inghame64f0dc2011-09-13 23:25:31 +0000433 m_wait_for = false;
434 m_process_name.erase();
435 m_process_pid = LLDB_INVALID_PROCESS_ID;
Greg Clayton66111032010-06-23 01:19:29 +0000436}
437
438void
Jim Inghamed3252f2013-09-14 00:20:24 +0000439Driver::OptionData::AddInitialCommand (const char *command, bool before_file, bool is_file, SBError &error)
440{
441 std::vector<std::pair<bool, std::string> > *command_set;
442 if (before_file)
443 command_set = &(m_initial_commands);
444 else
445 command_set = &(m_after_file_commands);
446
447 if (is_file)
448 {
449 SBFileSpec file(command);
450 if (file.Exists())
451 command_set->push_back (std::pair<bool, std::string> (true, optarg));
452 else if (file.ResolveExecutableLocation())
453 {
454 char final_path[PATH_MAX];
455 file.GetPath (final_path, sizeof(final_path));
456 std::string path_str (final_path);
457 command_set->push_back (std::pair<bool, std::string> (true, path_str));
458 }
459 else
460 error.SetErrorStringWithFormat("file specified in --source (-s) option doesn't exist: '%s'", optarg);
461 }
462 else
463 command_set->push_back (std::pair<bool, std::string> (false, optarg));
464}
465
466void
Greg Clayton66111032010-06-23 01:19:29 +0000467Driver::ResetOptionValues ()
468{
469 m_option_data.Clear ();
470}
471
472const char *
473Driver::GetFilename() const
474{
Greg Clayton8d846da2010-12-08 22:23:24 +0000475 if (m_option_data.m_args.empty())
Greg Clayton66111032010-06-23 01:19:29 +0000476 return NULL;
Greg Clayton8d846da2010-12-08 22:23:24 +0000477 return m_option_data.m_args.front().c_str();
Greg Clayton66111032010-06-23 01:19:29 +0000478}
479
480const char *
481Driver::GetCrashLogFilename() const
482{
483 if (m_option_data.m_crash_log.empty())
484 return NULL;
485 return m_option_data.m_crash_log.c_str();
486}
487
488lldb::ScriptLanguage
489Driver::GetScriptLanguage() const
490{
491 return m_option_data.m_script_lang;
492}
493
Jim Inghamed3252f2013-09-14 00:20:24 +0000494void
495Driver::ExecuteInitialCommands (bool before_file)
Greg Clayton66111032010-06-23 01:19:29 +0000496{
Jim Inghamed3252f2013-09-14 00:20:24 +0000497 size_t num_commands;
498 std::vector<std::pair<bool, std::string> > *command_set;
499 if (before_file)
500 command_set = &(m_option_data.m_initial_commands);
501 else
502 command_set = &(m_option_data.m_after_file_commands);
503
504 num_commands = command_set->size();
505 SBCommandReturnObject result;
506 bool old_async = GetDebugger().GetAsync();
507 GetDebugger().SetAsync(false);
508 for (size_t idx = 0; idx < num_commands; idx++)
509 {
510 bool is_file = (*command_set)[idx].first;
511 const char *command = (*command_set)[idx].second.c_str();
512 char command_string[PATH_MAX * 2];
513 const bool dump_stream_only_if_no_immediate = true;
514 const char *executed_command = command;
515 if (is_file)
516 {
517 ::snprintf (command_string, sizeof(command_string), "command source '%s'", command);
518 executed_command = command_string;
519 }
520
521 m_debugger.GetCommandInterpreter().HandleCommand (executed_command, result, false);
522 if (!m_option_data.m_source_quietly || result.Succeeded() == false)
523 {
524 const size_t output_size = result.GetOutputSize();
525 if (output_size > 0)
526 m_io_channel_ap->OutWrite (result.GetOutput(dump_stream_only_if_no_immediate), output_size, NO_ASYNC);
527 const size_t error_size = result.GetErrorSize();
528 if (error_size > 0)
529 m_io_channel_ap->OutWrite (result.GetError(dump_stream_only_if_no_immediate), error_size, NO_ASYNC);
530 }
531
532 if (result.Succeeded() == false)
533 {
534 char error_buffer[1024];
535 size_t error_size;
536 const char *type = before_file ? "before file" : "after_file";
537 if (is_file)
538 error_size = ::snprintf(error_buffer, sizeof(error_buffer), "Aborting %s command execution, command file: '%s' failed.\n", type, command);
539 else
540 error_size = ::snprintf(error_buffer, sizeof(error_buffer), "Aborting %s command execution, command: '%s' failed.\n", type, command);
541
542 m_io_channel_ap->OutWrite(error_buffer, error_size, NO_ASYNC);
543 break;
544 }
545 result.Clear();
546 }
547 GetDebugger().SetAsync(old_async);
Greg Clayton66111032010-06-23 01:19:29 +0000548}
549
550bool
551Driver::GetDebugMode() const
552{
553 return m_option_data.m_debug_mode;
554}
555
556
557// Check the arguments that were passed to this program to make sure they are valid and to get their
558// argument values (if any). Return a boolean value indicating whether or not to start up the full
559// debugger (i.e. the Command Interpreter) or not. Return FALSE if the arguments were invalid OR
560// if the user only wanted help or version information.
561
562SBError
563Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exit)
564{
565 ResetOptionValues ();
566
567 SBCommandReturnObject result;
568
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000569 SBError error;
570 std::string option_string;
571 struct option *long_options = NULL;
Caroline Tice4ab31c92010-10-12 21:57:09 +0000572 std::vector<struct option> long_options_vector;
Greg Claytonc982c762010-07-09 20:39:50 +0000573 uint32_t num_options;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000574
Greg Claytonc982c762010-07-09 20:39:50 +0000575 for (num_options = 0; g_options[num_options].long_option != NULL; ++num_options)
576 /* Do Nothing. */;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000577
578 if (num_options == 0)
579 {
580 if (argc > 1)
581 error.SetErrorStringWithFormat ("invalid number of options");
582 return error;
583 }
584
Caroline Tice4ab31c92010-10-12 21:57:09 +0000585 BuildGetOptTable (g_options, long_options_vector, num_options);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000586
Caroline Tice4ab31c92010-10-12 21:57:09 +0000587 if (long_options_vector.empty())
588 long_options = NULL;
589 else
590 long_options = &long_options_vector.front();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000591
592 if (long_options == NULL)
593 {
594 error.SetErrorStringWithFormat ("invalid long options");
595 return error;
596 }
597
Greg Claytonb7ad58a2013-04-04 20:35:24 +0000598 // Build the option_string argument for call to getopt_long_only.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000599
600 for (int i = 0; long_options[i].name != NULL; ++i)
601 {
602 if (long_options[i].flag == NULL)
603 {
604 option_string.push_back ((char) long_options[i].val);
605 switch (long_options[i].has_arg)
606 {
607 default:
608 case no_argument:
609 break;
610 case required_argument:
611 option_string.push_back (':');
612 break;
613 case optional_argument:
614 option_string.append ("::");
615 break;
616 }
617 }
618 }
619
Jim Ingham06942692011-08-13 00:22:20 +0000620 // This is kind of a pain, but since we make the debugger in the Driver's constructor, we can't
621 // know at that point whether we should read in init files yet. So we don't read them in in the
622 // Driver constructor, then set the flags back to "read them in" here, and then if we see the
623 // "-n" flag, we'll turn it off again. Finally we have to read them in by hand later in the
624 // main loop.
625
626 m_debugger.SkipLLDBInitFiles (false);
627 m_debugger.SkipAppInitFiles (false);
628
Greg Claytonb7ad58a2013-04-04 20:35:24 +0000629 // Prepare for & make calls to getopt_long_only.
Eli Friedmanadb35022010-06-13 19:18:49 +0000630#if __GLIBC__
631 optind = 0;
632#else
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000633 optreset = 1;
634 optind = 1;
Eli Friedmanadb35022010-06-13 19:18:49 +0000635#endif
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000636 int val;
637 while (1)
638 {
639 int long_options_index = -1;
Greg Claytonb7ad58a2013-04-04 20:35:24 +0000640 val = ::getopt_long_only (argc, const_cast<char **>(argv), option_string.c_str(), long_options, &long_options_index);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000641
642 if (val == -1)
643 break;
644 else if (val == '?')
645 {
Greg Clayton66111032010-06-23 01:19:29 +0000646 m_option_data.m_print_help = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000647 error.SetErrorStringWithFormat ("unknown or ambiguous option");
648 break;
649 }
650 else if (val == 0)
651 continue;
652 else
653 {
Greg Clayton66111032010-06-23 01:19:29 +0000654 m_option_data.m_seen_options.insert ((char) val);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000655 if (long_options_index == -1)
656 {
657 for (int i = 0;
658 long_options[i].name || long_options[i].has_arg || long_options[i].flag || long_options[i].val;
659 ++i)
660 {
661 if (long_options[i].val == val)
662 {
663 long_options_index = i;
664 break;
665 }
666 }
667 }
668
669 if (long_options_index >= 0)
670 {
Greg Clayton3bcdfc02012-12-04 00:32:51 +0000671 const int short_option = g_options[long_options_index].short_option;
Greg Clayton66111032010-06-23 01:19:29 +0000672
673 switch (short_option)
674 {
675 case 'h':
676 m_option_data.m_print_help = true;
677 break;
678
679 case 'v':
680 m_option_data.m_print_version = true;
681 break;
682
Jim Inghame2231ac2012-12-21 22:22:26 +0000683 case 'P':
684 m_option_data.m_print_python_path = true;
685 break;
686
Greg Clayton66111032010-06-23 01:19:29 +0000687 case 'c':
Johnny Cheneb46f782012-08-15 22:10:42 +0000688 {
689 SBFileSpec file(optarg);
690 if (file.Exists())
691 {
692 m_option_data.m_core_file = optarg;
693 }
694 else
695 error.SetErrorStringWithFormat("file specified in --core (-c) option doesn't exist: '%s'", optarg);
696 }
Greg Clayton66111032010-06-23 01:19:29 +0000697 break;
Johnny Cheneb46f782012-08-15 22:10:42 +0000698
Jim Inghame40e4212010-08-30 19:44:40 +0000699 case 'e':
700 m_option_data.m_use_external_editor = true;
701 break;
Greg Clayton6eee5aa2010-10-11 01:05:37 +0000702
Jim Inghame64f0dc2011-09-13 23:25:31 +0000703 case 'x':
Greg Clayton6eee5aa2010-10-11 01:05:37 +0000704 m_debugger.SkipLLDBInitFiles (true);
Jim Ingham06942692011-08-13 00:22:20 +0000705 m_debugger.SkipAppInitFiles (true);
Greg Clayton6eee5aa2010-10-11 01:05:37 +0000706 break;
707
Jim Inghamed3252f2013-09-14 00:20:24 +0000708 case 'X':
Michael Sartainc3ce7f272013-05-23 20:47:45 +0000709 m_debugger.SetUseColor (false);
710 break;
711
Greg Clayton66111032010-06-23 01:19:29 +0000712 case 'f':
713 {
714 SBFileSpec file(optarg);
715 if (file.Exists())
Greg Clayton8d846da2010-12-08 22:23:24 +0000716 {
717 m_option_data.m_args.push_back (optarg);
718 }
Caroline Tice428a9a52010-09-10 04:48:55 +0000719 else if (file.ResolveExecutableLocation())
720 {
721 char path[PATH_MAX];
Johnny Chen25f3a3c2011-08-10 22:06:24 +0000722 file.GetPath (path, sizeof(path));
Greg Clayton8d846da2010-12-08 22:23:24 +0000723 m_option_data.m_args.push_back (path);
Caroline Tice428a9a52010-09-10 04:48:55 +0000724 }
Greg Clayton66111032010-06-23 01:19:29 +0000725 else
726 error.SetErrorStringWithFormat("file specified in --file (-f) option doesn't exist: '%s'", optarg);
727 }
728 break;
729
730 case 'a':
731 if (!m_debugger.SetDefaultArchitecture (optarg))
732 error.SetErrorStringWithFormat("invalid architecture in the -a or --arch option: '%s'", optarg);
733 break;
734
735 case 'l':
736 m_option_data.m_script_lang = m_debugger.GetScriptingLanguage (optarg);
737 break;
738
739 case 'd':
740 m_option_data.m_debug_mode = true;
741 break;
742
Jim Inghamed3252f2013-09-14 00:20:24 +0000743 case 'q':
744 m_option_data.m_source_quietly = true;
745 break;
746
Jim Inghame64f0dc2011-09-13 23:25:31 +0000747 case 'n':
748 m_option_data.m_process_name = optarg;
749 break;
750
751 case 'w':
752 m_option_data.m_wait_for = true;
753 break;
754
755 case 'p':
756 {
757 char *remainder;
758 m_option_data.m_process_pid = strtol (optarg, &remainder, 0);
759 if (remainder == optarg || *remainder != '\0')
760 error.SetErrorStringWithFormat ("Could not convert process PID: \"%s\" into a pid.",
761 optarg);
762 }
763 break;
Greg Clayton66111032010-06-23 01:19:29 +0000764 case 's':
Jim Inghamed3252f2013-09-14 00:20:24 +0000765 m_option_data.AddInitialCommand(optarg, false, true, error);
Greg Clayton66111032010-06-23 01:19:29 +0000766 break;
Jim Inghamed3252f2013-09-14 00:20:24 +0000767 case 'o':
768 m_option_data.AddInitialCommand(optarg, false, false, error);
769 break;
770 case 'S':
771 m_option_data.AddInitialCommand(optarg, true, true, error);
772 break;
773 case 'O':
774 m_option_data.AddInitialCommand(optarg, true, false, error);
775 break;
Greg Clayton66111032010-06-23 01:19:29 +0000776 default:
777 m_option_data.m_print_help = true;
778 error.SetErrorStringWithFormat ("unrecognized option %c", short_option);
779 break;
780 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000781 }
782 else
783 {
784 error.SetErrorStringWithFormat ("invalid option with value %i", val);
785 }
786 if (error.Fail())
Caroline Tice4ab31c92010-10-12 21:57:09 +0000787 {
Greg Clayton66111032010-06-23 01:19:29 +0000788 return error;
Caroline Tice4ab31c92010-10-12 21:57:09 +0000789 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000790 }
791 }
Jim Ingham86511212010-06-15 18:47:14 +0000792
Greg Clayton66111032010-06-23 01:19:29 +0000793 if (error.Fail() || m_option_data.m_print_help)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000794 {
795 ShowUsage (out_fh, g_options, m_option_data);
Greg Claytone46dd322010-10-11 01:13:37 +0000796 exit = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000797 }
798 else if (m_option_data.m_print_version)
799 {
Greg Clayton66111032010-06-23 01:19:29 +0000800 ::fprintf (out_fh, "%s\n", m_debugger.GetVersionString());
801 exit = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000802 }
Jim Inghame2231ac2012-12-21 22:22:26 +0000803 else if (m_option_data.m_print_python_path)
804 {
805 SBFileSpec python_file_spec = SBHostOS::GetLLDBPythonPath();
806 if (python_file_spec.IsValid())
807 {
808 char python_path[PATH_MAX];
809 size_t num_chars = python_file_spec.GetPath(python_path, PATH_MAX);
810 if (num_chars < PATH_MAX)
811 {
812 ::fprintf (out_fh, "%s\n", python_path);
813 }
814 else
815 ::fprintf (out_fh, "<PATH TOO LONG>\n");
816 }
817 else
818 ::fprintf (out_fh, "<COULD NOT FIND PATH>\n");
819 exit = true;
820 }
Jim Inghame64f0dc2011-09-13 23:25:31 +0000821 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 +0000822 {
Greg Clayton8d846da2010-12-08 22:23:24 +0000823 // Any arguments that are left over after option parsing are for
824 // the program. If a file was specified with -f then the filename
825 // is already in the m_option_data.m_args array, and any remaining args
826 // are arguments for the inferior program. If no file was specified with
827 // -f, then what is left is the program name followed by any arguments.
828
Greg Claytonb7ad58a2013-04-04 20:35:24 +0000829 // Skip any options we consumed with getopt_long_only
Greg Clayton8d846da2010-12-08 22:23:24 +0000830 argc -= optind;
831 argv += optind;
832
833 if (argc > 0)
834 {
835 for (int arg_idx=0; arg_idx<argc; ++arg_idx)
836 {
837 const char *arg = argv[arg_idx];
838 if (arg)
839 m_option_data.m_args.push_back (arg);
840 }
841 }
842
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000843 }
Jim Inghame64f0dc2011-09-13 23:25:31 +0000844 else
845 {
Greg Claytonb7ad58a2013-04-04 20:35:24 +0000846 // Skip any options we consumed with getopt_long_only
Jim Inghame64f0dc2011-09-13 23:25:31 +0000847 argc -= optind;
Greg Clayton23f59502012-07-17 03:23:13 +0000848 //argv += optind; // Commented out to keep static analyzer happy
Jim Inghame64f0dc2011-09-13 23:25:31 +0000849
850 if (argc > 0)
851 ::fprintf (out_fh, "Warning: program arguments are ignored when attaching.\n");
852 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000853
Greg Clayton66111032010-06-23 01:19:29 +0000854 return error;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000855}
856
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000857size_t
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000858Driver::GetProcessSTDOUT ()
859{
860 // The process has stuff waiting for stdout; get it and write it out to the appropriate place.
861 char stdio_buffer[1024];
862 size_t len;
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000863 size_t total_bytes = 0;
Jim Ingham2976d002010-08-26 21:32:51 +0000864 while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0)
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000865 {
Greg Claytoneea37ee2013-05-14 17:36:51 +0000866 m_io_channel_ap->OutWrite (stdio_buffer, len, NO_ASYNC);
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000867 total_bytes += len;
868 }
869 return total_bytes;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000870}
871
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000872size_t
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000873Driver::GetProcessSTDERR ()
874{
875 // The process has stuff waiting for stderr; get it and write it out to the appropriate place.
876 char stdio_buffer[1024];
877 size_t len;
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000878 size_t total_bytes = 0;
Jim Ingham2976d002010-08-26 21:32:51 +0000879 while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0)
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000880 {
Greg Claytoneea37ee2013-05-14 17:36:51 +0000881 m_io_channel_ap->ErrWrite (stdio_buffer, len, NO_ASYNC);
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000882 total_bytes += len;
883 }
884 return total_bytes;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000885}
886
887void
Jim Ingham2976d002010-08-26 21:32:51 +0000888Driver::UpdateSelectedThread ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000889{
890 using namespace lldb;
Jim Ingham2976d002010-08-26 21:32:51 +0000891 SBProcess process(m_debugger.GetSelectedTarget().GetProcess());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000892 if (process.IsValid())
893 {
Jim Ingham2976d002010-08-26 21:32:51 +0000894 SBThread curr_thread (process.GetSelectedThread());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000895 SBThread thread;
896 StopReason curr_thread_stop_reason = eStopReasonInvalid;
897 curr_thread_stop_reason = curr_thread.GetStopReason();
898
899 if (!curr_thread.IsValid() ||
900 curr_thread_stop_reason == eStopReasonInvalid ||
901 curr_thread_stop_reason == eStopReasonNone)
902 {
903 // Prefer a thread that has just completed its plan over another thread as current thread.
904 SBThread plan_thread;
905 SBThread other_thread;
906 const size_t num_threads = process.GetNumThreads();
907 size_t i;
908 for (i = 0; i < num_threads; ++i)
909 {
910 thread = process.GetThreadAtIndex(i);
911 StopReason thread_stop_reason = thread.GetStopReason();
912 switch (thread_stop_reason)
913 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000914 case eStopReasonInvalid:
915 case eStopReasonNone:
916 break;
917
918 case eStopReasonTrace:
919 case eStopReasonBreakpoint:
920 case eStopReasonWatchpoint:
921 case eStopReasonSignal:
922 case eStopReasonException:
Greg Clayton90ba8112012-12-05 00:16:59 +0000923 case eStopReasonExec:
Andrew Kaylorf85defa2012-12-20 23:08:03 +0000924 case eStopReasonThreadExiting:
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000925 if (!other_thread.IsValid())
926 other_thread = thread;
927 break;
928 case eStopReasonPlanComplete:
929 if (!plan_thread.IsValid())
930 plan_thread = thread;
931 break;
932 }
933 }
934 if (plan_thread.IsValid())
Jim Ingham2976d002010-08-26 21:32:51 +0000935 process.SetSelectedThread (plan_thread);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000936 else if (other_thread.IsValid())
Jim Ingham2976d002010-08-26 21:32:51 +0000937 process.SetSelectedThread (other_thread);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000938 else
939 {
940 if (curr_thread.IsValid())
941 thread = curr_thread;
942 else
943 thread = process.GetThreadAtIndex(0);
944
945 if (thread.IsValid())
Jim Ingham2976d002010-08-26 21:32:51 +0000946 process.SetSelectedThread (thread);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000947 }
948 }
949 }
950}
951
Jim Inghame6bc6cb2012-02-08 05:23:15 +0000952// This function handles events that were broadcast by the process.
953void
954Driver::HandleBreakpointEvent (const SBEvent &event)
955{
956 using namespace lldb;
957 const uint32_t event_type = SBBreakpoint::GetBreakpointEventTypeFromEvent (event);
958
959 if (event_type & eBreakpointEventTypeAdded
960 || event_type & eBreakpointEventTypeRemoved
961 || event_type & eBreakpointEventTypeEnabled
962 || event_type & eBreakpointEventTypeDisabled
963 || event_type & eBreakpointEventTypeCommandChanged
964 || event_type & eBreakpointEventTypeConditionChanged
965 || event_type & eBreakpointEventTypeIgnoreChanged
966 || event_type & eBreakpointEventTypeLocationsResolved)
967 {
968 // Don't do anything about these events, since the breakpoint commands already echo these actions.
969 }
970 else if (event_type & eBreakpointEventTypeLocationsAdded)
971 {
972 char message[256];
973 uint32_t num_new_locations = SBBreakpoint::GetNumBreakpointLocationsFromEvent(event);
974 if (num_new_locations > 0)
975 {
976 SBBreakpoint breakpoint = SBBreakpoint::GetBreakpointFromEvent(event);
Jim Inghamfab10e82012-03-06 00:37:27 +0000977 int message_len = ::snprintf (message, sizeof(message), "%d location%s added to breakpoint %d\n",
Jim Inghame6bc6cb2012-02-08 05:23:15 +0000978 num_new_locations,
Jason Molenda65c28cb2012-09-28 01:50:47 +0000979 num_new_locations == 1 ? "" : "s",
Jim Inghame6bc6cb2012-02-08 05:23:15 +0000980 breakpoint.GetID());
981 m_io_channel_ap->OutWrite(message, message_len, ASYNC);
982 }
983 }
984 else if (event_type & eBreakpointEventTypeLocationsRemoved)
985 {
986 // These locations just get disabled, not sure it is worth spamming folks about this on the command line.
987 }
988 else if (event_type & eBreakpointEventTypeLocationsResolved)
989 {
990 // This might be an interesting thing to note, but I'm going to leave it quiet for now, it just looked noisy.
991 }
992}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000993
994// This function handles events that were broadcast by the process.
995void
996Driver::HandleProcessEvent (const SBEvent &event)
997{
998 using namespace lldb;
999 const uint32_t event_type = event.GetType();
1000
1001 if (event_type & SBProcess::eBroadcastBitSTDOUT)
1002 {
1003 // The process has stdout available, get it and write it out to the
1004 // appropriate place.
Caroline Tice969ed3d2011-05-02 20:41:46 +00001005 GetProcessSTDOUT ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001006 }
1007 else if (event_type & SBProcess::eBroadcastBitSTDERR)
1008 {
1009 // The process has stderr available, get it and write it out to the
1010 // appropriate place.
Caroline Tice969ed3d2011-05-02 20:41:46 +00001011 GetProcessSTDERR ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001012 }
1013 else if (event_type & SBProcess::eBroadcastBitStateChanged)
1014 {
1015 // Drain all stout and stderr so we don't see any output come after
1016 // we print our prompts
Caroline Tice969ed3d2011-05-02 20:41:46 +00001017 GetProcessSTDOUT ();
1018 GetProcessSTDERR ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001019 // Something changed in the process; get the event and report the process's current status and location to
1020 // the user.
1021 StateType event_state = SBProcess::GetStateFromEvent (event);
1022 if (event_state == eStateInvalid)
1023 return;
1024
1025 SBProcess process (SBProcess::GetProcessFromEvent (event));
1026 assert (process.IsValid());
1027
1028 switch (event_state)
1029 {
1030 case eStateInvalid:
1031 case eStateUnloaded:
Greg Claytonb766a732011-02-04 01:58:07 +00001032 case eStateConnected:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001033 case eStateAttaching:
1034 case eStateLaunching:
1035 case eStateStepping:
1036 case eStateDetached:
1037 {
1038 char message[1024];
Daniel Malead01b2952012-11-29 21:49:15 +00001039 int message_len = ::snprintf (message, sizeof(message), "Process %" PRIu64 " %s\n", process.GetProcessID(),
Greg Clayton66111032010-06-23 01:19:29 +00001040 m_debugger.StateAsCString (event_state));
Caroline Tice969ed3d2011-05-02 20:41:46 +00001041 m_io_channel_ap->OutWrite(message, message_len, ASYNC);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001042 }
1043 break;
1044
1045 case eStateRunning:
1046 // Don't be chatty when we run...
1047 break;
1048
1049 case eStateExited:
Caroline Ticebd13b8d2010-09-29 18:35:42 +00001050 {
1051 SBCommandReturnObject result;
1052 m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
Caroline Tice969ed3d2011-05-02 20:41:46 +00001053 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize(), ASYNC);
1054 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize(), ASYNC);
Caroline Ticebd13b8d2010-09-29 18:35:42 +00001055 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001056 break;
1057
1058 case eStateStopped:
1059 case eStateCrashed:
1060 case eStateSuspended:
1061 // Make sure the program hasn't been auto-restarted:
1062 if (SBProcess::GetRestartedFromEvent (event))
1063 {
Jim Ingham0161b492013-02-09 01:29:05 +00001064 size_t num_reasons = SBProcess::GetNumRestartedReasonsFromEvent(event);
1065 if (num_reasons > 0)
1066 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001067 // FIXME: Do we want to report this, or would that just be annoyingly chatty?
Jim Ingham0161b492013-02-09 01:29:05 +00001068 if (num_reasons == 1)
1069 {
1070 char message[1024];
1071 const char *reason = SBProcess::GetRestartedReasonAtIndexFromEvent (event, 0);
1072 int message_len = ::snprintf (message, sizeof(message), "Process %" PRIu64 " stopped and restarted: %s\n",
1073 process.GetProcessID(), reason ? reason : "<UNKNOWN REASON>");
1074 m_io_channel_ap->OutWrite(message, message_len, ASYNC);
1075 }
1076 else
1077 {
1078 char message[1024];
1079 int message_len = ::snprintf (message, sizeof(message), "Process %" PRIu64 " stopped and restarted, reasons:\n",
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001080 process.GetProcessID());
Jim Ingham0161b492013-02-09 01:29:05 +00001081 m_io_channel_ap->OutWrite(message, message_len, ASYNC);
1082 for (size_t i = 0; i < num_reasons; i++)
1083 {
1084 const char *reason = SBProcess::GetRestartedReasonAtIndexFromEvent (event, i);
1085 int message_len = ::snprintf(message, sizeof(message), "\t%s\n", reason ? reason : "<UNKNOWN REASON>");
1086 m_io_channel_ap->OutWrite(message, message_len, ASYNC);
1087 }
1088 }
1089 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001090 }
1091 else
1092 {
Jim Ingham8499e1a2012-05-08 23:06:07 +00001093 if (GetDebugger().GetSelectedTarget() == process.GetTarget())
1094 {
1095 SBCommandReturnObject result;
1096 UpdateSelectedThread ();
1097 m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
1098 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize(), ASYNC);
1099 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize(), ASYNC);
1100 }
1101 else
1102 {
1103 SBStream out_stream;
1104 uint32_t target_idx = GetDebugger().GetIndexOfTarget(process.GetTarget());
1105 if (target_idx != UINT32_MAX)
1106 out_stream.Printf ("Target %d: (", target_idx);
1107 else
1108 out_stream.Printf ("Target <unknown index>: (");
1109 process.GetTarget().GetDescription (out_stream, eDescriptionLevelBrief);
1110 out_stream.Printf (") stopped.\n");
1111 m_io_channel_ap->OutWrite (out_stream.GetData(), out_stream.GetSize(), ASYNC);
1112 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001113 }
1114 break;
1115 }
1116 }
1117}
1118
Jim Ingham4f465cf2012-10-10 18:32:14 +00001119void
1120Driver::HandleThreadEvent (const SBEvent &event)
1121{
1122 // At present the only thread event we handle is the Frame Changed event, and all we do for that is just
1123 // reprint the thread status for that thread.
1124 using namespace lldb;
1125 const uint32_t event_type = event.GetType();
Jim Inghamc3faa192012-12-11 02:31:48 +00001126 if (event_type == SBThread::eBroadcastBitStackChanged
1127 || event_type == SBThread::eBroadcastBitThreadSelected)
Jim Ingham4f465cf2012-10-10 18:32:14 +00001128 {
1129 SBThread thread = SBThread::GetThreadFromEvent (event);
1130 if (thread.IsValid())
1131 {
1132 SBStream out_stream;
1133 thread.GetStatus(out_stream);
1134 m_io_channel_ap->OutWrite (out_stream.GetData (), out_stream.GetSize (), ASYNC);
1135 }
1136 }
1137}
1138
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001139// This function handles events broadcast by the IOChannel (HasInput, UserInterrupt, or ThreadShouldExit).
1140
1141bool
1142Driver::HandleIOEvent (const SBEvent &event)
1143{
1144 bool quit = false;
1145
1146 const uint32_t event_type = event.GetType();
1147
1148 if (event_type & IOChannel::eBroadcastBitHasUserInput)
1149 {
1150 // We got some input (i.e. a command string) from the user; pass it off to the command interpreter for
1151 // handling.
1152
1153 const char *command_string = SBEvent::GetCStringFromEvent(event);
1154 if (command_string == NULL)
Greg Claytonc982c762010-07-09 20:39:50 +00001155 command_string = "";
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001156 SBCommandReturnObject result;
Jim Ingham85e8b812011-02-19 02:53:09 +00001157
Caroline Ticeb5059ac2011-05-16 19:20:50 +00001158 // We don't want the result to bypass the OutWrite function in IOChannel, as this can result in odd
1159 // output orderings and problems with the prompt.
Greg Claytoneea37ee2013-05-14 17:36:51 +00001160
1161 // Note that we are in the process of executing a command
1162 m_executing_user_command = true;
1163
Jim Ingham85e8b812011-02-19 02:53:09 +00001164 m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, true);
1165
Greg Claytoneea37ee2013-05-14 17:36:51 +00001166 // Note that we are back from executing a user command
1167 m_executing_user_command = false;
1168
1169 // Display any STDOUT/STDERR _prior_ to emitting the command result text
1170 GetProcessSTDOUT ();
1171 GetProcessSTDERR ();
1172
Enrico Granatacd4d24d2012-10-16 20:57:12 +00001173 const bool only_if_no_immediate = true;
1174
Greg Claytoneea37ee2013-05-14 17:36:51 +00001175 // Now emit the command output text from the command we just executed
Enrico Granata430e5402012-10-16 21:11:14 +00001176 const size_t output_size = result.GetOutputSize();
Enrico Granatacd4d24d2012-10-16 20:57:12 +00001177 if (output_size > 0)
1178 m_io_channel_ap->OutWrite (result.GetOutput(only_if_no_immediate), output_size, NO_ASYNC);
1179
Greg Claytoneea37ee2013-05-14 17:36:51 +00001180 // Now emit the command error text from the command we just executed
Enrico Granata430e5402012-10-16 21:11:14 +00001181 const size_t error_size = result.GetErrorSize();
Enrico Granatacd4d24d2012-10-16 20:57:12 +00001182 if (error_size > 0)
1183 m_io_channel_ap->OutWrite (result.GetError(only_if_no_immediate), error_size, NO_ASYNC);
Caroline Ticeb5059ac2011-05-16 19:20:50 +00001184
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001185 // We are done getting and running our command, we can now clear the
1186 // m_waiting_for_command so we can get another one.
1187 m_waiting_for_command = false;
1188
1189 // If our editline input reader is active, it means another input reader
1190 // got pushed onto the input reader and caused us to become deactivated.
1191 // When the input reader above us gets popped, we will get re-activated
1192 // and our prompt will refresh in our callback
1193 if (m_editline_reader.IsActive())
1194 {
1195 ReadyForCommand ();
1196 }
1197 }
1198 else if (event_type & IOChannel::eBroadcastBitUserInterrupt)
1199 {
1200 // This is here to handle control-c interrupts from the user. It has not yet really been implemented.
1201 // TO BE DONE: PROPERLY HANDLE CONTROL-C FROM USER
1202 //m_io_channel_ap->CancelInput();
1203 // Anything else? Send Interrupt to process?
1204 }
1205 else if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
1206 (event_type & IOChannel::eBroadcastBitThreadDidExit))
1207 {
1208 // If the IOChannel thread is trying to go away, then it is definitely
1209 // time to end the debugging session.
1210 quit = true;
1211 }
1212
1213 return quit;
1214}
1215
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001216void
1217Driver::MasterThreadBytesReceived (void *baton, const void *src, size_t src_len)
1218{
1219 Driver *driver = (Driver*)baton;
1220 driver->GetFromMaster ((const char *)src, src_len);
1221}
1222
1223void
1224Driver::GetFromMaster (const char *src, size_t src_len)
1225{
1226 // Echo the characters back to the Debugger's stdout, that way if you
1227 // type characters while a command is running, you'll see what you've typed.
Greg Clayton66111032010-06-23 01:19:29 +00001228 FILE *out_fh = m_debugger.GetOutputFileHandle();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001229 if (out_fh)
1230 ::fwrite (src, 1, src_len, out_fh);
1231}
1232
1233size_t
1234Driver::EditLineInputReaderCallback
1235(
1236 void *baton,
1237 SBInputReader *reader,
1238 InputReaderAction notification,
1239 const char *bytes,
1240 size_t bytes_len
1241)
1242{
1243 Driver *driver = (Driver *)baton;
1244
1245 switch (notification)
1246 {
1247 case eInputReaderActivate:
1248 break;
1249
1250 case eInputReaderReactivate:
Greg Claytoneea37ee2013-05-14 17:36:51 +00001251 if (driver->m_executing_user_command == false)
1252 driver->ReadyForCommand();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001253 break;
1254
1255 case eInputReaderDeactivate:
1256 break;
Caroline Tice969ed3d2011-05-02 20:41:46 +00001257
1258 case eInputReaderAsynchronousOutputWritten:
1259 if (driver->m_io_channel_ap.get() != NULL)
1260 driver->m_io_channel_ap->RefreshPrompt();
1261 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001262
Caroline Ticeefed6132010-11-19 20:47:54 +00001263 case eInputReaderInterrupt:
1264 if (driver->m_io_channel_ap.get() != NULL)
1265 {
Jim Inghamcfc09352012-07-27 23:57:19 +00001266 SBProcess process(driver->GetDebugger().GetSelectedTarget().GetProcess());
Jim Inghamd242f1c2012-06-01 01:07:02 +00001267 if (!driver->m_io_channel_ap->EditLineHasCharacters()
Jim Inghamcfc09352012-07-27 23:57:19 +00001268 && process.IsValid()
1269 && (process.GetState() == lldb::eStateRunning || process.GetState() == lldb::eStateAttaching))
Jim Inghamd242f1c2012-06-01 01:07:02 +00001270 {
Jim Inghamcfc09352012-07-27 23:57:19 +00001271 process.SendAsyncInterrupt ();
Jim Inghamd242f1c2012-06-01 01:07:02 +00001272 }
1273 else
1274 {
1275 driver->m_io_channel_ap->OutWrite ("^C\n", 3, NO_ASYNC);
1276 // I wish I could erase the entire input line, but there's no public API for that.
1277 driver->m_io_channel_ap->EraseCharsBeforeCursor();
1278 driver->m_io_channel_ap->RefreshPrompt();
1279 }
Caroline Ticeefed6132010-11-19 20:47:54 +00001280 }
1281 break;
1282
1283 case eInputReaderEndOfFile:
1284 if (driver->m_io_channel_ap.get() != NULL)
1285 {
Caroline Tice969ed3d2011-05-02 20:41:46 +00001286 driver->m_io_channel_ap->OutWrite ("^D\n", 3, NO_ASYNC);
Caroline Ticeefed6132010-11-19 20:47:54 +00001287 driver->m_io_channel_ap->RefreshPrompt ();
1288 }
1289 write (driver->m_editline_pty.GetMasterFileDescriptor(), "quit\n", 5);
1290 break;
1291
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001292 case eInputReaderGotToken:
1293 write (driver->m_editline_pty.GetMasterFileDescriptor(), bytes, bytes_len);
1294 break;
1295
1296 case eInputReaderDone:
1297 break;
1298 }
1299 return bytes_len;
1300}
1301
1302void
1303Driver::MainLoop ()
1304{
1305 char error_str[1024];
1306 if (m_editline_pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, error_str, sizeof(error_str)) == false)
1307 {
1308 ::fprintf (stderr, "error: failed to open driver pseudo terminal : %s", error_str);
1309 exit(1);
1310 }
1311 else
1312 {
1313 const char *driver_slave_name = m_editline_pty.GetSlaveName (error_str, sizeof(error_str));
1314 if (driver_slave_name == NULL)
1315 {
1316 ::fprintf (stderr, "error: failed to get slave name for driver pseudo terminal : %s", error_str);
1317 exit(2);
1318 }
1319 else
1320 {
1321 m_editline_slave_fh = ::fopen (driver_slave_name, "r+");
1322 if (m_editline_slave_fh == NULL)
1323 {
1324 SBError error;
1325 error.SetErrorToErrno();
1326 ::fprintf (stderr, "error: failed to get open slave for driver pseudo terminal : %s",
1327 error.GetCString());
1328 exit(3);
1329 }
1330
1331 ::setbuf (m_editline_slave_fh, NULL);
1332 }
1333 }
1334
Caroline Tice969ed3d2011-05-02 20:41:46 +00001335 lldb_utility::PseudoTerminal editline_output_pty;
1336 FILE *editline_output_slave_fh = NULL;
1337
1338 if (editline_output_pty.OpenFirstAvailableMaster (O_RDWR|O_NOCTTY, error_str, sizeof (error_str)) == false)
1339 {
1340 ::fprintf (stderr, "error: failed to open output pseudo terminal : %s", error_str);
1341 exit(1);
1342 }
1343 else
1344 {
1345 const char *output_slave_name = editline_output_pty.GetSlaveName (error_str, sizeof(error_str));
1346 if (output_slave_name == NULL)
1347 {
1348 ::fprintf (stderr, "error: failed to get slave name for output pseudo terminal : %s", error_str);
1349 exit(2);
1350 }
1351 else
1352 {
1353 editline_output_slave_fh = ::fopen (output_slave_name, "r+");
1354 if (editline_output_slave_fh == NULL)
1355 {
1356 SBError error;
1357 error.SetErrorToErrno();
1358 ::fprintf (stderr, "error: failed to get open slave for output pseudo terminal : %s",
1359 error.GetCString());
1360 exit(3);
1361 }
1362 ::setbuf (editline_output_slave_fh, NULL);
1363 }
1364 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001365
1366 // struct termios stdin_termios;
1367
1368 if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0)
Greg Claytonf571b892012-02-02 19:28:31 +00001369 {
1370 g_old_stdin_termios_is_valid = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001371 atexit (reset_stdin_termios);
Greg Claytonf571b892012-02-02 19:28:31 +00001372 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001373
1374 ::setbuf (stdin, NULL);
1375 ::setbuf (stdout, NULL);
1376
Greg Clayton66111032010-06-23 01:19:29 +00001377 m_debugger.SetErrorFileHandle (stderr, false);
1378 m_debugger.SetOutputFileHandle (stdout, false);
1379 m_debugger.SetInputFileHandle (stdin, true);
Jim Inghame40e4212010-08-30 19:44:40 +00001380
1381 m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001382
1383 // You have to drain anything that comes to the master side of the PTY. master_out_comm is
1384 // for that purpose. The reason you need to do this is a curious reason... editline will echo
1385 // characters to the PTY when it gets characters while el_gets is not running, and then when
1386 // you call el_gets (or el_getc) it will try to reset the terminal back to raw mode which blocks
1387 // if there are unconsumed characters in the out buffer.
1388 // However, you don't need to do anything with the characters, since editline will dump these
1389 // unconsumed characters after printing the prompt again in el_gets.
1390
Greg Claytond46c87a2010-12-04 02:39:47 +00001391 SBCommunication master_out_comm("driver.editline");
1392 master_out_comm.SetCloseOnEOF (false);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001393 master_out_comm.AdoptFileDesriptor(m_editline_pty.GetMasterFileDescriptor(), false);
1394 master_out_comm.SetReadThreadBytesReceivedCallback(Driver::MasterThreadBytesReceived, this);
1395
1396 if (master_out_comm.ReadThreadStart () == false)
1397 {
1398 ::fprintf (stderr, "error: failed to start master out read thread");
1399 exit(5);
1400 }
1401
Greg Clayton66111032010-06-23 01:19:29 +00001402 SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001403
Caroline Tice969ed3d2011-05-02 20:41:46 +00001404 m_io_channel_ap.reset (new IOChannel(m_editline_slave_fh, editline_output_slave_fh, stdout, stderr, this));
1405
1406 SBCommunication out_comm_2("driver.editline_output");
1407 out_comm_2.SetCloseOnEOF (false);
1408 out_comm_2.AdoptFileDesriptor (editline_output_pty.GetMasterFileDescriptor(), false);
1409 out_comm_2.SetReadThreadBytesReceivedCallback (IOChannel::LibeditOutputBytesReceived, m_io_channel_ap.get());
1410
1411 if (out_comm_2.ReadThreadStart () == false)
1412 {
1413 ::fprintf (stderr, "error: failed to start libedit output read thread");
1414 exit (5);
1415 }
1416
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001417
1418 struct winsize window_size;
1419 if (isatty (STDIN_FILENO)
1420 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
1421 {
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001422 if (window_size.ws_col > 0)
Greg Claytona7015092010-09-18 01:14:36 +00001423 m_debugger.SetTerminalWidth (window_size.ws_col);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001424 }
1425
1426 // Since input can be redirected by the debugger, we must insert our editline
1427 // input reader in the queue so we know when our reader should be active
1428 // and so we can receive bytes only when we are supposed to.
Greg Clayton66111032010-06-23 01:19:29 +00001429 SBError err (m_editline_reader.Initialize (m_debugger,
1430 Driver::EditLineInputReaderCallback, // callback
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001431 this, // baton
1432 eInputReaderGranularityByte, // token_size
1433 NULL, // end token - NULL means never done
1434 NULL, // prompt - taken care of elsewhere
1435 false)); // echo input - don't need Debugger
1436 // to do this, we handle it elsewhere
1437
1438 if (err.Fail())
1439 {
1440 ::fprintf (stderr, "error: %s", err.GetCString());
1441 exit (6);
1442 }
1443
Greg Clayton66111032010-06-23 01:19:29 +00001444 m_debugger.PushInputReader (m_editline_reader);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001445
Greg Clayton66111032010-06-23 01:19:29 +00001446 SBListener listener(m_debugger.GetListener());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001447 if (listener.IsValid())
1448 {
1449
Jim Ingham4f465cf2012-10-10 18:32:14 +00001450 listener.StartListeningForEventClass(m_debugger,
1451 SBTarget::GetBroadcasterClassName(),
1452 SBTarget::eBroadcastBitBreakpointChanged);
1453 listener.StartListeningForEventClass(m_debugger,
1454 SBThread::GetBroadcasterClassName(),
Jim Inghamc3faa192012-12-11 02:31:48 +00001455 SBThread::eBroadcastBitStackChanged |
1456 SBThread::eBroadcastBitThreadSelected);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001457 listener.StartListeningForEvents (*m_io_channel_ap,
1458 IOChannel::eBroadcastBitHasUserInput |
1459 IOChannel::eBroadcastBitUserInterrupt |
1460 IOChannel::eBroadcastBitThreadShouldExit |
1461 IOChannel::eBroadcastBitThreadDidStart |
1462 IOChannel::eBroadcastBitThreadDidExit);
1463
1464 if (m_io_channel_ap->Start ())
1465 {
1466 bool iochannel_thread_exited = false;
1467
1468 listener.StartListeningForEvents (sb_interpreter.GetBroadcaster(),
Caroline Tice86a73f92011-05-03 20:53:11 +00001469 SBCommandInterpreter::eBroadcastBitQuitCommandReceived |
1470 SBCommandInterpreter::eBroadcastBitAsynchronousOutputData |
1471 SBCommandInterpreter::eBroadcastBitAsynchronousErrorData);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001472
1473 // Before we handle any options from the command line, we parse the
1474 // .lldbinit file in the user's home directory.
1475 SBCommandReturnObject result;
1476 sb_interpreter.SourceInitFileInHomeDirectory(result);
1477 if (GetDebugMode())
1478 {
Greg Clayton66111032010-06-23 01:19:29 +00001479 result.PutError (m_debugger.GetErrorFileHandle());
1480 result.PutOutput (m_debugger.GetOutputFileHandle());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001481 }
1482
1483 // Now we handle options we got from the command line
Jim Inghamed3252f2013-09-14 00:20:24 +00001484 // First source in the commands specified to be run before the file arguments are processed.
1485 ExecuteInitialCommands(true);
1486
Johnny Cheneb46f782012-08-15 22:10:42 +00001487 // Was there a core file specified?
1488 std::string core_file_spec("");
1489 if (!m_option_data.m_core_file.empty())
1490 core_file_spec.append("--core ").append(m_option_data.m_core_file);
1491
Jim Inghamed3252f2013-09-14 00:20:24 +00001492 char command_string[PATH_MAX * 2];
Greg Clayton8d846da2010-12-08 22:23:24 +00001493 const size_t num_args = m_option_data.m_args.size();
1494 if (num_args > 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001495 {
1496 char arch_name[64];
Greg Clayton66111032010-06-23 01:19:29 +00001497 if (m_debugger.GetDefaultArchitecture (arch_name, sizeof (arch_name)))
Greg Clayton8d846da2010-12-08 22:23:24 +00001498 ::snprintf (command_string,
1499 sizeof (command_string),
Johnny Cheneb46f782012-08-15 22:10:42 +00001500 "target create --arch=%s %s \"%s\"",
Greg Clayton8d846da2010-12-08 22:23:24 +00001501 arch_name,
Johnny Cheneb46f782012-08-15 22:10:42 +00001502 core_file_spec.c_str(),
Greg Clayton8d846da2010-12-08 22:23:24 +00001503 m_option_data.m_args[0].c_str());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001504 else
Greg Clayton8d846da2010-12-08 22:23:24 +00001505 ::snprintf (command_string,
1506 sizeof(command_string),
Johnny Cheneb46f782012-08-15 22:10:42 +00001507 "target create %s \"%s\"",
1508 core_file_spec.c_str(),
Greg Clayton8d846da2010-12-08 22:23:24 +00001509 m_option_data.m_args[0].c_str());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001510
Greg Clayton66111032010-06-23 01:19:29 +00001511 m_debugger.HandleCommand (command_string);
Greg Clayton8d846da2010-12-08 22:23:24 +00001512
1513 if (num_args > 1)
1514 {
Greg Clayton1d885962011-11-08 02:43:13 +00001515 m_debugger.HandleCommand ("settings clear target.run-args");
Greg Clayton8d846da2010-12-08 22:23:24 +00001516 char arg_cstr[1024];
1517 for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx)
1518 {
Jim Inghame64f0dc2011-09-13 23:25:31 +00001519 ::snprintf (arg_cstr,
1520 sizeof(arg_cstr),
Greg Clayton1d885962011-11-08 02:43:13 +00001521 "settings append target.run-args \"%s\"",
Jim Inghame64f0dc2011-09-13 23:25:31 +00001522 m_option_data.m_args[arg_idx].c_str());
Greg Clayton8d846da2010-12-08 22:23:24 +00001523 m_debugger.HandleCommand (arg_cstr);
1524 }
1525 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001526 }
Johnny Cheneb46f782012-08-15 22:10:42 +00001527 else if (!core_file_spec.empty())
1528 {
1529 ::snprintf (command_string,
1530 sizeof(command_string),
1531 "target create %s",
1532 core_file_spec.c_str());
1533 m_debugger.HandleCommand (command_string);;
1534 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001535
1536 // Now that all option parsing is done, we try and parse the .lldbinit
1537 // file in the current working directory
1538 sb_interpreter.SourceInitFileInCurrentWorkingDirectory (result);
1539 if (GetDebugMode())
1540 {
Greg Clayton66111032010-06-23 01:19:29 +00001541 result.PutError(m_debugger.GetErrorFileHandle());
1542 result.PutOutput(m_debugger.GetOutputFileHandle());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001543 }
Jim Inghamed3252f2013-09-14 00:20:24 +00001544
1545 // Now execute the commands specified for after the file arguments are processed.
1546 ExecuteInitialCommands(false);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001547
1548 SBEvent event;
1549
1550 // Make sure the IO channel is started up before we try to tell it we
1551 // are ready for input
1552 listener.WaitForEventForBroadcasterWithType (UINT32_MAX,
1553 *m_io_channel_ap,
1554 IOChannel::eBroadcastBitThreadDidStart,
1555 event);
Jim Inghame64f0dc2011-09-13 23:25:31 +00001556 // If we were asked to attach, then do that here:
1557 // I'm going to use the command string rather than directly
1558 // calling the API's because then I don't have to recode the
1559 // event handling here.
1560 if (!m_option_data.m_process_name.empty()
1561 || m_option_data.m_process_pid != LLDB_INVALID_PROCESS_ID)
1562 {
1563 std::string command_str("process attach ");
1564 if (m_option_data.m_process_pid != LLDB_INVALID_PROCESS_ID)
1565 {
1566 command_str.append("-p ");
1567 char pid_buffer[32];
Daniel Malead01b2952012-11-29 21:49:15 +00001568 ::snprintf (pid_buffer, sizeof(pid_buffer), "%" PRIu64, m_option_data.m_process_pid);
Jim Inghame64f0dc2011-09-13 23:25:31 +00001569 command_str.append(pid_buffer);
1570 }
1571 else
1572 {
1573 command_str.append("-n \"");
1574 command_str.append(m_option_data.m_process_name);
1575 command_str.push_back('\"');
1576 if (m_option_data.m_wait_for)
1577 command_str.append(" -w");
1578 }
1579
1580 if (m_debugger.GetOutputFileHandle())
1581 ::fprintf (m_debugger.GetOutputFileHandle(),
1582 "Attaching to process with:\n %s\n",
1583 command_str.c_str());
1584
1585 // Force the attach to be synchronous:
1586 bool orig_async = m_debugger.GetAsync();
1587 m_debugger.SetAsync(true);
1588 m_debugger.HandleCommand(command_str.c_str());
1589 m_debugger.SetAsync(orig_async);
1590 }
1591
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001592 ReadyForCommand ();
1593
Greg Claytona9f7b792012-02-29 04:21:24 +00001594 while (!GetIsDone())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001595 {
1596 listener.WaitForEvent (UINT32_MAX, event);
1597 if (event.IsValid())
1598 {
1599 if (event.GetBroadcaster().IsValid())
1600 {
1601 uint32_t event_type = event.GetType();
1602 if (event.BroadcasterMatchesRef (*m_io_channel_ap))
1603 {
1604 if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
1605 (event_type & IOChannel::eBroadcastBitThreadDidExit))
1606 {
Greg Claytona9f7b792012-02-29 04:21:24 +00001607 SetIsDone();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001608 if (event_type & IOChannel::eBroadcastBitThreadDidExit)
1609 iochannel_thread_exited = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001610 }
1611 else
Greg Claytona9f7b792012-02-29 04:21:24 +00001612 {
1613 if (HandleIOEvent (event))
1614 SetIsDone();
1615 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001616 }
Jim Inghame6bc6cb2012-02-08 05:23:15 +00001617 else if (SBProcess::EventIsProcessEvent (event))
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001618 {
1619 HandleProcessEvent (event);
1620 }
Jim Inghame6bc6cb2012-02-08 05:23:15 +00001621 else if (SBBreakpoint::EventIsBreakpointEvent (event))
1622 {
1623 HandleBreakpointEvent (event);
1624 }
Jim Ingham4f465cf2012-10-10 18:32:14 +00001625 else if (SBThread::EventIsThreadEvent (event))
1626 {
1627 HandleThreadEvent (event);
1628 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001629 else if (event.BroadcasterMatchesRef (sb_interpreter.GetBroadcaster()))
1630 {
Greg Claytona9f7b792012-02-29 04:21:24 +00001631 // TODO: deprecate the eBroadcastBitQuitCommandReceived event
1632 // now that we have SBCommandInterpreter::SetCommandOverrideCallback()
1633 // that can take over a command
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001634 if (event_type & SBCommandInterpreter::eBroadcastBitQuitCommandReceived)
Greg Clayton74d41932012-01-31 04:56:17 +00001635 {
Greg Claytona9f7b792012-02-29 04:21:24 +00001636 SetIsDone();
Greg Clayton74d41932012-01-31 04:56:17 +00001637 }
Caroline Tice86a73f92011-05-03 20:53:11 +00001638 else if (event_type & SBCommandInterpreter::eBroadcastBitAsynchronousErrorData)
1639 {
1640 const char *data = SBEvent::GetCStringFromEvent (event);
1641 m_io_channel_ap->ErrWrite (data, strlen(data), ASYNC);
1642 }
1643 else if (event_type & SBCommandInterpreter::eBroadcastBitAsynchronousOutputData)
1644 {
1645 const char *data = SBEvent::GetCStringFromEvent (event);
1646 m_io_channel_ap->OutWrite (data, strlen(data), ASYNC);
1647 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001648 }
1649 }
1650 }
1651 }
1652
Michael Sartain816cf1d2013-05-22 23:31:28 +00001653 master_out_comm.SetReadThreadBytesReceivedCallback(NULL, NULL);
Greg Claytonf571b892012-02-02 19:28:31 +00001654 master_out_comm.Disconnect();
Michael Sartain816cf1d2013-05-22 23:31:28 +00001655 master_out_comm.ReadThreadStop();
1656
1657 out_comm_2.SetReadThreadBytesReceivedCallback(NULL, NULL);
Greg Claytonf571b892012-02-02 19:28:31 +00001658 out_comm_2.Disconnect();
Michael Sartain816cf1d2013-05-22 23:31:28 +00001659 out_comm_2.ReadThreadStop();
1660
1661 editline_output_pty.CloseMasterFileDescriptor();
Greg Claytonf571b892012-02-02 19:28:31 +00001662 reset_stdin_termios();
1663 fclose (stdin);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001664
1665 CloseIOChannelFile ();
1666
1667 if (!iochannel_thread_exited)
1668 {
Greg Claytonb1320972010-07-14 00:18:15 +00001669 event.Clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001670 listener.GetNextEventForBroadcasterWithType (*m_io_channel_ap,
1671 IOChannel::eBroadcastBitThreadDidExit,
1672 event);
1673 if (!event.IsValid())
1674 {
1675 // Send end EOF to the driver file descriptor
1676 m_io_channel_ap->Stop();
1677 }
1678 }
1679
Jim Ingham12e9a202011-09-15 21:30:02 +00001680 SBDebugger::Destroy (m_debugger);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001681 }
1682 }
1683}
1684
1685
1686void
1687Driver::ReadyForCommand ()
1688{
1689 if (m_waiting_for_command == false)
1690 {
1691 m_waiting_for_command = true;
1692 BroadcastEventByType (Driver::eBroadcastBitReadyForInput, true);
1693 }
1694}
1695
Jim Inghamc46fe7c2013-02-22 22:56:55 +00001696void
1697Driver::ResizeWindow (unsigned short col)
1698{
1699 GetDebugger().SetTerminalWidth (col);
1700 if (m_io_channel_ap.get() != NULL)
1701 {
1702 m_io_channel_ap->ElResize();
1703 }
1704}
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001705
Caroline Ticedd759852010-09-09 17:45:09 +00001706void
1707sigwinch_handler (int signo)
1708{
1709 struct winsize window_size;
1710 if (isatty (STDIN_FILENO)
1711 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
1712 {
Jim Ingham57190ba2012-04-26 21:39:32 +00001713 if ((window_size.ws_col > 0) && g_driver != NULL)
Caroline Ticedd759852010-09-09 17:45:09 +00001714 {
Jim Inghamc46fe7c2013-02-22 22:56:55 +00001715 g_driver->ResizeWindow (window_size.ws_col);
Caroline Ticedd759852010-09-09 17:45:09 +00001716 }
1717 }
1718}
1719
Caroline Ticeefed6132010-11-19 20:47:54 +00001720void
1721sigint_handler (int signo)
1722{
1723 static bool g_interrupt_sent = false;
1724 if (g_driver)
1725 {
1726 if (!g_interrupt_sent)
1727 {
1728 g_interrupt_sent = true;
1729 g_driver->GetDebugger().DispatchInputInterrupt();
1730 g_interrupt_sent = false;
1731 return;
1732 }
1733 }
1734
1735 exit (signo);
1736}
1737
Jim Inghamc5917d92012-11-30 20:23:19 +00001738void
1739sigtstp_handler (int signo)
1740{
1741 g_driver->GetDebugger().SaveInputTerminalState();
1742 signal (signo, SIG_DFL);
1743 kill (getpid(), signo);
1744 signal (signo, sigtstp_handler);
1745}
1746
1747void
1748sigcont_handler (int signo)
1749{
1750 g_driver->GetDebugger().RestoreInputTerminalState();
1751 signal (signo, SIG_DFL);
1752 kill (getpid(), signo);
1753 signal (signo, sigcont_handler);
1754}
1755
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001756int
Jim Inghama462f5c2011-01-27 20:15:39 +00001757main (int argc, char const *argv[], const char *envp[])
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001758{
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001759 SBDebugger::Initialize();
1760
Greg Clayton2ccf8cf2010-11-07 21:02:03 +00001761 SBHostOS::ThreadCreated ("<lldb.driver.main-thread>");
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001762
Greg Clayton3fcbed62010-10-19 03:25:40 +00001763 signal (SIGPIPE, SIG_IGN);
Caroline Ticedd759852010-09-09 17:45:09 +00001764 signal (SIGWINCH, sigwinch_handler);
Caroline Ticeefed6132010-11-19 20:47:54 +00001765 signal (SIGINT, sigint_handler);
Jim Inghamc5917d92012-11-30 20:23:19 +00001766 signal (SIGTSTP, sigtstp_handler);
1767 signal (SIGCONT, sigcont_handler);
Caroline Ticedd759852010-09-09 17:45:09 +00001768
Greg Clayton66111032010-06-23 01:19:29 +00001769 // Create a scope for driver so that the driver object will destroy itself
1770 // before SBDebugger::Terminate() is called.
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001771 {
Greg Clayton66111032010-06-23 01:19:29 +00001772 Driver driver;
1773
1774 bool exit = false;
1775 SBError error (driver.ParseArgs (argc, argv, stdout, exit));
1776 if (error.Fail())
1777 {
1778 const char *error_cstr = error.GetCString ();
1779 if (error_cstr)
1780 ::fprintf (stderr, "error: %s\n", error_cstr);
1781 }
1782 else if (!exit)
1783 {
1784 driver.MainLoop ();
1785 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001786 }
1787
1788 SBDebugger::Terminate();
1789 return 0;
1790}