blob: 3cf542ff4474becaa60c6beb2c9897f79df41295 [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"
33#include "lldb/API/SBTarget.h"
34#include "lldb/API/SBThread.h"
35#include "lldb/API/SBProcess.h"
Chris Lattner24943d22010-06-08 16:52:24 +000036
37using namespace lldb;
38
39static void reset_stdin_termios ();
40static struct termios g_old_stdin_termios;
41
Caroline Ticeb8314fe2010-09-09 17:45:09 +000042static char *g_debugger_name = (char *) "";
Caroline Ticec4f55fe2010-11-19 20:47:54 +000043static Driver *g_driver = NULL;
Caroline Ticeb8314fe2010-09-09 17:45:09 +000044
Chris Lattner24943d22010-06-08 16:52:24 +000045// In the Driver::MainLoop, we change the terminal settings. This function is
46// added as an atexit handler to make sure we clean them up.
47static void
48reset_stdin_termios ()
49{
50 ::tcsetattr (STDIN_FILENO, TCSANOW, &g_old_stdin_termios);
51}
52
53static lldb::OptionDefinition g_options[] =
54{
Caroline Tice4d6675c2010-10-01 19:59:14 +000055 { LLDB_OPT_SET_1, true, "help", 'h', no_argument, NULL, NULL, eArgTypeNone,
Chris Lattner24943d22010-06-08 16:52:24 +000056 "Prints out the usage information for the LLDB debugger." },
57
Caroline Tice4d6675c2010-10-01 19:59:14 +000058 { LLDB_OPT_SET_2, true, "version", 'v', no_argument, NULL, NULL, eArgTypeNone,
Chris Lattner24943d22010-06-08 16:52:24 +000059 "Prints out the current version number of the LLDB debugger." },
60
Caroline Tice4d6675c2010-10-01 19:59:14 +000061 { LLDB_OPT_SET_3, true, "arch", 'a', required_argument, NULL, NULL, eArgTypeArchitecture,
Chris Lattner24943d22010-06-08 16:52:24 +000062 "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." },
63
Caroline Tice4d6675c2010-10-01 19:59:14 +000064 { LLDB_OPT_SET_3 | LLDB_OPT_SET_4, false, "script-language",'l', required_argument, NULL, NULL, eArgTypeScriptLang,
Chris Lattner24943d22010-06-08 16:52:24 +000065 "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." },
66
Caroline Tice4d6675c2010-10-01 19:59:14 +000067 { LLDB_OPT_SET_3 | LLDB_OPT_SET_4, false, "debug", 'd', no_argument, NULL, NULL, eArgTypeNone,
Chris Lattner24943d22010-06-08 16:52:24 +000068 "Tells the debugger to print out extra information for debugging itself." },
69
Caroline Tice4d6675c2010-10-01 19:59:14 +000070 { LLDB_OPT_SET_3 | LLDB_OPT_SET_4, false, "source", 's', required_argument, NULL, NULL, eArgTypeFilename,
Chris Lattner24943d22010-06-08 16:52:24 +000071 "Tells the debugger to read in and execute the file <file>, which should contain lldb commands." },
72
Caroline Tice4d6675c2010-10-01 19:59:14 +000073 { LLDB_OPT_SET_3, true, "file", 'f', required_argument, NULL, NULL, eArgTypeFilename,
Jim Ingham34e9a982010-06-15 18:47:14 +000074 "Tells the debugger to use the file <filename> as the program to be debugged." },
75
Caroline Tice4d6675c2010-10-01 19:59:14 +000076 { LLDB_OPT_SET_ALL, false, "editor", 'e', no_argument, NULL, NULL, eArgTypeNone,
Jim Ingham74989e82010-08-30 19:44:40 +000077 "Tells the debugger to open source files using the host's \"external editor\" mechanism." },
78
Greg Clayton887aa282010-10-11 01:05:37 +000079 { LLDB_OPT_SET_ALL, false, "no-lldbinit", 'n', no_argument, NULL, NULL, eArgTypeNone,
80 "Do not automatically parse any '.lldbinit' files." },
81
Caroline Tice4d6675c2010-10-01 19:59:14 +000082// { LLDB_OPT_SET_4, true, "crash-log", 'c', required_argument, NULL, NULL, eArgTypeFilename,
Greg Clayton12bec712010-06-28 21:30:43 +000083// "Load executable images from a crash log for symbolication." },
Chris Lattner24943d22010-06-08 16:52:24 +000084
Caroline Tice4d6675c2010-10-01 19:59:14 +000085 { 0, false, NULL, 0, 0, NULL, NULL, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +000086};
87
88
89Driver::Driver () :
90 SBBroadcaster ("Driver"),
Greg Clayton63094e02010-06-23 01:19:29 +000091 m_debugger (SBDebugger::Create()),
Chris Lattner24943d22010-06-08 16:52:24 +000092 m_editline_pty (),
93 m_editline_slave_fh (NULL),
94 m_editline_reader (),
95 m_io_channel_ap (),
96 m_option_data (),
97 m_waiting_for_command (false)
98{
Caroline Ticeb8314fe2010-09-09 17:45:09 +000099 g_debugger_name = (char *) m_debugger.GetInstanceName();
100 if (g_debugger_name == NULL)
101 g_debugger_name = (char *) "";
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000102 g_driver = this;
Chris Lattner24943d22010-06-08 16:52:24 +0000103}
104
105Driver::~Driver ()
106{
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000107 g_driver = NULL;
108 g_debugger_name = NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000109}
110
111void
112Driver::CloseIOChannelFile ()
113{
114 // Write and End of File sequence to the file descriptor to ensure any
115 // read functions can exit.
116 char eof_str[] = "\x04";
117 ::write (m_editline_pty.GetMasterFileDescriptor(), eof_str, strlen(eof_str));
118
119 m_editline_pty.CloseMasterFileDescriptor();
120
121 if (m_editline_slave_fh)
122 {
123 ::fclose (m_editline_slave_fh);
124 m_editline_slave_fh = NULL;
125 }
126}
127
Greg Clayton54e7afa2010-07-09 20:39:50 +0000128// This function takes INDENT, which tells how many spaces to output at the front
129// of each line; TEXT, which is the text that is to be output. It outputs the
130// text, on multiple lines if necessary, to RESULT, with INDENT spaces at the
131// front of each line. It breaks lines on spaces, tabs or newlines, shortening
132// the line if necessary to not break in the middle of a word. It assumes that
133// each output line should contain a maximum of OUTPUT_MAX_COLUMNS characters.
Chris Lattner24943d22010-06-08 16:52:24 +0000134
135void
Greg Clayton54e7afa2010-07-09 20:39:50 +0000136OutputFormattedUsageText (FILE *out, int indent, const char *text, int output_max_columns)
Chris Lattner24943d22010-06-08 16:52:24 +0000137{
138 int len = strlen (text);
139 std::string text_string (text);
Chris Lattner24943d22010-06-08 16:52:24 +0000140
141 // Force indentation to be reasonable.
142 if (indent >= output_max_columns)
143 indent = 0;
144
145 // Will it all fit on one line?
146
147 if (len + indent < output_max_columns)
148 // Output as a single line
Greg Clayton54e7afa2010-07-09 20:39:50 +0000149 fprintf (out, "%*s%s\n", indent, "", text);
Chris Lattner24943d22010-06-08 16:52:24 +0000150 else
151 {
152 // We need to break it up into multiple lines.
153 int text_width = output_max_columns - indent - 1;
154 int start = 0;
155 int end = start;
156 int final_end = len;
157 int sub_len;
158
159 while (end < final_end)
160 {
161 // Dont start the 'text' on a space, since we're already outputting the indentation.
162 while ((start < final_end) && (text[start] == ' '))
163 start++;
164
165 end = start + text_width;
166 if (end > final_end)
167 end = final_end;
168 else
169 {
170 // If we're not at the end of the text, make sure we break the line on white space.
171 while (end > start
172 && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
173 end--;
174 }
175 sub_len = end - start;
176 std::string substring = text_string.substr (start, sub_len);
Greg Clayton54e7afa2010-07-09 20:39:50 +0000177 fprintf (out, "%*s%s\n", indent, "", substring.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000178 start = end + 1;
179 }
180 }
181}
182
Caroline Tice4d6675c2010-10-01 19:59:14 +0000183void
184GetArgumentName (const CommandArgumentType arg_type, std::string &arg_name)
185{
186 //Fudge this function here, since we can't call the "real" version in lldb_private::CommandObject...
187
188 switch (arg_type)
189 {
190 // Make cases for all the arg_types used in Driver.cpp
191
192 case eArgTypeNone:
193 arg_name = "";
194 break;
195
196 case eArgTypeArchitecture:
197 arg_name = "architecture";
198 break;
199
200 case eArgTypeScriptLang:
201 arg_name = "script-language";
202 break;
203
204 case eArgTypeFilename:
205 arg_name = "filename";
206 break;
207 }
208 return;
209}
210
211
Chris Lattner24943d22010-06-08 16:52:24 +0000212void
213ShowUsage (FILE *out, lldb::OptionDefinition *option_table, Driver::OptionData data)
214{
215 uint32_t screen_width = 80;
216 uint32_t indent_level = 0;
217 const char *name = "lldb";
Jim Ingham34e9a982010-06-15 18:47:14 +0000218
Chris Lattner24943d22010-06-08 16:52:24 +0000219 fprintf (out, "\nUsage:\n\n");
220
221 indent_level += 2;
222
223
224 // First, show each usage level set of options, e.g. <cmd> [options-for-level-0]
225 // <cmd> [options-for-level-1]
226 // etc.
227
Chris Lattner24943d22010-06-08 16:52:24 +0000228 uint32_t num_options;
Jim Ingham34e9a982010-06-15 18:47:14 +0000229 uint32_t num_option_sets = 0;
230
231 for (num_options = 0; option_table[num_options].long_option != NULL; ++num_options)
Chris Lattner24943d22010-06-08 16:52:24 +0000232 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000233 uint32_t this_usage_mask = option_table[num_options].usage_mask;
234 if (this_usage_mask == LLDB_OPT_SET_ALL)
Chris Lattner24943d22010-06-08 16:52:24 +0000235 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000236 if (num_option_sets == 0)
237 num_option_sets = 1;
Chris Lattner24943d22010-06-08 16:52:24 +0000238 }
239 else
240 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000241 for (uint32_t j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++)
Jim Ingham34e9a982010-06-15 18:47:14 +0000242 {
243 if (this_usage_mask & 1 << j)
244 {
245 if (num_option_sets <= j)
246 num_option_sets = j + 1;
247 }
248 }
249 }
250 }
251
252 for (uint32_t opt_set = 0; opt_set < num_option_sets; opt_set++)
253 {
254 uint32_t opt_set_mask;
255
256 opt_set_mask = 1 << opt_set;
257
258 if (opt_set > 0)
259 fprintf (out, "\n");
Greg Clayton54e7afa2010-07-09 20:39:50 +0000260 fprintf (out, "%*s%s", indent_level, "", name);
Jim Ingham34e9a982010-06-15 18:47:14 +0000261
262 for (uint32_t i = 0; i < num_options; ++i)
263 {
264 if (option_table[i].usage_mask & opt_set_mask)
265 {
Caroline Tice4d6675c2010-10-01 19:59:14 +0000266 CommandArgumentType arg_type = option_table[i].argument_type;
267 std::string arg_name;
268 GetArgumentName (arg_type, arg_name);
Jim Ingham34e9a982010-06-15 18:47:14 +0000269 if (option_table[i].required)
270 {
271 if (option_table[i].option_has_arg == required_argument)
Caroline Tice4d6675c2010-10-01 19:59:14 +0000272 fprintf (out, " -%c <%s>", option_table[i].short_option, arg_name.c_str());
Jim Ingham34e9a982010-06-15 18:47:14 +0000273 else if (option_table[i].option_has_arg == optional_argument)
Caroline Tice4d6675c2010-10-01 19:59:14 +0000274 fprintf (out, " -%c [<%s>]", option_table[i].short_option, arg_name.c_str());
Jim Ingham34e9a982010-06-15 18:47:14 +0000275 else
276 fprintf (out, " -%c", option_table[i].short_option);
277 }
278 else
279 {
280 if (option_table[i].option_has_arg == required_argument)
Caroline Tice4d6675c2010-10-01 19:59:14 +0000281 fprintf (out, " [-%c <%s>]", option_table[i].short_option, arg_name.c_str());
Jim Ingham34e9a982010-06-15 18:47:14 +0000282 else if (option_table[i].option_has_arg == optional_argument)
Caroline Tice4d6675c2010-10-01 19:59:14 +0000283 fprintf (out, " [-%c [<%s>]]", option_table[i].short_option, arg_name.c_str());
Jim Ingham34e9a982010-06-15 18:47:14 +0000284 else
285 fprintf (out, " [-%c]", option_table[i].short_option);
286 }
287 }
Chris Lattner24943d22010-06-08 16:52:24 +0000288 }
289 }
290
291 fprintf (out, "\n\n");
292
293 // Now print out all the detailed information about the various options: long form, short form and help text:
294 // -- long_name <argument>
295 // - short <argument>
296 // help text
297
298 // This variable is used to keep track of which options' info we've printed out, because some options can be in
299 // more than one usage level, but we only want to print the long form of its information once.
300
301 Driver::OptionData::OptionSet options_seen;
302 Driver::OptionData::OptionSet::iterator pos;
303
304 indent_level += 5;
305
Jim Ingham34e9a982010-06-15 18:47:14 +0000306 for (uint32_t i = 0; i < num_options; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000307 {
308 // Only print this option if we haven't already seen it.
309 pos = options_seen.find (option_table[i].short_option);
310 if (pos == options_seen.end())
311 {
Caroline Tice4d6675c2010-10-01 19:59:14 +0000312 CommandArgumentType arg_type = option_table[i].argument_type;
313 std::string arg_name;
314 GetArgumentName (arg_type, arg_name);
315
Chris Lattner24943d22010-06-08 16:52:24 +0000316 options_seen.insert (option_table[i].short_option);
Greg Clayton54e7afa2010-07-09 20:39:50 +0000317 fprintf (out, "%*s-%c ", indent_level, "", option_table[i].short_option);
Caroline Tice4d6675c2010-10-01 19:59:14 +0000318 if (arg_type != eArgTypeNone)
319 fprintf (out, "<%s>", arg_name.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000320 fprintf (out, "\n");
Greg Clayton54e7afa2010-07-09 20:39:50 +0000321 fprintf (out, "%*s--%s ", indent_level, "", option_table[i].long_option);
Caroline Tice4d6675c2010-10-01 19:59:14 +0000322 if (arg_type != eArgTypeNone)
323 fprintf (out, "<%s>", arg_name.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000324 fprintf (out, "\n");
325 indent_level += 5;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000326 OutputFormattedUsageText (out, indent_level, option_table[i].usage_text, screen_width);
Chris Lattner24943d22010-06-08 16:52:24 +0000327 indent_level -= 5;
328 fprintf (out, "\n");
329 }
330 }
331
332 indent_level -= 5;
333
Greg Clayton54e7afa2010-07-09 20:39:50 +0000334 fprintf (out, "\n%*s('%s <filename>' also works, to specify the file to be debugged.)\n\n",
335 indent_level, "", name);
Chris Lattner24943d22010-06-08 16:52:24 +0000336}
337
338void
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000339BuildGetOptTable (lldb::OptionDefinition *expanded_option_table, std::vector<struct option> &getopt_table,
340 uint32_t num_options)
Chris Lattner24943d22010-06-08 16:52:24 +0000341{
342 if (num_options == 0)
343 return;
344
345 uint32_t i;
346 uint32_t j;
347 std::bitset<256> option_seen;
348
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000349 getopt_table.resize (num_options + 1);
350
Chris Lattner24943d22010-06-08 16:52:24 +0000351 for (i = 0, j = 0; i < num_options; ++i)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000352 {
Chris Lattner24943d22010-06-08 16:52:24 +0000353 char short_opt = expanded_option_table[i].short_option;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000354
Chris Lattner24943d22010-06-08 16:52:24 +0000355 if (option_seen.test(short_opt) == false)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000356 {
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000357 getopt_table[j].name = expanded_option_table[i].long_option;
358 getopt_table[j].has_arg = expanded_option_table[i].option_has_arg;
359 getopt_table[j].flag = NULL;
360 getopt_table[j].val = expanded_option_table[i].short_option;
Chris Lattner24943d22010-06-08 16:52:24 +0000361 option_seen.set(short_opt);
362 ++j;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000363 }
364 }
Chris Lattner24943d22010-06-08 16:52:24 +0000365
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000366 getopt_table[j].name = NULL;
367 getopt_table[j].has_arg = 0;
368 getopt_table[j].flag = NULL;
369 getopt_table[j].val = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000370
371}
372
Greg Clayton63094e02010-06-23 01:19:29 +0000373Driver::OptionData::OptionData () :
Greg Clayton4dc18922010-12-08 22:23:24 +0000374 m_args(),
Greg Clayton63094e02010-06-23 01:19:29 +0000375 m_script_lang (lldb::eScriptLanguageDefault),
Greg Clayton54e7afa2010-07-09 20:39:50 +0000376 m_crash_log (),
Greg Clayton63094e02010-06-23 01:19:29 +0000377 m_source_command_files (),
378 m_debug_mode (false),
Greg Clayton54e7afa2010-07-09 20:39:50 +0000379 m_print_version (false),
Greg Clayton63094e02010-06-23 01:19:29 +0000380 m_print_help (false),
Jim Ingham74989e82010-08-30 19:44:40 +0000381 m_seen_options(),
382 m_use_external_editor(false)
Chris Lattner24943d22010-06-08 16:52:24 +0000383{
Greg Clayton63094e02010-06-23 01:19:29 +0000384}
385
386Driver::OptionData::~OptionData ()
387{
388}
389
390void
391Driver::OptionData::Clear ()
392{
Greg Clayton4dc18922010-12-08 22:23:24 +0000393 m_args.clear ();
Greg Clayton63094e02010-06-23 01:19:29 +0000394 m_script_lang = lldb::eScriptLanguageDefault;
395 m_source_command_files.clear ();
396 m_debug_mode = false;
397 m_print_help = false;
398 m_print_version = false;
Jim Ingham74989e82010-08-30 19:44:40 +0000399 m_use_external_editor = false;
Greg Clayton63094e02010-06-23 01:19:29 +0000400}
401
402void
403Driver::ResetOptionValues ()
404{
405 m_option_data.Clear ();
406}
407
408const char *
409Driver::GetFilename() const
410{
Greg Clayton4dc18922010-12-08 22:23:24 +0000411 if (m_option_data.m_args.empty())
Greg Clayton63094e02010-06-23 01:19:29 +0000412 return NULL;
Greg Clayton4dc18922010-12-08 22:23:24 +0000413 return m_option_data.m_args.front().c_str();
Greg Clayton63094e02010-06-23 01:19:29 +0000414}
415
416const char *
417Driver::GetCrashLogFilename() const
418{
419 if (m_option_data.m_crash_log.empty())
420 return NULL;
421 return m_option_data.m_crash_log.c_str();
422}
423
424lldb::ScriptLanguage
425Driver::GetScriptLanguage() const
426{
427 return m_option_data.m_script_lang;
428}
429
430size_t
431Driver::GetNumSourceCommandFiles () const
432{
433 return m_option_data.m_source_command_files.size();
434}
435
436const char *
437Driver::GetSourceCommandFileAtIndex (uint32_t idx) const
438{
439 if (idx < m_option_data.m_source_command_files.size())
440 return m_option_data.m_source_command_files[idx].c_str();
441 return NULL;
442}
443
444bool
445Driver::GetDebugMode() const
446{
447 return m_option_data.m_debug_mode;
448}
449
450
451// Check the arguments that were passed to this program to make sure they are valid and to get their
452// argument values (if any). Return a boolean value indicating whether or not to start up the full
453// debugger (i.e. the Command Interpreter) or not. Return FALSE if the arguments were invalid OR
454// if the user only wanted help or version information.
455
456SBError
457Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exit)
458{
459 ResetOptionValues ();
460
461 SBCommandReturnObject result;
462
Chris Lattner24943d22010-06-08 16:52:24 +0000463 SBError error;
464 std::string option_string;
465 struct option *long_options = NULL;
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000466 std::vector<struct option> long_options_vector;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000467 uint32_t num_options;
Chris Lattner24943d22010-06-08 16:52:24 +0000468
Greg Clayton54e7afa2010-07-09 20:39:50 +0000469 for (num_options = 0; g_options[num_options].long_option != NULL; ++num_options)
470 /* Do Nothing. */;
Chris Lattner24943d22010-06-08 16:52:24 +0000471
472 if (num_options == 0)
473 {
474 if (argc > 1)
475 error.SetErrorStringWithFormat ("invalid number of options");
476 return error;
477 }
478
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000479 BuildGetOptTable (g_options, long_options_vector, num_options);
Chris Lattner24943d22010-06-08 16:52:24 +0000480
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000481 if (long_options_vector.empty())
482 long_options = NULL;
483 else
484 long_options = &long_options_vector.front();
Chris Lattner24943d22010-06-08 16:52:24 +0000485
486 if (long_options == NULL)
487 {
488 error.SetErrorStringWithFormat ("invalid long options");
489 return error;
490 }
491
492 // Build the option_string argument for call to getopt_long.
493
494 for (int i = 0; long_options[i].name != NULL; ++i)
495 {
496 if (long_options[i].flag == NULL)
497 {
498 option_string.push_back ((char) long_options[i].val);
499 switch (long_options[i].has_arg)
500 {
501 default:
502 case no_argument:
503 break;
504 case required_argument:
505 option_string.push_back (':');
506 break;
507 case optional_argument:
508 option_string.append ("::");
509 break;
510 }
511 }
512 }
513
514 // Prepare for & make calls to getopt_long.
Eli Friedmanef2bc872010-06-13 19:18:49 +0000515#if __GLIBC__
516 optind = 0;
517#else
Chris Lattner24943d22010-06-08 16:52:24 +0000518 optreset = 1;
519 optind = 1;
Eli Friedmanef2bc872010-06-13 19:18:49 +0000520#endif
Chris Lattner24943d22010-06-08 16:52:24 +0000521 int val;
522 while (1)
523 {
524 int long_options_index = -1;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000525 val = ::getopt_long (argc, const_cast<char **>(argv), option_string.c_str(), long_options, &long_options_index);
Chris Lattner24943d22010-06-08 16:52:24 +0000526
527 if (val == -1)
528 break;
529 else if (val == '?')
530 {
Greg Clayton63094e02010-06-23 01:19:29 +0000531 m_option_data.m_print_help = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000532 error.SetErrorStringWithFormat ("unknown or ambiguous option");
533 break;
534 }
535 else if (val == 0)
536 continue;
537 else
538 {
Greg Clayton63094e02010-06-23 01:19:29 +0000539 m_option_data.m_seen_options.insert ((char) val);
Chris Lattner24943d22010-06-08 16:52:24 +0000540 if (long_options_index == -1)
541 {
542 for (int i = 0;
543 long_options[i].name || long_options[i].has_arg || long_options[i].flag || long_options[i].val;
544 ++i)
545 {
546 if (long_options[i].val == val)
547 {
548 long_options_index = i;
549 break;
550 }
551 }
552 }
553
554 if (long_options_index >= 0)
555 {
Greg Clayton63094e02010-06-23 01:19:29 +0000556 const char short_option = (char) g_options[long_options_index].short_option;
557
558 switch (short_option)
559 {
560 case 'h':
561 m_option_data.m_print_help = true;
562 break;
563
564 case 'v':
565 m_option_data.m_print_version = true;
566 break;
567
568 case 'c':
569 m_option_data.m_crash_log = optarg;
570 break;
Greg Clayton887aa282010-10-11 01:05:37 +0000571
Jim Ingham74989e82010-08-30 19:44:40 +0000572 case 'e':
573 m_option_data.m_use_external_editor = true;
574 break;
Greg Clayton887aa282010-10-11 01:05:37 +0000575
576 case 'n':
577 m_debugger.SkipLLDBInitFiles (true);
578 break;
579
Greg Clayton63094e02010-06-23 01:19:29 +0000580 case 'f':
581 {
582 SBFileSpec file(optarg);
583 if (file.Exists())
Greg Clayton4dc18922010-12-08 22:23:24 +0000584 {
585 m_option_data.m_args.push_back (optarg);
586 }
Caroline Ticeeddffe92010-09-10 04:48:55 +0000587 else if (file.ResolveExecutableLocation())
588 {
589 char path[PATH_MAX];
590 int path_len;
591 file.GetPath (path, path_len);
Greg Clayton4dc18922010-12-08 22:23:24 +0000592 m_option_data.m_args.push_back (path);
Caroline Ticeeddffe92010-09-10 04:48:55 +0000593 }
Greg Clayton63094e02010-06-23 01:19:29 +0000594 else
595 error.SetErrorStringWithFormat("file specified in --file (-f) option doesn't exist: '%s'", optarg);
596 }
597 break;
598
599 case 'a':
600 if (!m_debugger.SetDefaultArchitecture (optarg))
601 error.SetErrorStringWithFormat("invalid architecture in the -a or --arch option: '%s'", optarg);
602 break;
603
604 case 'l':
605 m_option_data.m_script_lang = m_debugger.GetScriptingLanguage (optarg);
606 break;
607
608 case 'd':
609 m_option_data.m_debug_mode = true;
610 break;
611
612 case 's':
613 {
614 SBFileSpec file(optarg);
615 if (file.Exists())
616 m_option_data.m_source_command_files.push_back (optarg);
Caroline Ticeeddffe92010-09-10 04:48:55 +0000617 else if (file.ResolveExecutableLocation())
618 {
619 char final_path[PATH_MAX];
620 size_t path_len;
621 file.GetPath (final_path, path_len);
622 std::string path_str (final_path);
623 m_option_data.m_source_command_files.push_back (path_str);
624 }
Greg Clayton63094e02010-06-23 01:19:29 +0000625 else
626 error.SetErrorStringWithFormat("file specified in --source (-s) option doesn't exist: '%s'", optarg);
627 }
628 break;
629
630 default:
631 m_option_data.m_print_help = true;
632 error.SetErrorStringWithFormat ("unrecognized option %c", short_option);
633 break;
634 }
Chris Lattner24943d22010-06-08 16:52:24 +0000635 }
636 else
637 {
638 error.SetErrorStringWithFormat ("invalid option with value %i", val);
639 }
640 if (error.Fail())
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000641 {
Greg Clayton63094e02010-06-23 01:19:29 +0000642 return error;
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000643 }
Chris Lattner24943d22010-06-08 16:52:24 +0000644 }
645 }
Jim Ingham34e9a982010-06-15 18:47:14 +0000646
Greg Clayton63094e02010-06-23 01:19:29 +0000647 if (error.Fail() || m_option_data.m_print_help)
Chris Lattner24943d22010-06-08 16:52:24 +0000648 {
649 ShowUsage (out_fh, g_options, m_option_data);
Greg Clayton9caa9462010-10-11 01:13:37 +0000650 exit = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000651 }
652 else if (m_option_data.m_print_version)
653 {
Greg Clayton63094e02010-06-23 01:19:29 +0000654 ::fprintf (out_fh, "%s\n", m_debugger.GetVersionString());
655 exit = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000656 }
657 else if (! m_option_data.m_crash_log.empty())
658 {
659 // Handle crash log stuff here.
660 }
661 else
662 {
Greg Clayton4dc18922010-12-08 22:23:24 +0000663 // Any arguments that are left over after option parsing are for
664 // the program. If a file was specified with -f then the filename
665 // is already in the m_option_data.m_args array, and any remaining args
666 // are arguments for the inferior program. If no file was specified with
667 // -f, then what is left is the program name followed by any arguments.
668
669 // Skip any options we consumed with getopt_long
670 argc -= optind;
671 argv += optind;
672
673 if (argc > 0)
674 {
675 for (int arg_idx=0; arg_idx<argc; ++arg_idx)
676 {
677 const char *arg = argv[arg_idx];
678 if (arg)
679 m_option_data.m_args.push_back (arg);
680 }
681 }
682
Chris Lattner24943d22010-06-08 16:52:24 +0000683 }
684
Greg Clayton63094e02010-06-23 01:19:29 +0000685 return error;
Chris Lattner24943d22010-06-08 16:52:24 +0000686}
687
Caroline Tice757500e2010-09-29 18:35:42 +0000688size_t
Chris Lattner24943d22010-06-08 16:52:24 +0000689Driver::GetProcessSTDOUT ()
690{
691 // The process has stuff waiting for stdout; get it and write it out to the appropriate place.
692 char stdio_buffer[1024];
693 size_t len;
Caroline Tice757500e2010-09-29 18:35:42 +0000694 size_t total_bytes = 0;
Jim Inghamc8332952010-08-26 21:32:51 +0000695 while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0)
Caroline Tice757500e2010-09-29 18:35:42 +0000696 {
Chris Lattner24943d22010-06-08 16:52:24 +0000697 m_io_channel_ap->OutWrite (stdio_buffer, len);
Caroline Tice757500e2010-09-29 18:35:42 +0000698 total_bytes += len;
699 }
700 return total_bytes;
Chris Lattner24943d22010-06-08 16:52:24 +0000701}
702
Caroline Tice757500e2010-09-29 18:35:42 +0000703size_t
Chris Lattner24943d22010-06-08 16:52:24 +0000704Driver::GetProcessSTDERR ()
705{
706 // The process has stuff waiting for stderr; get it and write it out to the appropriate place.
707 char stdio_buffer[1024];
708 size_t len;
Caroline Tice757500e2010-09-29 18:35:42 +0000709 size_t total_bytes = 0;
Jim Inghamc8332952010-08-26 21:32:51 +0000710 while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0)
Caroline Tice757500e2010-09-29 18:35:42 +0000711 {
Chris Lattner24943d22010-06-08 16:52:24 +0000712 m_io_channel_ap->ErrWrite (stdio_buffer, len);
Caroline Tice757500e2010-09-29 18:35:42 +0000713 total_bytes += len;
714 }
715 return total_bytes;
Chris Lattner24943d22010-06-08 16:52:24 +0000716}
717
718void
Jim Inghamc8332952010-08-26 21:32:51 +0000719Driver::UpdateSelectedThread ()
Chris Lattner24943d22010-06-08 16:52:24 +0000720{
721 using namespace lldb;
Jim Inghamc8332952010-08-26 21:32:51 +0000722 SBProcess process(m_debugger.GetSelectedTarget().GetProcess());
Chris Lattner24943d22010-06-08 16:52:24 +0000723 if (process.IsValid())
724 {
Jim Inghamc8332952010-08-26 21:32:51 +0000725 SBThread curr_thread (process.GetSelectedThread());
Chris Lattner24943d22010-06-08 16:52:24 +0000726 SBThread thread;
727 StopReason curr_thread_stop_reason = eStopReasonInvalid;
728 curr_thread_stop_reason = curr_thread.GetStopReason();
729
730 if (!curr_thread.IsValid() ||
731 curr_thread_stop_reason == eStopReasonInvalid ||
732 curr_thread_stop_reason == eStopReasonNone)
733 {
734 // Prefer a thread that has just completed its plan over another thread as current thread.
735 SBThread plan_thread;
736 SBThread other_thread;
737 const size_t num_threads = process.GetNumThreads();
738 size_t i;
739 for (i = 0; i < num_threads; ++i)
740 {
741 thread = process.GetThreadAtIndex(i);
742 StopReason thread_stop_reason = thread.GetStopReason();
743 switch (thread_stop_reason)
744 {
745 default:
746 case eStopReasonInvalid:
747 case eStopReasonNone:
748 break;
749
750 case eStopReasonTrace:
751 case eStopReasonBreakpoint:
752 case eStopReasonWatchpoint:
753 case eStopReasonSignal:
754 case eStopReasonException:
755 if (!other_thread.IsValid())
756 other_thread = thread;
757 break;
758 case eStopReasonPlanComplete:
759 if (!plan_thread.IsValid())
760 plan_thread = thread;
761 break;
762 }
763 }
764 if (plan_thread.IsValid())
Jim Inghamc8332952010-08-26 21:32:51 +0000765 process.SetSelectedThread (plan_thread);
Chris Lattner24943d22010-06-08 16:52:24 +0000766 else if (other_thread.IsValid())
Jim Inghamc8332952010-08-26 21:32:51 +0000767 process.SetSelectedThread (other_thread);
Chris Lattner24943d22010-06-08 16:52:24 +0000768 else
769 {
770 if (curr_thread.IsValid())
771 thread = curr_thread;
772 else
773 thread = process.GetThreadAtIndex(0);
774
775 if (thread.IsValid())
Jim Inghamc8332952010-08-26 21:32:51 +0000776 process.SetSelectedThread (thread);
Chris Lattner24943d22010-06-08 16:52:24 +0000777 }
778 }
779 }
780}
781
782
783// This function handles events that were broadcast by the process.
784void
785Driver::HandleProcessEvent (const SBEvent &event)
786{
787 using namespace lldb;
788 const uint32_t event_type = event.GetType();
789
790 if (event_type & SBProcess::eBroadcastBitSTDOUT)
791 {
792 // The process has stdout available, get it and write it out to the
793 // appropriate place.
Caroline Tice757500e2010-09-29 18:35:42 +0000794 if (GetProcessSTDOUT ())
795 m_io_channel_ap->RefreshPrompt();
Chris Lattner24943d22010-06-08 16:52:24 +0000796 }
797 else if (event_type & SBProcess::eBroadcastBitSTDERR)
798 {
799 // The process has stderr available, get it and write it out to the
800 // appropriate place.
Caroline Tice757500e2010-09-29 18:35:42 +0000801 if (GetProcessSTDERR ())
802 m_io_channel_ap->RefreshPrompt();
Chris Lattner24943d22010-06-08 16:52:24 +0000803 }
804 else if (event_type & SBProcess::eBroadcastBitStateChanged)
805 {
806 // Drain all stout and stderr so we don't see any output come after
807 // we print our prompts
Caroline Tice757500e2010-09-29 18:35:42 +0000808 if (GetProcessSTDOUT ()
809 || GetProcessSTDERR ())
810 m_io_channel_ap->RefreshPrompt();
Chris Lattner24943d22010-06-08 16:52:24 +0000811
812 // Something changed in the process; get the event and report the process's current status and location to
813 // the user.
814 StateType event_state = SBProcess::GetStateFromEvent (event);
815 if (event_state == eStateInvalid)
816 return;
817
818 SBProcess process (SBProcess::GetProcessFromEvent (event));
819 assert (process.IsValid());
820
821 switch (event_state)
822 {
823 case eStateInvalid:
824 case eStateUnloaded:
Greg Claytone71e2582011-02-04 01:58:07 +0000825 case eStateConnected:
Chris Lattner24943d22010-06-08 16:52:24 +0000826 case eStateAttaching:
827 case eStateLaunching:
828 case eStateStepping:
829 case eStateDetached:
830 {
831 char message[1024];
832 int message_len = ::snprintf (message, sizeof(message), "Process %d %s\n", process.GetProcessID(),
Greg Clayton63094e02010-06-23 01:19:29 +0000833 m_debugger.StateAsCString (event_state));
Chris Lattner24943d22010-06-08 16:52:24 +0000834 m_io_channel_ap->OutWrite(message, message_len);
835 }
836 break;
837
838 case eStateRunning:
839 // Don't be chatty when we run...
840 break;
841
842 case eStateExited:
Caroline Tice757500e2010-09-29 18:35:42 +0000843 {
844 SBCommandReturnObject result;
845 m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
846 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize());
847 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize());
848 m_io_channel_ap->RefreshPrompt();
849 }
Chris Lattner24943d22010-06-08 16:52:24 +0000850 break;
851
852 case eStateStopped:
853 case eStateCrashed:
854 case eStateSuspended:
855 // Make sure the program hasn't been auto-restarted:
856 if (SBProcess::GetRestartedFromEvent (event))
857 {
858 // FIXME: Do we want to report this, or would that just be annoyingly chatty?
859 char message[1024];
860 int message_len = ::snprintf (message, sizeof(message), "Process %d stopped and was programmatically restarted.\n",
861 process.GetProcessID());
862 m_io_channel_ap->OutWrite(message, message_len);
Caroline Tice757500e2010-09-29 18:35:42 +0000863 m_io_channel_ap->RefreshPrompt ();
Chris Lattner24943d22010-06-08 16:52:24 +0000864 }
865 else
866 {
Caroline Tice757500e2010-09-29 18:35:42 +0000867 SBCommandReturnObject result;
Jim Inghamc8332952010-08-26 21:32:51 +0000868 UpdateSelectedThread ();
Caroline Tice757500e2010-09-29 18:35:42 +0000869 m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
870 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize());
871 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize());
872 m_io_channel_ap->RefreshPrompt ();
Chris Lattner24943d22010-06-08 16:52:24 +0000873 }
874 break;
875 }
876 }
877}
878
879// This function handles events broadcast by the IOChannel (HasInput, UserInterrupt, or ThreadShouldExit).
880
881bool
882Driver::HandleIOEvent (const SBEvent &event)
883{
884 bool quit = false;
885
886 const uint32_t event_type = event.GetType();
887
888 if (event_type & IOChannel::eBroadcastBitHasUserInput)
889 {
890 // We got some input (i.e. a command string) from the user; pass it off to the command interpreter for
891 // handling.
892
893 const char *command_string = SBEvent::GetCStringFromEvent(event);
894 if (command_string == NULL)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000895 command_string = "";
Chris Lattner24943d22010-06-08 16:52:24 +0000896 SBCommandReturnObject result;
Greg Clayton63094e02010-06-23 01:19:29 +0000897 if (m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, true) != lldb::eReturnStatusQuit)
Chris Lattner24943d22010-06-08 16:52:24 +0000898 {
899 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize());
900 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize());
901 }
902 // We are done getting and running our command, we can now clear the
903 // m_waiting_for_command so we can get another one.
904 m_waiting_for_command = false;
905
906 // If our editline input reader is active, it means another input reader
907 // got pushed onto the input reader and caused us to become deactivated.
908 // When the input reader above us gets popped, we will get re-activated
909 // and our prompt will refresh in our callback
910 if (m_editline_reader.IsActive())
911 {
912 ReadyForCommand ();
913 }
914 }
915 else if (event_type & IOChannel::eBroadcastBitUserInterrupt)
916 {
917 // This is here to handle control-c interrupts from the user. It has not yet really been implemented.
918 // TO BE DONE: PROPERLY HANDLE CONTROL-C FROM USER
919 //m_io_channel_ap->CancelInput();
920 // Anything else? Send Interrupt to process?
921 }
922 else if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
923 (event_type & IOChannel::eBroadcastBitThreadDidExit))
924 {
925 // If the IOChannel thread is trying to go away, then it is definitely
926 // time to end the debugging session.
927 quit = true;
928 }
929
930 return quit;
931}
932
933
934//struct CrashImageInfo
935//{
936// std::string path;
937// VMRange text_range;
Greg Clayton0467c782011-02-04 18:53:10 +0000938// lldb_private::UUID uuid;
Chris Lattner24943d22010-06-08 16:52:24 +0000939//};
940//
941//void
942//Driver::ParseCrashLog (const char *crash_log)
943//{
944// printf("Parsing crash log: %s\n", crash_log);
945//
946// char image_path[PATH_MAX];
947// std::vector<CrashImageInfo> crash_infos;
948// if (crash_log && crash_log[0])
949// {
950// FileSpec crash_log_file (crash_log);
951// STLStringArray crash_log_lines;
952// if (crash_log_file.ReadFileLines (crash_log_lines))
953// {
954// const size_t num_crash_log_lines = crash_log_lines.size();
955// size_t i;
956// for (i=0; i<num_crash_log_lines; ++i)
957// {
958// const char *line = crash_log_lines[i].c_str();
959// if (strstr (line, "Code Type:"))
960// {
961// char arch_string[256];
962// if (sscanf(line, "%s", arch_string))
963// {
964// if (strcmp(arch_string, "X86-64"))
965// lldb::GetDefaultArchitecture ().SetArch ("x86_64");
966// else if (strcmp(arch_string, "X86"))
967// lldb::GetDefaultArchitecture ().SetArch ("i386");
968// else
969// {
970// ArchSpec arch(arch_string);
971// if (arch.IsValid ())
972// lldb::GetDefaultArchitecture () = arch;
973// else
974// fprintf(stderr, "Unrecognized architecture: %s\n", arch_string);
975// }
976// }
977// }
978// else
979// if (strstr(line, "Path:"))
980// {
981// const char *p = line + strlen("Path:");
982// while (isspace(*p))
983// ++p;
984//
985// m_option_data.m_filename.assign (p);
986// }
987// else
988// if (strstr(line, "Binary Images:"))
989// {
990// while (++i < num_crash_log_lines)
991// {
992// if (crash_log_lines[i].empty())
993// break;
994//
995// line = crash_log_lines[i].c_str();
996// uint64_t text_start_addr;
997// uint64_t text_end_addr;
998// char uuid_cstr[64];
999// int bytes_consumed_before_uuid = 0;
1000// int bytes_consumed_after_uuid = 0;
1001//
1002// int items_parsed = ::sscanf (line,
1003// "%llx - %llx %*s %*s %*s %n%s %n",
1004// &text_start_addr,
1005// &text_end_addr,
1006// &bytes_consumed_before_uuid,
1007// uuid_cstr,
1008// &bytes_consumed_after_uuid);
1009//
1010// if (items_parsed == 3)
1011// {
1012//
1013// CrashImageInfo info;
1014// info.text_range.SetBaseAddress(text_start_addr);
1015// info.text_range.SetEndAddress(text_end_addr);
1016//
1017// if (uuid_cstr[0] == '<')
1018// {
1019// if (info.uuid.SetfromCString (&uuid_cstr[1]) == 0)
1020// info.uuid.Clear();
1021//
1022// ::strncpy (image_path, line + bytes_consumed_after_uuid, sizeof(image_path));
1023// }
1024// else
1025// {
1026// ::strncpy (image_path, line + bytes_consumed_before_uuid, sizeof(image_path));
1027// }
1028//
1029// info.path = image_path;
1030//
1031// crash_infos.push_back (info);
1032//
1033// info.uuid.GetAsCString(uuid_cstr, sizeof(uuid_cstr));
1034//
1035// printf("0x%16.16llx - 0x%16.16llx <%s> %s\n",
1036// text_start_addr,
1037// text_end_addr,
1038// uuid_cstr,
1039// image_path);
1040// }
1041// }
1042// }
1043// }
1044// }
1045//
1046// if (crash_infos.size())
1047// {
Greg Clayton63094e02010-06-23 01:19:29 +00001048// SBTarget target (m_debugger.CreateTarget (crash_infos.front().path.c_str(),
Chris Lattner24943d22010-06-08 16:52:24 +00001049// lldb::GetDefaultArchitecture().AsCString (),
1050// false));
1051// if (target.IsValid())
1052// {
1053//
1054// }
1055// }
1056// }
1057//}
1058//
1059
1060void
1061Driver::MasterThreadBytesReceived (void *baton, const void *src, size_t src_len)
1062{
1063 Driver *driver = (Driver*)baton;
1064 driver->GetFromMaster ((const char *)src, src_len);
1065}
1066
1067void
1068Driver::GetFromMaster (const char *src, size_t src_len)
1069{
1070 // Echo the characters back to the Debugger's stdout, that way if you
1071 // type characters while a command is running, you'll see what you've typed.
Greg Clayton63094e02010-06-23 01:19:29 +00001072 FILE *out_fh = m_debugger.GetOutputFileHandle();
Chris Lattner24943d22010-06-08 16:52:24 +00001073 if (out_fh)
1074 ::fwrite (src, 1, src_len, out_fh);
1075}
1076
1077size_t
1078Driver::EditLineInputReaderCallback
1079(
1080 void *baton,
1081 SBInputReader *reader,
1082 InputReaderAction notification,
1083 const char *bytes,
1084 size_t bytes_len
1085)
1086{
1087 Driver *driver = (Driver *)baton;
1088
1089 switch (notification)
1090 {
1091 case eInputReaderActivate:
1092 break;
1093
1094 case eInputReaderReactivate:
1095 driver->ReadyForCommand();
1096 break;
1097
1098 case eInputReaderDeactivate:
1099 break;
1100
Caroline Ticec4f55fe2010-11-19 20:47:54 +00001101 case eInputReaderInterrupt:
1102 if (driver->m_io_channel_ap.get() != NULL)
1103 {
1104 driver->m_io_channel_ap->OutWrite ("^C\n", 3);
1105 driver->m_io_channel_ap->RefreshPrompt();
1106 }
1107 break;
1108
1109 case eInputReaderEndOfFile:
1110 if (driver->m_io_channel_ap.get() != NULL)
1111 {
1112 driver->m_io_channel_ap->OutWrite ("^D\n", 3);
1113 driver->m_io_channel_ap->RefreshPrompt ();
1114 }
1115 write (driver->m_editline_pty.GetMasterFileDescriptor(), "quit\n", 5);
1116 break;
1117
Chris Lattner24943d22010-06-08 16:52:24 +00001118 case eInputReaderGotToken:
1119 write (driver->m_editline_pty.GetMasterFileDescriptor(), bytes, bytes_len);
1120 break;
1121
1122 case eInputReaderDone:
1123 break;
1124 }
1125 return bytes_len;
1126}
1127
1128void
1129Driver::MainLoop ()
1130{
1131 char error_str[1024];
1132 if (m_editline_pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, error_str, sizeof(error_str)) == false)
1133 {
1134 ::fprintf (stderr, "error: failed to open driver pseudo terminal : %s", error_str);
1135 exit(1);
1136 }
1137 else
1138 {
1139 const char *driver_slave_name = m_editline_pty.GetSlaveName (error_str, sizeof(error_str));
1140 if (driver_slave_name == NULL)
1141 {
1142 ::fprintf (stderr, "error: failed to get slave name for driver pseudo terminal : %s", error_str);
1143 exit(2);
1144 }
1145 else
1146 {
1147 m_editline_slave_fh = ::fopen (driver_slave_name, "r+");
1148 if (m_editline_slave_fh == NULL)
1149 {
1150 SBError error;
1151 error.SetErrorToErrno();
1152 ::fprintf (stderr, "error: failed to get open slave for driver pseudo terminal : %s",
1153 error.GetCString());
1154 exit(3);
1155 }
1156
1157 ::setbuf (m_editline_slave_fh, NULL);
1158 }
1159 }
1160
1161
1162 // struct termios stdin_termios;
1163
1164 if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0)
1165 atexit (reset_stdin_termios);
1166
1167 ::setbuf (stdin, NULL);
1168 ::setbuf (stdout, NULL);
1169
Greg Clayton63094e02010-06-23 01:19:29 +00001170 m_debugger.SetErrorFileHandle (stderr, false);
1171 m_debugger.SetOutputFileHandle (stdout, false);
1172 m_debugger.SetInputFileHandle (stdin, true);
Jim Ingham74989e82010-08-30 19:44:40 +00001173
1174 m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor);
Chris Lattner24943d22010-06-08 16:52:24 +00001175
1176 // You have to drain anything that comes to the master side of the PTY. master_out_comm is
1177 // for that purpose. The reason you need to do this is a curious reason... editline will echo
1178 // characters to the PTY when it gets characters while el_gets is not running, and then when
1179 // you call el_gets (or el_getc) it will try to reset the terminal back to raw mode which blocks
1180 // if there are unconsumed characters in the out buffer.
1181 // However, you don't need to do anything with the characters, since editline will dump these
1182 // unconsumed characters after printing the prompt again in el_gets.
1183
Greg Claytoneecb0f32010-12-04 02:39:47 +00001184 SBCommunication master_out_comm("driver.editline");
1185 master_out_comm.SetCloseOnEOF (false);
Chris Lattner24943d22010-06-08 16:52:24 +00001186 master_out_comm.AdoptFileDesriptor(m_editline_pty.GetMasterFileDescriptor(), false);
1187 master_out_comm.SetReadThreadBytesReceivedCallback(Driver::MasterThreadBytesReceived, this);
1188
1189 if (master_out_comm.ReadThreadStart () == false)
1190 {
1191 ::fprintf (stderr, "error: failed to start master out read thread");
1192 exit(5);
1193 }
1194
1195// const char *crash_log = GetCrashLogFilename();
1196// if (crash_log)
1197// {
1198// ParseCrashLog (crash_log);
1199// }
1200//
Greg Clayton63094e02010-06-23 01:19:29 +00001201 SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter();
Chris Lattner24943d22010-06-08 16:52:24 +00001202
1203 m_io_channel_ap.reset (new IOChannel(m_editline_slave_fh, stdout, stderr, this));
1204
1205 struct winsize window_size;
1206 if (isatty (STDIN_FILENO)
1207 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
1208 {
Caroline Tice6e4c5ce2010-09-04 00:03:46 +00001209 if (window_size.ws_col > 0)
Greg Clayton238c0a12010-09-18 01:14:36 +00001210 m_debugger.SetTerminalWidth (window_size.ws_col);
Chris Lattner24943d22010-06-08 16:52:24 +00001211 }
1212
1213 // Since input can be redirected by the debugger, we must insert our editline
1214 // input reader in the queue so we know when our reader should be active
1215 // and so we can receive bytes only when we are supposed to.
Greg Clayton63094e02010-06-23 01:19:29 +00001216 SBError err (m_editline_reader.Initialize (m_debugger,
1217 Driver::EditLineInputReaderCallback, // callback
Chris Lattner24943d22010-06-08 16:52:24 +00001218 this, // baton
1219 eInputReaderGranularityByte, // token_size
1220 NULL, // end token - NULL means never done
1221 NULL, // prompt - taken care of elsewhere
1222 false)); // echo input - don't need Debugger
1223 // to do this, we handle it elsewhere
1224
1225 if (err.Fail())
1226 {
1227 ::fprintf (stderr, "error: %s", err.GetCString());
1228 exit (6);
1229 }
1230
Greg Clayton63094e02010-06-23 01:19:29 +00001231 m_debugger.PushInputReader (m_editline_reader);
Chris Lattner24943d22010-06-08 16:52:24 +00001232
Greg Clayton63094e02010-06-23 01:19:29 +00001233 SBListener listener(m_debugger.GetListener());
Chris Lattner24943d22010-06-08 16:52:24 +00001234 if (listener.IsValid())
1235 {
1236
1237 listener.StartListeningForEvents (*m_io_channel_ap,
1238 IOChannel::eBroadcastBitHasUserInput |
1239 IOChannel::eBroadcastBitUserInterrupt |
1240 IOChannel::eBroadcastBitThreadShouldExit |
1241 IOChannel::eBroadcastBitThreadDidStart |
1242 IOChannel::eBroadcastBitThreadDidExit);
1243
1244 if (m_io_channel_ap->Start ())
1245 {
1246 bool iochannel_thread_exited = false;
1247
1248 listener.StartListeningForEvents (sb_interpreter.GetBroadcaster(),
1249 SBCommandInterpreter::eBroadcastBitQuitCommandReceived);
1250
1251 // Before we handle any options from the command line, we parse the
1252 // .lldbinit file in the user's home directory.
1253 SBCommandReturnObject result;
1254 sb_interpreter.SourceInitFileInHomeDirectory(result);
1255 if (GetDebugMode())
1256 {
Greg Clayton63094e02010-06-23 01:19:29 +00001257 result.PutError (m_debugger.GetErrorFileHandle());
1258 result.PutOutput (m_debugger.GetOutputFileHandle());
Chris Lattner24943d22010-06-08 16:52:24 +00001259 }
1260
1261 // Now we handle options we got from the command line
1262 char command_string[PATH_MAX * 2];
1263 const size_t num_source_command_files = GetNumSourceCommandFiles();
1264 if (num_source_command_files > 0)
1265 {
1266 for (size_t i=0; i < num_source_command_files; ++i)
1267 {
1268 const char *command_file = GetSourceCommandFileAtIndex(i);
Johnny Chen7c984242010-07-28 21:16:11 +00001269 ::snprintf (command_string, sizeof(command_string), "command source '%s'", command_file);
Greg Clayton63094e02010-06-23 01:19:29 +00001270 m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, false);
Chris Lattner24943d22010-06-08 16:52:24 +00001271 if (GetDebugMode())
1272 {
Greg Clayton63094e02010-06-23 01:19:29 +00001273 result.PutError (m_debugger.GetErrorFileHandle());
1274 result.PutOutput (m_debugger.GetOutputFileHandle());
Chris Lattner24943d22010-06-08 16:52:24 +00001275 }
1276 }
1277 }
1278
Greg Clayton4dc18922010-12-08 22:23:24 +00001279 const size_t num_args = m_option_data.m_args.size();
1280 if (num_args > 0)
Chris Lattner24943d22010-06-08 16:52:24 +00001281 {
1282 char arch_name[64];
Greg Clayton63094e02010-06-23 01:19:29 +00001283 if (m_debugger.GetDefaultArchitecture (arch_name, sizeof (arch_name)))
Greg Clayton4dc18922010-12-08 22:23:24 +00001284 ::snprintf (command_string,
1285 sizeof (command_string),
1286 "file --arch=%s '%s'",
1287 arch_name,
1288 m_option_data.m_args[0].c_str());
Chris Lattner24943d22010-06-08 16:52:24 +00001289 else
Greg Clayton4dc18922010-12-08 22:23:24 +00001290 ::snprintf (command_string,
1291 sizeof(command_string),
1292 "file '%s'",
1293 m_option_data.m_args[0].c_str());
Chris Lattner24943d22010-06-08 16:52:24 +00001294
Greg Clayton63094e02010-06-23 01:19:29 +00001295 m_debugger.HandleCommand (command_string);
Greg Clayton4dc18922010-12-08 22:23:24 +00001296
1297 if (num_args > 1)
1298 {
1299 m_debugger.HandleCommand ("settings clear target.process.run-args");
1300 char arg_cstr[1024];
1301 for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx)
1302 {
1303 ::snprintf (arg_cstr, sizeof(arg_cstr), "settings append target.process.run-args \"%s\"", m_option_data.m_args[arg_idx].c_str());
1304 m_debugger.HandleCommand (arg_cstr);
1305 }
1306 }
Chris Lattner24943d22010-06-08 16:52:24 +00001307 }
1308
1309 // Now that all option parsing is done, we try and parse the .lldbinit
1310 // file in the current working directory
1311 sb_interpreter.SourceInitFileInCurrentWorkingDirectory (result);
1312 if (GetDebugMode())
1313 {
Greg Clayton63094e02010-06-23 01:19:29 +00001314 result.PutError(m_debugger.GetErrorFileHandle());
1315 result.PutOutput(m_debugger.GetOutputFileHandle());
Chris Lattner24943d22010-06-08 16:52:24 +00001316 }
1317
1318 SBEvent event;
1319
1320 // Make sure the IO channel is started up before we try to tell it we
1321 // are ready for input
1322 listener.WaitForEventForBroadcasterWithType (UINT32_MAX,
1323 *m_io_channel_ap,
1324 IOChannel::eBroadcastBitThreadDidStart,
1325 event);
1326
1327 ReadyForCommand ();
1328
1329 bool done = false;
1330 while (!done)
1331 {
1332 listener.WaitForEvent (UINT32_MAX, event);
1333 if (event.IsValid())
1334 {
1335 if (event.GetBroadcaster().IsValid())
1336 {
1337 uint32_t event_type = event.GetType();
1338 if (event.BroadcasterMatchesRef (*m_io_channel_ap))
1339 {
1340 if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
1341 (event_type & IOChannel::eBroadcastBitThreadDidExit))
1342 {
1343 done = true;
1344 if (event_type & IOChannel::eBroadcastBitThreadDidExit)
1345 iochannel_thread_exited = true;
1346 break;
1347 }
1348 else
1349 done = HandleIOEvent (event);
1350 }
Jim Inghamc8332952010-08-26 21:32:51 +00001351 else if (event.BroadcasterMatchesRef (m_debugger.GetSelectedTarget().GetProcess().GetBroadcaster()))
Chris Lattner24943d22010-06-08 16:52:24 +00001352 {
1353 HandleProcessEvent (event);
1354 }
1355 else if (event.BroadcasterMatchesRef (sb_interpreter.GetBroadcaster()))
1356 {
1357 if (event_type & SBCommandInterpreter::eBroadcastBitQuitCommandReceived)
1358 done = true;
1359 }
1360 }
1361 }
1362 }
1363
1364 reset_stdin_termios ();
1365
1366 CloseIOChannelFile ();
1367
1368 if (!iochannel_thread_exited)
1369 {
Greg Claytonbef15832010-07-14 00:18:15 +00001370 event.Clear();
Chris Lattner24943d22010-06-08 16:52:24 +00001371 listener.GetNextEventForBroadcasterWithType (*m_io_channel_ap,
1372 IOChannel::eBroadcastBitThreadDidExit,
1373 event);
1374 if (!event.IsValid())
1375 {
1376 // Send end EOF to the driver file descriptor
1377 m_io_channel_ap->Stop();
1378 }
1379 }
1380
Jim Inghamc8332952010-08-26 21:32:51 +00001381 SBProcess process = m_debugger.GetSelectedTarget().GetProcess();
Chris Lattner24943d22010-06-08 16:52:24 +00001382 if (process.IsValid())
1383 process.Destroy();
1384 }
1385 }
1386}
1387
1388
1389void
1390Driver::ReadyForCommand ()
1391{
1392 if (m_waiting_for_command == false)
1393 {
1394 m_waiting_for_command = true;
1395 BroadcastEventByType (Driver::eBroadcastBitReadyForInput, true);
1396 }
1397}
1398
1399
Caroline Ticeb8314fe2010-09-09 17:45:09 +00001400void
1401sigwinch_handler (int signo)
1402{
1403 struct winsize window_size;
1404 if (isatty (STDIN_FILENO)
1405 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
1406 {
1407 if ((window_size.ws_col > 0) && (strlen (g_debugger_name) > 0))
1408 {
1409 char width_str_buffer[25];
1410 ::sprintf (width_str_buffer, "%d", window_size.ws_col);
1411 SBDebugger::SetInternalVariable ("term-width", width_str_buffer, g_debugger_name);
1412 }
1413 }
1414}
1415
Caroline Ticec4f55fe2010-11-19 20:47:54 +00001416void
1417sigint_handler (int signo)
1418{
1419 static bool g_interrupt_sent = false;
1420 if (g_driver)
1421 {
1422 if (!g_interrupt_sent)
1423 {
1424 g_interrupt_sent = true;
1425 g_driver->GetDebugger().DispatchInputInterrupt();
1426 g_interrupt_sent = false;
1427 return;
1428 }
1429 }
1430
1431 exit (signo);
1432}
1433
Chris Lattner24943d22010-06-08 16:52:24 +00001434int
Jim Inghamb2b604f2011-01-27 20:15:39 +00001435main (int argc, char const *argv[], const char *envp[])
Chris Lattner24943d22010-06-08 16:52:24 +00001436{
Chris Lattner24943d22010-06-08 16:52:24 +00001437 SBDebugger::Initialize();
1438
Greg Clayton95e33b72010-11-07 21:02:03 +00001439 SBHostOS::ThreadCreated ("<lldb.driver.main-thread>");
Chris Lattner24943d22010-06-08 16:52:24 +00001440
Greg Clayton36f63a92010-10-19 03:25:40 +00001441 signal (SIGPIPE, SIG_IGN);
Caroline Ticeb8314fe2010-09-09 17:45:09 +00001442 signal (SIGWINCH, sigwinch_handler);
Caroline Ticec4f55fe2010-11-19 20:47:54 +00001443 signal (SIGINT, sigint_handler);
Caroline Ticeb8314fe2010-09-09 17:45:09 +00001444
Greg Clayton63094e02010-06-23 01:19:29 +00001445 // Create a scope for driver so that the driver object will destroy itself
1446 // before SBDebugger::Terminate() is called.
Chris Lattner24943d22010-06-08 16:52:24 +00001447 {
Greg Clayton63094e02010-06-23 01:19:29 +00001448 Driver driver;
1449
1450 bool exit = false;
1451 SBError error (driver.ParseArgs (argc, argv, stdout, exit));
1452 if (error.Fail())
1453 {
1454 const char *error_cstr = error.GetCString ();
1455 if (error_cstr)
1456 ::fprintf (stderr, "error: %s\n", error_cstr);
1457 }
1458 else if (!exit)
1459 {
1460 driver.MainLoop ();
1461 }
Chris Lattner24943d22010-06-08 16:52:24 +00001462 }
1463
1464 SBDebugger::Terminate();
1465 return 0;
1466}