blob: 3ec2c2fd6d60e6758a2dad9b88adc9f942d4c62d [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- Driver.cpp ----------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "Driver.h"
11
12#include <getopt.h>
13#include <libgen.h>
14#include <sys/ioctl.h>
15#include <termios.h>
16#include <unistd.h>
Eli Friedmanf2f321d2010-06-09 09:50:17 +000017#include <string.h>
18#include <stdlib.h>
19#include <limits.h>
Eli Friedmand6e167d2010-06-09 19:11:30 +000020#include <fcntl.h>
Chris Lattner24943d22010-06-08 16:52:24 +000021
22#include <string>
23
24#include "IOChannel.h"
Eli Friedmanf2f321d2010-06-09 09:50:17 +000025#include "lldb/API/SBCommandInterpreter.h"
26#include "lldb/API/SBCommandReturnObject.h"
27#include "lldb/API/SBCommunication.h"
28#include "lldb/API/SBDebugger.h"
29#include "lldb/API/SBEvent.h"
30#include "lldb/API/SBHostOS.h"
31#include "lldb/API/SBListener.h"
32#include "lldb/API/SBSourceManager.h"
Jim Ingham2e8cb8a2011-02-19 02:53:09 +000033#include "lldb/API/SBStream.h"
Eli Friedmanf2f321d2010-06-09 09:50:17 +000034#include "lldb/API/SBTarget.h"
35#include "lldb/API/SBThread.h"
36#include "lldb/API/SBProcess.h"
Chris Lattner24943d22010-06-08 16:52:24 +000037
38using namespace lldb;
39
40static void reset_stdin_termios ();
41static struct termios g_old_stdin_termios;
42
Caroline Ticeb8314fe2010-09-09 17:45:09 +000043static char *g_debugger_name = (char *) "";
Caroline Ticec4f55fe2010-11-19 20:47:54 +000044static Driver *g_driver = NULL;
Caroline Ticeb8314fe2010-09-09 17:45:09 +000045
Chris Lattner24943d22010-06-08 16:52:24 +000046// In the Driver::MainLoop, we change the terminal settings. This function is
47// added as an atexit handler to make sure we clean them up.
48static void
49reset_stdin_termios ()
50{
51 ::tcsetattr (STDIN_FILENO, TCSANOW, &g_old_stdin_termios);
52}
53
54static lldb::OptionDefinition g_options[] =
55{
Caroline Tice4d6675c2010-10-01 19:59:14 +000056 { LLDB_OPT_SET_1, true, "help", 'h', no_argument, NULL, NULL, eArgTypeNone,
Chris Lattner24943d22010-06-08 16:52:24 +000057 "Prints out the usage information for the LLDB debugger." },
58
Caroline Tice4d6675c2010-10-01 19:59:14 +000059 { LLDB_OPT_SET_2, true, "version", 'v', no_argument, NULL, NULL, eArgTypeNone,
Chris Lattner24943d22010-06-08 16:52:24 +000060 "Prints out the current version number of the LLDB debugger." },
61
Caroline Tice4d6675c2010-10-01 19:59:14 +000062 { LLDB_OPT_SET_3, true, "arch", 'a', required_argument, NULL, NULL, eArgTypeArchitecture,
Chris Lattner24943d22010-06-08 16:52:24 +000063 "Tells the debugger to use the specified architecture when starting and running the program. <architecture> must be one of the architectures for which the program was compiled." },
64
Caroline Tice4d6675c2010-10-01 19:59:14 +000065 { LLDB_OPT_SET_3 | LLDB_OPT_SET_4, false, "script-language",'l', required_argument, NULL, NULL, eArgTypeScriptLang,
Chris Lattner24943d22010-06-08 16:52:24 +000066 "Tells the debugger to use the specified scripting language for user-defined scripts, rather than the default. Valid scripting languages that can be specified include Python, Perl, Ruby and Tcl. Currently only the Python extensions have been implemented." },
67
Caroline Tice4d6675c2010-10-01 19:59:14 +000068 { LLDB_OPT_SET_3 | LLDB_OPT_SET_4, false, "debug", 'd', no_argument, NULL, NULL, eArgTypeNone,
Chris Lattner24943d22010-06-08 16:52:24 +000069 "Tells the debugger to print out extra information for debugging itself." },
70
Caroline Tice4d6675c2010-10-01 19:59:14 +000071 { LLDB_OPT_SET_3 | LLDB_OPT_SET_4, false, "source", 's', required_argument, NULL, NULL, eArgTypeFilename,
Chris Lattner24943d22010-06-08 16:52:24 +000072 "Tells the debugger to read in and execute the file <file>, which should contain lldb commands." },
73
Caroline Tice4d6675c2010-10-01 19:59:14 +000074 { LLDB_OPT_SET_3, true, "file", 'f', required_argument, NULL, NULL, eArgTypeFilename,
Jim Ingham34e9a982010-06-15 18:47:14 +000075 "Tells the debugger to use the file <filename> as the program to be debugged." },
76
Caroline Tice4d6675c2010-10-01 19:59:14 +000077 { LLDB_OPT_SET_ALL, false, "editor", 'e', no_argument, NULL, NULL, eArgTypeNone,
Jim Ingham74989e82010-08-30 19:44:40 +000078 "Tells the debugger to open source files using the host's \"external editor\" mechanism." },
79
Greg Clayton887aa282010-10-11 01:05:37 +000080 { LLDB_OPT_SET_ALL, false, "no-lldbinit", 'n', no_argument, NULL, NULL, eArgTypeNone,
81 "Do not automatically parse any '.lldbinit' files." },
82
Caroline Tice4d6675c2010-10-01 19:59:14 +000083// { LLDB_OPT_SET_4, true, "crash-log", 'c', required_argument, NULL, NULL, eArgTypeFilename,
Greg Clayton12bec712010-06-28 21:30:43 +000084// "Load executable images from a crash log for symbolication." },
Chris Lattner24943d22010-06-08 16:52:24 +000085
Caroline Tice4d6675c2010-10-01 19:59:14 +000086 { 0, false, NULL, 0, 0, NULL, NULL, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +000087};
88
89
90Driver::Driver () :
91 SBBroadcaster ("Driver"),
Greg Clayton63094e02010-06-23 01:19:29 +000092 m_debugger (SBDebugger::Create()),
Chris Lattner24943d22010-06-08 16:52:24 +000093 m_editline_pty (),
94 m_editline_slave_fh (NULL),
95 m_editline_reader (),
96 m_io_channel_ap (),
97 m_option_data (),
98 m_waiting_for_command (false)
99{
Caroline Ticeb8314fe2010-09-09 17:45:09 +0000100 g_debugger_name = (char *) m_debugger.GetInstanceName();
101 if (g_debugger_name == NULL)
102 g_debugger_name = (char *) "";
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000103 g_driver = this;
Chris Lattner24943d22010-06-08 16:52:24 +0000104}
105
106Driver::~Driver ()
107{
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000108 g_driver = NULL;
109 g_debugger_name = NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000110}
111
112void
113Driver::CloseIOChannelFile ()
114{
115 // Write and End of File sequence to the file descriptor to ensure any
116 // read functions can exit.
117 char eof_str[] = "\x04";
118 ::write (m_editline_pty.GetMasterFileDescriptor(), eof_str, strlen(eof_str));
119
120 m_editline_pty.CloseMasterFileDescriptor();
121
122 if (m_editline_slave_fh)
123 {
124 ::fclose (m_editline_slave_fh);
125 m_editline_slave_fh = NULL;
126 }
127}
128
Greg Clayton54e7afa2010-07-09 20:39:50 +0000129// This function takes INDENT, which tells how many spaces to output at the front
130// of each line; TEXT, which is the text that is to be output. It outputs the
131// text, on multiple lines if necessary, to RESULT, with INDENT spaces at the
132// front of each line. It breaks lines on spaces, tabs or newlines, shortening
133// the line if necessary to not break in the middle of a word. It assumes that
134// each output line should contain a maximum of OUTPUT_MAX_COLUMNS characters.
Chris Lattner24943d22010-06-08 16:52:24 +0000135
136void
Greg Clayton54e7afa2010-07-09 20:39:50 +0000137OutputFormattedUsageText (FILE *out, int indent, const char *text, int output_max_columns)
Chris Lattner24943d22010-06-08 16:52:24 +0000138{
139 int len = strlen (text);
140 std::string text_string (text);
Chris Lattner24943d22010-06-08 16:52:24 +0000141
142 // Force indentation to be reasonable.
143 if (indent >= output_max_columns)
144 indent = 0;
145
146 // Will it all fit on one line?
147
148 if (len + indent < output_max_columns)
149 // Output as a single line
Greg Clayton54e7afa2010-07-09 20:39:50 +0000150 fprintf (out, "%*s%s\n", indent, "", text);
Chris Lattner24943d22010-06-08 16:52:24 +0000151 else
152 {
153 // We need to break it up into multiple lines.
154 int text_width = output_max_columns - indent - 1;
155 int start = 0;
156 int end = start;
157 int final_end = len;
158 int sub_len;
159
160 while (end < final_end)
161 {
162 // Dont start the 'text' on a space, since we're already outputting the indentation.
163 while ((start < final_end) && (text[start] == ' '))
164 start++;
165
166 end = start + text_width;
167 if (end > final_end)
168 end = final_end;
169 else
170 {
171 // If we're not at the end of the text, make sure we break the line on white space.
172 while (end > start
173 && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
174 end--;
175 }
176 sub_len = end - start;
177 std::string substring = text_string.substr (start, sub_len);
Greg Clayton54e7afa2010-07-09 20:39:50 +0000178 fprintf (out, "%*s%s\n", indent, "", substring.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000179 start = end + 1;
180 }
181 }
182}
183
184void
185ShowUsage (FILE *out, lldb::OptionDefinition *option_table, Driver::OptionData data)
186{
187 uint32_t screen_width = 80;
188 uint32_t indent_level = 0;
189 const char *name = "lldb";
Jim Ingham34e9a982010-06-15 18:47:14 +0000190
Chris Lattner24943d22010-06-08 16:52:24 +0000191 fprintf (out, "\nUsage:\n\n");
192
193 indent_level += 2;
194
195
196 // First, show each usage level set of options, e.g. <cmd> [options-for-level-0]
197 // <cmd> [options-for-level-1]
198 // etc.
199
Chris Lattner24943d22010-06-08 16:52:24 +0000200 uint32_t num_options;
Jim Ingham34e9a982010-06-15 18:47:14 +0000201 uint32_t num_option_sets = 0;
202
203 for (num_options = 0; option_table[num_options].long_option != NULL; ++num_options)
Chris Lattner24943d22010-06-08 16:52:24 +0000204 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000205 uint32_t this_usage_mask = option_table[num_options].usage_mask;
206 if (this_usage_mask == LLDB_OPT_SET_ALL)
Chris Lattner24943d22010-06-08 16:52:24 +0000207 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000208 if (num_option_sets == 0)
209 num_option_sets = 1;
Chris Lattner24943d22010-06-08 16:52:24 +0000210 }
211 else
212 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000213 for (uint32_t j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++)
Jim Ingham34e9a982010-06-15 18:47:14 +0000214 {
215 if (this_usage_mask & 1 << j)
216 {
217 if (num_option_sets <= j)
218 num_option_sets = j + 1;
219 }
220 }
221 }
222 }
223
224 for (uint32_t opt_set = 0; opt_set < num_option_sets; opt_set++)
225 {
226 uint32_t opt_set_mask;
227
228 opt_set_mask = 1 << opt_set;
229
230 if (opt_set > 0)
231 fprintf (out, "\n");
Greg Clayton54e7afa2010-07-09 20:39:50 +0000232 fprintf (out, "%*s%s", indent_level, "", name);
Jim Ingham34e9a982010-06-15 18:47:14 +0000233
234 for (uint32_t i = 0; i < num_options; ++i)
235 {
236 if (option_table[i].usage_mask & opt_set_mask)
237 {
Caroline Tice4d6675c2010-10-01 19:59:14 +0000238 CommandArgumentType arg_type = option_table[i].argument_type;
Greg Claytonaa378b12011-02-20 02:15:07 +0000239 const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type);
Jim Ingham34e9a982010-06-15 18:47:14 +0000240 if (option_table[i].required)
241 {
242 if (option_table[i].option_has_arg == required_argument)
Greg Claytonaa378b12011-02-20 02:15:07 +0000243 fprintf (out, " -%c <%s>", option_table[i].short_option, arg_name);
Jim Ingham34e9a982010-06-15 18:47:14 +0000244 else if (option_table[i].option_has_arg == optional_argument)
Greg Claytonaa378b12011-02-20 02:15:07 +0000245 fprintf (out, " -%c [<%s>]", option_table[i].short_option, arg_name);
Jim Ingham34e9a982010-06-15 18:47:14 +0000246 else
247 fprintf (out, " -%c", option_table[i].short_option);
248 }
249 else
250 {
251 if (option_table[i].option_has_arg == required_argument)
Greg Claytonaa378b12011-02-20 02:15:07 +0000252 fprintf (out, " [-%c <%s>]", option_table[i].short_option, arg_name);
Jim Ingham34e9a982010-06-15 18:47:14 +0000253 else if (option_table[i].option_has_arg == optional_argument)
Greg Claytonaa378b12011-02-20 02:15:07 +0000254 fprintf (out, " [-%c [<%s>]]", option_table[i].short_option, arg_name);
Jim Ingham34e9a982010-06-15 18:47:14 +0000255 else
256 fprintf (out, " [-%c]", option_table[i].short_option);
257 }
258 }
Chris Lattner24943d22010-06-08 16:52:24 +0000259 }
260 }
261
262 fprintf (out, "\n\n");
263
264 // Now print out all the detailed information about the various options: long form, short form and help text:
265 // -- long_name <argument>
266 // - short <argument>
267 // help text
268
269 // This variable is used to keep track of which options' info we've printed out, because some options can be in
270 // more than one usage level, but we only want to print the long form of its information once.
271
272 Driver::OptionData::OptionSet options_seen;
273 Driver::OptionData::OptionSet::iterator pos;
274
275 indent_level += 5;
276
Jim Ingham34e9a982010-06-15 18:47:14 +0000277 for (uint32_t i = 0; i < num_options; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000278 {
279 // Only print this option if we haven't already seen it.
280 pos = options_seen.find (option_table[i].short_option);
281 if (pos == options_seen.end())
282 {
Caroline Tice4d6675c2010-10-01 19:59:14 +0000283 CommandArgumentType arg_type = option_table[i].argument_type;
Greg Claytonaa378b12011-02-20 02:15:07 +0000284 const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type);
Caroline Tice4d6675c2010-10-01 19:59:14 +0000285
Chris Lattner24943d22010-06-08 16:52:24 +0000286 options_seen.insert (option_table[i].short_option);
Greg Clayton54e7afa2010-07-09 20:39:50 +0000287 fprintf (out, "%*s-%c ", indent_level, "", option_table[i].short_option);
Caroline Tice4d6675c2010-10-01 19:59:14 +0000288 if (arg_type != eArgTypeNone)
Greg Claytonaa378b12011-02-20 02:15:07 +0000289 fprintf (out, "<%s>", arg_name);
Chris Lattner24943d22010-06-08 16:52:24 +0000290 fprintf (out, "\n");
Greg Clayton54e7afa2010-07-09 20:39:50 +0000291 fprintf (out, "%*s--%s ", indent_level, "", option_table[i].long_option);
Caroline Tice4d6675c2010-10-01 19:59:14 +0000292 if (arg_type != eArgTypeNone)
Greg Claytonaa378b12011-02-20 02:15:07 +0000293 fprintf (out, "<%s>", arg_name);
Chris Lattner24943d22010-06-08 16:52:24 +0000294 fprintf (out, "\n");
295 indent_level += 5;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000296 OutputFormattedUsageText (out, indent_level, option_table[i].usage_text, screen_width);
Chris Lattner24943d22010-06-08 16:52:24 +0000297 indent_level -= 5;
298 fprintf (out, "\n");
299 }
300 }
301
302 indent_level -= 5;
303
Greg Clayton54e7afa2010-07-09 20:39:50 +0000304 fprintf (out, "\n%*s('%s <filename>' also works, to specify the file to be debugged.)\n\n",
305 indent_level, "", name);
Chris Lattner24943d22010-06-08 16:52:24 +0000306}
307
308void
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000309BuildGetOptTable (lldb::OptionDefinition *expanded_option_table, std::vector<struct option> &getopt_table,
310 uint32_t num_options)
Chris Lattner24943d22010-06-08 16:52:24 +0000311{
312 if (num_options == 0)
313 return;
314
315 uint32_t i;
316 uint32_t j;
317 std::bitset<256> option_seen;
318
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000319 getopt_table.resize (num_options + 1);
320
Chris Lattner24943d22010-06-08 16:52:24 +0000321 for (i = 0, j = 0; i < num_options; ++i)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000322 {
Chris Lattner24943d22010-06-08 16:52:24 +0000323 char short_opt = expanded_option_table[i].short_option;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000324
Chris Lattner24943d22010-06-08 16:52:24 +0000325 if (option_seen.test(short_opt) == false)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000326 {
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000327 getopt_table[j].name = expanded_option_table[i].long_option;
328 getopt_table[j].has_arg = expanded_option_table[i].option_has_arg;
329 getopt_table[j].flag = NULL;
330 getopt_table[j].val = expanded_option_table[i].short_option;
Chris Lattner24943d22010-06-08 16:52:24 +0000331 option_seen.set(short_opt);
332 ++j;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000333 }
334 }
Chris Lattner24943d22010-06-08 16:52:24 +0000335
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000336 getopt_table[j].name = NULL;
337 getopt_table[j].has_arg = 0;
338 getopt_table[j].flag = NULL;
339 getopt_table[j].val = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000340
341}
342
Greg Clayton63094e02010-06-23 01:19:29 +0000343Driver::OptionData::OptionData () :
Greg Clayton4dc18922010-12-08 22:23:24 +0000344 m_args(),
Greg Clayton63094e02010-06-23 01:19:29 +0000345 m_script_lang (lldb::eScriptLanguageDefault),
Greg Clayton54e7afa2010-07-09 20:39:50 +0000346 m_crash_log (),
Greg Clayton63094e02010-06-23 01:19:29 +0000347 m_source_command_files (),
348 m_debug_mode (false),
Greg Clayton54e7afa2010-07-09 20:39:50 +0000349 m_print_version (false),
Greg Clayton63094e02010-06-23 01:19:29 +0000350 m_print_help (false),
Jim Ingham74989e82010-08-30 19:44:40 +0000351 m_seen_options(),
352 m_use_external_editor(false)
Chris Lattner24943d22010-06-08 16:52:24 +0000353{
Greg Clayton63094e02010-06-23 01:19:29 +0000354}
355
356Driver::OptionData::~OptionData ()
357{
358}
359
360void
361Driver::OptionData::Clear ()
362{
Greg Clayton4dc18922010-12-08 22:23:24 +0000363 m_args.clear ();
Greg Clayton63094e02010-06-23 01:19:29 +0000364 m_script_lang = lldb::eScriptLanguageDefault;
365 m_source_command_files.clear ();
366 m_debug_mode = false;
367 m_print_help = false;
368 m_print_version = false;
Jim Ingham74989e82010-08-30 19:44:40 +0000369 m_use_external_editor = false;
Greg Clayton63094e02010-06-23 01:19:29 +0000370}
371
372void
373Driver::ResetOptionValues ()
374{
375 m_option_data.Clear ();
376}
377
378const char *
379Driver::GetFilename() const
380{
Greg Clayton4dc18922010-12-08 22:23:24 +0000381 if (m_option_data.m_args.empty())
Greg Clayton63094e02010-06-23 01:19:29 +0000382 return NULL;
Greg Clayton4dc18922010-12-08 22:23:24 +0000383 return m_option_data.m_args.front().c_str();
Greg Clayton63094e02010-06-23 01:19:29 +0000384}
385
386const char *
387Driver::GetCrashLogFilename() const
388{
389 if (m_option_data.m_crash_log.empty())
390 return NULL;
391 return m_option_data.m_crash_log.c_str();
392}
393
394lldb::ScriptLanguage
395Driver::GetScriptLanguage() const
396{
397 return m_option_data.m_script_lang;
398}
399
400size_t
401Driver::GetNumSourceCommandFiles () const
402{
403 return m_option_data.m_source_command_files.size();
404}
405
406const char *
407Driver::GetSourceCommandFileAtIndex (uint32_t idx) const
408{
409 if (idx < m_option_data.m_source_command_files.size())
410 return m_option_data.m_source_command_files[idx].c_str();
411 return NULL;
412}
413
414bool
415Driver::GetDebugMode() const
416{
417 return m_option_data.m_debug_mode;
418}
419
420
421// Check the arguments that were passed to this program to make sure they are valid and to get their
422// argument values (if any). Return a boolean value indicating whether or not to start up the full
423// debugger (i.e. the Command Interpreter) or not. Return FALSE if the arguments were invalid OR
424// if the user only wanted help or version information.
425
426SBError
427Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exit)
428{
429 ResetOptionValues ();
430
431 SBCommandReturnObject result;
432
Chris Lattner24943d22010-06-08 16:52:24 +0000433 SBError error;
434 std::string option_string;
435 struct option *long_options = NULL;
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000436 std::vector<struct option> long_options_vector;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000437 uint32_t num_options;
Chris Lattner24943d22010-06-08 16:52:24 +0000438
Greg Clayton54e7afa2010-07-09 20:39:50 +0000439 for (num_options = 0; g_options[num_options].long_option != NULL; ++num_options)
440 /* Do Nothing. */;
Chris Lattner24943d22010-06-08 16:52:24 +0000441
442 if (num_options == 0)
443 {
444 if (argc > 1)
445 error.SetErrorStringWithFormat ("invalid number of options");
446 return error;
447 }
448
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000449 BuildGetOptTable (g_options, long_options_vector, num_options);
Chris Lattner24943d22010-06-08 16:52:24 +0000450
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000451 if (long_options_vector.empty())
452 long_options = NULL;
453 else
454 long_options = &long_options_vector.front();
Chris Lattner24943d22010-06-08 16:52:24 +0000455
456 if (long_options == NULL)
457 {
458 error.SetErrorStringWithFormat ("invalid long options");
459 return error;
460 }
461
462 // Build the option_string argument for call to getopt_long.
463
464 for (int i = 0; long_options[i].name != NULL; ++i)
465 {
466 if (long_options[i].flag == NULL)
467 {
468 option_string.push_back ((char) long_options[i].val);
469 switch (long_options[i].has_arg)
470 {
471 default:
472 case no_argument:
473 break;
474 case required_argument:
475 option_string.push_back (':');
476 break;
477 case optional_argument:
478 option_string.append ("::");
479 break;
480 }
481 }
482 }
483
484 // Prepare for & make calls to getopt_long.
Eli Friedmanef2bc872010-06-13 19:18:49 +0000485#if __GLIBC__
486 optind = 0;
487#else
Chris Lattner24943d22010-06-08 16:52:24 +0000488 optreset = 1;
489 optind = 1;
Eli Friedmanef2bc872010-06-13 19:18:49 +0000490#endif
Chris Lattner24943d22010-06-08 16:52:24 +0000491 int val;
492 while (1)
493 {
494 int long_options_index = -1;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000495 val = ::getopt_long (argc, const_cast<char **>(argv), option_string.c_str(), long_options, &long_options_index);
Chris Lattner24943d22010-06-08 16:52:24 +0000496
497 if (val == -1)
498 break;
499 else if (val == '?')
500 {
Greg Clayton63094e02010-06-23 01:19:29 +0000501 m_option_data.m_print_help = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000502 error.SetErrorStringWithFormat ("unknown or ambiguous option");
503 break;
504 }
505 else if (val == 0)
506 continue;
507 else
508 {
Greg Clayton63094e02010-06-23 01:19:29 +0000509 m_option_data.m_seen_options.insert ((char) val);
Chris Lattner24943d22010-06-08 16:52:24 +0000510 if (long_options_index == -1)
511 {
512 for (int i = 0;
513 long_options[i].name || long_options[i].has_arg || long_options[i].flag || long_options[i].val;
514 ++i)
515 {
516 if (long_options[i].val == val)
517 {
518 long_options_index = i;
519 break;
520 }
521 }
522 }
523
524 if (long_options_index >= 0)
525 {
Greg Clayton63094e02010-06-23 01:19:29 +0000526 const char short_option = (char) g_options[long_options_index].short_option;
527
528 switch (short_option)
529 {
530 case 'h':
531 m_option_data.m_print_help = true;
532 break;
533
534 case 'v':
535 m_option_data.m_print_version = true;
536 break;
537
538 case 'c':
539 m_option_data.m_crash_log = optarg;
540 break;
Greg Clayton887aa282010-10-11 01:05:37 +0000541
Jim Ingham74989e82010-08-30 19:44:40 +0000542 case 'e':
543 m_option_data.m_use_external_editor = true;
544 break;
Greg Clayton887aa282010-10-11 01:05:37 +0000545
546 case 'n':
547 m_debugger.SkipLLDBInitFiles (true);
548 break;
549
Greg Clayton63094e02010-06-23 01:19:29 +0000550 case 'f':
551 {
552 SBFileSpec file(optarg);
553 if (file.Exists())
Greg Clayton4dc18922010-12-08 22:23:24 +0000554 {
555 m_option_data.m_args.push_back (optarg);
556 }
Caroline Ticeeddffe92010-09-10 04:48:55 +0000557 else if (file.ResolveExecutableLocation())
558 {
559 char path[PATH_MAX];
560 int path_len;
561 file.GetPath (path, path_len);
Greg Clayton4dc18922010-12-08 22:23:24 +0000562 m_option_data.m_args.push_back (path);
Caroline Ticeeddffe92010-09-10 04:48:55 +0000563 }
Greg Clayton63094e02010-06-23 01:19:29 +0000564 else
565 error.SetErrorStringWithFormat("file specified in --file (-f) option doesn't exist: '%s'", optarg);
566 }
567 break;
568
569 case 'a':
570 if (!m_debugger.SetDefaultArchitecture (optarg))
571 error.SetErrorStringWithFormat("invalid architecture in the -a or --arch option: '%s'", optarg);
572 break;
573
574 case 'l':
575 m_option_data.m_script_lang = m_debugger.GetScriptingLanguage (optarg);
576 break;
577
578 case 'd':
579 m_option_data.m_debug_mode = true;
580 break;
581
582 case 's':
583 {
584 SBFileSpec file(optarg);
585 if (file.Exists())
586 m_option_data.m_source_command_files.push_back (optarg);
Caroline Ticeeddffe92010-09-10 04:48:55 +0000587 else if (file.ResolveExecutableLocation())
588 {
589 char final_path[PATH_MAX];
590 size_t path_len;
591 file.GetPath (final_path, path_len);
592 std::string path_str (final_path);
593 m_option_data.m_source_command_files.push_back (path_str);
594 }
Greg Clayton63094e02010-06-23 01:19:29 +0000595 else
596 error.SetErrorStringWithFormat("file specified in --source (-s) option doesn't exist: '%s'", optarg);
597 }
598 break;
599
600 default:
601 m_option_data.m_print_help = true;
602 error.SetErrorStringWithFormat ("unrecognized option %c", short_option);
603 break;
604 }
Chris Lattner24943d22010-06-08 16:52:24 +0000605 }
606 else
607 {
608 error.SetErrorStringWithFormat ("invalid option with value %i", val);
609 }
610 if (error.Fail())
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000611 {
Greg Clayton63094e02010-06-23 01:19:29 +0000612 return error;
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000613 }
Chris Lattner24943d22010-06-08 16:52:24 +0000614 }
615 }
Jim Ingham34e9a982010-06-15 18:47:14 +0000616
Greg Clayton63094e02010-06-23 01:19:29 +0000617 if (error.Fail() || m_option_data.m_print_help)
Chris Lattner24943d22010-06-08 16:52:24 +0000618 {
619 ShowUsage (out_fh, g_options, m_option_data);
Greg Clayton9caa9462010-10-11 01:13:37 +0000620 exit = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000621 }
622 else if (m_option_data.m_print_version)
623 {
Greg Clayton63094e02010-06-23 01:19:29 +0000624 ::fprintf (out_fh, "%s\n", m_debugger.GetVersionString());
625 exit = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000626 }
627 else if (! m_option_data.m_crash_log.empty())
628 {
629 // Handle crash log stuff here.
630 }
631 else
632 {
Greg Clayton4dc18922010-12-08 22:23:24 +0000633 // Any arguments that are left over after option parsing are for
634 // the program. If a file was specified with -f then the filename
635 // is already in the m_option_data.m_args array, and any remaining args
636 // are arguments for the inferior program. If no file was specified with
637 // -f, then what is left is the program name followed by any arguments.
638
639 // Skip any options we consumed with getopt_long
640 argc -= optind;
641 argv += optind;
642
643 if (argc > 0)
644 {
645 for (int arg_idx=0; arg_idx<argc; ++arg_idx)
646 {
647 const char *arg = argv[arg_idx];
648 if (arg)
649 m_option_data.m_args.push_back (arg);
650 }
651 }
652
Chris Lattner24943d22010-06-08 16:52:24 +0000653 }
654
Greg Clayton63094e02010-06-23 01:19:29 +0000655 return error;
Chris Lattner24943d22010-06-08 16:52:24 +0000656}
657
Caroline Tice757500e2010-09-29 18:35:42 +0000658size_t
Chris Lattner24943d22010-06-08 16:52:24 +0000659Driver::GetProcessSTDOUT ()
660{
661 // The process has stuff waiting for stdout; get it and write it out to the appropriate place.
662 char stdio_buffer[1024];
663 size_t len;
Caroline Tice757500e2010-09-29 18:35:42 +0000664 size_t total_bytes = 0;
Jim Inghamc8332952010-08-26 21:32:51 +0000665 while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0)
Caroline Tice757500e2010-09-29 18:35:42 +0000666 {
Chris Lattner24943d22010-06-08 16:52:24 +0000667 m_io_channel_ap->OutWrite (stdio_buffer, len);
Caroline Tice757500e2010-09-29 18:35:42 +0000668 total_bytes += len;
669 }
670 return total_bytes;
Chris Lattner24943d22010-06-08 16:52:24 +0000671}
672
Caroline Tice757500e2010-09-29 18:35:42 +0000673size_t
Chris Lattner24943d22010-06-08 16:52:24 +0000674Driver::GetProcessSTDERR ()
675{
676 // The process has stuff waiting for stderr; get it and write it out to the appropriate place.
677 char stdio_buffer[1024];
678 size_t len;
Caroline Tice757500e2010-09-29 18:35:42 +0000679 size_t total_bytes = 0;
Jim Inghamc8332952010-08-26 21:32:51 +0000680 while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0)
Caroline Tice757500e2010-09-29 18:35:42 +0000681 {
Chris Lattner24943d22010-06-08 16:52:24 +0000682 m_io_channel_ap->ErrWrite (stdio_buffer, len);
Caroline Tice757500e2010-09-29 18:35:42 +0000683 total_bytes += len;
684 }
685 return total_bytes;
Chris Lattner24943d22010-06-08 16:52:24 +0000686}
687
688void
Jim Inghamc8332952010-08-26 21:32:51 +0000689Driver::UpdateSelectedThread ()
Chris Lattner24943d22010-06-08 16:52:24 +0000690{
691 using namespace lldb;
Jim Inghamc8332952010-08-26 21:32:51 +0000692 SBProcess process(m_debugger.GetSelectedTarget().GetProcess());
Chris Lattner24943d22010-06-08 16:52:24 +0000693 if (process.IsValid())
694 {
Jim Inghamc8332952010-08-26 21:32:51 +0000695 SBThread curr_thread (process.GetSelectedThread());
Chris Lattner24943d22010-06-08 16:52:24 +0000696 SBThread thread;
697 StopReason curr_thread_stop_reason = eStopReasonInvalid;
698 curr_thread_stop_reason = curr_thread.GetStopReason();
699
700 if (!curr_thread.IsValid() ||
701 curr_thread_stop_reason == eStopReasonInvalid ||
702 curr_thread_stop_reason == eStopReasonNone)
703 {
704 // Prefer a thread that has just completed its plan over another thread as current thread.
705 SBThread plan_thread;
706 SBThread other_thread;
707 const size_t num_threads = process.GetNumThreads();
708 size_t i;
709 for (i = 0; i < num_threads; ++i)
710 {
711 thread = process.GetThreadAtIndex(i);
712 StopReason thread_stop_reason = thread.GetStopReason();
713 switch (thread_stop_reason)
714 {
715 default:
716 case eStopReasonInvalid:
717 case eStopReasonNone:
718 break;
719
720 case eStopReasonTrace:
721 case eStopReasonBreakpoint:
722 case eStopReasonWatchpoint:
723 case eStopReasonSignal:
724 case eStopReasonException:
725 if (!other_thread.IsValid())
726 other_thread = thread;
727 break;
728 case eStopReasonPlanComplete:
729 if (!plan_thread.IsValid())
730 plan_thread = thread;
731 break;
732 }
733 }
734 if (plan_thread.IsValid())
Jim Inghamc8332952010-08-26 21:32:51 +0000735 process.SetSelectedThread (plan_thread);
Chris Lattner24943d22010-06-08 16:52:24 +0000736 else if (other_thread.IsValid())
Jim Inghamc8332952010-08-26 21:32:51 +0000737 process.SetSelectedThread (other_thread);
Chris Lattner24943d22010-06-08 16:52:24 +0000738 else
739 {
740 if (curr_thread.IsValid())
741 thread = curr_thread;
742 else
743 thread = process.GetThreadAtIndex(0);
744
745 if (thread.IsValid())
Jim Inghamc8332952010-08-26 21:32:51 +0000746 process.SetSelectedThread (thread);
Chris Lattner24943d22010-06-08 16:52:24 +0000747 }
748 }
749 }
750}
751
752
753// This function handles events that were broadcast by the process.
754void
755Driver::HandleProcessEvent (const SBEvent &event)
756{
757 using namespace lldb;
758 const uint32_t event_type = event.GetType();
759
760 if (event_type & SBProcess::eBroadcastBitSTDOUT)
761 {
762 // The process has stdout available, get it and write it out to the
763 // appropriate place.
Caroline Tice757500e2010-09-29 18:35:42 +0000764 if (GetProcessSTDOUT ())
765 m_io_channel_ap->RefreshPrompt();
Chris Lattner24943d22010-06-08 16:52:24 +0000766 }
767 else if (event_type & SBProcess::eBroadcastBitSTDERR)
768 {
769 // The process has stderr available, get it and write it out to the
770 // appropriate place.
Caroline Tice757500e2010-09-29 18:35:42 +0000771 if (GetProcessSTDERR ())
772 m_io_channel_ap->RefreshPrompt();
Chris Lattner24943d22010-06-08 16:52:24 +0000773 }
774 else if (event_type & SBProcess::eBroadcastBitStateChanged)
775 {
776 // Drain all stout and stderr so we don't see any output come after
777 // we print our prompts
Caroline Tice757500e2010-09-29 18:35:42 +0000778 if (GetProcessSTDOUT ()
779 || GetProcessSTDERR ())
780 m_io_channel_ap->RefreshPrompt();
Chris Lattner24943d22010-06-08 16:52:24 +0000781
782 // Something changed in the process; get the event and report the process's current status and location to
783 // the user.
784 StateType event_state = SBProcess::GetStateFromEvent (event);
785 if (event_state == eStateInvalid)
786 return;
787
788 SBProcess process (SBProcess::GetProcessFromEvent (event));
789 assert (process.IsValid());
790
791 switch (event_state)
792 {
793 case eStateInvalid:
794 case eStateUnloaded:
Greg Claytone71e2582011-02-04 01:58:07 +0000795 case eStateConnected:
Chris Lattner24943d22010-06-08 16:52:24 +0000796 case eStateAttaching:
797 case eStateLaunching:
798 case eStateStepping:
799 case eStateDetached:
800 {
801 char message[1024];
802 int message_len = ::snprintf (message, sizeof(message), "Process %d %s\n", process.GetProcessID(),
Greg Clayton63094e02010-06-23 01:19:29 +0000803 m_debugger.StateAsCString (event_state));
Chris Lattner24943d22010-06-08 16:52:24 +0000804 m_io_channel_ap->OutWrite(message, message_len);
805 }
806 break;
807
808 case eStateRunning:
809 // Don't be chatty when we run...
810 break;
811
812 case eStateExited:
Caroline Tice757500e2010-09-29 18:35:42 +0000813 {
814 SBCommandReturnObject result;
815 m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
816 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize());
817 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize());
818 m_io_channel_ap->RefreshPrompt();
819 }
Chris Lattner24943d22010-06-08 16:52:24 +0000820 break;
821
822 case eStateStopped:
823 case eStateCrashed:
824 case eStateSuspended:
825 // Make sure the program hasn't been auto-restarted:
826 if (SBProcess::GetRestartedFromEvent (event))
827 {
828 // FIXME: Do we want to report this, or would that just be annoyingly chatty?
829 char message[1024];
830 int message_len = ::snprintf (message, sizeof(message), "Process %d stopped and was programmatically restarted.\n",
831 process.GetProcessID());
832 m_io_channel_ap->OutWrite(message, message_len);
Caroline Tice757500e2010-09-29 18:35:42 +0000833 m_io_channel_ap->RefreshPrompt ();
Chris Lattner24943d22010-06-08 16:52:24 +0000834 }
835 else
836 {
Caroline Tice757500e2010-09-29 18:35:42 +0000837 SBCommandReturnObject result;
Jim Inghamc8332952010-08-26 21:32:51 +0000838 UpdateSelectedThread ();
Caroline Tice757500e2010-09-29 18:35:42 +0000839 m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
840 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize());
841 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize());
842 m_io_channel_ap->RefreshPrompt ();
Chris Lattner24943d22010-06-08 16:52:24 +0000843 }
844 break;
845 }
846 }
847}
848
849// This function handles events broadcast by the IOChannel (HasInput, UserInterrupt, or ThreadShouldExit).
850
851bool
852Driver::HandleIOEvent (const SBEvent &event)
853{
854 bool quit = false;
855
856 const uint32_t event_type = event.GetType();
857
858 if (event_type & IOChannel::eBroadcastBitHasUserInput)
859 {
860 // We got some input (i.e. a command string) from the user; pass it off to the command interpreter for
861 // handling.
862
863 const char *command_string = SBEvent::GetCStringFromEvent(event);
864 if (command_string == NULL)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000865 command_string = "";
Chris Lattner24943d22010-06-08 16:52:24 +0000866 SBCommandReturnObject result;
Jim Ingham2e8cb8a2011-02-19 02:53:09 +0000867 result.SetImmediateOutputFile (m_debugger.GetOutputFileHandle());
868 result.SetImmediateErrorFile (m_debugger.GetErrorFileHandle());
869
870 // We've set the result to dump immediately.
871 m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, true);
872
Chris Lattner24943d22010-06-08 16:52:24 +0000873 // We are done getting and running our command, we can now clear the
874 // m_waiting_for_command so we can get another one.
875 m_waiting_for_command = false;
876
877 // If our editline input reader is active, it means another input reader
878 // got pushed onto the input reader and caused us to become deactivated.
879 // When the input reader above us gets popped, we will get re-activated
880 // and our prompt will refresh in our callback
881 if (m_editline_reader.IsActive())
882 {
883 ReadyForCommand ();
884 }
885 }
886 else if (event_type & IOChannel::eBroadcastBitUserInterrupt)
887 {
888 // This is here to handle control-c interrupts from the user. It has not yet really been implemented.
889 // TO BE DONE: PROPERLY HANDLE CONTROL-C FROM USER
890 //m_io_channel_ap->CancelInput();
891 // Anything else? Send Interrupt to process?
892 }
893 else if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
894 (event_type & IOChannel::eBroadcastBitThreadDidExit))
895 {
896 // If the IOChannel thread is trying to go away, then it is definitely
897 // time to end the debugging session.
898 quit = true;
899 }
900
901 return quit;
902}
903
904
905//struct CrashImageInfo
906//{
907// std::string path;
908// VMRange text_range;
Greg Clayton0467c782011-02-04 18:53:10 +0000909// lldb_private::UUID uuid;
Chris Lattner24943d22010-06-08 16:52:24 +0000910//};
911//
912//void
913//Driver::ParseCrashLog (const char *crash_log)
914//{
915// printf("Parsing crash log: %s\n", crash_log);
916//
917// char image_path[PATH_MAX];
918// std::vector<CrashImageInfo> crash_infos;
919// if (crash_log && crash_log[0])
920// {
921// FileSpec crash_log_file (crash_log);
922// STLStringArray crash_log_lines;
923// if (crash_log_file.ReadFileLines (crash_log_lines))
924// {
925// const size_t num_crash_log_lines = crash_log_lines.size();
926// size_t i;
927// for (i=0; i<num_crash_log_lines; ++i)
928// {
929// const char *line = crash_log_lines[i].c_str();
930// if (strstr (line, "Code Type:"))
931// {
932// char arch_string[256];
933// if (sscanf(line, "%s", arch_string))
934// {
935// if (strcmp(arch_string, "X86-64"))
936// lldb::GetDefaultArchitecture ().SetArch ("x86_64");
937// else if (strcmp(arch_string, "X86"))
938// lldb::GetDefaultArchitecture ().SetArch ("i386");
939// else
940// {
941// ArchSpec arch(arch_string);
942// if (arch.IsValid ())
943// lldb::GetDefaultArchitecture () = arch;
944// else
945// fprintf(stderr, "Unrecognized architecture: %s\n", arch_string);
946// }
947// }
948// }
949// else
950// if (strstr(line, "Path:"))
951// {
952// const char *p = line + strlen("Path:");
953// while (isspace(*p))
954// ++p;
955//
956// m_option_data.m_filename.assign (p);
957// }
958// else
959// if (strstr(line, "Binary Images:"))
960// {
961// while (++i < num_crash_log_lines)
962// {
963// if (crash_log_lines[i].empty())
964// break;
965//
966// line = crash_log_lines[i].c_str();
967// uint64_t text_start_addr;
968// uint64_t text_end_addr;
969// char uuid_cstr[64];
970// int bytes_consumed_before_uuid = 0;
971// int bytes_consumed_after_uuid = 0;
972//
973// int items_parsed = ::sscanf (line,
974// "%llx - %llx %*s %*s %*s %n%s %n",
975// &text_start_addr,
976// &text_end_addr,
977// &bytes_consumed_before_uuid,
978// uuid_cstr,
979// &bytes_consumed_after_uuid);
980//
981// if (items_parsed == 3)
982// {
983//
984// CrashImageInfo info;
985// info.text_range.SetBaseAddress(text_start_addr);
986// info.text_range.SetEndAddress(text_end_addr);
987//
988// if (uuid_cstr[0] == '<')
989// {
990// if (info.uuid.SetfromCString (&uuid_cstr[1]) == 0)
991// info.uuid.Clear();
992//
993// ::strncpy (image_path, line + bytes_consumed_after_uuid, sizeof(image_path));
994// }
995// else
996// {
997// ::strncpy (image_path, line + bytes_consumed_before_uuid, sizeof(image_path));
998// }
999//
1000// info.path = image_path;
1001//
1002// crash_infos.push_back (info);
1003//
1004// info.uuid.GetAsCString(uuid_cstr, sizeof(uuid_cstr));
1005//
1006// printf("0x%16.16llx - 0x%16.16llx <%s> %s\n",
1007// text_start_addr,
1008// text_end_addr,
1009// uuid_cstr,
1010// image_path);
1011// }
1012// }
1013// }
1014// }
1015// }
1016//
1017// if (crash_infos.size())
1018// {
Greg Clayton63094e02010-06-23 01:19:29 +00001019// SBTarget target (m_debugger.CreateTarget (crash_infos.front().path.c_str(),
Chris Lattner24943d22010-06-08 16:52:24 +00001020// lldb::GetDefaultArchitecture().AsCString (),
1021// false));
1022// if (target.IsValid())
1023// {
1024//
1025// }
1026// }
1027// }
1028//}
1029//
1030
1031void
1032Driver::MasterThreadBytesReceived (void *baton, const void *src, size_t src_len)
1033{
1034 Driver *driver = (Driver*)baton;
1035 driver->GetFromMaster ((const char *)src, src_len);
1036}
1037
1038void
1039Driver::GetFromMaster (const char *src, size_t src_len)
1040{
1041 // Echo the characters back to the Debugger's stdout, that way if you
1042 // type characters while a command is running, you'll see what you've typed.
Greg Clayton63094e02010-06-23 01:19:29 +00001043 FILE *out_fh = m_debugger.GetOutputFileHandle();
Chris Lattner24943d22010-06-08 16:52:24 +00001044 if (out_fh)
1045 ::fwrite (src, 1, src_len, out_fh);
1046}
1047
1048size_t
1049Driver::EditLineInputReaderCallback
1050(
1051 void *baton,
1052 SBInputReader *reader,
1053 InputReaderAction notification,
1054 const char *bytes,
1055 size_t bytes_len
1056)
1057{
1058 Driver *driver = (Driver *)baton;
1059
1060 switch (notification)
1061 {
1062 case eInputReaderActivate:
1063 break;
1064
1065 case eInputReaderReactivate:
1066 driver->ReadyForCommand();
1067 break;
1068
1069 case eInputReaderDeactivate:
1070 break;
1071
Caroline Ticec4f55fe2010-11-19 20:47:54 +00001072 case eInputReaderInterrupt:
1073 if (driver->m_io_channel_ap.get() != NULL)
1074 {
1075 driver->m_io_channel_ap->OutWrite ("^C\n", 3);
1076 driver->m_io_channel_ap->RefreshPrompt();
1077 }
1078 break;
1079
1080 case eInputReaderEndOfFile:
1081 if (driver->m_io_channel_ap.get() != NULL)
1082 {
1083 driver->m_io_channel_ap->OutWrite ("^D\n", 3);
1084 driver->m_io_channel_ap->RefreshPrompt ();
1085 }
1086 write (driver->m_editline_pty.GetMasterFileDescriptor(), "quit\n", 5);
1087 break;
1088
Chris Lattner24943d22010-06-08 16:52:24 +00001089 case eInputReaderGotToken:
1090 write (driver->m_editline_pty.GetMasterFileDescriptor(), bytes, bytes_len);
1091 break;
1092
1093 case eInputReaderDone:
1094 break;
1095 }
1096 return bytes_len;
1097}
1098
1099void
1100Driver::MainLoop ()
1101{
1102 char error_str[1024];
1103 if (m_editline_pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, error_str, sizeof(error_str)) == false)
1104 {
1105 ::fprintf (stderr, "error: failed to open driver pseudo terminal : %s", error_str);
1106 exit(1);
1107 }
1108 else
1109 {
1110 const char *driver_slave_name = m_editline_pty.GetSlaveName (error_str, sizeof(error_str));
1111 if (driver_slave_name == NULL)
1112 {
1113 ::fprintf (stderr, "error: failed to get slave name for driver pseudo terminal : %s", error_str);
1114 exit(2);
1115 }
1116 else
1117 {
1118 m_editline_slave_fh = ::fopen (driver_slave_name, "r+");
1119 if (m_editline_slave_fh == NULL)
1120 {
1121 SBError error;
1122 error.SetErrorToErrno();
1123 ::fprintf (stderr, "error: failed to get open slave for driver pseudo terminal : %s",
1124 error.GetCString());
1125 exit(3);
1126 }
1127
1128 ::setbuf (m_editline_slave_fh, NULL);
1129 }
1130 }
1131
1132
1133 // struct termios stdin_termios;
1134
1135 if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0)
1136 atexit (reset_stdin_termios);
1137
1138 ::setbuf (stdin, NULL);
1139 ::setbuf (stdout, NULL);
1140
Greg Clayton63094e02010-06-23 01:19:29 +00001141 m_debugger.SetErrorFileHandle (stderr, false);
1142 m_debugger.SetOutputFileHandle (stdout, false);
1143 m_debugger.SetInputFileHandle (stdin, true);
Jim Ingham74989e82010-08-30 19:44:40 +00001144
1145 m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor);
Chris Lattner24943d22010-06-08 16:52:24 +00001146
1147 // You have to drain anything that comes to the master side of the PTY. master_out_comm is
1148 // for that purpose. The reason you need to do this is a curious reason... editline will echo
1149 // characters to the PTY when it gets characters while el_gets is not running, and then when
1150 // you call el_gets (or el_getc) it will try to reset the terminal back to raw mode which blocks
1151 // if there are unconsumed characters in the out buffer.
1152 // However, you don't need to do anything with the characters, since editline will dump these
1153 // unconsumed characters after printing the prompt again in el_gets.
1154
Greg Claytoneecb0f32010-12-04 02:39:47 +00001155 SBCommunication master_out_comm("driver.editline");
1156 master_out_comm.SetCloseOnEOF (false);
Chris Lattner24943d22010-06-08 16:52:24 +00001157 master_out_comm.AdoptFileDesriptor(m_editline_pty.GetMasterFileDescriptor(), false);
1158 master_out_comm.SetReadThreadBytesReceivedCallback(Driver::MasterThreadBytesReceived, this);
1159
1160 if (master_out_comm.ReadThreadStart () == false)
1161 {
1162 ::fprintf (stderr, "error: failed to start master out read thread");
1163 exit(5);
1164 }
1165
1166// const char *crash_log = GetCrashLogFilename();
1167// if (crash_log)
1168// {
1169// ParseCrashLog (crash_log);
1170// }
1171//
Greg Clayton63094e02010-06-23 01:19:29 +00001172 SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter();
Chris Lattner24943d22010-06-08 16:52:24 +00001173
1174 m_io_channel_ap.reset (new IOChannel(m_editline_slave_fh, stdout, stderr, this));
1175
1176 struct winsize window_size;
1177 if (isatty (STDIN_FILENO)
1178 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
1179 {
Caroline Tice6e4c5ce2010-09-04 00:03:46 +00001180 if (window_size.ws_col > 0)
Greg Clayton238c0a12010-09-18 01:14:36 +00001181 m_debugger.SetTerminalWidth (window_size.ws_col);
Chris Lattner24943d22010-06-08 16:52:24 +00001182 }
1183
1184 // Since input can be redirected by the debugger, we must insert our editline
1185 // input reader in the queue so we know when our reader should be active
1186 // and so we can receive bytes only when we are supposed to.
Greg Clayton63094e02010-06-23 01:19:29 +00001187 SBError err (m_editline_reader.Initialize (m_debugger,
1188 Driver::EditLineInputReaderCallback, // callback
Chris Lattner24943d22010-06-08 16:52:24 +00001189 this, // baton
1190 eInputReaderGranularityByte, // token_size
1191 NULL, // end token - NULL means never done
1192 NULL, // prompt - taken care of elsewhere
1193 false)); // echo input - don't need Debugger
1194 // to do this, we handle it elsewhere
1195
1196 if (err.Fail())
1197 {
1198 ::fprintf (stderr, "error: %s", err.GetCString());
1199 exit (6);
1200 }
1201
Greg Clayton63094e02010-06-23 01:19:29 +00001202 m_debugger.PushInputReader (m_editline_reader);
Chris Lattner24943d22010-06-08 16:52:24 +00001203
Greg Clayton63094e02010-06-23 01:19:29 +00001204 SBListener listener(m_debugger.GetListener());
Chris Lattner24943d22010-06-08 16:52:24 +00001205 if (listener.IsValid())
1206 {
1207
1208 listener.StartListeningForEvents (*m_io_channel_ap,
1209 IOChannel::eBroadcastBitHasUserInput |
1210 IOChannel::eBroadcastBitUserInterrupt |
1211 IOChannel::eBroadcastBitThreadShouldExit |
1212 IOChannel::eBroadcastBitThreadDidStart |
1213 IOChannel::eBroadcastBitThreadDidExit);
1214
1215 if (m_io_channel_ap->Start ())
1216 {
1217 bool iochannel_thread_exited = false;
1218
1219 listener.StartListeningForEvents (sb_interpreter.GetBroadcaster(),
1220 SBCommandInterpreter::eBroadcastBitQuitCommandReceived);
1221
1222 // Before we handle any options from the command line, we parse the
1223 // .lldbinit file in the user's home directory.
1224 SBCommandReturnObject result;
1225 sb_interpreter.SourceInitFileInHomeDirectory(result);
1226 if (GetDebugMode())
1227 {
Greg Clayton63094e02010-06-23 01:19:29 +00001228 result.PutError (m_debugger.GetErrorFileHandle());
1229 result.PutOutput (m_debugger.GetOutputFileHandle());
Chris Lattner24943d22010-06-08 16:52:24 +00001230 }
1231
1232 // Now we handle options we got from the command line
1233 char command_string[PATH_MAX * 2];
1234 const size_t num_source_command_files = GetNumSourceCommandFiles();
1235 if (num_source_command_files > 0)
1236 {
1237 for (size_t i=0; i < num_source_command_files; ++i)
1238 {
1239 const char *command_file = GetSourceCommandFileAtIndex(i);
Johnny Chen7c984242010-07-28 21:16:11 +00001240 ::snprintf (command_string, sizeof(command_string), "command source '%s'", command_file);
Greg Clayton63094e02010-06-23 01:19:29 +00001241 m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, false);
Chris Lattner24943d22010-06-08 16:52:24 +00001242 if (GetDebugMode())
1243 {
Greg Clayton63094e02010-06-23 01:19:29 +00001244 result.PutError (m_debugger.GetErrorFileHandle());
1245 result.PutOutput (m_debugger.GetOutputFileHandle());
Chris Lattner24943d22010-06-08 16:52:24 +00001246 }
1247 }
1248 }
1249
Greg Clayton4dc18922010-12-08 22:23:24 +00001250 const size_t num_args = m_option_data.m_args.size();
1251 if (num_args > 0)
Chris Lattner24943d22010-06-08 16:52:24 +00001252 {
1253 char arch_name[64];
Greg Clayton63094e02010-06-23 01:19:29 +00001254 if (m_debugger.GetDefaultArchitecture (arch_name, sizeof (arch_name)))
Greg Clayton4dc18922010-12-08 22:23:24 +00001255 ::snprintf (command_string,
1256 sizeof (command_string),
1257 "file --arch=%s '%s'",
1258 arch_name,
1259 m_option_data.m_args[0].c_str());
Chris Lattner24943d22010-06-08 16:52:24 +00001260 else
Greg Clayton4dc18922010-12-08 22:23:24 +00001261 ::snprintf (command_string,
1262 sizeof(command_string),
1263 "file '%s'",
1264 m_option_data.m_args[0].c_str());
Chris Lattner24943d22010-06-08 16:52:24 +00001265
Greg Clayton63094e02010-06-23 01:19:29 +00001266 m_debugger.HandleCommand (command_string);
Greg Clayton4dc18922010-12-08 22:23:24 +00001267
1268 if (num_args > 1)
1269 {
1270 m_debugger.HandleCommand ("settings clear target.process.run-args");
1271 char arg_cstr[1024];
1272 for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx)
1273 {
1274 ::snprintf (arg_cstr, sizeof(arg_cstr), "settings append target.process.run-args \"%s\"", m_option_data.m_args[arg_idx].c_str());
1275 m_debugger.HandleCommand (arg_cstr);
1276 }
1277 }
Chris Lattner24943d22010-06-08 16:52:24 +00001278 }
1279
1280 // Now that all option parsing is done, we try and parse the .lldbinit
1281 // file in the current working directory
1282 sb_interpreter.SourceInitFileInCurrentWorkingDirectory (result);
1283 if (GetDebugMode())
1284 {
Greg Clayton63094e02010-06-23 01:19:29 +00001285 result.PutError(m_debugger.GetErrorFileHandle());
1286 result.PutOutput(m_debugger.GetOutputFileHandle());
Chris Lattner24943d22010-06-08 16:52:24 +00001287 }
1288
1289 SBEvent event;
1290
1291 // Make sure the IO channel is started up before we try to tell it we
1292 // are ready for input
1293 listener.WaitForEventForBroadcasterWithType (UINT32_MAX,
1294 *m_io_channel_ap,
1295 IOChannel::eBroadcastBitThreadDidStart,
1296 event);
1297
1298 ReadyForCommand ();
1299
1300 bool done = false;
1301 while (!done)
1302 {
1303 listener.WaitForEvent (UINT32_MAX, event);
1304 if (event.IsValid())
1305 {
1306 if (event.GetBroadcaster().IsValid())
1307 {
1308 uint32_t event_type = event.GetType();
1309 if (event.BroadcasterMatchesRef (*m_io_channel_ap))
1310 {
1311 if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
1312 (event_type & IOChannel::eBroadcastBitThreadDidExit))
1313 {
1314 done = true;
1315 if (event_type & IOChannel::eBroadcastBitThreadDidExit)
1316 iochannel_thread_exited = true;
1317 break;
1318 }
1319 else
1320 done = HandleIOEvent (event);
1321 }
Jim Inghamc8332952010-08-26 21:32:51 +00001322 else if (event.BroadcasterMatchesRef (m_debugger.GetSelectedTarget().GetProcess().GetBroadcaster()))
Chris Lattner24943d22010-06-08 16:52:24 +00001323 {
1324 HandleProcessEvent (event);
1325 }
1326 else if (event.BroadcasterMatchesRef (sb_interpreter.GetBroadcaster()))
1327 {
1328 if (event_type & SBCommandInterpreter::eBroadcastBitQuitCommandReceived)
1329 done = true;
1330 }
1331 }
1332 }
1333 }
1334
1335 reset_stdin_termios ();
1336
1337 CloseIOChannelFile ();
1338
1339 if (!iochannel_thread_exited)
1340 {
Greg Claytonbef15832010-07-14 00:18:15 +00001341 event.Clear();
Chris Lattner24943d22010-06-08 16:52:24 +00001342 listener.GetNextEventForBroadcasterWithType (*m_io_channel_ap,
1343 IOChannel::eBroadcastBitThreadDidExit,
1344 event);
1345 if (!event.IsValid())
1346 {
1347 // Send end EOF to the driver file descriptor
1348 m_io_channel_ap->Stop();
1349 }
1350 }
1351
Jim Inghamc8332952010-08-26 21:32:51 +00001352 SBProcess process = m_debugger.GetSelectedTarget().GetProcess();
Chris Lattner24943d22010-06-08 16:52:24 +00001353 if (process.IsValid())
1354 process.Destroy();
1355 }
1356 }
1357}
1358
1359
1360void
1361Driver::ReadyForCommand ()
1362{
1363 if (m_waiting_for_command == false)
1364 {
1365 m_waiting_for_command = true;
1366 BroadcastEventByType (Driver::eBroadcastBitReadyForInput, true);
1367 }
1368}
1369
1370
Caroline Ticeb8314fe2010-09-09 17:45:09 +00001371void
1372sigwinch_handler (int signo)
1373{
1374 struct winsize window_size;
1375 if (isatty (STDIN_FILENO)
1376 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
1377 {
1378 if ((window_size.ws_col > 0) && (strlen (g_debugger_name) > 0))
1379 {
1380 char width_str_buffer[25];
1381 ::sprintf (width_str_buffer, "%d", window_size.ws_col);
1382 SBDebugger::SetInternalVariable ("term-width", width_str_buffer, g_debugger_name);
1383 }
1384 }
1385}
1386
Caroline Ticec4f55fe2010-11-19 20:47:54 +00001387void
1388sigint_handler (int signo)
1389{
1390 static bool g_interrupt_sent = false;
1391 if (g_driver)
1392 {
1393 if (!g_interrupt_sent)
1394 {
1395 g_interrupt_sent = true;
1396 g_driver->GetDebugger().DispatchInputInterrupt();
1397 g_interrupt_sent = false;
1398 return;
1399 }
1400 }
1401
1402 exit (signo);
1403}
1404
Chris Lattner24943d22010-06-08 16:52:24 +00001405int
Jim Inghamb2b604f2011-01-27 20:15:39 +00001406main (int argc, char const *argv[], const char *envp[])
Chris Lattner24943d22010-06-08 16:52:24 +00001407{
Chris Lattner24943d22010-06-08 16:52:24 +00001408 SBDebugger::Initialize();
1409
Greg Clayton95e33b72010-11-07 21:02:03 +00001410 SBHostOS::ThreadCreated ("<lldb.driver.main-thread>");
Chris Lattner24943d22010-06-08 16:52:24 +00001411
Greg Clayton36f63a92010-10-19 03:25:40 +00001412 signal (SIGPIPE, SIG_IGN);
Caroline Ticeb8314fe2010-09-09 17:45:09 +00001413 signal (SIGWINCH, sigwinch_handler);
Caroline Ticec4f55fe2010-11-19 20:47:54 +00001414 signal (SIGINT, sigint_handler);
Caroline Ticeb8314fe2010-09-09 17:45:09 +00001415
Greg Clayton63094e02010-06-23 01:19:29 +00001416 // Create a scope for driver so that the driver object will destroy itself
1417 // before SBDebugger::Terminate() is called.
Chris Lattner24943d22010-06-08 16:52:24 +00001418 {
Greg Clayton63094e02010-06-23 01:19:29 +00001419 Driver driver;
1420
1421 bool exit = false;
1422 SBError error (driver.ParseArgs (argc, argv, stdout, exit));
1423 if (error.Fail())
1424 {
1425 const char *error_cstr = error.GetCString ();
1426 if (error_cstr)
1427 ::fprintf (stderr, "error: %s\n", error_cstr);
1428 }
1429 else if (!exit)
1430 {
1431 driver.MainLoop ();
1432 }
Chris Lattner24943d22010-06-08 16:52:24 +00001433 }
1434
1435 SBDebugger::Terminate();
1436 return 0;
1437}