blob: a4fc67f5fbe2baed0624244be9367d621d148aca [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 Ingham47ea51f2013-09-17 01:53:35 +0000105 "Tells the debugger to read in and execute the lldb commands in the given file, after any file provided on the command line has been loaded." },
Jim Inghamed3252f2013-09-14 00:20:24 +0000106 { LLDB_3_TO_5, false, "one-line" , 'o', required_argument, 0, eArgTypeNone,
Jim Ingham47ea51f2013-09-17 01:53:35 +0000107 "Tells the debugger to execute this one-line lldb command after any file provided on the command line has been loaded." },
Jim Inghamed3252f2013-09-14 00:20:24 +0000108 { LLDB_3_TO_5, false, "source-before-file" , 'S', required_argument, 0, eArgTypeFilename,
Jim Ingham47ea51f2013-09-17 01:53:35 +0000109 "Tells the debugger to read in and execute the lldb commands in the given file, before any file provided on the command line has been loaded." },
Jim Inghamed3252f2013-09-14 00:20:24 +0000110 { LLDB_3_TO_5, false, "one-line-before-file" , 'O', required_argument, 0, eArgTypeNone,
Jim Ingham47ea51f2013-09-17 01:53:35 +0000111 "Tells the debugger to execute this one-line lldb command before any file provided on the command line has been loaded." },
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 Ingham47ea51f2013-09-17 01:53:35 +0000352 fprintf (out, "\n%*sMultiple \"-s\" and \"-o\" options can be provided. They will be processed from left to right in order, "
353 "\n%*swith the source files and commands interleaved. The same is true of the \"-S\" and \"-O\" options."
354 "\n%*sThe before file and after file sets can intermixed freely, the command parser will sort them out."
355 "\n%*sThe order of the file specifiers (\"-c\", \"-f\", etc.) is not significant in this regard.\n\n",
356 indent_level, "",
357 indent_level, "",
358 indent_level, "",
359 indent_level, "");
360
Jim Inghama9deaf92011-08-16 23:57:58 +0000361 fprintf (out, "\n%*s(If you don't provide -f then the first argument will be the file to be debugged"
362 "\n%*s so '%s -- <filename> [<ARG1> [<ARG2>]]' also works."
363 "\n%*s Remember to end the options with \"--\" if any of your arguments have a \"-\" in them.)\n\n",
364 indent_level, "",
365 indent_level, "",
366 name,
367 indent_level, "");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000368}
369
370void
Greg Claytone0d378b2011-03-24 21:19:54 +0000371BuildGetOptTable (OptionDefinition *expanded_option_table, std::vector<struct option> &getopt_table,
Caroline Tice4ab31c92010-10-12 21:57:09 +0000372 uint32_t num_options)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000373{
374 if (num_options == 0)
375 return;
376
377 uint32_t i;
378 uint32_t j;
379 std::bitset<256> option_seen;
380
Caroline Tice4ab31c92010-10-12 21:57:09 +0000381 getopt_table.resize (num_options + 1);
382
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000383 for (i = 0, j = 0; i < num_options; ++i)
Greg Claytonc982c762010-07-09 20:39:50 +0000384 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000385 char short_opt = expanded_option_table[i].short_option;
Greg Claytonc982c762010-07-09 20:39:50 +0000386
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000387 if (option_seen.test(short_opt) == false)
Greg Claytonc982c762010-07-09 20:39:50 +0000388 {
Caroline Tice4ab31c92010-10-12 21:57:09 +0000389 getopt_table[j].name = expanded_option_table[i].long_option;
390 getopt_table[j].has_arg = expanded_option_table[i].option_has_arg;
391 getopt_table[j].flag = NULL;
392 getopt_table[j].val = expanded_option_table[i].short_option;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000393 option_seen.set(short_opt);
394 ++j;
Greg Claytonc982c762010-07-09 20:39:50 +0000395 }
396 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000397
Caroline Tice4ab31c92010-10-12 21:57:09 +0000398 getopt_table[j].name = NULL;
399 getopt_table[j].has_arg = 0;
400 getopt_table[j].flag = NULL;
401 getopt_table[j].val = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000402
403}
404
Greg Clayton66111032010-06-23 01:19:29 +0000405Driver::OptionData::OptionData () :
Greg Clayton8d846da2010-12-08 22:23:24 +0000406 m_args(),
Greg Clayton66111032010-06-23 01:19:29 +0000407 m_script_lang (lldb::eScriptLanguageDefault),
Johnny Cheneb46f782012-08-15 22:10:42 +0000408 m_core_file (),
Greg Claytonc982c762010-07-09 20:39:50 +0000409 m_crash_log (),
Jim Inghamed3252f2013-09-14 00:20:24 +0000410 m_initial_commands (),
411 m_after_file_commands (),
Greg Clayton66111032010-06-23 01:19:29 +0000412 m_debug_mode (false),
Jim Inghamed3252f2013-09-14 00:20:24 +0000413 m_source_quietly(false),
Greg Claytonc982c762010-07-09 20:39:50 +0000414 m_print_version (false),
Jim Inghame2231ac2012-12-21 22:22:26 +0000415 m_print_python_path (false),
Greg Clayton66111032010-06-23 01:19:29 +0000416 m_print_help (false),
Jim Inghame64f0dc2011-09-13 23:25:31 +0000417 m_wait_for(false),
418 m_process_name(),
419 m_process_pid(LLDB_INVALID_PROCESS_ID),
Daniel Dunbara08823f2011-10-31 22:50:49 +0000420 m_use_external_editor(false),
Stephen Wilson71c21d12011-04-11 19:41:40 +0000421 m_seen_options()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000422{
Greg Clayton66111032010-06-23 01:19:29 +0000423}
424
425Driver::OptionData::~OptionData ()
426{
427}
428
429void
430Driver::OptionData::Clear ()
431{
Greg Clayton8d846da2010-12-08 22:23:24 +0000432 m_args.clear ();
Greg Clayton66111032010-06-23 01:19:29 +0000433 m_script_lang = lldb::eScriptLanguageDefault;
Jim Inghamed3252f2013-09-14 00:20:24 +0000434 m_initial_commands.clear ();
435 m_after_file_commands.clear ();
Greg Clayton66111032010-06-23 01:19:29 +0000436 m_debug_mode = false;
Jim Inghamed3252f2013-09-14 00:20:24 +0000437 m_source_quietly = false;
Greg Clayton66111032010-06-23 01:19:29 +0000438 m_print_help = false;
439 m_print_version = false;
Jim Inghame2231ac2012-12-21 22:22:26 +0000440 m_print_python_path = false;
Jim Inghame40e4212010-08-30 19:44:40 +0000441 m_use_external_editor = false;
Jim Inghame64f0dc2011-09-13 23:25:31 +0000442 m_wait_for = false;
443 m_process_name.erase();
444 m_process_pid = LLDB_INVALID_PROCESS_ID;
Greg Clayton66111032010-06-23 01:19:29 +0000445}
446
447void
Jim Inghamed3252f2013-09-14 00:20:24 +0000448Driver::OptionData::AddInitialCommand (const char *command, bool before_file, bool is_file, SBError &error)
449{
450 std::vector<std::pair<bool, std::string> > *command_set;
451 if (before_file)
452 command_set = &(m_initial_commands);
453 else
454 command_set = &(m_after_file_commands);
455
456 if (is_file)
457 {
458 SBFileSpec file(command);
459 if (file.Exists())
460 command_set->push_back (std::pair<bool, std::string> (true, optarg));
461 else if (file.ResolveExecutableLocation())
462 {
463 char final_path[PATH_MAX];
464 file.GetPath (final_path, sizeof(final_path));
465 std::string path_str (final_path);
466 command_set->push_back (std::pair<bool, std::string> (true, path_str));
467 }
468 else
469 error.SetErrorStringWithFormat("file specified in --source (-s) option doesn't exist: '%s'", optarg);
470 }
471 else
472 command_set->push_back (std::pair<bool, std::string> (false, optarg));
473}
474
475void
Greg Clayton66111032010-06-23 01:19:29 +0000476Driver::ResetOptionValues ()
477{
478 m_option_data.Clear ();
479}
480
481const char *
482Driver::GetFilename() const
483{
Greg Clayton8d846da2010-12-08 22:23:24 +0000484 if (m_option_data.m_args.empty())
Greg Clayton66111032010-06-23 01:19:29 +0000485 return NULL;
Greg Clayton8d846da2010-12-08 22:23:24 +0000486 return m_option_data.m_args.front().c_str();
Greg Clayton66111032010-06-23 01:19:29 +0000487}
488
489const char *
490Driver::GetCrashLogFilename() const
491{
492 if (m_option_data.m_crash_log.empty())
493 return NULL;
494 return m_option_data.m_crash_log.c_str();
495}
496
497lldb::ScriptLanguage
498Driver::GetScriptLanguage() const
499{
500 return m_option_data.m_script_lang;
501}
502
Jim Inghamed3252f2013-09-14 00:20:24 +0000503void
504Driver::ExecuteInitialCommands (bool before_file)
Greg Clayton66111032010-06-23 01:19:29 +0000505{
Jim Inghamed3252f2013-09-14 00:20:24 +0000506 size_t num_commands;
507 std::vector<std::pair<bool, std::string> > *command_set;
508 if (before_file)
509 command_set = &(m_option_data.m_initial_commands);
510 else
511 command_set = &(m_option_data.m_after_file_commands);
512
513 num_commands = command_set->size();
514 SBCommandReturnObject result;
515 bool old_async = GetDebugger().GetAsync();
516 GetDebugger().SetAsync(false);
517 for (size_t idx = 0; idx < num_commands; idx++)
518 {
519 bool is_file = (*command_set)[idx].first;
520 const char *command = (*command_set)[idx].second.c_str();
521 char command_string[PATH_MAX * 2];
522 const bool dump_stream_only_if_no_immediate = true;
523 const char *executed_command = command;
524 if (is_file)
525 {
526 ::snprintf (command_string, sizeof(command_string), "command source '%s'", command);
527 executed_command = command_string;
528 }
529
530 m_debugger.GetCommandInterpreter().HandleCommand (executed_command, result, false);
531 if (!m_option_data.m_source_quietly || result.Succeeded() == false)
532 {
533 const size_t output_size = result.GetOutputSize();
534 if (output_size > 0)
535 m_io_channel_ap->OutWrite (result.GetOutput(dump_stream_only_if_no_immediate), output_size, NO_ASYNC);
536 const size_t error_size = result.GetErrorSize();
537 if (error_size > 0)
538 m_io_channel_ap->OutWrite (result.GetError(dump_stream_only_if_no_immediate), error_size, NO_ASYNC);
539 }
540
541 if (result.Succeeded() == false)
542 {
543 char error_buffer[1024];
544 size_t error_size;
545 const char *type = before_file ? "before file" : "after_file";
546 if (is_file)
547 error_size = ::snprintf(error_buffer, sizeof(error_buffer), "Aborting %s command execution, command file: '%s' failed.\n", type, command);
548 else
549 error_size = ::snprintf(error_buffer, sizeof(error_buffer), "Aborting %s command execution, command: '%s' failed.\n", type, command);
550
551 m_io_channel_ap->OutWrite(error_buffer, error_size, NO_ASYNC);
552 break;
553 }
554 result.Clear();
555 }
556 GetDebugger().SetAsync(old_async);
Greg Clayton66111032010-06-23 01:19:29 +0000557}
558
559bool
560Driver::GetDebugMode() const
561{
562 return m_option_data.m_debug_mode;
563}
564
565
566// Check the arguments that were passed to this program to make sure they are valid and to get their
567// argument values (if any). Return a boolean value indicating whether or not to start up the full
568// debugger (i.e. the Command Interpreter) or not. Return FALSE if the arguments were invalid OR
569// if the user only wanted help or version information.
570
571SBError
572Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exit)
573{
574 ResetOptionValues ();
575
576 SBCommandReturnObject result;
577
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000578 SBError error;
579 std::string option_string;
580 struct option *long_options = NULL;
Caroline Tice4ab31c92010-10-12 21:57:09 +0000581 std::vector<struct option> long_options_vector;
Greg Claytonc982c762010-07-09 20:39:50 +0000582 uint32_t num_options;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000583
Greg Claytonc982c762010-07-09 20:39:50 +0000584 for (num_options = 0; g_options[num_options].long_option != NULL; ++num_options)
585 /* Do Nothing. */;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000586
587 if (num_options == 0)
588 {
589 if (argc > 1)
590 error.SetErrorStringWithFormat ("invalid number of options");
591 return error;
592 }
593
Caroline Tice4ab31c92010-10-12 21:57:09 +0000594 BuildGetOptTable (g_options, long_options_vector, num_options);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000595
Caroline Tice4ab31c92010-10-12 21:57:09 +0000596 if (long_options_vector.empty())
597 long_options = NULL;
598 else
599 long_options = &long_options_vector.front();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000600
601 if (long_options == NULL)
602 {
603 error.SetErrorStringWithFormat ("invalid long options");
604 return error;
605 }
606
Greg Claytonb7ad58a2013-04-04 20:35:24 +0000607 // Build the option_string argument for call to getopt_long_only.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000608
609 for (int i = 0; long_options[i].name != NULL; ++i)
610 {
611 if (long_options[i].flag == NULL)
612 {
613 option_string.push_back ((char) long_options[i].val);
614 switch (long_options[i].has_arg)
615 {
616 default:
617 case no_argument:
618 break;
619 case required_argument:
620 option_string.push_back (':');
621 break;
622 case optional_argument:
623 option_string.append ("::");
624 break;
625 }
626 }
627 }
628
Jim Ingham06942692011-08-13 00:22:20 +0000629 // This is kind of a pain, but since we make the debugger in the Driver's constructor, we can't
630 // know at that point whether we should read in init files yet. So we don't read them in in the
631 // Driver constructor, then set the flags back to "read them in" here, and then if we see the
632 // "-n" flag, we'll turn it off again. Finally we have to read them in by hand later in the
633 // main loop.
634
635 m_debugger.SkipLLDBInitFiles (false);
636 m_debugger.SkipAppInitFiles (false);
637
Greg Claytonb7ad58a2013-04-04 20:35:24 +0000638 // Prepare for & make calls to getopt_long_only.
Eli Friedmanadb35022010-06-13 19:18:49 +0000639#if __GLIBC__
640 optind = 0;
641#else
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000642 optreset = 1;
643 optind = 1;
Eli Friedmanadb35022010-06-13 19:18:49 +0000644#endif
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000645 int val;
646 while (1)
647 {
648 int long_options_index = -1;
Greg Claytonb7ad58a2013-04-04 20:35:24 +0000649 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 +0000650
651 if (val == -1)
652 break;
653 else if (val == '?')
654 {
Greg Clayton66111032010-06-23 01:19:29 +0000655 m_option_data.m_print_help = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000656 error.SetErrorStringWithFormat ("unknown or ambiguous option");
657 break;
658 }
659 else if (val == 0)
660 continue;
661 else
662 {
Greg Clayton66111032010-06-23 01:19:29 +0000663 m_option_data.m_seen_options.insert ((char) val);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000664 if (long_options_index == -1)
665 {
666 for (int i = 0;
667 long_options[i].name || long_options[i].has_arg || long_options[i].flag || long_options[i].val;
668 ++i)
669 {
670 if (long_options[i].val == val)
671 {
672 long_options_index = i;
673 break;
674 }
675 }
676 }
677
678 if (long_options_index >= 0)
679 {
Greg Clayton3bcdfc02012-12-04 00:32:51 +0000680 const int short_option = g_options[long_options_index].short_option;
Greg Clayton66111032010-06-23 01:19:29 +0000681
682 switch (short_option)
683 {
684 case 'h':
685 m_option_data.m_print_help = true;
686 break;
687
688 case 'v':
689 m_option_data.m_print_version = true;
690 break;
691
Jim Inghame2231ac2012-12-21 22:22:26 +0000692 case 'P':
693 m_option_data.m_print_python_path = true;
694 break;
695
Greg Clayton66111032010-06-23 01:19:29 +0000696 case 'c':
Johnny Cheneb46f782012-08-15 22:10:42 +0000697 {
698 SBFileSpec file(optarg);
699 if (file.Exists())
700 {
701 m_option_data.m_core_file = optarg;
702 }
703 else
704 error.SetErrorStringWithFormat("file specified in --core (-c) option doesn't exist: '%s'", optarg);
705 }
Greg Clayton66111032010-06-23 01:19:29 +0000706 break;
Johnny Cheneb46f782012-08-15 22:10:42 +0000707
Jim Inghame40e4212010-08-30 19:44:40 +0000708 case 'e':
709 m_option_data.m_use_external_editor = true;
710 break;
Greg Clayton6eee5aa2010-10-11 01:05:37 +0000711
Jim Inghame64f0dc2011-09-13 23:25:31 +0000712 case 'x':
Greg Clayton6eee5aa2010-10-11 01:05:37 +0000713 m_debugger.SkipLLDBInitFiles (true);
Jim Ingham06942692011-08-13 00:22:20 +0000714 m_debugger.SkipAppInitFiles (true);
Greg Clayton6eee5aa2010-10-11 01:05:37 +0000715 break;
716
Jim Inghamed3252f2013-09-14 00:20:24 +0000717 case 'X':
Michael Sartainc3ce7f272013-05-23 20:47:45 +0000718 m_debugger.SetUseColor (false);
719 break;
720
Greg Clayton66111032010-06-23 01:19:29 +0000721 case 'f':
722 {
723 SBFileSpec file(optarg);
724 if (file.Exists())
Greg Clayton8d846da2010-12-08 22:23:24 +0000725 {
726 m_option_data.m_args.push_back (optarg);
727 }
Caroline Tice428a9a52010-09-10 04:48:55 +0000728 else if (file.ResolveExecutableLocation())
729 {
730 char path[PATH_MAX];
Johnny Chen25f3a3c2011-08-10 22:06:24 +0000731 file.GetPath (path, sizeof(path));
Greg Clayton8d846da2010-12-08 22:23:24 +0000732 m_option_data.m_args.push_back (path);
Caroline Tice428a9a52010-09-10 04:48:55 +0000733 }
Greg Clayton66111032010-06-23 01:19:29 +0000734 else
735 error.SetErrorStringWithFormat("file specified in --file (-f) option doesn't exist: '%s'", optarg);
736 }
737 break;
738
739 case 'a':
740 if (!m_debugger.SetDefaultArchitecture (optarg))
741 error.SetErrorStringWithFormat("invalid architecture in the -a or --arch option: '%s'", optarg);
742 break;
743
744 case 'l':
745 m_option_data.m_script_lang = m_debugger.GetScriptingLanguage (optarg);
746 break;
747
748 case 'd':
749 m_option_data.m_debug_mode = true;
750 break;
751
Jim Inghamed3252f2013-09-14 00:20:24 +0000752 case 'q':
753 m_option_data.m_source_quietly = true;
754 break;
755
Jim Inghame64f0dc2011-09-13 23:25:31 +0000756 case 'n':
757 m_option_data.m_process_name = optarg;
758 break;
759
760 case 'w':
761 m_option_data.m_wait_for = true;
762 break;
763
764 case 'p':
765 {
766 char *remainder;
767 m_option_data.m_process_pid = strtol (optarg, &remainder, 0);
768 if (remainder == optarg || *remainder != '\0')
769 error.SetErrorStringWithFormat ("Could not convert process PID: \"%s\" into a pid.",
770 optarg);
771 }
772 break;
Greg Clayton66111032010-06-23 01:19:29 +0000773 case 's':
Jim Inghamed3252f2013-09-14 00:20:24 +0000774 m_option_data.AddInitialCommand(optarg, false, true, error);
Greg Clayton66111032010-06-23 01:19:29 +0000775 break;
Jim Inghamed3252f2013-09-14 00:20:24 +0000776 case 'o':
777 m_option_data.AddInitialCommand(optarg, false, false, error);
778 break;
779 case 'S':
780 m_option_data.AddInitialCommand(optarg, true, true, error);
781 break;
782 case 'O':
783 m_option_data.AddInitialCommand(optarg, true, false, error);
784 break;
Greg Clayton66111032010-06-23 01:19:29 +0000785 default:
786 m_option_data.m_print_help = true;
787 error.SetErrorStringWithFormat ("unrecognized option %c", short_option);
788 break;
789 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000790 }
791 else
792 {
793 error.SetErrorStringWithFormat ("invalid option with value %i", val);
794 }
795 if (error.Fail())
Caroline Tice4ab31c92010-10-12 21:57:09 +0000796 {
Greg Clayton66111032010-06-23 01:19:29 +0000797 return error;
Caroline Tice4ab31c92010-10-12 21:57:09 +0000798 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000799 }
800 }
Jim Ingham86511212010-06-15 18:47:14 +0000801
Greg Clayton66111032010-06-23 01:19:29 +0000802 if (error.Fail() || m_option_data.m_print_help)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000803 {
804 ShowUsage (out_fh, g_options, m_option_data);
Greg Claytone46dd322010-10-11 01:13:37 +0000805 exit = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000806 }
807 else if (m_option_data.m_print_version)
808 {
Greg Clayton66111032010-06-23 01:19:29 +0000809 ::fprintf (out_fh, "%s\n", m_debugger.GetVersionString());
810 exit = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000811 }
Jim Inghame2231ac2012-12-21 22:22:26 +0000812 else if (m_option_data.m_print_python_path)
813 {
814 SBFileSpec python_file_spec = SBHostOS::GetLLDBPythonPath();
815 if (python_file_spec.IsValid())
816 {
817 char python_path[PATH_MAX];
818 size_t num_chars = python_file_spec.GetPath(python_path, PATH_MAX);
819 if (num_chars < PATH_MAX)
820 {
821 ::fprintf (out_fh, "%s\n", python_path);
822 }
823 else
824 ::fprintf (out_fh, "<PATH TOO LONG>\n");
825 }
826 else
827 ::fprintf (out_fh, "<COULD NOT FIND PATH>\n");
828 exit = true;
829 }
Jim Inghame64f0dc2011-09-13 23:25:31 +0000830 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 +0000831 {
Greg Clayton8d846da2010-12-08 22:23:24 +0000832 // Any arguments that are left over after option parsing are for
833 // the program. If a file was specified with -f then the filename
834 // is already in the m_option_data.m_args array, and any remaining args
835 // are arguments for the inferior program. If no file was specified with
836 // -f, then what is left is the program name followed by any arguments.
837
Greg Claytonb7ad58a2013-04-04 20:35:24 +0000838 // Skip any options we consumed with getopt_long_only
Greg Clayton8d846da2010-12-08 22:23:24 +0000839 argc -= optind;
840 argv += optind;
841
842 if (argc > 0)
843 {
844 for (int arg_idx=0; arg_idx<argc; ++arg_idx)
845 {
846 const char *arg = argv[arg_idx];
847 if (arg)
848 m_option_data.m_args.push_back (arg);
849 }
850 }
851
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000852 }
Jim Inghame64f0dc2011-09-13 23:25:31 +0000853 else
854 {
Greg Claytonb7ad58a2013-04-04 20:35:24 +0000855 // Skip any options we consumed with getopt_long_only
Jim Inghame64f0dc2011-09-13 23:25:31 +0000856 argc -= optind;
Greg Clayton23f59502012-07-17 03:23:13 +0000857 //argv += optind; // Commented out to keep static analyzer happy
Jim Inghame64f0dc2011-09-13 23:25:31 +0000858
859 if (argc > 0)
860 ::fprintf (out_fh, "Warning: program arguments are ignored when attaching.\n");
861 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000862
Greg Clayton66111032010-06-23 01:19:29 +0000863 return error;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000864}
865
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000866size_t
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000867Driver::GetProcessSTDOUT ()
868{
869 // The process has stuff waiting for stdout; get it and write it out to the appropriate place.
870 char stdio_buffer[1024];
871 size_t len;
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000872 size_t total_bytes = 0;
Jim Ingham2976d002010-08-26 21:32:51 +0000873 while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0)
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000874 {
Greg Claytoneea37ee2013-05-14 17:36:51 +0000875 m_io_channel_ap->OutWrite (stdio_buffer, len, NO_ASYNC);
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000876 total_bytes += len;
877 }
878 return total_bytes;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000879}
880
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000881size_t
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000882Driver::GetProcessSTDERR ()
883{
884 // The process has stuff waiting for stderr; get it and write it out to the appropriate place.
885 char stdio_buffer[1024];
886 size_t len;
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000887 size_t total_bytes = 0;
Jim Ingham2976d002010-08-26 21:32:51 +0000888 while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0)
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000889 {
Greg Claytoneea37ee2013-05-14 17:36:51 +0000890 m_io_channel_ap->ErrWrite (stdio_buffer, len, NO_ASYNC);
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000891 total_bytes += len;
892 }
893 return total_bytes;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000894}
895
896void
Jim Ingham2976d002010-08-26 21:32:51 +0000897Driver::UpdateSelectedThread ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000898{
899 using namespace lldb;
Jim Ingham2976d002010-08-26 21:32:51 +0000900 SBProcess process(m_debugger.GetSelectedTarget().GetProcess());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000901 if (process.IsValid())
902 {
Jim Ingham2976d002010-08-26 21:32:51 +0000903 SBThread curr_thread (process.GetSelectedThread());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000904 SBThread thread;
905 StopReason curr_thread_stop_reason = eStopReasonInvalid;
906 curr_thread_stop_reason = curr_thread.GetStopReason();
907
908 if (!curr_thread.IsValid() ||
909 curr_thread_stop_reason == eStopReasonInvalid ||
910 curr_thread_stop_reason == eStopReasonNone)
911 {
912 // Prefer a thread that has just completed its plan over another thread as current thread.
913 SBThread plan_thread;
914 SBThread other_thread;
915 const size_t num_threads = process.GetNumThreads();
916 size_t i;
917 for (i = 0; i < num_threads; ++i)
918 {
919 thread = process.GetThreadAtIndex(i);
920 StopReason thread_stop_reason = thread.GetStopReason();
921 switch (thread_stop_reason)
922 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000923 case eStopReasonInvalid:
924 case eStopReasonNone:
925 break;
926
927 case eStopReasonTrace:
928 case eStopReasonBreakpoint:
929 case eStopReasonWatchpoint:
930 case eStopReasonSignal:
931 case eStopReasonException:
Greg Clayton90ba8112012-12-05 00:16:59 +0000932 case eStopReasonExec:
Andrew Kaylorf85defa2012-12-20 23:08:03 +0000933 case eStopReasonThreadExiting:
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000934 if (!other_thread.IsValid())
935 other_thread = thread;
936 break;
937 case eStopReasonPlanComplete:
938 if (!plan_thread.IsValid())
939 plan_thread = thread;
940 break;
941 }
942 }
943 if (plan_thread.IsValid())
Jim Ingham2976d002010-08-26 21:32:51 +0000944 process.SetSelectedThread (plan_thread);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000945 else if (other_thread.IsValid())
Jim Ingham2976d002010-08-26 21:32:51 +0000946 process.SetSelectedThread (other_thread);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000947 else
948 {
949 if (curr_thread.IsValid())
950 thread = curr_thread;
951 else
952 thread = process.GetThreadAtIndex(0);
953
954 if (thread.IsValid())
Jim Ingham2976d002010-08-26 21:32:51 +0000955 process.SetSelectedThread (thread);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000956 }
957 }
958 }
959}
960
Jim Inghame6bc6cb2012-02-08 05:23:15 +0000961// This function handles events that were broadcast by the process.
962void
963Driver::HandleBreakpointEvent (const SBEvent &event)
964{
965 using namespace lldb;
966 const uint32_t event_type = SBBreakpoint::GetBreakpointEventTypeFromEvent (event);
967
968 if (event_type & eBreakpointEventTypeAdded
969 || event_type & eBreakpointEventTypeRemoved
970 || event_type & eBreakpointEventTypeEnabled
971 || event_type & eBreakpointEventTypeDisabled
972 || event_type & eBreakpointEventTypeCommandChanged
973 || event_type & eBreakpointEventTypeConditionChanged
974 || event_type & eBreakpointEventTypeIgnoreChanged
975 || event_type & eBreakpointEventTypeLocationsResolved)
976 {
977 // Don't do anything about these events, since the breakpoint commands already echo these actions.
978 }
979 else if (event_type & eBreakpointEventTypeLocationsAdded)
980 {
981 char message[256];
982 uint32_t num_new_locations = SBBreakpoint::GetNumBreakpointLocationsFromEvent(event);
983 if (num_new_locations > 0)
984 {
985 SBBreakpoint breakpoint = SBBreakpoint::GetBreakpointFromEvent(event);
Jim Inghamfab10e82012-03-06 00:37:27 +0000986 int message_len = ::snprintf (message, sizeof(message), "%d location%s added to breakpoint %d\n",
Jim Inghame6bc6cb2012-02-08 05:23:15 +0000987 num_new_locations,
Jason Molenda65c28cb2012-09-28 01:50:47 +0000988 num_new_locations == 1 ? "" : "s",
Jim Inghame6bc6cb2012-02-08 05:23:15 +0000989 breakpoint.GetID());
990 m_io_channel_ap->OutWrite(message, message_len, ASYNC);
991 }
992 }
993 else if (event_type & eBreakpointEventTypeLocationsRemoved)
994 {
995 // These locations just get disabled, not sure it is worth spamming folks about this on the command line.
996 }
997 else if (event_type & eBreakpointEventTypeLocationsResolved)
998 {
999 // This might be an interesting thing to note, but I'm going to leave it quiet for now, it just looked noisy.
1000 }
1001}
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001002
1003// This function handles events that were broadcast by the process.
1004void
1005Driver::HandleProcessEvent (const SBEvent &event)
1006{
1007 using namespace lldb;
1008 const uint32_t event_type = event.GetType();
1009
1010 if (event_type & SBProcess::eBroadcastBitSTDOUT)
1011 {
1012 // The process has stdout available, get it and write it out to the
1013 // appropriate place.
Caroline Tice969ed3d2011-05-02 20:41:46 +00001014 GetProcessSTDOUT ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001015 }
1016 else if (event_type & SBProcess::eBroadcastBitSTDERR)
1017 {
1018 // The process has stderr available, get it and write it out to the
1019 // appropriate place.
Caroline Tice969ed3d2011-05-02 20:41:46 +00001020 GetProcessSTDERR ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001021 }
1022 else if (event_type & SBProcess::eBroadcastBitStateChanged)
1023 {
1024 // Drain all stout and stderr so we don't see any output come after
1025 // we print our prompts
Caroline Tice969ed3d2011-05-02 20:41:46 +00001026 GetProcessSTDOUT ();
1027 GetProcessSTDERR ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001028 // Something changed in the process; get the event and report the process's current status and location to
1029 // the user.
1030 StateType event_state = SBProcess::GetStateFromEvent (event);
1031 if (event_state == eStateInvalid)
1032 return;
1033
1034 SBProcess process (SBProcess::GetProcessFromEvent (event));
1035 assert (process.IsValid());
1036
1037 switch (event_state)
1038 {
1039 case eStateInvalid:
1040 case eStateUnloaded:
Greg Claytonb766a732011-02-04 01:58:07 +00001041 case eStateConnected:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001042 case eStateAttaching:
1043 case eStateLaunching:
1044 case eStateStepping:
1045 case eStateDetached:
1046 {
1047 char message[1024];
Daniel Malead01b2952012-11-29 21:49:15 +00001048 int message_len = ::snprintf (message, sizeof(message), "Process %" PRIu64 " %s\n", process.GetProcessID(),
Greg Clayton66111032010-06-23 01:19:29 +00001049 m_debugger.StateAsCString (event_state));
Caroline Tice969ed3d2011-05-02 20:41:46 +00001050 m_io_channel_ap->OutWrite(message, message_len, ASYNC);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001051 }
1052 break;
1053
1054 case eStateRunning:
1055 // Don't be chatty when we run...
1056 break;
1057
1058 case eStateExited:
Caroline Ticebd13b8d2010-09-29 18:35:42 +00001059 {
1060 SBCommandReturnObject result;
1061 m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
Caroline Tice969ed3d2011-05-02 20:41:46 +00001062 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize(), ASYNC);
1063 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize(), ASYNC);
Caroline Ticebd13b8d2010-09-29 18:35:42 +00001064 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001065 break;
1066
1067 case eStateStopped:
1068 case eStateCrashed:
1069 case eStateSuspended:
1070 // Make sure the program hasn't been auto-restarted:
1071 if (SBProcess::GetRestartedFromEvent (event))
1072 {
Jim Ingham0161b492013-02-09 01:29:05 +00001073 size_t num_reasons = SBProcess::GetNumRestartedReasonsFromEvent(event);
1074 if (num_reasons > 0)
1075 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001076 // FIXME: Do we want to report this, or would that just be annoyingly chatty?
Jim Ingham0161b492013-02-09 01:29:05 +00001077 if (num_reasons == 1)
1078 {
1079 char message[1024];
1080 const char *reason = SBProcess::GetRestartedReasonAtIndexFromEvent (event, 0);
1081 int message_len = ::snprintf (message, sizeof(message), "Process %" PRIu64 " stopped and restarted: %s\n",
1082 process.GetProcessID(), reason ? reason : "<UNKNOWN REASON>");
1083 m_io_channel_ap->OutWrite(message, message_len, ASYNC);
1084 }
1085 else
1086 {
1087 char message[1024];
1088 int message_len = ::snprintf (message, sizeof(message), "Process %" PRIu64 " stopped and restarted, reasons:\n",
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001089 process.GetProcessID());
Jim Ingham0161b492013-02-09 01:29:05 +00001090 m_io_channel_ap->OutWrite(message, message_len, ASYNC);
1091 for (size_t i = 0; i < num_reasons; i++)
1092 {
1093 const char *reason = SBProcess::GetRestartedReasonAtIndexFromEvent (event, i);
1094 int message_len = ::snprintf(message, sizeof(message), "\t%s\n", reason ? reason : "<UNKNOWN REASON>");
1095 m_io_channel_ap->OutWrite(message, message_len, ASYNC);
1096 }
1097 }
1098 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001099 }
1100 else
1101 {
Jim Ingham8499e1a2012-05-08 23:06:07 +00001102 if (GetDebugger().GetSelectedTarget() == process.GetTarget())
1103 {
1104 SBCommandReturnObject result;
1105 UpdateSelectedThread ();
1106 m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
1107 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize(), ASYNC);
1108 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize(), ASYNC);
1109 }
1110 else
1111 {
1112 SBStream out_stream;
1113 uint32_t target_idx = GetDebugger().GetIndexOfTarget(process.GetTarget());
1114 if (target_idx != UINT32_MAX)
1115 out_stream.Printf ("Target %d: (", target_idx);
1116 else
1117 out_stream.Printf ("Target <unknown index>: (");
1118 process.GetTarget().GetDescription (out_stream, eDescriptionLevelBrief);
1119 out_stream.Printf (") stopped.\n");
1120 m_io_channel_ap->OutWrite (out_stream.GetData(), out_stream.GetSize(), ASYNC);
1121 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001122 }
1123 break;
1124 }
1125 }
1126}
1127
Jim Ingham4f465cf2012-10-10 18:32:14 +00001128void
1129Driver::HandleThreadEvent (const SBEvent &event)
1130{
1131 // At present the only thread event we handle is the Frame Changed event, and all we do for that is just
1132 // reprint the thread status for that thread.
1133 using namespace lldb;
1134 const uint32_t event_type = event.GetType();
Jim Inghamc3faa192012-12-11 02:31:48 +00001135 if (event_type == SBThread::eBroadcastBitStackChanged
1136 || event_type == SBThread::eBroadcastBitThreadSelected)
Jim Ingham4f465cf2012-10-10 18:32:14 +00001137 {
1138 SBThread thread = SBThread::GetThreadFromEvent (event);
1139 if (thread.IsValid())
1140 {
1141 SBStream out_stream;
1142 thread.GetStatus(out_stream);
1143 m_io_channel_ap->OutWrite (out_stream.GetData (), out_stream.GetSize (), ASYNC);
1144 }
1145 }
1146}
1147
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001148// This function handles events broadcast by the IOChannel (HasInput, UserInterrupt, or ThreadShouldExit).
1149
1150bool
1151Driver::HandleIOEvent (const SBEvent &event)
1152{
1153 bool quit = false;
1154
1155 const uint32_t event_type = event.GetType();
1156
1157 if (event_type & IOChannel::eBroadcastBitHasUserInput)
1158 {
1159 // We got some input (i.e. a command string) from the user; pass it off to the command interpreter for
1160 // handling.
1161
1162 const char *command_string = SBEvent::GetCStringFromEvent(event);
1163 if (command_string == NULL)
Greg Claytonc982c762010-07-09 20:39:50 +00001164 command_string = "";
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001165 SBCommandReturnObject result;
Jim Ingham85e8b812011-02-19 02:53:09 +00001166
Caroline Ticeb5059ac2011-05-16 19:20:50 +00001167 // We don't want the result to bypass the OutWrite function in IOChannel, as this can result in odd
1168 // output orderings and problems with the prompt.
Greg Claytoneea37ee2013-05-14 17:36:51 +00001169
1170 // Note that we are in the process of executing a command
1171 m_executing_user_command = true;
1172
Jim Ingham85e8b812011-02-19 02:53:09 +00001173 m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, true);
1174
Greg Claytoneea37ee2013-05-14 17:36:51 +00001175 // Note that we are back from executing a user command
1176 m_executing_user_command = false;
1177
1178 // Display any STDOUT/STDERR _prior_ to emitting the command result text
1179 GetProcessSTDOUT ();
1180 GetProcessSTDERR ();
1181
Enrico Granatacd4d24d2012-10-16 20:57:12 +00001182 const bool only_if_no_immediate = true;
1183
Greg Claytoneea37ee2013-05-14 17:36:51 +00001184 // Now emit the command output text from the command we just executed
Enrico Granata430e5402012-10-16 21:11:14 +00001185 const size_t output_size = result.GetOutputSize();
Enrico Granatacd4d24d2012-10-16 20:57:12 +00001186 if (output_size > 0)
1187 m_io_channel_ap->OutWrite (result.GetOutput(only_if_no_immediate), output_size, NO_ASYNC);
1188
Greg Claytoneea37ee2013-05-14 17:36:51 +00001189 // Now emit the command error text from the command we just executed
Enrico Granata430e5402012-10-16 21:11:14 +00001190 const size_t error_size = result.GetErrorSize();
Enrico Granatacd4d24d2012-10-16 20:57:12 +00001191 if (error_size > 0)
1192 m_io_channel_ap->OutWrite (result.GetError(only_if_no_immediate), error_size, NO_ASYNC);
Caroline Ticeb5059ac2011-05-16 19:20:50 +00001193
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001194 // We are done getting and running our command, we can now clear the
1195 // m_waiting_for_command so we can get another one.
1196 m_waiting_for_command = false;
1197
1198 // If our editline input reader is active, it means another input reader
1199 // got pushed onto the input reader and caused us to become deactivated.
1200 // When the input reader above us gets popped, we will get re-activated
1201 // and our prompt will refresh in our callback
1202 if (m_editline_reader.IsActive())
1203 {
1204 ReadyForCommand ();
1205 }
1206 }
1207 else if (event_type & IOChannel::eBroadcastBitUserInterrupt)
1208 {
1209 // This is here to handle control-c interrupts from the user. It has not yet really been implemented.
1210 // TO BE DONE: PROPERLY HANDLE CONTROL-C FROM USER
1211 //m_io_channel_ap->CancelInput();
1212 // Anything else? Send Interrupt to process?
1213 }
1214 else if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
1215 (event_type & IOChannel::eBroadcastBitThreadDidExit))
1216 {
1217 // If the IOChannel thread is trying to go away, then it is definitely
1218 // time to end the debugging session.
1219 quit = true;
1220 }
1221
1222 return quit;
1223}
1224
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001225void
1226Driver::MasterThreadBytesReceived (void *baton, const void *src, size_t src_len)
1227{
1228 Driver *driver = (Driver*)baton;
1229 driver->GetFromMaster ((const char *)src, src_len);
1230}
1231
1232void
1233Driver::GetFromMaster (const char *src, size_t src_len)
1234{
1235 // Echo the characters back to the Debugger's stdout, that way if you
1236 // type characters while a command is running, you'll see what you've typed.
Greg Clayton66111032010-06-23 01:19:29 +00001237 FILE *out_fh = m_debugger.GetOutputFileHandle();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001238 if (out_fh)
1239 ::fwrite (src, 1, src_len, out_fh);
1240}
1241
1242size_t
1243Driver::EditLineInputReaderCallback
1244(
1245 void *baton,
1246 SBInputReader *reader,
1247 InputReaderAction notification,
1248 const char *bytes,
1249 size_t bytes_len
1250)
1251{
1252 Driver *driver = (Driver *)baton;
1253
1254 switch (notification)
1255 {
1256 case eInputReaderActivate:
1257 break;
1258
1259 case eInputReaderReactivate:
Greg Claytoneea37ee2013-05-14 17:36:51 +00001260 if (driver->m_executing_user_command == false)
1261 driver->ReadyForCommand();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001262 break;
1263
1264 case eInputReaderDeactivate:
1265 break;
Caroline Tice969ed3d2011-05-02 20:41:46 +00001266
1267 case eInputReaderAsynchronousOutputWritten:
1268 if (driver->m_io_channel_ap.get() != NULL)
1269 driver->m_io_channel_ap->RefreshPrompt();
1270 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001271
Caroline Ticeefed6132010-11-19 20:47:54 +00001272 case eInputReaderInterrupt:
1273 if (driver->m_io_channel_ap.get() != NULL)
1274 {
Jim Inghamcfc09352012-07-27 23:57:19 +00001275 SBProcess process(driver->GetDebugger().GetSelectedTarget().GetProcess());
Jim Inghamd242f1c2012-06-01 01:07:02 +00001276 if (!driver->m_io_channel_ap->EditLineHasCharacters()
Jim Inghamcfc09352012-07-27 23:57:19 +00001277 && process.IsValid()
1278 && (process.GetState() == lldb::eStateRunning || process.GetState() == lldb::eStateAttaching))
Jim Inghamd242f1c2012-06-01 01:07:02 +00001279 {
Jim Inghamcfc09352012-07-27 23:57:19 +00001280 process.SendAsyncInterrupt ();
Jim Inghamd242f1c2012-06-01 01:07:02 +00001281 }
1282 else
1283 {
1284 driver->m_io_channel_ap->OutWrite ("^C\n", 3, NO_ASYNC);
1285 // I wish I could erase the entire input line, but there's no public API for that.
1286 driver->m_io_channel_ap->EraseCharsBeforeCursor();
1287 driver->m_io_channel_ap->RefreshPrompt();
1288 }
Caroline Ticeefed6132010-11-19 20:47:54 +00001289 }
1290 break;
1291
1292 case eInputReaderEndOfFile:
1293 if (driver->m_io_channel_ap.get() != NULL)
1294 {
Caroline Tice969ed3d2011-05-02 20:41:46 +00001295 driver->m_io_channel_ap->OutWrite ("^D\n", 3, NO_ASYNC);
Caroline Ticeefed6132010-11-19 20:47:54 +00001296 driver->m_io_channel_ap->RefreshPrompt ();
1297 }
1298 write (driver->m_editline_pty.GetMasterFileDescriptor(), "quit\n", 5);
1299 break;
1300
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001301 case eInputReaderGotToken:
1302 write (driver->m_editline_pty.GetMasterFileDescriptor(), bytes, bytes_len);
1303 break;
1304
1305 case eInputReaderDone:
1306 break;
1307 }
1308 return bytes_len;
1309}
1310
1311void
1312Driver::MainLoop ()
1313{
1314 char error_str[1024];
1315 if (m_editline_pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, error_str, sizeof(error_str)) == false)
1316 {
1317 ::fprintf (stderr, "error: failed to open driver pseudo terminal : %s", error_str);
1318 exit(1);
1319 }
1320 else
1321 {
1322 const char *driver_slave_name = m_editline_pty.GetSlaveName (error_str, sizeof(error_str));
1323 if (driver_slave_name == NULL)
1324 {
1325 ::fprintf (stderr, "error: failed to get slave name for driver pseudo terminal : %s", error_str);
1326 exit(2);
1327 }
1328 else
1329 {
1330 m_editline_slave_fh = ::fopen (driver_slave_name, "r+");
1331 if (m_editline_slave_fh == NULL)
1332 {
1333 SBError error;
1334 error.SetErrorToErrno();
1335 ::fprintf (stderr, "error: failed to get open slave for driver pseudo terminal : %s",
1336 error.GetCString());
1337 exit(3);
1338 }
1339
1340 ::setbuf (m_editline_slave_fh, NULL);
1341 }
1342 }
1343
Caroline Tice969ed3d2011-05-02 20:41:46 +00001344 lldb_utility::PseudoTerminal editline_output_pty;
1345 FILE *editline_output_slave_fh = NULL;
1346
1347 if (editline_output_pty.OpenFirstAvailableMaster (O_RDWR|O_NOCTTY, error_str, sizeof (error_str)) == false)
1348 {
1349 ::fprintf (stderr, "error: failed to open output pseudo terminal : %s", error_str);
1350 exit(1);
1351 }
1352 else
1353 {
1354 const char *output_slave_name = editline_output_pty.GetSlaveName (error_str, sizeof(error_str));
1355 if (output_slave_name == NULL)
1356 {
1357 ::fprintf (stderr, "error: failed to get slave name for output pseudo terminal : %s", error_str);
1358 exit(2);
1359 }
1360 else
1361 {
1362 editline_output_slave_fh = ::fopen (output_slave_name, "r+");
1363 if (editline_output_slave_fh == NULL)
1364 {
1365 SBError error;
1366 error.SetErrorToErrno();
1367 ::fprintf (stderr, "error: failed to get open slave for output pseudo terminal : %s",
1368 error.GetCString());
1369 exit(3);
1370 }
1371 ::setbuf (editline_output_slave_fh, NULL);
1372 }
1373 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001374
1375 // struct termios stdin_termios;
1376
1377 if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0)
Greg Claytonf571b892012-02-02 19:28:31 +00001378 {
1379 g_old_stdin_termios_is_valid = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001380 atexit (reset_stdin_termios);
Greg Claytonf571b892012-02-02 19:28:31 +00001381 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001382
1383 ::setbuf (stdin, NULL);
1384 ::setbuf (stdout, NULL);
1385
Greg Clayton66111032010-06-23 01:19:29 +00001386 m_debugger.SetErrorFileHandle (stderr, false);
1387 m_debugger.SetOutputFileHandle (stdout, false);
1388 m_debugger.SetInputFileHandle (stdin, true);
Jim Inghame40e4212010-08-30 19:44:40 +00001389
1390 m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001391
1392 // You have to drain anything that comes to the master side of the PTY. master_out_comm is
1393 // for that purpose. The reason you need to do this is a curious reason... editline will echo
1394 // characters to the PTY when it gets characters while el_gets is not running, and then when
1395 // you call el_gets (or el_getc) it will try to reset the terminal back to raw mode which blocks
1396 // if there are unconsumed characters in the out buffer.
1397 // However, you don't need to do anything with the characters, since editline will dump these
1398 // unconsumed characters after printing the prompt again in el_gets.
1399
Greg Claytond46c87a2010-12-04 02:39:47 +00001400 SBCommunication master_out_comm("driver.editline");
1401 master_out_comm.SetCloseOnEOF (false);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001402 master_out_comm.AdoptFileDesriptor(m_editline_pty.GetMasterFileDescriptor(), false);
1403 master_out_comm.SetReadThreadBytesReceivedCallback(Driver::MasterThreadBytesReceived, this);
1404
1405 if (master_out_comm.ReadThreadStart () == false)
1406 {
1407 ::fprintf (stderr, "error: failed to start master out read thread");
1408 exit(5);
1409 }
1410
Greg Clayton66111032010-06-23 01:19:29 +00001411 SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001412
Caroline Tice969ed3d2011-05-02 20:41:46 +00001413 m_io_channel_ap.reset (new IOChannel(m_editline_slave_fh, editline_output_slave_fh, stdout, stderr, this));
1414
1415 SBCommunication out_comm_2("driver.editline_output");
1416 out_comm_2.SetCloseOnEOF (false);
1417 out_comm_2.AdoptFileDesriptor (editline_output_pty.GetMasterFileDescriptor(), false);
1418 out_comm_2.SetReadThreadBytesReceivedCallback (IOChannel::LibeditOutputBytesReceived, m_io_channel_ap.get());
1419
1420 if (out_comm_2.ReadThreadStart () == false)
1421 {
1422 ::fprintf (stderr, "error: failed to start libedit output read thread");
1423 exit (5);
1424 }
1425
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001426
1427 struct winsize window_size;
1428 if (isatty (STDIN_FILENO)
1429 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
1430 {
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001431 if (window_size.ws_col > 0)
Greg Claytona7015092010-09-18 01:14:36 +00001432 m_debugger.SetTerminalWidth (window_size.ws_col);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001433 }
1434
1435 // Since input can be redirected by the debugger, we must insert our editline
1436 // input reader in the queue so we know when our reader should be active
1437 // and so we can receive bytes only when we are supposed to.
Greg Clayton66111032010-06-23 01:19:29 +00001438 SBError err (m_editline_reader.Initialize (m_debugger,
1439 Driver::EditLineInputReaderCallback, // callback
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001440 this, // baton
1441 eInputReaderGranularityByte, // token_size
1442 NULL, // end token - NULL means never done
1443 NULL, // prompt - taken care of elsewhere
1444 false)); // echo input - don't need Debugger
1445 // to do this, we handle it elsewhere
1446
1447 if (err.Fail())
1448 {
1449 ::fprintf (stderr, "error: %s", err.GetCString());
1450 exit (6);
1451 }
1452
Greg Clayton66111032010-06-23 01:19:29 +00001453 m_debugger.PushInputReader (m_editline_reader);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001454
Greg Clayton66111032010-06-23 01:19:29 +00001455 SBListener listener(m_debugger.GetListener());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001456 if (listener.IsValid())
1457 {
1458
Jim Ingham4f465cf2012-10-10 18:32:14 +00001459 listener.StartListeningForEventClass(m_debugger,
1460 SBTarget::GetBroadcasterClassName(),
1461 SBTarget::eBroadcastBitBreakpointChanged);
1462 listener.StartListeningForEventClass(m_debugger,
1463 SBThread::GetBroadcasterClassName(),
Jim Inghamc3faa192012-12-11 02:31:48 +00001464 SBThread::eBroadcastBitStackChanged |
1465 SBThread::eBroadcastBitThreadSelected);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001466 listener.StartListeningForEvents (*m_io_channel_ap,
1467 IOChannel::eBroadcastBitHasUserInput |
1468 IOChannel::eBroadcastBitUserInterrupt |
1469 IOChannel::eBroadcastBitThreadShouldExit |
1470 IOChannel::eBroadcastBitThreadDidStart |
1471 IOChannel::eBroadcastBitThreadDidExit);
1472
1473 if (m_io_channel_ap->Start ())
1474 {
1475 bool iochannel_thread_exited = false;
1476
1477 listener.StartListeningForEvents (sb_interpreter.GetBroadcaster(),
Caroline Tice86a73f92011-05-03 20:53:11 +00001478 SBCommandInterpreter::eBroadcastBitQuitCommandReceived |
1479 SBCommandInterpreter::eBroadcastBitAsynchronousOutputData |
1480 SBCommandInterpreter::eBroadcastBitAsynchronousErrorData);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001481
1482 // Before we handle any options from the command line, we parse the
1483 // .lldbinit file in the user's home directory.
1484 SBCommandReturnObject result;
1485 sb_interpreter.SourceInitFileInHomeDirectory(result);
1486 if (GetDebugMode())
1487 {
Greg Clayton66111032010-06-23 01:19:29 +00001488 result.PutError (m_debugger.GetErrorFileHandle());
1489 result.PutOutput (m_debugger.GetOutputFileHandle());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001490 }
1491
1492 // Now we handle options we got from the command line
Jim Inghamed3252f2013-09-14 00:20:24 +00001493 // First source in the commands specified to be run before the file arguments are processed.
1494 ExecuteInitialCommands(true);
1495
Johnny Cheneb46f782012-08-15 22:10:42 +00001496 // Was there a core file specified?
1497 std::string core_file_spec("");
1498 if (!m_option_data.m_core_file.empty())
1499 core_file_spec.append("--core ").append(m_option_data.m_core_file);
1500
Jim Inghamed3252f2013-09-14 00:20:24 +00001501 char command_string[PATH_MAX * 2];
Greg Clayton8d846da2010-12-08 22:23:24 +00001502 const size_t num_args = m_option_data.m_args.size();
1503 if (num_args > 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001504 {
1505 char arch_name[64];
Greg Clayton66111032010-06-23 01:19:29 +00001506 if (m_debugger.GetDefaultArchitecture (arch_name, sizeof (arch_name)))
Greg Clayton8d846da2010-12-08 22:23:24 +00001507 ::snprintf (command_string,
1508 sizeof (command_string),
Johnny Cheneb46f782012-08-15 22:10:42 +00001509 "target create --arch=%s %s \"%s\"",
Greg Clayton8d846da2010-12-08 22:23:24 +00001510 arch_name,
Johnny Cheneb46f782012-08-15 22:10:42 +00001511 core_file_spec.c_str(),
Greg Clayton8d846da2010-12-08 22:23:24 +00001512 m_option_data.m_args[0].c_str());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001513 else
Greg Clayton8d846da2010-12-08 22:23:24 +00001514 ::snprintf (command_string,
1515 sizeof(command_string),
Johnny Cheneb46f782012-08-15 22:10:42 +00001516 "target create %s \"%s\"",
1517 core_file_spec.c_str(),
Greg Clayton8d846da2010-12-08 22:23:24 +00001518 m_option_data.m_args[0].c_str());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001519
Greg Clayton66111032010-06-23 01:19:29 +00001520 m_debugger.HandleCommand (command_string);
Greg Clayton8d846da2010-12-08 22:23:24 +00001521
1522 if (num_args > 1)
1523 {
Greg Clayton1d885962011-11-08 02:43:13 +00001524 m_debugger.HandleCommand ("settings clear target.run-args");
Greg Clayton8d846da2010-12-08 22:23:24 +00001525 char arg_cstr[1024];
1526 for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx)
1527 {
Jim Inghame64f0dc2011-09-13 23:25:31 +00001528 ::snprintf (arg_cstr,
1529 sizeof(arg_cstr),
Greg Clayton1d885962011-11-08 02:43:13 +00001530 "settings append target.run-args \"%s\"",
Jim Inghame64f0dc2011-09-13 23:25:31 +00001531 m_option_data.m_args[arg_idx].c_str());
Greg Clayton8d846da2010-12-08 22:23:24 +00001532 m_debugger.HandleCommand (arg_cstr);
1533 }
1534 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001535 }
Johnny Cheneb46f782012-08-15 22:10:42 +00001536 else if (!core_file_spec.empty())
1537 {
1538 ::snprintf (command_string,
1539 sizeof(command_string),
1540 "target create %s",
1541 core_file_spec.c_str());
1542 m_debugger.HandleCommand (command_string);;
1543 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001544
1545 // Now that all option parsing is done, we try and parse the .lldbinit
1546 // file in the current working directory
1547 sb_interpreter.SourceInitFileInCurrentWorkingDirectory (result);
1548 if (GetDebugMode())
1549 {
Greg Clayton66111032010-06-23 01:19:29 +00001550 result.PutError(m_debugger.GetErrorFileHandle());
1551 result.PutOutput(m_debugger.GetOutputFileHandle());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001552 }
Jim Inghamed3252f2013-09-14 00:20:24 +00001553
1554 // Now execute the commands specified for after the file arguments are processed.
1555 ExecuteInitialCommands(false);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001556
1557 SBEvent event;
1558
1559 // Make sure the IO channel is started up before we try to tell it we
1560 // are ready for input
1561 listener.WaitForEventForBroadcasterWithType (UINT32_MAX,
1562 *m_io_channel_ap,
1563 IOChannel::eBroadcastBitThreadDidStart,
1564 event);
Jim Inghame64f0dc2011-09-13 23:25:31 +00001565 // If we were asked to attach, then do that here:
1566 // I'm going to use the command string rather than directly
1567 // calling the API's because then I don't have to recode the
1568 // event handling here.
1569 if (!m_option_data.m_process_name.empty()
1570 || m_option_data.m_process_pid != LLDB_INVALID_PROCESS_ID)
1571 {
1572 std::string command_str("process attach ");
1573 if (m_option_data.m_process_pid != LLDB_INVALID_PROCESS_ID)
1574 {
1575 command_str.append("-p ");
1576 char pid_buffer[32];
Daniel Malead01b2952012-11-29 21:49:15 +00001577 ::snprintf (pid_buffer, sizeof(pid_buffer), "%" PRIu64, m_option_data.m_process_pid);
Jim Inghame64f0dc2011-09-13 23:25:31 +00001578 command_str.append(pid_buffer);
1579 }
1580 else
1581 {
1582 command_str.append("-n \"");
1583 command_str.append(m_option_data.m_process_name);
1584 command_str.push_back('\"');
1585 if (m_option_data.m_wait_for)
1586 command_str.append(" -w");
1587 }
1588
1589 if (m_debugger.GetOutputFileHandle())
1590 ::fprintf (m_debugger.GetOutputFileHandle(),
1591 "Attaching to process with:\n %s\n",
1592 command_str.c_str());
1593
1594 // Force the attach to be synchronous:
1595 bool orig_async = m_debugger.GetAsync();
1596 m_debugger.SetAsync(true);
1597 m_debugger.HandleCommand(command_str.c_str());
1598 m_debugger.SetAsync(orig_async);
1599 }
1600
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001601 ReadyForCommand ();
1602
Greg Claytona9f7b792012-02-29 04:21:24 +00001603 while (!GetIsDone())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001604 {
1605 listener.WaitForEvent (UINT32_MAX, event);
1606 if (event.IsValid())
1607 {
1608 if (event.GetBroadcaster().IsValid())
1609 {
1610 uint32_t event_type = event.GetType();
1611 if (event.BroadcasterMatchesRef (*m_io_channel_ap))
1612 {
1613 if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
1614 (event_type & IOChannel::eBroadcastBitThreadDidExit))
1615 {
Greg Claytona9f7b792012-02-29 04:21:24 +00001616 SetIsDone();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001617 if (event_type & IOChannel::eBroadcastBitThreadDidExit)
1618 iochannel_thread_exited = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001619 }
1620 else
Greg Claytona9f7b792012-02-29 04:21:24 +00001621 {
1622 if (HandleIOEvent (event))
1623 SetIsDone();
1624 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001625 }
Jim Inghame6bc6cb2012-02-08 05:23:15 +00001626 else if (SBProcess::EventIsProcessEvent (event))
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001627 {
1628 HandleProcessEvent (event);
1629 }
Jim Inghame6bc6cb2012-02-08 05:23:15 +00001630 else if (SBBreakpoint::EventIsBreakpointEvent (event))
1631 {
1632 HandleBreakpointEvent (event);
1633 }
Jim Ingham4f465cf2012-10-10 18:32:14 +00001634 else if (SBThread::EventIsThreadEvent (event))
1635 {
1636 HandleThreadEvent (event);
1637 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001638 else if (event.BroadcasterMatchesRef (sb_interpreter.GetBroadcaster()))
1639 {
Greg Claytona9f7b792012-02-29 04:21:24 +00001640 // TODO: deprecate the eBroadcastBitQuitCommandReceived event
1641 // now that we have SBCommandInterpreter::SetCommandOverrideCallback()
1642 // that can take over a command
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001643 if (event_type & SBCommandInterpreter::eBroadcastBitQuitCommandReceived)
Greg Clayton74d41932012-01-31 04:56:17 +00001644 {
Greg Claytona9f7b792012-02-29 04:21:24 +00001645 SetIsDone();
Greg Clayton74d41932012-01-31 04:56:17 +00001646 }
Caroline Tice86a73f92011-05-03 20:53:11 +00001647 else if (event_type & SBCommandInterpreter::eBroadcastBitAsynchronousErrorData)
1648 {
1649 const char *data = SBEvent::GetCStringFromEvent (event);
1650 m_io_channel_ap->ErrWrite (data, strlen(data), ASYNC);
1651 }
1652 else if (event_type & SBCommandInterpreter::eBroadcastBitAsynchronousOutputData)
1653 {
1654 const char *data = SBEvent::GetCStringFromEvent (event);
1655 m_io_channel_ap->OutWrite (data, strlen(data), ASYNC);
1656 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001657 }
1658 }
1659 }
1660 }
1661
Michael Sartain816cf1d2013-05-22 23:31:28 +00001662 master_out_comm.SetReadThreadBytesReceivedCallback(NULL, NULL);
Greg Claytonf571b892012-02-02 19:28:31 +00001663 master_out_comm.Disconnect();
Michael Sartain816cf1d2013-05-22 23:31:28 +00001664 master_out_comm.ReadThreadStop();
1665
1666 out_comm_2.SetReadThreadBytesReceivedCallback(NULL, NULL);
Greg Claytonf571b892012-02-02 19:28:31 +00001667 out_comm_2.Disconnect();
Michael Sartain816cf1d2013-05-22 23:31:28 +00001668 out_comm_2.ReadThreadStop();
1669
1670 editline_output_pty.CloseMasterFileDescriptor();
Greg Claytonf571b892012-02-02 19:28:31 +00001671 reset_stdin_termios();
1672 fclose (stdin);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001673
1674 CloseIOChannelFile ();
1675
1676 if (!iochannel_thread_exited)
1677 {
Greg Claytonb1320972010-07-14 00:18:15 +00001678 event.Clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001679 listener.GetNextEventForBroadcasterWithType (*m_io_channel_ap,
1680 IOChannel::eBroadcastBitThreadDidExit,
1681 event);
1682 if (!event.IsValid())
1683 {
1684 // Send end EOF to the driver file descriptor
1685 m_io_channel_ap->Stop();
1686 }
1687 }
1688
Jim Ingham12e9a202011-09-15 21:30:02 +00001689 SBDebugger::Destroy (m_debugger);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001690 }
1691 }
1692}
1693
1694
1695void
1696Driver::ReadyForCommand ()
1697{
1698 if (m_waiting_for_command == false)
1699 {
1700 m_waiting_for_command = true;
1701 BroadcastEventByType (Driver::eBroadcastBitReadyForInput, true);
1702 }
1703}
1704
Jim Inghamc46fe7c2013-02-22 22:56:55 +00001705void
1706Driver::ResizeWindow (unsigned short col)
1707{
1708 GetDebugger().SetTerminalWidth (col);
1709 if (m_io_channel_ap.get() != NULL)
1710 {
1711 m_io_channel_ap->ElResize();
1712 }
1713}
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001714
Caroline Ticedd759852010-09-09 17:45:09 +00001715void
1716sigwinch_handler (int signo)
1717{
1718 struct winsize window_size;
1719 if (isatty (STDIN_FILENO)
1720 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
1721 {
Jim Ingham57190ba2012-04-26 21:39:32 +00001722 if ((window_size.ws_col > 0) && g_driver != NULL)
Caroline Ticedd759852010-09-09 17:45:09 +00001723 {
Jim Inghamc46fe7c2013-02-22 22:56:55 +00001724 g_driver->ResizeWindow (window_size.ws_col);
Caroline Ticedd759852010-09-09 17:45:09 +00001725 }
1726 }
1727}
1728
Caroline Ticeefed6132010-11-19 20:47:54 +00001729void
1730sigint_handler (int signo)
1731{
1732 static bool g_interrupt_sent = false;
1733 if (g_driver)
1734 {
1735 if (!g_interrupt_sent)
1736 {
1737 g_interrupt_sent = true;
1738 g_driver->GetDebugger().DispatchInputInterrupt();
1739 g_interrupt_sent = false;
1740 return;
1741 }
1742 }
1743
1744 exit (signo);
1745}
1746
Jim Inghamc5917d92012-11-30 20:23:19 +00001747void
1748sigtstp_handler (int signo)
1749{
1750 g_driver->GetDebugger().SaveInputTerminalState();
1751 signal (signo, SIG_DFL);
1752 kill (getpid(), signo);
1753 signal (signo, sigtstp_handler);
1754}
1755
1756void
1757sigcont_handler (int signo)
1758{
1759 g_driver->GetDebugger().RestoreInputTerminalState();
1760 signal (signo, SIG_DFL);
1761 kill (getpid(), signo);
1762 signal (signo, sigcont_handler);
1763}
1764
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001765int
Jim Inghama462f5c2011-01-27 20:15:39 +00001766main (int argc, char const *argv[], const char *envp[])
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001767{
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001768 SBDebugger::Initialize();
1769
Greg Clayton2ccf8cf2010-11-07 21:02:03 +00001770 SBHostOS::ThreadCreated ("<lldb.driver.main-thread>");
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001771
Greg Clayton3fcbed62010-10-19 03:25:40 +00001772 signal (SIGPIPE, SIG_IGN);
Caroline Ticedd759852010-09-09 17:45:09 +00001773 signal (SIGWINCH, sigwinch_handler);
Caroline Ticeefed6132010-11-19 20:47:54 +00001774 signal (SIGINT, sigint_handler);
Jim Inghamc5917d92012-11-30 20:23:19 +00001775 signal (SIGTSTP, sigtstp_handler);
1776 signal (SIGCONT, sigcont_handler);
Caroline Ticedd759852010-09-09 17:45:09 +00001777
Greg Clayton66111032010-06-23 01:19:29 +00001778 // Create a scope for driver so that the driver object will destroy itself
1779 // before SBDebugger::Terminate() is called.
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001780 {
Greg Clayton66111032010-06-23 01:19:29 +00001781 Driver driver;
1782
1783 bool exit = false;
1784 SBError error (driver.ParseArgs (argc, argv, stdout, exit));
1785 if (error.Fail())
1786 {
1787 const char *error_cstr = error.GetCString ();
1788 if (error_cstr)
1789 ::fprintf (stderr, "error: %s\n", error_cstr);
1790 }
1791 else if (!exit)
1792 {
1793 driver.MainLoop ();
1794 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001795 }
1796
1797 SBDebugger::Terminate();
1798 return 0;
1799}