blob: fbedc1da8d647e902797032d8d3d01f65adfec0d [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- Driver.cpp ----------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "Driver.h"
11
12#include <getopt.h>
13#include <libgen.h>
14#include <sys/ioctl.h>
15#include <termios.h>
16#include <unistd.h>
Eli Friedmana382d472010-06-09 09:50:17 +000017#include <string.h>
18#include <stdlib.h>
19#include <limits.h>
Eli Friedman07b16272010-06-09 19:11:30 +000020#include <fcntl.h>
Daniel Malead01b2952012-11-29 21:49:15 +000021#include <inttypes.h>
Chris Lattner30fdc8d2010-06-08 16:52:24 +000022
23#include <string>
24
25#include "IOChannel.h"
Jim Inghame6bc6cb2012-02-08 05:23:15 +000026#include "lldb/API/SBBreakpoint.h"
Eli Friedmana382d472010-06-09 09:50:17 +000027#include "lldb/API/SBCommandInterpreter.h"
28#include "lldb/API/SBCommandReturnObject.h"
29#include "lldb/API/SBCommunication.h"
30#include "lldb/API/SBDebugger.h"
31#include "lldb/API/SBEvent.h"
32#include "lldb/API/SBHostOS.h"
33#include "lldb/API/SBListener.h"
Jim Ingham85e8b812011-02-19 02:53:09 +000034#include "lldb/API/SBStream.h"
Eli Friedmana382d472010-06-09 09:50:17 +000035#include "lldb/API/SBTarget.h"
36#include "lldb/API/SBThread.h"
37#include "lldb/API/SBProcess.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000038
39using namespace lldb;
40
41static void reset_stdin_termios ();
Greg Claytonf571b892012-02-02 19:28:31 +000042static bool g_old_stdin_termios_is_valid = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000043static struct termios g_old_stdin_termios;
44
Caroline Ticedd759852010-09-09 17:45:09 +000045static char *g_debugger_name = (char *) "";
Caroline Ticeefed6132010-11-19 20:47:54 +000046static Driver *g_driver = NULL;
Caroline Ticedd759852010-09-09 17:45:09 +000047
Chris Lattner30fdc8d2010-06-08 16:52:24 +000048// In the Driver::MainLoop, we change the terminal settings. This function is
49// added as an atexit handler to make sure we clean them up.
50static void
51reset_stdin_termios ()
52{
Greg Claytonf571b892012-02-02 19:28:31 +000053 if (g_old_stdin_termios_is_valid)
54 {
55 g_old_stdin_termios_is_valid = false;
56 ::tcsetattr (STDIN_FILENO, TCSANOW, &g_old_stdin_termios);
57 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +000058}
59
Greg Claytone0d378b2011-03-24 21:19:54 +000060typedef struct
Chris Lattner30fdc8d2010-06-08 16:52:24 +000061{
Greg Claytone0d378b2011-03-24 21:19:54 +000062 uint32_t usage_mask; // Used to mark options that can be used together. If (1 << n & usage_mask) != 0
63 // then this option belongs to option set n.
64 bool required; // This option is required (in the current usage level)
65 const char * long_option; // Full name for this option.
Greg Clayton3bcdfc02012-12-04 00:32:51 +000066 int short_option; // Single character for this option.
Greg Claytone0d378b2011-03-24 21:19:54 +000067 int option_has_arg; // no_argument, required_argument or optional_argument
Greg Claytonab65b342011-04-13 22:47:15 +000068 uint32_t completion_type; // Cookie the option class can use to do define the argument completion.
Greg Claytone0d378b2011-03-24 21:19:54 +000069 lldb::CommandArgumentType argument_type; // Type of argument this option takes
70 const char * usage_text; // Full text explaining what this options does and what (if any) argument to
71 // pass it.
72} OptionDefinition;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000073
Jim Inghame64f0dc2011-09-13 23:25:31 +000074#define LLDB_3_TO_5 LLDB_OPT_SET_3|LLDB_OPT_SET_4|LLDB_OPT_SET_5
75#define LLDB_4_TO_5 LLDB_OPT_SET_4|LLDB_OPT_SET_5
76
Greg Claytone0d378b2011-03-24 21:19:54 +000077static OptionDefinition g_options[] =
78{
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +000079 { LLDB_OPT_SET_1, true , "help" , 'h', no_argument , 0, eArgTypeNone,
Jim Ingham12e9a202011-09-15 21:30:02 +000080 "Prints out the usage information for the LLDB debugger." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +000081 { LLDB_OPT_SET_2, true , "version" , 'v', no_argument , 0, eArgTypeNone,
Jim Ingham12e9a202011-09-15 21:30:02 +000082 "Prints out the current version number of the LLDB debugger." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +000083 { LLDB_OPT_SET_3, true , "arch" , 'a', required_argument, 0, eArgTypeArchitecture,
Jim Ingham12e9a202011-09-15 21:30:02 +000084 "Tells the debugger to use the specified architecture when starting and running the program. <architecture> must "
85 "be one of the architectures for which the program was compiled." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +000086 { LLDB_OPT_SET_3, true , "file" , 'f', required_argument, 0, eArgTypeFilename,
Jim Ingham12e9a202011-09-15 21:30:02 +000087 "Tells the debugger to use the file <filename> as the program to be debugged." },
Jason Molenda67c3cf52012-10-24 03:29:40 +000088 { LLDB_OPT_SET_3, false, "core" , 'c', required_argument, 0, eArgTypeFilename,
Johnny Cheneb46f782012-08-15 22:10:42 +000089 "Tells the debugger to use the fullpath to <path> as the core file." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +000090 { LLDB_OPT_SET_4, true , "attach-name" , 'n', required_argument, 0, eArgTypeProcessName,
Jim Ingham12e9a202011-09-15 21:30:02 +000091 "Tells the debugger to attach to a process with the given name." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +000092 { LLDB_OPT_SET_4, true , "wait-for" , 'w', no_argument , 0, eArgTypeNone,
Jim Ingham12e9a202011-09-15 21:30:02 +000093 "Tells the debugger to wait for a process with the given pid or name to launch before attaching." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +000094 { LLDB_OPT_SET_5, true , "attach-pid" , 'p', required_argument, 0, eArgTypePid,
Jim Ingham12e9a202011-09-15 21:30:02 +000095 "Tells the debugger to attach to a process with the given pid." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +000096 { LLDB_3_TO_5, false, "script-language", 'l', required_argument, 0, eArgTypeScriptLang,
Jim Ingham12e9a202011-09-15 21:30:02 +000097 "Tells the debugger to use the specified scripting language for user-defined scripts, rather than the default. "
98 "Valid scripting languages that can be specified include Python, Perl, Ruby and Tcl. Currently only the Python "
99 "extensions have been implemented." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +0000100 { LLDB_3_TO_5, false, "debug" , 'd', no_argument , 0, eArgTypeNone,
Jim Ingham12e9a202011-09-15 21:30:02 +0000101 "Tells the debugger to print out extra information for debugging itself." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +0000102 { LLDB_3_TO_5, false, "source" , 's', required_argument, 0, eArgTypeFilename,
Jim Ingham12e9a202011-09-15 21:30:02 +0000103 "Tells the debugger to read in and execute the file <file>, which should contain lldb commands." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +0000104 { LLDB_3_TO_5, false, "editor" , 'e', no_argument , 0, eArgTypeNone,
Jim Ingham12e9a202011-09-15 21:30:02 +0000105 "Tells the debugger to open source files using the host's \"external editor\" mechanism." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +0000106 { LLDB_3_TO_5, false, "no-lldbinit" , 'x', no_argument , 0, eArgTypeNone,
Jim Ingham12e9a202011-09-15 21:30:02 +0000107 "Do not automatically parse any '.lldbinit' files." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +0000108 { 0, false, NULL , 0 , 0 , 0, eArgTypeNone, NULL }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000109};
110
Jim Inghame64f0dc2011-09-13 23:25:31 +0000111static const uint32_t last_option_set_with_args = 2;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000112
113Driver::Driver () :
114 SBBroadcaster ("Driver"),
Jim Ingham06942692011-08-13 00:22:20 +0000115 m_debugger (SBDebugger::Create(false)),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000116 m_editline_pty (),
117 m_editline_slave_fh (NULL),
118 m_editline_reader (),
119 m_io_channel_ap (),
120 m_option_data (),
121 m_waiting_for_command (false)
122{
Greg Claytonfc3f0272011-05-29 04:06:55 +0000123 // We want to be able to handle CTRL+D in the terminal to have it terminate
124 // certain input
125 m_debugger.SetCloseInputOnEOF (false);
Caroline Ticedd759852010-09-09 17:45:09 +0000126 g_debugger_name = (char *) m_debugger.GetInstanceName();
127 if (g_debugger_name == NULL)
128 g_debugger_name = (char *) "";
Caroline Ticeefed6132010-11-19 20:47:54 +0000129 g_driver = this;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000130}
131
132Driver::~Driver ()
133{
Caroline Ticeefed6132010-11-19 20:47:54 +0000134 g_driver = NULL;
135 g_debugger_name = NULL;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000136}
137
138void
139Driver::CloseIOChannelFile ()
140{
Johnny Chene26c7212012-05-16 22:01:10 +0000141 // Write an End of File sequence to the file descriptor to ensure any
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000142 // read functions can exit.
143 char eof_str[] = "\x04";
144 ::write (m_editline_pty.GetMasterFileDescriptor(), eof_str, strlen(eof_str));
145
146 m_editline_pty.CloseMasterFileDescriptor();
147
148 if (m_editline_slave_fh)
149 {
150 ::fclose (m_editline_slave_fh);
151 m_editline_slave_fh = NULL;
152 }
153}
154
Greg Claytonc982c762010-07-09 20:39:50 +0000155// This function takes INDENT, which tells how many spaces to output at the front
156// of each line; TEXT, which is the text that is to be output. It outputs the
157// text, on multiple lines if necessary, to RESULT, with INDENT spaces at the
158// front of each line. It breaks lines on spaces, tabs or newlines, shortening
159// the line if necessary to not break in the middle of a word. It assumes that
160// each output line should contain a maximum of OUTPUT_MAX_COLUMNS characters.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000161
162void
Greg Claytonc982c762010-07-09 20:39:50 +0000163OutputFormattedUsageText (FILE *out, int indent, const char *text, int output_max_columns)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000164{
165 int len = strlen (text);
166 std::string text_string (text);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000167
168 // Force indentation to be reasonable.
169 if (indent >= output_max_columns)
170 indent = 0;
171
172 // Will it all fit on one line?
173
174 if (len + indent < output_max_columns)
175 // Output as a single line
Greg Claytonc982c762010-07-09 20:39:50 +0000176 fprintf (out, "%*s%s\n", indent, "", text);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000177 else
178 {
179 // We need to break it up into multiple lines.
180 int text_width = output_max_columns - indent - 1;
181 int start = 0;
182 int end = start;
183 int final_end = len;
184 int sub_len;
185
186 while (end < final_end)
187 {
188 // Dont start the 'text' on a space, since we're already outputting the indentation.
189 while ((start < final_end) && (text[start] == ' '))
190 start++;
191
192 end = start + text_width;
193 if (end > final_end)
194 end = final_end;
195 else
196 {
197 // If we're not at the end of the text, make sure we break the line on white space.
198 while (end > start
199 && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
200 end--;
201 }
202 sub_len = end - start;
203 std::string substring = text_string.substr (start, sub_len);
Greg Claytonc982c762010-07-09 20:39:50 +0000204 fprintf (out, "%*s%s\n", indent, "", substring.c_str());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000205 start = end + 1;
206 }
207 }
208}
209
210void
Greg Claytone0d378b2011-03-24 21:19:54 +0000211ShowUsage (FILE *out, OptionDefinition *option_table, Driver::OptionData data)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000212{
213 uint32_t screen_width = 80;
214 uint32_t indent_level = 0;
215 const char *name = "lldb";
Jim Ingham86511212010-06-15 18:47:14 +0000216
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000217 fprintf (out, "\nUsage:\n\n");
218
219 indent_level += 2;
220
221
222 // First, show each usage level set of options, e.g. <cmd> [options-for-level-0]
223 // <cmd> [options-for-level-1]
224 // etc.
225
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000226 uint32_t num_options;
Jim Ingham86511212010-06-15 18:47:14 +0000227 uint32_t num_option_sets = 0;
228
229 for (num_options = 0; option_table[num_options].long_option != NULL; ++num_options)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000230 {
Jim Ingham86511212010-06-15 18:47:14 +0000231 uint32_t this_usage_mask = option_table[num_options].usage_mask;
232 if (this_usage_mask == LLDB_OPT_SET_ALL)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000233 {
Jim Ingham86511212010-06-15 18:47:14 +0000234 if (num_option_sets == 0)
235 num_option_sets = 1;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000236 }
237 else
238 {
Greg Claytonc982c762010-07-09 20:39:50 +0000239 for (uint32_t j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++)
Jim Ingham86511212010-06-15 18:47:14 +0000240 {
241 if (this_usage_mask & 1 << j)
242 {
243 if (num_option_sets <= j)
244 num_option_sets = j + 1;
245 }
246 }
247 }
248 }
249
250 for (uint32_t opt_set = 0; opt_set < num_option_sets; opt_set++)
251 {
252 uint32_t opt_set_mask;
253
254 opt_set_mask = 1 << opt_set;
255
256 if (opt_set > 0)
257 fprintf (out, "\n");
Greg Claytonc982c762010-07-09 20:39:50 +0000258 fprintf (out, "%*s%s", indent_level, "", name);
Jim Ingham556e6532011-08-16 23:15:02 +0000259 bool is_help_line = false;
Jim Ingham86511212010-06-15 18:47:14 +0000260
261 for (uint32_t i = 0; i < num_options; ++i)
262 {
263 if (option_table[i].usage_mask & opt_set_mask)
264 {
Caroline Ticedeaab222010-10-01 19:59:14 +0000265 CommandArgumentType arg_type = option_table[i].argument_type;
Greg Clayton9d0402b2011-02-20 02:15:07 +0000266 const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type);
Jim Ingham556e6532011-08-16 23:15:02 +0000267 // This is a bit of a hack, but there's no way to say certain options don't have arguments yet...
268 // so we do it by hand here.
269 if (option_table[i].short_option == 'h')
270 is_help_line = true;
271
Jim Ingham86511212010-06-15 18:47:14 +0000272 if (option_table[i].required)
273 {
274 if (option_table[i].option_has_arg == required_argument)
Greg Clayton9d0402b2011-02-20 02:15:07 +0000275 fprintf (out, " -%c <%s>", option_table[i].short_option, arg_name);
Jim Ingham86511212010-06-15 18:47:14 +0000276 else if (option_table[i].option_has_arg == optional_argument)
Greg Clayton9d0402b2011-02-20 02:15:07 +0000277 fprintf (out, " -%c [<%s>]", option_table[i].short_option, arg_name);
Jim Ingham86511212010-06-15 18:47:14 +0000278 else
279 fprintf (out, " -%c", option_table[i].short_option);
280 }
281 else
282 {
283 if (option_table[i].option_has_arg == required_argument)
Greg Clayton9d0402b2011-02-20 02:15:07 +0000284 fprintf (out, " [-%c <%s>]", option_table[i].short_option, arg_name);
Jim Ingham86511212010-06-15 18:47:14 +0000285 else if (option_table[i].option_has_arg == optional_argument)
Greg Clayton9d0402b2011-02-20 02:15:07 +0000286 fprintf (out, " [-%c [<%s>]]", option_table[i].short_option, arg_name);
Jim Ingham86511212010-06-15 18:47:14 +0000287 else
288 fprintf (out, " [-%c]", option_table[i].short_option);
289 }
290 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000291 }
Jim Inghame64f0dc2011-09-13 23:25:31 +0000292 if (!is_help_line && (opt_set <= last_option_set_with_args))
Jim Ingham556e6532011-08-16 23:15:02 +0000293 fprintf (out, " [[--] <PROGRAM-ARG-1> [<PROGRAM_ARG-2> ...]]");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000294 }
295
296 fprintf (out, "\n\n");
297
298 // Now print out all the detailed information about the various options: long form, short form and help text:
299 // -- long_name <argument>
300 // - short <argument>
301 // help text
302
303 // This variable is used to keep track of which options' info we've printed out, because some options can be in
304 // more than one usage level, but we only want to print the long form of its information once.
305
306 Driver::OptionData::OptionSet options_seen;
307 Driver::OptionData::OptionSet::iterator pos;
308
309 indent_level += 5;
310
Jim Ingham86511212010-06-15 18:47:14 +0000311 for (uint32_t i = 0; i < num_options; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000312 {
313 // Only print this option if we haven't already seen it.
314 pos = options_seen.find (option_table[i].short_option);
315 if (pos == options_seen.end())
316 {
Caroline Ticedeaab222010-10-01 19:59:14 +0000317 CommandArgumentType arg_type = option_table[i].argument_type;
Greg Clayton9d0402b2011-02-20 02:15:07 +0000318 const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type);
Caroline Ticedeaab222010-10-01 19:59:14 +0000319
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000320 options_seen.insert (option_table[i].short_option);
Greg Claytonc982c762010-07-09 20:39:50 +0000321 fprintf (out, "%*s-%c ", indent_level, "", option_table[i].short_option);
Caroline Ticedeaab222010-10-01 19:59:14 +0000322 if (arg_type != eArgTypeNone)
Greg Clayton9d0402b2011-02-20 02:15:07 +0000323 fprintf (out, "<%s>", arg_name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000324 fprintf (out, "\n");
Greg Claytonc982c762010-07-09 20:39:50 +0000325 fprintf (out, "%*s--%s ", indent_level, "", option_table[i].long_option);
Caroline Ticedeaab222010-10-01 19:59:14 +0000326 if (arg_type != eArgTypeNone)
Greg Clayton9d0402b2011-02-20 02:15:07 +0000327 fprintf (out, "<%s>", arg_name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000328 fprintf (out, "\n");
329 indent_level += 5;
Greg Claytonc982c762010-07-09 20:39:50 +0000330 OutputFormattedUsageText (out, indent_level, option_table[i].usage_text, screen_width);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000331 indent_level -= 5;
332 fprintf (out, "\n");
333 }
334 }
335
336 indent_level -= 5;
337
Jim Inghama9deaf92011-08-16 23:57:58 +0000338 fprintf (out, "\n%*s(If you don't provide -f then the first argument will be the file to be debugged"
339 "\n%*s so '%s -- <filename> [<ARG1> [<ARG2>]]' also works."
340 "\n%*s Remember to end the options with \"--\" if any of your arguments have a \"-\" in them.)\n\n",
341 indent_level, "",
342 indent_level, "",
343 name,
344 indent_level, "");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000345}
346
347void
Greg Claytone0d378b2011-03-24 21:19:54 +0000348BuildGetOptTable (OptionDefinition *expanded_option_table, std::vector<struct option> &getopt_table,
Caroline Tice4ab31c92010-10-12 21:57:09 +0000349 uint32_t num_options)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000350{
351 if (num_options == 0)
352 return;
353
354 uint32_t i;
355 uint32_t j;
356 std::bitset<256> option_seen;
357
Caroline Tice4ab31c92010-10-12 21:57:09 +0000358 getopt_table.resize (num_options + 1);
359
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000360 for (i = 0, j = 0; i < num_options; ++i)
Greg Claytonc982c762010-07-09 20:39:50 +0000361 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000362 char short_opt = expanded_option_table[i].short_option;
Greg Claytonc982c762010-07-09 20:39:50 +0000363
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000364 if (option_seen.test(short_opt) == false)
Greg Claytonc982c762010-07-09 20:39:50 +0000365 {
Caroline Tice4ab31c92010-10-12 21:57:09 +0000366 getopt_table[j].name = expanded_option_table[i].long_option;
367 getopt_table[j].has_arg = expanded_option_table[i].option_has_arg;
368 getopt_table[j].flag = NULL;
369 getopt_table[j].val = expanded_option_table[i].short_option;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000370 option_seen.set(short_opt);
371 ++j;
Greg Claytonc982c762010-07-09 20:39:50 +0000372 }
373 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000374
Caroline Tice4ab31c92010-10-12 21:57:09 +0000375 getopt_table[j].name = NULL;
376 getopt_table[j].has_arg = 0;
377 getopt_table[j].flag = NULL;
378 getopt_table[j].val = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000379
380}
381
Greg Clayton66111032010-06-23 01:19:29 +0000382Driver::OptionData::OptionData () :
Greg Clayton8d846da2010-12-08 22:23:24 +0000383 m_args(),
Greg Clayton66111032010-06-23 01:19:29 +0000384 m_script_lang (lldb::eScriptLanguageDefault),
Johnny Cheneb46f782012-08-15 22:10:42 +0000385 m_core_file (),
Greg Claytonc982c762010-07-09 20:39:50 +0000386 m_crash_log (),
Greg Clayton66111032010-06-23 01:19:29 +0000387 m_source_command_files (),
388 m_debug_mode (false),
Greg Claytonc982c762010-07-09 20:39:50 +0000389 m_print_version (false),
Greg Clayton66111032010-06-23 01:19:29 +0000390 m_print_help (false),
Jim Inghame64f0dc2011-09-13 23:25:31 +0000391 m_wait_for(false),
392 m_process_name(),
393 m_process_pid(LLDB_INVALID_PROCESS_ID),
Daniel Dunbara08823f2011-10-31 22:50:49 +0000394 m_use_external_editor(false),
Stephen Wilson71c21d12011-04-11 19:41:40 +0000395 m_seen_options()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000396{
Greg Clayton66111032010-06-23 01:19:29 +0000397}
398
399Driver::OptionData::~OptionData ()
400{
401}
402
403void
404Driver::OptionData::Clear ()
405{
Greg Clayton8d846da2010-12-08 22:23:24 +0000406 m_args.clear ();
Greg Clayton66111032010-06-23 01:19:29 +0000407 m_script_lang = lldb::eScriptLanguageDefault;
408 m_source_command_files.clear ();
409 m_debug_mode = false;
410 m_print_help = false;
411 m_print_version = false;
Jim Inghame40e4212010-08-30 19:44:40 +0000412 m_use_external_editor = false;
Jim Inghame64f0dc2011-09-13 23:25:31 +0000413 m_wait_for = false;
414 m_process_name.erase();
415 m_process_pid = LLDB_INVALID_PROCESS_ID;
Greg Clayton66111032010-06-23 01:19:29 +0000416}
417
418void
419Driver::ResetOptionValues ()
420{
421 m_option_data.Clear ();
422}
423
424const char *
425Driver::GetFilename() const
426{
Greg Clayton8d846da2010-12-08 22:23:24 +0000427 if (m_option_data.m_args.empty())
Greg Clayton66111032010-06-23 01:19:29 +0000428 return NULL;
Greg Clayton8d846da2010-12-08 22:23:24 +0000429 return m_option_data.m_args.front().c_str();
Greg Clayton66111032010-06-23 01:19:29 +0000430}
431
432const char *
433Driver::GetCrashLogFilename() const
434{
435 if (m_option_data.m_crash_log.empty())
436 return NULL;
437 return m_option_data.m_crash_log.c_str();
438}
439
440lldb::ScriptLanguage
441Driver::GetScriptLanguage() const
442{
443 return m_option_data.m_script_lang;
444}
445
446size_t
447Driver::GetNumSourceCommandFiles () const
448{
449 return m_option_data.m_source_command_files.size();
450}
451
452const char *
453Driver::GetSourceCommandFileAtIndex (uint32_t idx) const
454{
455 if (idx < m_option_data.m_source_command_files.size())
456 return m_option_data.m_source_command_files[idx].c_str();
457 return NULL;
458}
459
460bool
461Driver::GetDebugMode() const
462{
463 return m_option_data.m_debug_mode;
464}
465
466
467// Check the arguments that were passed to this program to make sure they are valid and to get their
468// argument values (if any). Return a boolean value indicating whether or not to start up the full
469// debugger (i.e. the Command Interpreter) or not. Return FALSE if the arguments were invalid OR
470// if the user only wanted help or version information.
471
472SBError
473Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exit)
474{
475 ResetOptionValues ();
476
477 SBCommandReturnObject result;
478
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000479 SBError error;
480 std::string option_string;
481 struct option *long_options = NULL;
Caroline Tice4ab31c92010-10-12 21:57:09 +0000482 std::vector<struct option> long_options_vector;
Greg Claytonc982c762010-07-09 20:39:50 +0000483 uint32_t num_options;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000484
Greg Claytonc982c762010-07-09 20:39:50 +0000485 for (num_options = 0; g_options[num_options].long_option != NULL; ++num_options)
486 /* Do Nothing. */;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000487
488 if (num_options == 0)
489 {
490 if (argc > 1)
491 error.SetErrorStringWithFormat ("invalid number of options");
492 return error;
493 }
494
Caroline Tice4ab31c92010-10-12 21:57:09 +0000495 BuildGetOptTable (g_options, long_options_vector, num_options);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000496
Caroline Tice4ab31c92010-10-12 21:57:09 +0000497 if (long_options_vector.empty())
498 long_options = NULL;
499 else
500 long_options = &long_options_vector.front();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000501
502 if (long_options == NULL)
503 {
504 error.SetErrorStringWithFormat ("invalid long options");
505 return error;
506 }
507
508 // Build the option_string argument for call to getopt_long.
509
510 for (int i = 0; long_options[i].name != NULL; ++i)
511 {
512 if (long_options[i].flag == NULL)
513 {
514 option_string.push_back ((char) long_options[i].val);
515 switch (long_options[i].has_arg)
516 {
517 default:
518 case no_argument:
519 break;
520 case required_argument:
521 option_string.push_back (':');
522 break;
523 case optional_argument:
524 option_string.append ("::");
525 break;
526 }
527 }
528 }
529
Jim Ingham06942692011-08-13 00:22:20 +0000530 // This is kind of a pain, but since we make the debugger in the Driver's constructor, we can't
531 // know at that point whether we should read in init files yet. So we don't read them in in the
532 // Driver constructor, then set the flags back to "read them in" here, and then if we see the
533 // "-n" flag, we'll turn it off again. Finally we have to read them in by hand later in the
534 // main loop.
535
536 m_debugger.SkipLLDBInitFiles (false);
537 m_debugger.SkipAppInitFiles (false);
538
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000539 // Prepare for & make calls to getopt_long.
Eli Friedmanadb35022010-06-13 19:18:49 +0000540#if __GLIBC__
541 optind = 0;
542#else
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000543 optreset = 1;
544 optind = 1;
Eli Friedmanadb35022010-06-13 19:18:49 +0000545#endif
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000546 int val;
547 while (1)
548 {
549 int long_options_index = -1;
Greg Claytonc982c762010-07-09 20:39:50 +0000550 val = ::getopt_long (argc, const_cast<char **>(argv), option_string.c_str(), long_options, &long_options_index);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000551
552 if (val == -1)
553 break;
554 else if (val == '?')
555 {
Greg Clayton66111032010-06-23 01:19:29 +0000556 m_option_data.m_print_help = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000557 error.SetErrorStringWithFormat ("unknown or ambiguous option");
558 break;
559 }
560 else if (val == 0)
561 continue;
562 else
563 {
Greg Clayton66111032010-06-23 01:19:29 +0000564 m_option_data.m_seen_options.insert ((char) val);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000565 if (long_options_index == -1)
566 {
567 for (int i = 0;
568 long_options[i].name || long_options[i].has_arg || long_options[i].flag || long_options[i].val;
569 ++i)
570 {
571 if (long_options[i].val == val)
572 {
573 long_options_index = i;
574 break;
575 }
576 }
577 }
578
579 if (long_options_index >= 0)
580 {
Greg Clayton3bcdfc02012-12-04 00:32:51 +0000581 const int short_option = g_options[long_options_index].short_option;
Greg Clayton66111032010-06-23 01:19:29 +0000582
583 switch (short_option)
584 {
585 case 'h':
586 m_option_data.m_print_help = true;
587 break;
588
589 case 'v':
590 m_option_data.m_print_version = true;
591 break;
592
593 case 'c':
Johnny Cheneb46f782012-08-15 22:10:42 +0000594 {
595 SBFileSpec file(optarg);
596 if (file.Exists())
597 {
598 m_option_data.m_core_file = optarg;
599 }
600 else
601 error.SetErrorStringWithFormat("file specified in --core (-c) option doesn't exist: '%s'", optarg);
602 }
Greg Clayton66111032010-06-23 01:19:29 +0000603 break;
Johnny Cheneb46f782012-08-15 22:10:42 +0000604
Jim Inghame40e4212010-08-30 19:44:40 +0000605 case 'e':
606 m_option_data.m_use_external_editor = true;
607 break;
Greg Clayton6eee5aa2010-10-11 01:05:37 +0000608
Jim Inghame64f0dc2011-09-13 23:25:31 +0000609 case 'x':
Greg Clayton6eee5aa2010-10-11 01:05:37 +0000610 m_debugger.SkipLLDBInitFiles (true);
Jim Ingham06942692011-08-13 00:22:20 +0000611 m_debugger.SkipAppInitFiles (true);
Greg Clayton6eee5aa2010-10-11 01:05:37 +0000612 break;
613
Greg Clayton66111032010-06-23 01:19:29 +0000614 case 'f':
615 {
616 SBFileSpec file(optarg);
617 if (file.Exists())
Greg Clayton8d846da2010-12-08 22:23:24 +0000618 {
619 m_option_data.m_args.push_back (optarg);
620 }
Caroline Tice428a9a52010-09-10 04:48:55 +0000621 else if (file.ResolveExecutableLocation())
622 {
623 char path[PATH_MAX];
Johnny Chen25f3a3c2011-08-10 22:06:24 +0000624 file.GetPath (path, sizeof(path));
Greg Clayton8d846da2010-12-08 22:23:24 +0000625 m_option_data.m_args.push_back (path);
Caroline Tice428a9a52010-09-10 04:48:55 +0000626 }
Greg Clayton66111032010-06-23 01:19:29 +0000627 else
628 error.SetErrorStringWithFormat("file specified in --file (-f) option doesn't exist: '%s'", optarg);
629 }
630 break;
631
632 case 'a':
633 if (!m_debugger.SetDefaultArchitecture (optarg))
634 error.SetErrorStringWithFormat("invalid architecture in the -a or --arch option: '%s'", optarg);
635 break;
636
637 case 'l':
638 m_option_data.m_script_lang = m_debugger.GetScriptingLanguage (optarg);
639 break;
640
641 case 'd':
642 m_option_data.m_debug_mode = true;
643 break;
644
Jim Inghame64f0dc2011-09-13 23:25:31 +0000645 case 'n':
646 m_option_data.m_process_name = optarg;
647 break;
648
649 case 'w':
650 m_option_data.m_wait_for = true;
651 break;
652
653 case 'p':
654 {
655 char *remainder;
656 m_option_data.m_process_pid = strtol (optarg, &remainder, 0);
657 if (remainder == optarg || *remainder != '\0')
658 error.SetErrorStringWithFormat ("Could not convert process PID: \"%s\" into a pid.",
659 optarg);
660 }
661 break;
Greg Clayton66111032010-06-23 01:19:29 +0000662 case 's':
663 {
664 SBFileSpec file(optarg);
665 if (file.Exists())
666 m_option_data.m_source_command_files.push_back (optarg);
Caroline Tice428a9a52010-09-10 04:48:55 +0000667 else if (file.ResolveExecutableLocation())
668 {
669 char final_path[PATH_MAX];
Johnny Chen25f3a3c2011-08-10 22:06:24 +0000670 file.GetPath (final_path, sizeof(final_path));
Caroline Tice428a9a52010-09-10 04:48:55 +0000671 std::string path_str (final_path);
672 m_option_data.m_source_command_files.push_back (path_str);
673 }
Greg Clayton66111032010-06-23 01:19:29 +0000674 else
675 error.SetErrorStringWithFormat("file specified in --source (-s) option doesn't exist: '%s'", optarg);
676 }
677 break;
678
679 default:
680 m_option_data.m_print_help = true;
681 error.SetErrorStringWithFormat ("unrecognized option %c", short_option);
682 break;
683 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000684 }
685 else
686 {
687 error.SetErrorStringWithFormat ("invalid option with value %i", val);
688 }
689 if (error.Fail())
Caroline Tice4ab31c92010-10-12 21:57:09 +0000690 {
Greg Clayton66111032010-06-23 01:19:29 +0000691 return error;
Caroline Tice4ab31c92010-10-12 21:57:09 +0000692 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000693 }
694 }
Jim Ingham86511212010-06-15 18:47:14 +0000695
Greg Clayton66111032010-06-23 01:19:29 +0000696 if (error.Fail() || m_option_data.m_print_help)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000697 {
698 ShowUsage (out_fh, g_options, m_option_data);
Greg Claytone46dd322010-10-11 01:13:37 +0000699 exit = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000700 }
701 else if (m_option_data.m_print_version)
702 {
Greg Clayton66111032010-06-23 01:19:29 +0000703 ::fprintf (out_fh, "%s\n", m_debugger.GetVersionString());
704 exit = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000705 }
Jim Inghame64f0dc2011-09-13 23:25:31 +0000706 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 +0000707 {
Greg Clayton8d846da2010-12-08 22:23:24 +0000708 // Any arguments that are left over after option parsing are for
709 // the program. If a file was specified with -f then the filename
710 // is already in the m_option_data.m_args array, and any remaining args
711 // are arguments for the inferior program. If no file was specified with
712 // -f, then what is left is the program name followed by any arguments.
713
714 // Skip any options we consumed with getopt_long
715 argc -= optind;
716 argv += optind;
717
718 if (argc > 0)
719 {
720 for (int arg_idx=0; arg_idx<argc; ++arg_idx)
721 {
722 const char *arg = argv[arg_idx];
723 if (arg)
724 m_option_data.m_args.push_back (arg);
725 }
726 }
727
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000728 }
Jim Inghame64f0dc2011-09-13 23:25:31 +0000729 else
730 {
731 // Skip any options we consumed with getopt_long
732 argc -= optind;
Greg Clayton23f59502012-07-17 03:23:13 +0000733 //argv += optind; // Commented out to keep static analyzer happy
Jim Inghame64f0dc2011-09-13 23:25:31 +0000734
735 if (argc > 0)
736 ::fprintf (out_fh, "Warning: program arguments are ignored when attaching.\n");
737 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000738
Greg Clayton66111032010-06-23 01:19:29 +0000739 return error;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000740}
741
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000742size_t
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000743Driver::GetProcessSTDOUT ()
744{
745 // The process has stuff waiting for stdout; get it and write it out to the appropriate place.
746 char stdio_buffer[1024];
747 size_t len;
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000748 size_t total_bytes = 0;
Jim Ingham2976d002010-08-26 21:32:51 +0000749 while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0)
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000750 {
Caroline Tice969ed3d2011-05-02 20:41:46 +0000751 m_io_channel_ap->OutWrite (stdio_buffer, len, ASYNC);
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000752 total_bytes += len;
753 }
754 return total_bytes;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000755}
756
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000757size_t
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000758Driver::GetProcessSTDERR ()
759{
760 // The process has stuff waiting for stderr; get it and write it out to the appropriate place.
761 char stdio_buffer[1024];
762 size_t len;
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000763 size_t total_bytes = 0;
Jim Ingham2976d002010-08-26 21:32:51 +0000764 while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0)
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000765 {
Caroline Tice969ed3d2011-05-02 20:41:46 +0000766 m_io_channel_ap->ErrWrite (stdio_buffer, len, ASYNC);
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000767 total_bytes += len;
768 }
769 return total_bytes;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000770}
771
772void
Jim Ingham2976d002010-08-26 21:32:51 +0000773Driver::UpdateSelectedThread ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000774{
775 using namespace lldb;
Jim Ingham2976d002010-08-26 21:32:51 +0000776 SBProcess process(m_debugger.GetSelectedTarget().GetProcess());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000777 if (process.IsValid())
778 {
Jim Ingham2976d002010-08-26 21:32:51 +0000779 SBThread curr_thread (process.GetSelectedThread());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000780 SBThread thread;
781 StopReason curr_thread_stop_reason = eStopReasonInvalid;
782 curr_thread_stop_reason = curr_thread.GetStopReason();
783
784 if (!curr_thread.IsValid() ||
785 curr_thread_stop_reason == eStopReasonInvalid ||
786 curr_thread_stop_reason == eStopReasonNone)
787 {
788 // Prefer a thread that has just completed its plan over another thread as current thread.
789 SBThread plan_thread;
790 SBThread other_thread;
791 const size_t num_threads = process.GetNumThreads();
792 size_t i;
793 for (i = 0; i < num_threads; ++i)
794 {
795 thread = process.GetThreadAtIndex(i);
796 StopReason thread_stop_reason = thread.GetStopReason();
797 switch (thread_stop_reason)
798 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000799 case eStopReasonInvalid:
800 case eStopReasonNone:
801 break;
802
803 case eStopReasonTrace:
804 case eStopReasonBreakpoint:
805 case eStopReasonWatchpoint:
806 case eStopReasonSignal:
807 case eStopReasonException:
Greg Clayton90ba8112012-12-05 00:16:59 +0000808 case eStopReasonExec:
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000809 if (!other_thread.IsValid())
810 other_thread = thread;
811 break;
812 case eStopReasonPlanComplete:
813 if (!plan_thread.IsValid())
814 plan_thread = thread;
815 break;
816 }
817 }
818 if (plan_thread.IsValid())
Jim Ingham2976d002010-08-26 21:32:51 +0000819 process.SetSelectedThread (plan_thread);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000820 else if (other_thread.IsValid())
Jim Ingham2976d002010-08-26 21:32:51 +0000821 process.SetSelectedThread (other_thread);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000822 else
823 {
824 if (curr_thread.IsValid())
825 thread = curr_thread;
826 else
827 thread = process.GetThreadAtIndex(0);
828
829 if (thread.IsValid())
Jim Ingham2976d002010-08-26 21:32:51 +0000830 process.SetSelectedThread (thread);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000831 }
832 }
833 }
834}
835
Jim Inghame6bc6cb2012-02-08 05:23:15 +0000836// This function handles events that were broadcast by the process.
837void
838Driver::HandleBreakpointEvent (const SBEvent &event)
839{
840 using namespace lldb;
841 const uint32_t event_type = SBBreakpoint::GetBreakpointEventTypeFromEvent (event);
842
843 if (event_type & eBreakpointEventTypeAdded
844 || event_type & eBreakpointEventTypeRemoved
845 || event_type & eBreakpointEventTypeEnabled
846 || event_type & eBreakpointEventTypeDisabled
847 || event_type & eBreakpointEventTypeCommandChanged
848 || event_type & eBreakpointEventTypeConditionChanged
849 || event_type & eBreakpointEventTypeIgnoreChanged
850 || event_type & eBreakpointEventTypeLocationsResolved)
851 {
852 // Don't do anything about these events, since the breakpoint commands already echo these actions.
853 }
854 else if (event_type & eBreakpointEventTypeLocationsAdded)
855 {
856 char message[256];
857 uint32_t num_new_locations = SBBreakpoint::GetNumBreakpointLocationsFromEvent(event);
858 if (num_new_locations > 0)
859 {
860 SBBreakpoint breakpoint = SBBreakpoint::GetBreakpointFromEvent(event);
Jim Inghamfab10e82012-03-06 00:37:27 +0000861 int message_len = ::snprintf (message, sizeof(message), "%d location%s added to breakpoint %d\n",
Jim Inghame6bc6cb2012-02-08 05:23:15 +0000862 num_new_locations,
Jason Molenda65c28cb2012-09-28 01:50:47 +0000863 num_new_locations == 1 ? "" : "s",
Jim Inghame6bc6cb2012-02-08 05:23:15 +0000864 breakpoint.GetID());
865 m_io_channel_ap->OutWrite(message, message_len, ASYNC);
866 }
867 }
868 else if (event_type & eBreakpointEventTypeLocationsRemoved)
869 {
870 // These locations just get disabled, not sure it is worth spamming folks about this on the command line.
871 }
872 else if (event_type & eBreakpointEventTypeLocationsResolved)
873 {
874 // This might be an interesting thing to note, but I'm going to leave it quiet for now, it just looked noisy.
875 }
876}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000877
878// This function handles events that were broadcast by the process.
879void
880Driver::HandleProcessEvent (const SBEvent &event)
881{
882 using namespace lldb;
883 const uint32_t event_type = event.GetType();
884
885 if (event_type & SBProcess::eBroadcastBitSTDOUT)
886 {
887 // The process has stdout available, get it and write it out to the
888 // appropriate place.
Caroline Tice969ed3d2011-05-02 20:41:46 +0000889 GetProcessSTDOUT ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000890 }
891 else if (event_type & SBProcess::eBroadcastBitSTDERR)
892 {
893 // The process has stderr available, get it and write it out to the
894 // appropriate place.
Caroline Tice969ed3d2011-05-02 20:41:46 +0000895 GetProcessSTDERR ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000896 }
897 else if (event_type & SBProcess::eBroadcastBitStateChanged)
898 {
899 // Drain all stout and stderr so we don't see any output come after
900 // we print our prompts
Caroline Tice969ed3d2011-05-02 20:41:46 +0000901 GetProcessSTDOUT ();
902 GetProcessSTDERR ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000903 // Something changed in the process; get the event and report the process's current status and location to
904 // the user.
905 StateType event_state = SBProcess::GetStateFromEvent (event);
906 if (event_state == eStateInvalid)
907 return;
908
909 SBProcess process (SBProcess::GetProcessFromEvent (event));
910 assert (process.IsValid());
911
912 switch (event_state)
913 {
914 case eStateInvalid:
915 case eStateUnloaded:
Greg Claytonb766a732011-02-04 01:58:07 +0000916 case eStateConnected:
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000917 case eStateAttaching:
918 case eStateLaunching:
919 case eStateStepping:
920 case eStateDetached:
921 {
922 char message[1024];
Daniel Malead01b2952012-11-29 21:49:15 +0000923 int message_len = ::snprintf (message, sizeof(message), "Process %" PRIu64 " %s\n", process.GetProcessID(),
Greg Clayton66111032010-06-23 01:19:29 +0000924 m_debugger.StateAsCString (event_state));
Caroline Tice969ed3d2011-05-02 20:41:46 +0000925 m_io_channel_ap->OutWrite(message, message_len, ASYNC);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000926 }
927 break;
928
929 case eStateRunning:
930 // Don't be chatty when we run...
931 break;
932
933 case eStateExited:
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000934 {
935 SBCommandReturnObject result;
936 m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
Caroline Tice969ed3d2011-05-02 20:41:46 +0000937 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize(), ASYNC);
938 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize(), ASYNC);
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000939 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000940 break;
941
942 case eStateStopped:
943 case eStateCrashed:
944 case eStateSuspended:
945 // Make sure the program hasn't been auto-restarted:
946 if (SBProcess::GetRestartedFromEvent (event))
947 {
948 // FIXME: Do we want to report this, or would that just be annoyingly chatty?
949 char message[1024];
Daniel Malead01b2952012-11-29 21:49:15 +0000950 int message_len = ::snprintf (message, sizeof(message), "Process %" PRIu64 " stopped and was programmatically restarted.\n",
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000951 process.GetProcessID());
Caroline Tice969ed3d2011-05-02 20:41:46 +0000952 m_io_channel_ap->OutWrite(message, message_len, ASYNC);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000953 }
954 else
955 {
Jim Ingham8499e1a2012-05-08 23:06:07 +0000956 if (GetDebugger().GetSelectedTarget() == process.GetTarget())
957 {
958 SBCommandReturnObject result;
959 UpdateSelectedThread ();
960 m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
961 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize(), ASYNC);
962 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize(), ASYNC);
963 }
964 else
965 {
966 SBStream out_stream;
967 uint32_t target_idx = GetDebugger().GetIndexOfTarget(process.GetTarget());
968 if (target_idx != UINT32_MAX)
969 out_stream.Printf ("Target %d: (", target_idx);
970 else
971 out_stream.Printf ("Target <unknown index>: (");
972 process.GetTarget().GetDescription (out_stream, eDescriptionLevelBrief);
973 out_stream.Printf (") stopped.\n");
974 m_io_channel_ap->OutWrite (out_stream.GetData(), out_stream.GetSize(), ASYNC);
975 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000976 }
977 break;
978 }
979 }
980}
981
Jim Ingham4f465cf2012-10-10 18:32:14 +0000982void
983Driver::HandleThreadEvent (const SBEvent &event)
984{
985 // At present the only thread event we handle is the Frame Changed event, and all we do for that is just
986 // reprint the thread status for that thread.
987 using namespace lldb;
988 const uint32_t event_type = event.GetType();
Jim Inghamc3faa192012-12-11 02:31:48 +0000989 if (event_type == SBThread::eBroadcastBitStackChanged
990 || event_type == SBThread::eBroadcastBitThreadSelected)
Jim Ingham4f465cf2012-10-10 18:32:14 +0000991 {
992 SBThread thread = SBThread::GetThreadFromEvent (event);
993 if (thread.IsValid())
994 {
995 SBStream out_stream;
996 thread.GetStatus(out_stream);
997 m_io_channel_ap->OutWrite (out_stream.GetData (), out_stream.GetSize (), ASYNC);
998 }
999 }
1000}
1001
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001002// This function handles events broadcast by the IOChannel (HasInput, UserInterrupt, or ThreadShouldExit).
1003
1004bool
1005Driver::HandleIOEvent (const SBEvent &event)
1006{
1007 bool quit = false;
1008
1009 const uint32_t event_type = event.GetType();
1010
1011 if (event_type & IOChannel::eBroadcastBitHasUserInput)
1012 {
1013 // We got some input (i.e. a command string) from the user; pass it off to the command interpreter for
1014 // handling.
1015
1016 const char *command_string = SBEvent::GetCStringFromEvent(event);
1017 if (command_string == NULL)
Greg Claytonc982c762010-07-09 20:39:50 +00001018 command_string = "";
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001019 SBCommandReturnObject result;
Jim Ingham85e8b812011-02-19 02:53:09 +00001020
Caroline Ticeb5059ac2011-05-16 19:20:50 +00001021 // We don't want the result to bypass the OutWrite function in IOChannel, as this can result in odd
1022 // output orderings and problems with the prompt.
Jim Ingham85e8b812011-02-19 02:53:09 +00001023 m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, true);
1024
Enrico Granatacd4d24d2012-10-16 20:57:12 +00001025 const bool only_if_no_immediate = true;
1026
Enrico Granata430e5402012-10-16 21:11:14 +00001027 const size_t output_size = result.GetOutputSize();
Enrico Granatacd4d24d2012-10-16 20:57:12 +00001028
1029 if (output_size > 0)
1030 m_io_channel_ap->OutWrite (result.GetOutput(only_if_no_immediate), output_size, NO_ASYNC);
1031
Enrico Granata430e5402012-10-16 21:11:14 +00001032 const size_t error_size = result.GetErrorSize();
Enrico Granatacd4d24d2012-10-16 20:57:12 +00001033
1034 if (error_size > 0)
1035 m_io_channel_ap->OutWrite (result.GetError(only_if_no_immediate), error_size, NO_ASYNC);
Caroline Ticeb5059ac2011-05-16 19:20:50 +00001036
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001037 // We are done getting and running our command, we can now clear the
1038 // m_waiting_for_command so we can get another one.
1039 m_waiting_for_command = false;
1040
1041 // If our editline input reader is active, it means another input reader
1042 // got pushed onto the input reader and caused us to become deactivated.
1043 // When the input reader above us gets popped, we will get re-activated
1044 // and our prompt will refresh in our callback
1045 if (m_editline_reader.IsActive())
1046 {
1047 ReadyForCommand ();
1048 }
1049 }
1050 else if (event_type & IOChannel::eBroadcastBitUserInterrupt)
1051 {
1052 // This is here to handle control-c interrupts from the user. It has not yet really been implemented.
1053 // TO BE DONE: PROPERLY HANDLE CONTROL-C FROM USER
1054 //m_io_channel_ap->CancelInput();
1055 // Anything else? Send Interrupt to process?
1056 }
1057 else if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
1058 (event_type & IOChannel::eBroadcastBitThreadDidExit))
1059 {
1060 // If the IOChannel thread is trying to go away, then it is definitely
1061 // time to end the debugging session.
1062 quit = true;
1063 }
1064
1065 return quit;
1066}
1067
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001068void
1069Driver::MasterThreadBytesReceived (void *baton, const void *src, size_t src_len)
1070{
1071 Driver *driver = (Driver*)baton;
1072 driver->GetFromMaster ((const char *)src, src_len);
1073}
1074
1075void
1076Driver::GetFromMaster (const char *src, size_t src_len)
1077{
1078 // Echo the characters back to the Debugger's stdout, that way if you
1079 // type characters while a command is running, you'll see what you've typed.
Greg Clayton66111032010-06-23 01:19:29 +00001080 FILE *out_fh = m_debugger.GetOutputFileHandle();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001081 if (out_fh)
1082 ::fwrite (src, 1, src_len, out_fh);
1083}
1084
1085size_t
1086Driver::EditLineInputReaderCallback
1087(
1088 void *baton,
1089 SBInputReader *reader,
1090 InputReaderAction notification,
1091 const char *bytes,
1092 size_t bytes_len
1093)
1094{
1095 Driver *driver = (Driver *)baton;
1096
1097 switch (notification)
1098 {
1099 case eInputReaderActivate:
1100 break;
1101
1102 case eInputReaderReactivate:
1103 driver->ReadyForCommand();
1104 break;
1105
1106 case eInputReaderDeactivate:
1107 break;
Caroline Tice969ed3d2011-05-02 20:41:46 +00001108
1109 case eInputReaderAsynchronousOutputWritten:
1110 if (driver->m_io_channel_ap.get() != NULL)
1111 driver->m_io_channel_ap->RefreshPrompt();
1112 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001113
Caroline Ticeefed6132010-11-19 20:47:54 +00001114 case eInputReaderInterrupt:
1115 if (driver->m_io_channel_ap.get() != NULL)
1116 {
Jim Inghamcfc09352012-07-27 23:57:19 +00001117 SBProcess process(driver->GetDebugger().GetSelectedTarget().GetProcess());
Jim Inghamd242f1c2012-06-01 01:07:02 +00001118 if (!driver->m_io_channel_ap->EditLineHasCharacters()
Jim Inghamcfc09352012-07-27 23:57:19 +00001119 && process.IsValid()
1120 && (process.GetState() == lldb::eStateRunning || process.GetState() == lldb::eStateAttaching))
Jim Inghamd242f1c2012-06-01 01:07:02 +00001121 {
Jim Inghamcfc09352012-07-27 23:57:19 +00001122 process.SendAsyncInterrupt ();
Jim Inghamd242f1c2012-06-01 01:07:02 +00001123 }
1124 else
1125 {
1126 driver->m_io_channel_ap->OutWrite ("^C\n", 3, NO_ASYNC);
1127 // I wish I could erase the entire input line, but there's no public API for that.
1128 driver->m_io_channel_ap->EraseCharsBeforeCursor();
1129 driver->m_io_channel_ap->RefreshPrompt();
1130 }
Caroline Ticeefed6132010-11-19 20:47:54 +00001131 }
1132 break;
1133
1134 case eInputReaderEndOfFile:
1135 if (driver->m_io_channel_ap.get() != NULL)
1136 {
Caroline Tice969ed3d2011-05-02 20:41:46 +00001137 driver->m_io_channel_ap->OutWrite ("^D\n", 3, NO_ASYNC);
Caroline Ticeefed6132010-11-19 20:47:54 +00001138 driver->m_io_channel_ap->RefreshPrompt ();
1139 }
1140 write (driver->m_editline_pty.GetMasterFileDescriptor(), "quit\n", 5);
1141 break;
1142
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001143 case eInputReaderGotToken:
1144 write (driver->m_editline_pty.GetMasterFileDescriptor(), bytes, bytes_len);
1145 break;
1146
1147 case eInputReaderDone:
1148 break;
1149 }
1150 return bytes_len;
1151}
1152
1153void
1154Driver::MainLoop ()
1155{
1156 char error_str[1024];
1157 if (m_editline_pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, error_str, sizeof(error_str)) == false)
1158 {
1159 ::fprintf (stderr, "error: failed to open driver pseudo terminal : %s", error_str);
1160 exit(1);
1161 }
1162 else
1163 {
1164 const char *driver_slave_name = m_editline_pty.GetSlaveName (error_str, sizeof(error_str));
1165 if (driver_slave_name == NULL)
1166 {
1167 ::fprintf (stderr, "error: failed to get slave name for driver pseudo terminal : %s", error_str);
1168 exit(2);
1169 }
1170 else
1171 {
1172 m_editline_slave_fh = ::fopen (driver_slave_name, "r+");
1173 if (m_editline_slave_fh == NULL)
1174 {
1175 SBError error;
1176 error.SetErrorToErrno();
1177 ::fprintf (stderr, "error: failed to get open slave for driver pseudo terminal : %s",
1178 error.GetCString());
1179 exit(3);
1180 }
1181
1182 ::setbuf (m_editline_slave_fh, NULL);
1183 }
1184 }
1185
Caroline Tice969ed3d2011-05-02 20:41:46 +00001186 lldb_utility::PseudoTerminal editline_output_pty;
1187 FILE *editline_output_slave_fh = NULL;
1188
1189 if (editline_output_pty.OpenFirstAvailableMaster (O_RDWR|O_NOCTTY, error_str, sizeof (error_str)) == false)
1190 {
1191 ::fprintf (stderr, "error: failed to open output pseudo terminal : %s", error_str);
1192 exit(1);
1193 }
1194 else
1195 {
1196 const char *output_slave_name = editline_output_pty.GetSlaveName (error_str, sizeof(error_str));
1197 if (output_slave_name == NULL)
1198 {
1199 ::fprintf (stderr, "error: failed to get slave name for output pseudo terminal : %s", error_str);
1200 exit(2);
1201 }
1202 else
1203 {
1204 editline_output_slave_fh = ::fopen (output_slave_name, "r+");
1205 if (editline_output_slave_fh == NULL)
1206 {
1207 SBError error;
1208 error.SetErrorToErrno();
1209 ::fprintf (stderr, "error: failed to get open slave for output pseudo terminal : %s",
1210 error.GetCString());
1211 exit(3);
1212 }
1213 ::setbuf (editline_output_slave_fh, NULL);
1214 }
1215 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001216
1217 // struct termios stdin_termios;
1218
1219 if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0)
Greg Claytonf571b892012-02-02 19:28:31 +00001220 {
1221 g_old_stdin_termios_is_valid = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001222 atexit (reset_stdin_termios);
Greg Claytonf571b892012-02-02 19:28:31 +00001223 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001224
1225 ::setbuf (stdin, NULL);
1226 ::setbuf (stdout, NULL);
1227
Greg Clayton66111032010-06-23 01:19:29 +00001228 m_debugger.SetErrorFileHandle (stderr, false);
1229 m_debugger.SetOutputFileHandle (stdout, false);
1230 m_debugger.SetInputFileHandle (stdin, true);
Jim Inghame40e4212010-08-30 19:44:40 +00001231
1232 m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001233
1234 // You have to drain anything that comes to the master side of the PTY. master_out_comm is
1235 // for that purpose. The reason you need to do this is a curious reason... editline will echo
1236 // characters to the PTY when it gets characters while el_gets is not running, and then when
1237 // you call el_gets (or el_getc) it will try to reset the terminal back to raw mode which blocks
1238 // if there are unconsumed characters in the out buffer.
1239 // However, you don't need to do anything with the characters, since editline will dump these
1240 // unconsumed characters after printing the prompt again in el_gets.
1241
Greg Claytond46c87a2010-12-04 02:39:47 +00001242 SBCommunication master_out_comm("driver.editline");
1243 master_out_comm.SetCloseOnEOF (false);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001244 master_out_comm.AdoptFileDesriptor(m_editline_pty.GetMasterFileDescriptor(), false);
1245 master_out_comm.SetReadThreadBytesReceivedCallback(Driver::MasterThreadBytesReceived, this);
1246
1247 if (master_out_comm.ReadThreadStart () == false)
1248 {
1249 ::fprintf (stderr, "error: failed to start master out read thread");
1250 exit(5);
1251 }
1252
Greg Clayton66111032010-06-23 01:19:29 +00001253 SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001254
Caroline Tice969ed3d2011-05-02 20:41:46 +00001255 m_io_channel_ap.reset (new IOChannel(m_editline_slave_fh, editline_output_slave_fh, stdout, stderr, this));
1256
1257 SBCommunication out_comm_2("driver.editline_output");
1258 out_comm_2.SetCloseOnEOF (false);
1259 out_comm_2.AdoptFileDesriptor (editline_output_pty.GetMasterFileDescriptor(), false);
1260 out_comm_2.SetReadThreadBytesReceivedCallback (IOChannel::LibeditOutputBytesReceived, m_io_channel_ap.get());
1261
1262 if (out_comm_2.ReadThreadStart () == false)
1263 {
1264 ::fprintf (stderr, "error: failed to start libedit output read thread");
1265 exit (5);
1266 }
1267
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001268
1269 struct winsize window_size;
1270 if (isatty (STDIN_FILENO)
1271 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
1272 {
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001273 if (window_size.ws_col > 0)
Greg Claytona7015092010-09-18 01:14:36 +00001274 m_debugger.SetTerminalWidth (window_size.ws_col);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001275 }
1276
1277 // Since input can be redirected by the debugger, we must insert our editline
1278 // input reader in the queue so we know when our reader should be active
1279 // and so we can receive bytes only when we are supposed to.
Greg Clayton66111032010-06-23 01:19:29 +00001280 SBError err (m_editline_reader.Initialize (m_debugger,
1281 Driver::EditLineInputReaderCallback, // callback
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001282 this, // baton
1283 eInputReaderGranularityByte, // token_size
1284 NULL, // end token - NULL means never done
1285 NULL, // prompt - taken care of elsewhere
1286 false)); // echo input - don't need Debugger
1287 // to do this, we handle it elsewhere
1288
1289 if (err.Fail())
1290 {
1291 ::fprintf (stderr, "error: %s", err.GetCString());
1292 exit (6);
1293 }
1294
Greg Clayton66111032010-06-23 01:19:29 +00001295 m_debugger.PushInputReader (m_editline_reader);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001296
Greg Clayton66111032010-06-23 01:19:29 +00001297 SBListener listener(m_debugger.GetListener());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001298 if (listener.IsValid())
1299 {
1300
Jim Ingham4f465cf2012-10-10 18:32:14 +00001301 listener.StartListeningForEventClass(m_debugger,
1302 SBTarget::GetBroadcasterClassName(),
1303 SBTarget::eBroadcastBitBreakpointChanged);
1304 listener.StartListeningForEventClass(m_debugger,
1305 SBThread::GetBroadcasterClassName(),
Jim Inghamc3faa192012-12-11 02:31:48 +00001306 SBThread::eBroadcastBitStackChanged |
1307 SBThread::eBroadcastBitThreadSelected);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001308 listener.StartListeningForEvents (*m_io_channel_ap,
1309 IOChannel::eBroadcastBitHasUserInput |
1310 IOChannel::eBroadcastBitUserInterrupt |
1311 IOChannel::eBroadcastBitThreadShouldExit |
1312 IOChannel::eBroadcastBitThreadDidStart |
1313 IOChannel::eBroadcastBitThreadDidExit);
1314
1315 if (m_io_channel_ap->Start ())
1316 {
1317 bool iochannel_thread_exited = false;
1318
1319 listener.StartListeningForEvents (sb_interpreter.GetBroadcaster(),
Caroline Tice86a73f92011-05-03 20:53:11 +00001320 SBCommandInterpreter::eBroadcastBitQuitCommandReceived |
1321 SBCommandInterpreter::eBroadcastBitAsynchronousOutputData |
1322 SBCommandInterpreter::eBroadcastBitAsynchronousErrorData);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001323
1324 // Before we handle any options from the command line, we parse the
1325 // .lldbinit file in the user's home directory.
1326 SBCommandReturnObject result;
1327 sb_interpreter.SourceInitFileInHomeDirectory(result);
1328 if (GetDebugMode())
1329 {
Greg Clayton66111032010-06-23 01:19:29 +00001330 result.PutError (m_debugger.GetErrorFileHandle());
1331 result.PutOutput (m_debugger.GetOutputFileHandle());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001332 }
1333
1334 // Now we handle options we got from the command line
1335 char command_string[PATH_MAX * 2];
1336 const size_t num_source_command_files = GetNumSourceCommandFiles();
Enrico Granataaa0c8ff2012-12-13 20:20:11 +00001337 const bool dump_stream_only_if_no_immediate = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001338 if (num_source_command_files > 0)
1339 {
1340 for (size_t i=0; i < num_source_command_files; ++i)
1341 {
1342 const char *command_file = GetSourceCommandFileAtIndex(i);
Johnny Chen85ffddc2010-07-28 21:16:11 +00001343 ::snprintf (command_string, sizeof(command_string), "command source '%s'", command_file);
Greg Clayton66111032010-06-23 01:19:29 +00001344 m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, false);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001345 if (GetDebugMode())
1346 {
Greg Clayton66111032010-06-23 01:19:29 +00001347 result.PutError (m_debugger.GetErrorFileHandle());
1348 result.PutOutput (m_debugger.GetOutputFileHandle());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001349 }
Enrico Granataaa0c8ff2012-12-13 20:20:11 +00001350
1351 // if the command sourcing generated an error - dump the result object
Enrico Granatadc3f4f92012-12-14 00:52:54 +00001352 if (result.Succeeded() == false)
Enrico Granataaa0c8ff2012-12-13 20:20:11 +00001353 {
1354 const size_t output_size = result.GetOutputSize();
1355 if (output_size > 0)
1356 m_io_channel_ap->OutWrite (result.GetOutput(dump_stream_only_if_no_immediate), output_size, NO_ASYNC);
Enrico Granatadc3f4f92012-12-14 00:52:54 +00001357 const size_t error_size = result.GetErrorSize();
1358 if (error_size > 0)
1359 m_io_channel_ap->OutWrite (result.GetError(dump_stream_only_if_no_immediate), error_size, NO_ASYNC);
Enrico Granataaa0c8ff2012-12-13 20:20:11 +00001360 }
1361
1362 result.Clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001363 }
1364 }
1365
Johnny Cheneb46f782012-08-15 22:10:42 +00001366 // Was there a core file specified?
1367 std::string core_file_spec("");
1368 if (!m_option_data.m_core_file.empty())
1369 core_file_spec.append("--core ").append(m_option_data.m_core_file);
1370
Greg Clayton8d846da2010-12-08 22:23:24 +00001371 const size_t num_args = m_option_data.m_args.size();
1372 if (num_args > 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001373 {
1374 char arch_name[64];
Greg Clayton66111032010-06-23 01:19:29 +00001375 if (m_debugger.GetDefaultArchitecture (arch_name, sizeof (arch_name)))
Greg Clayton8d846da2010-12-08 22:23:24 +00001376 ::snprintf (command_string,
1377 sizeof (command_string),
Johnny Cheneb46f782012-08-15 22:10:42 +00001378 "target create --arch=%s %s \"%s\"",
Greg Clayton8d846da2010-12-08 22:23:24 +00001379 arch_name,
Johnny Cheneb46f782012-08-15 22:10:42 +00001380 core_file_spec.c_str(),
Greg Clayton8d846da2010-12-08 22:23:24 +00001381 m_option_data.m_args[0].c_str());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001382 else
Greg Clayton8d846da2010-12-08 22:23:24 +00001383 ::snprintf (command_string,
1384 sizeof(command_string),
Johnny Cheneb46f782012-08-15 22:10:42 +00001385 "target create %s \"%s\"",
1386 core_file_spec.c_str(),
Greg Clayton8d846da2010-12-08 22:23:24 +00001387 m_option_data.m_args[0].c_str());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001388
Greg Clayton66111032010-06-23 01:19:29 +00001389 m_debugger.HandleCommand (command_string);
Greg Clayton8d846da2010-12-08 22:23:24 +00001390
1391 if (num_args > 1)
1392 {
Greg Clayton1d885962011-11-08 02:43:13 +00001393 m_debugger.HandleCommand ("settings clear target.run-args");
Greg Clayton8d846da2010-12-08 22:23:24 +00001394 char arg_cstr[1024];
1395 for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx)
1396 {
Jim Inghame64f0dc2011-09-13 23:25:31 +00001397 ::snprintf (arg_cstr,
1398 sizeof(arg_cstr),
Greg Clayton1d885962011-11-08 02:43:13 +00001399 "settings append target.run-args \"%s\"",
Jim Inghame64f0dc2011-09-13 23:25:31 +00001400 m_option_data.m_args[arg_idx].c_str());
Greg Clayton8d846da2010-12-08 22:23:24 +00001401 m_debugger.HandleCommand (arg_cstr);
1402 }
1403 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001404 }
Johnny Cheneb46f782012-08-15 22:10:42 +00001405 else if (!core_file_spec.empty())
1406 {
1407 ::snprintf (command_string,
1408 sizeof(command_string),
1409 "target create %s",
1410 core_file_spec.c_str());
1411 m_debugger.HandleCommand (command_string);;
1412 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001413
1414 // Now that all option parsing is done, we try and parse the .lldbinit
1415 // file in the current working directory
1416 sb_interpreter.SourceInitFileInCurrentWorkingDirectory (result);
1417 if (GetDebugMode())
1418 {
Greg Clayton66111032010-06-23 01:19:29 +00001419 result.PutError(m_debugger.GetErrorFileHandle());
1420 result.PutOutput(m_debugger.GetOutputFileHandle());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001421 }
1422
1423 SBEvent event;
1424
1425 // Make sure the IO channel is started up before we try to tell it we
1426 // are ready for input
1427 listener.WaitForEventForBroadcasterWithType (UINT32_MAX,
1428 *m_io_channel_ap,
1429 IOChannel::eBroadcastBitThreadDidStart,
1430 event);
Jim Inghame64f0dc2011-09-13 23:25:31 +00001431 // If we were asked to attach, then do that here:
1432 // I'm going to use the command string rather than directly
1433 // calling the API's because then I don't have to recode the
1434 // event handling here.
1435 if (!m_option_data.m_process_name.empty()
1436 || m_option_data.m_process_pid != LLDB_INVALID_PROCESS_ID)
1437 {
1438 std::string command_str("process attach ");
1439 if (m_option_data.m_process_pid != LLDB_INVALID_PROCESS_ID)
1440 {
1441 command_str.append("-p ");
1442 char pid_buffer[32];
Daniel Malead01b2952012-11-29 21:49:15 +00001443 ::snprintf (pid_buffer, sizeof(pid_buffer), "%" PRIu64, m_option_data.m_process_pid);
Jim Inghame64f0dc2011-09-13 23:25:31 +00001444 command_str.append(pid_buffer);
1445 }
1446 else
1447 {
1448 command_str.append("-n \"");
1449 command_str.append(m_option_data.m_process_name);
1450 command_str.push_back('\"');
1451 if (m_option_data.m_wait_for)
1452 command_str.append(" -w");
1453 }
1454
1455 if (m_debugger.GetOutputFileHandle())
1456 ::fprintf (m_debugger.GetOutputFileHandle(),
1457 "Attaching to process with:\n %s\n",
1458 command_str.c_str());
1459
1460 // Force the attach to be synchronous:
1461 bool orig_async = m_debugger.GetAsync();
1462 m_debugger.SetAsync(true);
1463 m_debugger.HandleCommand(command_str.c_str());
1464 m_debugger.SetAsync(orig_async);
1465 }
1466
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001467 ReadyForCommand ();
1468
Greg Claytona9f7b792012-02-29 04:21:24 +00001469 while (!GetIsDone())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001470 {
1471 listener.WaitForEvent (UINT32_MAX, event);
1472 if (event.IsValid())
1473 {
1474 if (event.GetBroadcaster().IsValid())
1475 {
1476 uint32_t event_type = event.GetType();
1477 if (event.BroadcasterMatchesRef (*m_io_channel_ap))
1478 {
1479 if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
1480 (event_type & IOChannel::eBroadcastBitThreadDidExit))
1481 {
Greg Claytona9f7b792012-02-29 04:21:24 +00001482 SetIsDone();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001483 if (event_type & IOChannel::eBroadcastBitThreadDidExit)
1484 iochannel_thread_exited = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001485 }
1486 else
Greg Claytona9f7b792012-02-29 04:21:24 +00001487 {
1488 if (HandleIOEvent (event))
1489 SetIsDone();
1490 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001491 }
Jim Inghame6bc6cb2012-02-08 05:23:15 +00001492 else if (SBProcess::EventIsProcessEvent (event))
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001493 {
1494 HandleProcessEvent (event);
1495 }
Jim Inghame6bc6cb2012-02-08 05:23:15 +00001496 else if (SBBreakpoint::EventIsBreakpointEvent (event))
1497 {
1498 HandleBreakpointEvent (event);
1499 }
Jim Ingham4f465cf2012-10-10 18:32:14 +00001500 else if (SBThread::EventIsThreadEvent (event))
1501 {
1502 HandleThreadEvent (event);
1503 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001504 else if (event.BroadcasterMatchesRef (sb_interpreter.GetBroadcaster()))
1505 {
Greg Claytona9f7b792012-02-29 04:21:24 +00001506 // TODO: deprecate the eBroadcastBitQuitCommandReceived event
1507 // now that we have SBCommandInterpreter::SetCommandOverrideCallback()
1508 // that can take over a command
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001509 if (event_type & SBCommandInterpreter::eBroadcastBitQuitCommandReceived)
Greg Clayton74d41932012-01-31 04:56:17 +00001510 {
Greg Claytona9f7b792012-02-29 04:21:24 +00001511 SetIsDone();
Greg Clayton74d41932012-01-31 04:56:17 +00001512 }
Caroline Tice86a73f92011-05-03 20:53:11 +00001513 else if (event_type & SBCommandInterpreter::eBroadcastBitAsynchronousErrorData)
1514 {
1515 const char *data = SBEvent::GetCStringFromEvent (event);
1516 m_io_channel_ap->ErrWrite (data, strlen(data), ASYNC);
1517 }
1518 else if (event_type & SBCommandInterpreter::eBroadcastBitAsynchronousOutputData)
1519 {
1520 const char *data = SBEvent::GetCStringFromEvent (event);
1521 m_io_channel_ap->OutWrite (data, strlen(data), ASYNC);
1522 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001523 }
1524 }
1525 }
1526 }
1527
Greg Claytonf571b892012-02-02 19:28:31 +00001528 editline_output_pty.CloseMasterFileDescriptor();
1529 master_out_comm.Disconnect();
1530 out_comm_2.Disconnect();
1531 reset_stdin_termios();
1532 fclose (stdin);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001533
1534 CloseIOChannelFile ();
1535
1536 if (!iochannel_thread_exited)
1537 {
Greg Claytonb1320972010-07-14 00:18:15 +00001538 event.Clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001539 listener.GetNextEventForBroadcasterWithType (*m_io_channel_ap,
1540 IOChannel::eBroadcastBitThreadDidExit,
1541 event);
1542 if (!event.IsValid())
1543 {
1544 // Send end EOF to the driver file descriptor
1545 m_io_channel_ap->Stop();
1546 }
1547 }
1548
Jim Ingham12e9a202011-09-15 21:30:02 +00001549 SBDebugger::Destroy (m_debugger);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001550 }
1551 }
1552}
1553
1554
1555void
1556Driver::ReadyForCommand ()
1557{
1558 if (m_waiting_for_command == false)
1559 {
1560 m_waiting_for_command = true;
1561 BroadcastEventByType (Driver::eBroadcastBitReadyForInput, true);
1562 }
1563}
1564
1565
Caroline Ticedd759852010-09-09 17:45:09 +00001566void
1567sigwinch_handler (int signo)
1568{
1569 struct winsize window_size;
1570 if (isatty (STDIN_FILENO)
1571 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
1572 {
Jim Ingham57190ba2012-04-26 21:39:32 +00001573 if ((window_size.ws_col > 0) && g_driver != NULL)
Caroline Ticedd759852010-09-09 17:45:09 +00001574 {
Jim Ingham57190ba2012-04-26 21:39:32 +00001575 g_driver->GetDebugger().SetTerminalWidth (window_size.ws_col);
Caroline Ticedd759852010-09-09 17:45:09 +00001576 }
1577 }
1578}
1579
Caroline Ticeefed6132010-11-19 20:47:54 +00001580void
1581sigint_handler (int signo)
1582{
1583 static bool g_interrupt_sent = false;
1584 if (g_driver)
1585 {
1586 if (!g_interrupt_sent)
1587 {
1588 g_interrupt_sent = true;
1589 g_driver->GetDebugger().DispatchInputInterrupt();
1590 g_interrupt_sent = false;
1591 return;
1592 }
1593 }
1594
1595 exit (signo);
1596}
1597
Jim Inghamc5917d92012-11-30 20:23:19 +00001598void
1599sigtstp_handler (int signo)
1600{
1601 g_driver->GetDebugger().SaveInputTerminalState();
1602 signal (signo, SIG_DFL);
1603 kill (getpid(), signo);
1604 signal (signo, sigtstp_handler);
1605}
1606
1607void
1608sigcont_handler (int signo)
1609{
1610 g_driver->GetDebugger().RestoreInputTerminalState();
1611 signal (signo, SIG_DFL);
1612 kill (getpid(), signo);
1613 signal (signo, sigcont_handler);
1614}
1615
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001616int
Jim Inghama462f5c2011-01-27 20:15:39 +00001617main (int argc, char const *argv[], const char *envp[])
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001618{
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001619 SBDebugger::Initialize();
1620
Greg Clayton2ccf8cf2010-11-07 21:02:03 +00001621 SBHostOS::ThreadCreated ("<lldb.driver.main-thread>");
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001622
Greg Clayton3fcbed62010-10-19 03:25:40 +00001623 signal (SIGPIPE, SIG_IGN);
Caroline Ticedd759852010-09-09 17:45:09 +00001624 signal (SIGWINCH, sigwinch_handler);
Caroline Ticeefed6132010-11-19 20:47:54 +00001625 signal (SIGINT, sigint_handler);
Jim Inghamc5917d92012-11-30 20:23:19 +00001626 signal (SIGTSTP, sigtstp_handler);
1627 signal (SIGCONT, sigcont_handler);
Caroline Ticedd759852010-09-09 17:45:09 +00001628
Greg Clayton66111032010-06-23 01:19:29 +00001629 // Create a scope for driver so that the driver object will destroy itself
1630 // before SBDebugger::Terminate() is called.
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001631 {
Greg Clayton66111032010-06-23 01:19:29 +00001632 Driver driver;
1633
1634 bool exit = false;
1635 SBError error (driver.ParseArgs (argc, argv, stdout, exit));
1636 if (error.Fail())
1637 {
1638 const char *error_cstr = error.GetCString ();
1639 if (error_cstr)
1640 ::fprintf (stderr, "error: %s\n", error_cstr);
1641 }
1642 else if (!exit)
1643 {
1644 driver.MainLoop ();
1645 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001646 }
1647
1648 SBDebugger::Terminate();
1649 return 0;
1650}