blob: 04e69e45e169ef4b128a6754f2e8bd3ca6aa94c1 [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
Caroline Tice4d6675c2010-10-01 19:59:14 +0000184void
185GetArgumentName (const CommandArgumentType arg_type, std::string &arg_name)
186{
187 //Fudge this function here, since we can't call the "real" version in lldb_private::CommandObject...
188
189 switch (arg_type)
190 {
191 // Make cases for all the arg_types used in Driver.cpp
192
193 case eArgTypeNone:
194 arg_name = "";
195 break;
196
197 case eArgTypeArchitecture:
198 arg_name = "architecture";
199 break;
200
201 case eArgTypeScriptLang:
202 arg_name = "script-language";
203 break;
204
205 case eArgTypeFilename:
206 arg_name = "filename";
207 break;
208 }
209 return;
210}
211
212
Chris Lattner24943d22010-06-08 16:52:24 +0000213void
214ShowUsage (FILE *out, lldb::OptionDefinition *option_table, Driver::OptionData data)
215{
216 uint32_t screen_width = 80;
217 uint32_t indent_level = 0;
218 const char *name = "lldb";
Jim Ingham34e9a982010-06-15 18:47:14 +0000219
Chris Lattner24943d22010-06-08 16:52:24 +0000220 fprintf (out, "\nUsage:\n\n");
221
222 indent_level += 2;
223
224
225 // First, show each usage level set of options, e.g. <cmd> [options-for-level-0]
226 // <cmd> [options-for-level-1]
227 // etc.
228
Chris Lattner24943d22010-06-08 16:52:24 +0000229 uint32_t num_options;
Jim Ingham34e9a982010-06-15 18:47:14 +0000230 uint32_t num_option_sets = 0;
231
232 for (num_options = 0; option_table[num_options].long_option != NULL; ++num_options)
Chris Lattner24943d22010-06-08 16:52:24 +0000233 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000234 uint32_t this_usage_mask = option_table[num_options].usage_mask;
235 if (this_usage_mask == LLDB_OPT_SET_ALL)
Chris Lattner24943d22010-06-08 16:52:24 +0000236 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000237 if (num_option_sets == 0)
238 num_option_sets = 1;
Chris Lattner24943d22010-06-08 16:52:24 +0000239 }
240 else
241 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000242 for (uint32_t j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++)
Jim Ingham34e9a982010-06-15 18:47:14 +0000243 {
244 if (this_usage_mask & 1 << j)
245 {
246 if (num_option_sets <= j)
247 num_option_sets = j + 1;
248 }
249 }
250 }
251 }
252
253 for (uint32_t opt_set = 0; opt_set < num_option_sets; opt_set++)
254 {
255 uint32_t opt_set_mask;
256
257 opt_set_mask = 1 << opt_set;
258
259 if (opt_set > 0)
260 fprintf (out, "\n");
Greg Clayton54e7afa2010-07-09 20:39:50 +0000261 fprintf (out, "%*s%s", indent_level, "", name);
Jim Ingham34e9a982010-06-15 18:47:14 +0000262
263 for (uint32_t i = 0; i < num_options; ++i)
264 {
265 if (option_table[i].usage_mask & opt_set_mask)
266 {
Caroline Tice4d6675c2010-10-01 19:59:14 +0000267 CommandArgumentType arg_type = option_table[i].argument_type;
268 std::string arg_name;
269 GetArgumentName (arg_type, arg_name);
Jim Ingham34e9a982010-06-15 18:47:14 +0000270 if (option_table[i].required)
271 {
272 if (option_table[i].option_has_arg == required_argument)
Caroline Tice4d6675c2010-10-01 19:59:14 +0000273 fprintf (out, " -%c <%s>", option_table[i].short_option, arg_name.c_str());
Jim Ingham34e9a982010-06-15 18:47:14 +0000274 else if (option_table[i].option_has_arg == optional_argument)
Caroline Tice4d6675c2010-10-01 19:59:14 +0000275 fprintf (out, " -%c [<%s>]", option_table[i].short_option, arg_name.c_str());
Jim Ingham34e9a982010-06-15 18:47:14 +0000276 else
277 fprintf (out, " -%c", option_table[i].short_option);
278 }
279 else
280 {
281 if (option_table[i].option_has_arg == required_argument)
Caroline Tice4d6675c2010-10-01 19:59:14 +0000282 fprintf (out, " [-%c <%s>]", option_table[i].short_option, arg_name.c_str());
Jim Ingham34e9a982010-06-15 18:47:14 +0000283 else if (option_table[i].option_has_arg == optional_argument)
Caroline Tice4d6675c2010-10-01 19:59:14 +0000284 fprintf (out, " [-%c [<%s>]]", option_table[i].short_option, arg_name.c_str());
Jim Ingham34e9a982010-06-15 18:47:14 +0000285 else
286 fprintf (out, " [-%c]", option_table[i].short_option);
287 }
288 }
Chris Lattner24943d22010-06-08 16:52:24 +0000289 }
290 }
291
292 fprintf (out, "\n\n");
293
294 // Now print out all the detailed information about the various options: long form, short form and help text:
295 // -- long_name <argument>
296 // - short <argument>
297 // help text
298
299 // This variable is used to keep track of which options' info we've printed out, because some options can be in
300 // more than one usage level, but we only want to print the long form of its information once.
301
302 Driver::OptionData::OptionSet options_seen;
303 Driver::OptionData::OptionSet::iterator pos;
304
305 indent_level += 5;
306
Jim Ingham34e9a982010-06-15 18:47:14 +0000307 for (uint32_t i = 0; i < num_options; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000308 {
309 // Only print this option if we haven't already seen it.
310 pos = options_seen.find (option_table[i].short_option);
311 if (pos == options_seen.end())
312 {
Caroline Tice4d6675c2010-10-01 19:59:14 +0000313 CommandArgumentType arg_type = option_table[i].argument_type;
314 std::string arg_name;
315 GetArgumentName (arg_type, arg_name);
316
Chris Lattner24943d22010-06-08 16:52:24 +0000317 options_seen.insert (option_table[i].short_option);
Greg Clayton54e7afa2010-07-09 20:39:50 +0000318 fprintf (out, "%*s-%c ", indent_level, "", option_table[i].short_option);
Caroline Tice4d6675c2010-10-01 19:59:14 +0000319 if (arg_type != eArgTypeNone)
320 fprintf (out, "<%s>", arg_name.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000321 fprintf (out, "\n");
Greg Clayton54e7afa2010-07-09 20:39:50 +0000322 fprintf (out, "%*s--%s ", indent_level, "", option_table[i].long_option);
Caroline Tice4d6675c2010-10-01 19:59:14 +0000323 if (arg_type != eArgTypeNone)
324 fprintf (out, "<%s>", arg_name.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000325 fprintf (out, "\n");
326 indent_level += 5;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000327 OutputFormattedUsageText (out, indent_level, option_table[i].usage_text, screen_width);
Chris Lattner24943d22010-06-08 16:52:24 +0000328 indent_level -= 5;
329 fprintf (out, "\n");
330 }
331 }
332
333 indent_level -= 5;
334
Greg Clayton54e7afa2010-07-09 20:39:50 +0000335 fprintf (out, "\n%*s('%s <filename>' also works, to specify the file to be debugged.)\n\n",
336 indent_level, "", name);
Chris Lattner24943d22010-06-08 16:52:24 +0000337}
338
339void
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000340BuildGetOptTable (lldb::OptionDefinition *expanded_option_table, std::vector<struct option> &getopt_table,
341 uint32_t num_options)
Chris Lattner24943d22010-06-08 16:52:24 +0000342{
343 if (num_options == 0)
344 return;
345
346 uint32_t i;
347 uint32_t j;
348 std::bitset<256> option_seen;
349
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000350 getopt_table.resize (num_options + 1);
351
Chris Lattner24943d22010-06-08 16:52:24 +0000352 for (i = 0, j = 0; i < num_options; ++i)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000353 {
Chris Lattner24943d22010-06-08 16:52:24 +0000354 char short_opt = expanded_option_table[i].short_option;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000355
Chris Lattner24943d22010-06-08 16:52:24 +0000356 if (option_seen.test(short_opt) == false)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000357 {
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000358 getopt_table[j].name = expanded_option_table[i].long_option;
359 getopt_table[j].has_arg = expanded_option_table[i].option_has_arg;
360 getopt_table[j].flag = NULL;
361 getopt_table[j].val = expanded_option_table[i].short_option;
Chris Lattner24943d22010-06-08 16:52:24 +0000362 option_seen.set(short_opt);
363 ++j;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000364 }
365 }
Chris Lattner24943d22010-06-08 16:52:24 +0000366
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000367 getopt_table[j].name = NULL;
368 getopt_table[j].has_arg = 0;
369 getopt_table[j].flag = NULL;
370 getopt_table[j].val = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000371
372}
373
Greg Clayton63094e02010-06-23 01:19:29 +0000374Driver::OptionData::OptionData () :
Greg Clayton4dc18922010-12-08 22:23:24 +0000375 m_args(),
Greg Clayton63094e02010-06-23 01:19:29 +0000376 m_script_lang (lldb::eScriptLanguageDefault),
Greg Clayton54e7afa2010-07-09 20:39:50 +0000377 m_crash_log (),
Greg Clayton63094e02010-06-23 01:19:29 +0000378 m_source_command_files (),
379 m_debug_mode (false),
Greg Clayton54e7afa2010-07-09 20:39:50 +0000380 m_print_version (false),
Greg Clayton63094e02010-06-23 01:19:29 +0000381 m_print_help (false),
Jim Ingham74989e82010-08-30 19:44:40 +0000382 m_seen_options(),
383 m_use_external_editor(false)
Chris Lattner24943d22010-06-08 16:52:24 +0000384{
Greg Clayton63094e02010-06-23 01:19:29 +0000385}
386
387Driver::OptionData::~OptionData ()
388{
389}
390
391void
392Driver::OptionData::Clear ()
393{
Greg Clayton4dc18922010-12-08 22:23:24 +0000394 m_args.clear ();
Greg Clayton63094e02010-06-23 01:19:29 +0000395 m_script_lang = lldb::eScriptLanguageDefault;
396 m_source_command_files.clear ();
397 m_debug_mode = false;
398 m_print_help = false;
399 m_print_version = false;
Jim Ingham74989e82010-08-30 19:44:40 +0000400 m_use_external_editor = false;
Greg Clayton63094e02010-06-23 01:19:29 +0000401}
402
403void
404Driver::ResetOptionValues ()
405{
406 m_option_data.Clear ();
407}
408
409const char *
410Driver::GetFilename() const
411{
Greg Clayton4dc18922010-12-08 22:23:24 +0000412 if (m_option_data.m_args.empty())
Greg Clayton63094e02010-06-23 01:19:29 +0000413 return NULL;
Greg Clayton4dc18922010-12-08 22:23:24 +0000414 return m_option_data.m_args.front().c_str();
Greg Clayton63094e02010-06-23 01:19:29 +0000415}
416
417const char *
418Driver::GetCrashLogFilename() const
419{
420 if (m_option_data.m_crash_log.empty())
421 return NULL;
422 return m_option_data.m_crash_log.c_str();
423}
424
425lldb::ScriptLanguage
426Driver::GetScriptLanguage() const
427{
428 return m_option_data.m_script_lang;
429}
430
431size_t
432Driver::GetNumSourceCommandFiles () const
433{
434 return m_option_data.m_source_command_files.size();
435}
436
437const char *
438Driver::GetSourceCommandFileAtIndex (uint32_t idx) const
439{
440 if (idx < m_option_data.m_source_command_files.size())
441 return m_option_data.m_source_command_files[idx].c_str();
442 return NULL;
443}
444
445bool
446Driver::GetDebugMode() const
447{
448 return m_option_data.m_debug_mode;
449}
450
451
452// Check the arguments that were passed to this program to make sure they are valid and to get their
453// argument values (if any). Return a boolean value indicating whether or not to start up the full
454// debugger (i.e. the Command Interpreter) or not. Return FALSE if the arguments were invalid OR
455// if the user only wanted help or version information.
456
457SBError
458Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exit)
459{
460 ResetOptionValues ();
461
462 SBCommandReturnObject result;
463
Chris Lattner24943d22010-06-08 16:52:24 +0000464 SBError error;
465 std::string option_string;
466 struct option *long_options = NULL;
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000467 std::vector<struct option> long_options_vector;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000468 uint32_t num_options;
Chris Lattner24943d22010-06-08 16:52:24 +0000469
Greg Clayton54e7afa2010-07-09 20:39:50 +0000470 for (num_options = 0; g_options[num_options].long_option != NULL; ++num_options)
471 /* Do Nothing. */;
Chris Lattner24943d22010-06-08 16:52:24 +0000472
473 if (num_options == 0)
474 {
475 if (argc > 1)
476 error.SetErrorStringWithFormat ("invalid number of options");
477 return error;
478 }
479
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000480 BuildGetOptTable (g_options, long_options_vector, num_options);
Chris Lattner24943d22010-06-08 16:52:24 +0000481
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000482 if (long_options_vector.empty())
483 long_options = NULL;
484 else
485 long_options = &long_options_vector.front();
Chris Lattner24943d22010-06-08 16:52:24 +0000486
487 if (long_options == NULL)
488 {
489 error.SetErrorStringWithFormat ("invalid long options");
490 return error;
491 }
492
493 // Build the option_string argument for call to getopt_long.
494
495 for (int i = 0; long_options[i].name != NULL; ++i)
496 {
497 if (long_options[i].flag == NULL)
498 {
499 option_string.push_back ((char) long_options[i].val);
500 switch (long_options[i].has_arg)
501 {
502 default:
503 case no_argument:
504 break;
505 case required_argument:
506 option_string.push_back (':');
507 break;
508 case optional_argument:
509 option_string.append ("::");
510 break;
511 }
512 }
513 }
514
515 // Prepare for & make calls to getopt_long.
Eli Friedmanef2bc872010-06-13 19:18:49 +0000516#if __GLIBC__
517 optind = 0;
518#else
Chris Lattner24943d22010-06-08 16:52:24 +0000519 optreset = 1;
520 optind = 1;
Eli Friedmanef2bc872010-06-13 19:18:49 +0000521#endif
Chris Lattner24943d22010-06-08 16:52:24 +0000522 int val;
523 while (1)
524 {
525 int long_options_index = -1;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000526 val = ::getopt_long (argc, const_cast<char **>(argv), option_string.c_str(), long_options, &long_options_index);
Chris Lattner24943d22010-06-08 16:52:24 +0000527
528 if (val == -1)
529 break;
530 else if (val == '?')
531 {
Greg Clayton63094e02010-06-23 01:19:29 +0000532 m_option_data.m_print_help = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000533 error.SetErrorStringWithFormat ("unknown or ambiguous option");
534 break;
535 }
536 else if (val == 0)
537 continue;
538 else
539 {
Greg Clayton63094e02010-06-23 01:19:29 +0000540 m_option_data.m_seen_options.insert ((char) val);
Chris Lattner24943d22010-06-08 16:52:24 +0000541 if (long_options_index == -1)
542 {
543 for (int i = 0;
544 long_options[i].name || long_options[i].has_arg || long_options[i].flag || long_options[i].val;
545 ++i)
546 {
547 if (long_options[i].val == val)
548 {
549 long_options_index = i;
550 break;
551 }
552 }
553 }
554
555 if (long_options_index >= 0)
556 {
Greg Clayton63094e02010-06-23 01:19:29 +0000557 const char short_option = (char) g_options[long_options_index].short_option;
558
559 switch (short_option)
560 {
561 case 'h':
562 m_option_data.m_print_help = true;
563 break;
564
565 case 'v':
566 m_option_data.m_print_version = true;
567 break;
568
569 case 'c':
570 m_option_data.m_crash_log = optarg;
571 break;
Greg Clayton887aa282010-10-11 01:05:37 +0000572
Jim Ingham74989e82010-08-30 19:44:40 +0000573 case 'e':
574 m_option_data.m_use_external_editor = true;
575 break;
Greg Clayton887aa282010-10-11 01:05:37 +0000576
577 case 'n':
578 m_debugger.SkipLLDBInitFiles (true);
579 break;
580
Greg Clayton63094e02010-06-23 01:19:29 +0000581 case 'f':
582 {
583 SBFileSpec file(optarg);
584 if (file.Exists())
Greg Clayton4dc18922010-12-08 22:23:24 +0000585 {
586 m_option_data.m_args.push_back (optarg);
587 }
Caroline Ticeeddffe92010-09-10 04:48:55 +0000588 else if (file.ResolveExecutableLocation())
589 {
590 char path[PATH_MAX];
591 int path_len;
592 file.GetPath (path, path_len);
Greg Clayton4dc18922010-12-08 22:23:24 +0000593 m_option_data.m_args.push_back (path);
Caroline Ticeeddffe92010-09-10 04:48:55 +0000594 }
Greg Clayton63094e02010-06-23 01:19:29 +0000595 else
596 error.SetErrorStringWithFormat("file specified in --file (-f) option doesn't exist: '%s'", optarg);
597 }
598 break;
599
600 case 'a':
601 if (!m_debugger.SetDefaultArchitecture (optarg))
602 error.SetErrorStringWithFormat("invalid architecture in the -a or --arch option: '%s'", optarg);
603 break;
604
605 case 'l':
606 m_option_data.m_script_lang = m_debugger.GetScriptingLanguage (optarg);
607 break;
608
609 case 'd':
610 m_option_data.m_debug_mode = true;
611 break;
612
613 case 's':
614 {
615 SBFileSpec file(optarg);
616 if (file.Exists())
617 m_option_data.m_source_command_files.push_back (optarg);
Caroline Ticeeddffe92010-09-10 04:48:55 +0000618 else if (file.ResolveExecutableLocation())
619 {
620 char final_path[PATH_MAX];
621 size_t path_len;
622 file.GetPath (final_path, path_len);
623 std::string path_str (final_path);
624 m_option_data.m_source_command_files.push_back (path_str);
625 }
Greg Clayton63094e02010-06-23 01:19:29 +0000626 else
627 error.SetErrorStringWithFormat("file specified in --source (-s) option doesn't exist: '%s'", optarg);
628 }
629 break;
630
631 default:
632 m_option_data.m_print_help = true;
633 error.SetErrorStringWithFormat ("unrecognized option %c", short_option);
634 break;
635 }
Chris Lattner24943d22010-06-08 16:52:24 +0000636 }
637 else
638 {
639 error.SetErrorStringWithFormat ("invalid option with value %i", val);
640 }
641 if (error.Fail())
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000642 {
Greg Clayton63094e02010-06-23 01:19:29 +0000643 return error;
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000644 }
Chris Lattner24943d22010-06-08 16:52:24 +0000645 }
646 }
Jim Ingham34e9a982010-06-15 18:47:14 +0000647
Greg Clayton63094e02010-06-23 01:19:29 +0000648 if (error.Fail() || m_option_data.m_print_help)
Chris Lattner24943d22010-06-08 16:52:24 +0000649 {
650 ShowUsage (out_fh, g_options, m_option_data);
Greg Clayton9caa9462010-10-11 01:13:37 +0000651 exit = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000652 }
653 else if (m_option_data.m_print_version)
654 {
Greg Clayton63094e02010-06-23 01:19:29 +0000655 ::fprintf (out_fh, "%s\n", m_debugger.GetVersionString());
656 exit = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000657 }
658 else if (! m_option_data.m_crash_log.empty())
659 {
660 // Handle crash log stuff here.
661 }
662 else
663 {
Greg Clayton4dc18922010-12-08 22:23:24 +0000664 // Any arguments that are left over after option parsing are for
665 // the program. If a file was specified with -f then the filename
666 // is already in the m_option_data.m_args array, and any remaining args
667 // are arguments for the inferior program. If no file was specified with
668 // -f, then what is left is the program name followed by any arguments.
669
670 // Skip any options we consumed with getopt_long
671 argc -= optind;
672 argv += optind;
673
674 if (argc > 0)
675 {
676 for (int arg_idx=0; arg_idx<argc; ++arg_idx)
677 {
678 const char *arg = argv[arg_idx];
679 if (arg)
680 m_option_data.m_args.push_back (arg);
681 }
682 }
683
Chris Lattner24943d22010-06-08 16:52:24 +0000684 }
685
Greg Clayton63094e02010-06-23 01:19:29 +0000686 return error;
Chris Lattner24943d22010-06-08 16:52:24 +0000687}
688
Caroline Tice757500e2010-09-29 18:35:42 +0000689size_t
Chris Lattner24943d22010-06-08 16:52:24 +0000690Driver::GetProcessSTDOUT ()
691{
692 // The process has stuff waiting for stdout; get it and write it out to the appropriate place.
693 char stdio_buffer[1024];
694 size_t len;
Caroline Tice757500e2010-09-29 18:35:42 +0000695 size_t total_bytes = 0;
Jim Inghamc8332952010-08-26 21:32:51 +0000696 while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0)
Caroline Tice757500e2010-09-29 18:35:42 +0000697 {
Chris Lattner24943d22010-06-08 16:52:24 +0000698 m_io_channel_ap->OutWrite (stdio_buffer, len);
Caroline Tice757500e2010-09-29 18:35:42 +0000699 total_bytes += len;
700 }
701 return total_bytes;
Chris Lattner24943d22010-06-08 16:52:24 +0000702}
703
Caroline Tice757500e2010-09-29 18:35:42 +0000704size_t
Chris Lattner24943d22010-06-08 16:52:24 +0000705Driver::GetProcessSTDERR ()
706{
707 // The process has stuff waiting for stderr; get it and write it out to the appropriate place.
708 char stdio_buffer[1024];
709 size_t len;
Caroline Tice757500e2010-09-29 18:35:42 +0000710 size_t total_bytes = 0;
Jim Inghamc8332952010-08-26 21:32:51 +0000711 while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0)
Caroline Tice757500e2010-09-29 18:35:42 +0000712 {
Chris Lattner24943d22010-06-08 16:52:24 +0000713 m_io_channel_ap->ErrWrite (stdio_buffer, len);
Caroline Tice757500e2010-09-29 18:35:42 +0000714 total_bytes += len;
715 }
716 return total_bytes;
Chris Lattner24943d22010-06-08 16:52:24 +0000717}
718
719void
Jim Inghamc8332952010-08-26 21:32:51 +0000720Driver::UpdateSelectedThread ()
Chris Lattner24943d22010-06-08 16:52:24 +0000721{
722 using namespace lldb;
Jim Inghamc8332952010-08-26 21:32:51 +0000723 SBProcess process(m_debugger.GetSelectedTarget().GetProcess());
Chris Lattner24943d22010-06-08 16:52:24 +0000724 if (process.IsValid())
725 {
Jim Inghamc8332952010-08-26 21:32:51 +0000726 SBThread curr_thread (process.GetSelectedThread());
Chris Lattner24943d22010-06-08 16:52:24 +0000727 SBThread thread;
728 StopReason curr_thread_stop_reason = eStopReasonInvalid;
729 curr_thread_stop_reason = curr_thread.GetStopReason();
730
731 if (!curr_thread.IsValid() ||
732 curr_thread_stop_reason == eStopReasonInvalid ||
733 curr_thread_stop_reason == eStopReasonNone)
734 {
735 // Prefer a thread that has just completed its plan over another thread as current thread.
736 SBThread plan_thread;
737 SBThread other_thread;
738 const size_t num_threads = process.GetNumThreads();
739 size_t i;
740 for (i = 0; i < num_threads; ++i)
741 {
742 thread = process.GetThreadAtIndex(i);
743 StopReason thread_stop_reason = thread.GetStopReason();
744 switch (thread_stop_reason)
745 {
746 default:
747 case eStopReasonInvalid:
748 case eStopReasonNone:
749 break;
750
751 case eStopReasonTrace:
752 case eStopReasonBreakpoint:
753 case eStopReasonWatchpoint:
754 case eStopReasonSignal:
755 case eStopReasonException:
756 if (!other_thread.IsValid())
757 other_thread = thread;
758 break;
759 case eStopReasonPlanComplete:
760 if (!plan_thread.IsValid())
761 plan_thread = thread;
762 break;
763 }
764 }
765 if (plan_thread.IsValid())
Jim Inghamc8332952010-08-26 21:32:51 +0000766 process.SetSelectedThread (plan_thread);
Chris Lattner24943d22010-06-08 16:52:24 +0000767 else if (other_thread.IsValid())
Jim Inghamc8332952010-08-26 21:32:51 +0000768 process.SetSelectedThread (other_thread);
Chris Lattner24943d22010-06-08 16:52:24 +0000769 else
770 {
771 if (curr_thread.IsValid())
772 thread = curr_thread;
773 else
774 thread = process.GetThreadAtIndex(0);
775
776 if (thread.IsValid())
Jim Inghamc8332952010-08-26 21:32:51 +0000777 process.SetSelectedThread (thread);
Chris Lattner24943d22010-06-08 16:52:24 +0000778 }
779 }
780 }
781}
782
783
784// This function handles events that were broadcast by the process.
785void
786Driver::HandleProcessEvent (const SBEvent &event)
787{
788 using namespace lldb;
789 const uint32_t event_type = event.GetType();
790
791 if (event_type & SBProcess::eBroadcastBitSTDOUT)
792 {
793 // The process has stdout available, get it and write it out to the
794 // appropriate place.
Caroline Tice757500e2010-09-29 18:35:42 +0000795 if (GetProcessSTDOUT ())
796 m_io_channel_ap->RefreshPrompt();
Chris Lattner24943d22010-06-08 16:52:24 +0000797 }
798 else if (event_type & SBProcess::eBroadcastBitSTDERR)
799 {
800 // The process has stderr available, get it and write it out to the
801 // appropriate place.
Caroline Tice757500e2010-09-29 18:35:42 +0000802 if (GetProcessSTDERR ())
803 m_io_channel_ap->RefreshPrompt();
Chris Lattner24943d22010-06-08 16:52:24 +0000804 }
805 else if (event_type & SBProcess::eBroadcastBitStateChanged)
806 {
807 // Drain all stout and stderr so we don't see any output come after
808 // we print our prompts
Caroline Tice757500e2010-09-29 18:35:42 +0000809 if (GetProcessSTDOUT ()
810 || GetProcessSTDERR ())
811 m_io_channel_ap->RefreshPrompt();
Chris Lattner24943d22010-06-08 16:52:24 +0000812
813 // Something changed in the process; get the event and report the process's current status and location to
814 // the user.
815 StateType event_state = SBProcess::GetStateFromEvent (event);
816 if (event_state == eStateInvalid)
817 return;
818
819 SBProcess process (SBProcess::GetProcessFromEvent (event));
820 assert (process.IsValid());
821
822 switch (event_state)
823 {
824 case eStateInvalid:
825 case eStateUnloaded:
Greg Claytone71e2582011-02-04 01:58:07 +0000826 case eStateConnected:
Chris Lattner24943d22010-06-08 16:52:24 +0000827 case eStateAttaching:
828 case eStateLaunching:
829 case eStateStepping:
830 case eStateDetached:
831 {
832 char message[1024];
833 int message_len = ::snprintf (message, sizeof(message), "Process %d %s\n", process.GetProcessID(),
Greg Clayton63094e02010-06-23 01:19:29 +0000834 m_debugger.StateAsCString (event_state));
Chris Lattner24943d22010-06-08 16:52:24 +0000835 m_io_channel_ap->OutWrite(message, message_len);
836 }
837 break;
838
839 case eStateRunning:
840 // Don't be chatty when we run...
841 break;
842
843 case eStateExited:
Caroline Tice757500e2010-09-29 18:35:42 +0000844 {
845 SBCommandReturnObject result;
846 m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
847 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize());
848 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize());
849 m_io_channel_ap->RefreshPrompt();
850 }
Chris Lattner24943d22010-06-08 16:52:24 +0000851 break;
852
853 case eStateStopped:
854 case eStateCrashed:
855 case eStateSuspended:
856 // Make sure the program hasn't been auto-restarted:
857 if (SBProcess::GetRestartedFromEvent (event))
858 {
859 // FIXME: Do we want to report this, or would that just be annoyingly chatty?
860 char message[1024];
861 int message_len = ::snprintf (message, sizeof(message), "Process %d stopped and was programmatically restarted.\n",
862 process.GetProcessID());
863 m_io_channel_ap->OutWrite(message, message_len);
Caroline Tice757500e2010-09-29 18:35:42 +0000864 m_io_channel_ap->RefreshPrompt ();
Chris Lattner24943d22010-06-08 16:52:24 +0000865 }
866 else
867 {
Caroline Tice757500e2010-09-29 18:35:42 +0000868 SBCommandReturnObject result;
Jim Inghamc8332952010-08-26 21:32:51 +0000869 UpdateSelectedThread ();
Caroline Tice757500e2010-09-29 18:35:42 +0000870 m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
871 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize());
872 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize());
873 m_io_channel_ap->RefreshPrompt ();
Chris Lattner24943d22010-06-08 16:52:24 +0000874 }
875 break;
876 }
877 }
878}
879
880// This function handles events broadcast by the IOChannel (HasInput, UserInterrupt, or ThreadShouldExit).
881
882bool
883Driver::HandleIOEvent (const SBEvent &event)
884{
885 bool quit = false;
886
887 const uint32_t event_type = event.GetType();
888
889 if (event_type & IOChannel::eBroadcastBitHasUserInput)
890 {
891 // We got some input (i.e. a command string) from the user; pass it off to the command interpreter for
892 // handling.
893
894 const char *command_string = SBEvent::GetCStringFromEvent(event);
895 if (command_string == NULL)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000896 command_string = "";
Chris Lattner24943d22010-06-08 16:52:24 +0000897 SBCommandReturnObject result;
Jim Ingham2e8cb8a2011-02-19 02:53:09 +0000898 result.SetImmediateOutputFile (m_debugger.GetOutputFileHandle());
899 result.SetImmediateErrorFile (m_debugger.GetErrorFileHandle());
900
901 // We've set the result to dump immediately.
902 m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, true);
903
Chris Lattner24943d22010-06-08 16:52:24 +0000904 // We are done getting and running our command, we can now clear the
905 // m_waiting_for_command so we can get another one.
906 m_waiting_for_command = false;
907
908 // If our editline input reader is active, it means another input reader
909 // got pushed onto the input reader and caused us to become deactivated.
910 // When the input reader above us gets popped, we will get re-activated
911 // and our prompt will refresh in our callback
912 if (m_editline_reader.IsActive())
913 {
914 ReadyForCommand ();
915 }
916 }
917 else if (event_type & IOChannel::eBroadcastBitUserInterrupt)
918 {
919 // This is here to handle control-c interrupts from the user. It has not yet really been implemented.
920 // TO BE DONE: PROPERLY HANDLE CONTROL-C FROM USER
921 //m_io_channel_ap->CancelInput();
922 // Anything else? Send Interrupt to process?
923 }
924 else if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
925 (event_type & IOChannel::eBroadcastBitThreadDidExit))
926 {
927 // If the IOChannel thread is trying to go away, then it is definitely
928 // time to end the debugging session.
929 quit = true;
930 }
931
932 return quit;
933}
934
935
936//struct CrashImageInfo
937//{
938// std::string path;
939// VMRange text_range;
Greg Clayton0467c782011-02-04 18:53:10 +0000940// lldb_private::UUID uuid;
Chris Lattner24943d22010-06-08 16:52:24 +0000941//};
942//
943//void
944//Driver::ParseCrashLog (const char *crash_log)
945//{
946// printf("Parsing crash log: %s\n", crash_log);
947//
948// char image_path[PATH_MAX];
949// std::vector<CrashImageInfo> crash_infos;
950// if (crash_log && crash_log[0])
951// {
952// FileSpec crash_log_file (crash_log);
953// STLStringArray crash_log_lines;
954// if (crash_log_file.ReadFileLines (crash_log_lines))
955// {
956// const size_t num_crash_log_lines = crash_log_lines.size();
957// size_t i;
958// for (i=0; i<num_crash_log_lines; ++i)
959// {
960// const char *line = crash_log_lines[i].c_str();
961// if (strstr (line, "Code Type:"))
962// {
963// char arch_string[256];
964// if (sscanf(line, "%s", arch_string))
965// {
966// if (strcmp(arch_string, "X86-64"))
967// lldb::GetDefaultArchitecture ().SetArch ("x86_64");
968// else if (strcmp(arch_string, "X86"))
969// lldb::GetDefaultArchitecture ().SetArch ("i386");
970// else
971// {
972// ArchSpec arch(arch_string);
973// if (arch.IsValid ())
974// lldb::GetDefaultArchitecture () = arch;
975// else
976// fprintf(stderr, "Unrecognized architecture: %s\n", arch_string);
977// }
978// }
979// }
980// else
981// if (strstr(line, "Path:"))
982// {
983// const char *p = line + strlen("Path:");
984// while (isspace(*p))
985// ++p;
986//
987// m_option_data.m_filename.assign (p);
988// }
989// else
990// if (strstr(line, "Binary Images:"))
991// {
992// while (++i < num_crash_log_lines)
993// {
994// if (crash_log_lines[i].empty())
995// break;
996//
997// line = crash_log_lines[i].c_str();
998// uint64_t text_start_addr;
999// uint64_t text_end_addr;
1000// char uuid_cstr[64];
1001// int bytes_consumed_before_uuid = 0;
1002// int bytes_consumed_after_uuid = 0;
1003//
1004// int items_parsed = ::sscanf (line,
1005// "%llx - %llx %*s %*s %*s %n%s %n",
1006// &text_start_addr,
1007// &text_end_addr,
1008// &bytes_consumed_before_uuid,
1009// uuid_cstr,
1010// &bytes_consumed_after_uuid);
1011//
1012// if (items_parsed == 3)
1013// {
1014//
1015// CrashImageInfo info;
1016// info.text_range.SetBaseAddress(text_start_addr);
1017// info.text_range.SetEndAddress(text_end_addr);
1018//
1019// if (uuid_cstr[0] == '<')
1020// {
1021// if (info.uuid.SetfromCString (&uuid_cstr[1]) == 0)
1022// info.uuid.Clear();
1023//
1024// ::strncpy (image_path, line + bytes_consumed_after_uuid, sizeof(image_path));
1025// }
1026// else
1027// {
1028// ::strncpy (image_path, line + bytes_consumed_before_uuid, sizeof(image_path));
1029// }
1030//
1031// info.path = image_path;
1032//
1033// crash_infos.push_back (info);
1034//
1035// info.uuid.GetAsCString(uuid_cstr, sizeof(uuid_cstr));
1036//
1037// printf("0x%16.16llx - 0x%16.16llx <%s> %s\n",
1038// text_start_addr,
1039// text_end_addr,
1040// uuid_cstr,
1041// image_path);
1042// }
1043// }
1044// }
1045// }
1046// }
1047//
1048// if (crash_infos.size())
1049// {
Greg Clayton63094e02010-06-23 01:19:29 +00001050// SBTarget target (m_debugger.CreateTarget (crash_infos.front().path.c_str(),
Chris Lattner24943d22010-06-08 16:52:24 +00001051// lldb::GetDefaultArchitecture().AsCString (),
1052// false));
1053// if (target.IsValid())
1054// {
1055//
1056// }
1057// }
1058// }
1059//}
1060//
1061
1062void
1063Driver::MasterThreadBytesReceived (void *baton, const void *src, size_t src_len)
1064{
1065 Driver *driver = (Driver*)baton;
1066 driver->GetFromMaster ((const char *)src, src_len);
1067}
1068
1069void
1070Driver::GetFromMaster (const char *src, size_t src_len)
1071{
1072 // Echo the characters back to the Debugger's stdout, that way if you
1073 // type characters while a command is running, you'll see what you've typed.
Greg Clayton63094e02010-06-23 01:19:29 +00001074 FILE *out_fh = m_debugger.GetOutputFileHandle();
Chris Lattner24943d22010-06-08 16:52:24 +00001075 if (out_fh)
1076 ::fwrite (src, 1, src_len, out_fh);
1077}
1078
1079size_t
1080Driver::EditLineInputReaderCallback
1081(
1082 void *baton,
1083 SBInputReader *reader,
1084 InputReaderAction notification,
1085 const char *bytes,
1086 size_t bytes_len
1087)
1088{
1089 Driver *driver = (Driver *)baton;
1090
1091 switch (notification)
1092 {
1093 case eInputReaderActivate:
1094 break;
1095
1096 case eInputReaderReactivate:
1097 driver->ReadyForCommand();
1098 break;
1099
1100 case eInputReaderDeactivate:
1101 break;
1102
Caroline Ticec4f55fe2010-11-19 20:47:54 +00001103 case eInputReaderInterrupt:
1104 if (driver->m_io_channel_ap.get() != NULL)
1105 {
1106 driver->m_io_channel_ap->OutWrite ("^C\n", 3);
1107 driver->m_io_channel_ap->RefreshPrompt();
1108 }
1109 break;
1110
1111 case eInputReaderEndOfFile:
1112 if (driver->m_io_channel_ap.get() != NULL)
1113 {
1114 driver->m_io_channel_ap->OutWrite ("^D\n", 3);
1115 driver->m_io_channel_ap->RefreshPrompt ();
1116 }
1117 write (driver->m_editline_pty.GetMasterFileDescriptor(), "quit\n", 5);
1118 break;
1119
Chris Lattner24943d22010-06-08 16:52:24 +00001120 case eInputReaderGotToken:
1121 write (driver->m_editline_pty.GetMasterFileDescriptor(), bytes, bytes_len);
1122 break;
1123
1124 case eInputReaderDone:
1125 break;
1126 }
1127 return bytes_len;
1128}
1129
1130void
1131Driver::MainLoop ()
1132{
1133 char error_str[1024];
1134 if (m_editline_pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, error_str, sizeof(error_str)) == false)
1135 {
1136 ::fprintf (stderr, "error: failed to open driver pseudo terminal : %s", error_str);
1137 exit(1);
1138 }
1139 else
1140 {
1141 const char *driver_slave_name = m_editline_pty.GetSlaveName (error_str, sizeof(error_str));
1142 if (driver_slave_name == NULL)
1143 {
1144 ::fprintf (stderr, "error: failed to get slave name for driver pseudo terminal : %s", error_str);
1145 exit(2);
1146 }
1147 else
1148 {
1149 m_editline_slave_fh = ::fopen (driver_slave_name, "r+");
1150 if (m_editline_slave_fh == NULL)
1151 {
1152 SBError error;
1153 error.SetErrorToErrno();
1154 ::fprintf (stderr, "error: failed to get open slave for driver pseudo terminal : %s",
1155 error.GetCString());
1156 exit(3);
1157 }
1158
1159 ::setbuf (m_editline_slave_fh, NULL);
1160 }
1161 }
1162
1163
1164 // struct termios stdin_termios;
1165
1166 if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0)
1167 atexit (reset_stdin_termios);
1168
1169 ::setbuf (stdin, NULL);
1170 ::setbuf (stdout, NULL);
1171
Greg Clayton63094e02010-06-23 01:19:29 +00001172 m_debugger.SetErrorFileHandle (stderr, false);
1173 m_debugger.SetOutputFileHandle (stdout, false);
1174 m_debugger.SetInputFileHandle (stdin, true);
Jim Ingham74989e82010-08-30 19:44:40 +00001175
1176 m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor);
Chris Lattner24943d22010-06-08 16:52:24 +00001177
1178 // You have to drain anything that comes to the master side of the PTY. master_out_comm is
1179 // for that purpose. The reason you need to do this is a curious reason... editline will echo
1180 // characters to the PTY when it gets characters while el_gets is not running, and then when
1181 // you call el_gets (or el_getc) it will try to reset the terminal back to raw mode which blocks
1182 // if there are unconsumed characters in the out buffer.
1183 // However, you don't need to do anything with the characters, since editline will dump these
1184 // unconsumed characters after printing the prompt again in el_gets.
1185
Greg Claytoneecb0f32010-12-04 02:39:47 +00001186 SBCommunication master_out_comm("driver.editline");
1187 master_out_comm.SetCloseOnEOF (false);
Chris Lattner24943d22010-06-08 16:52:24 +00001188 master_out_comm.AdoptFileDesriptor(m_editline_pty.GetMasterFileDescriptor(), false);
1189 master_out_comm.SetReadThreadBytesReceivedCallback(Driver::MasterThreadBytesReceived, this);
1190
1191 if (master_out_comm.ReadThreadStart () == false)
1192 {
1193 ::fprintf (stderr, "error: failed to start master out read thread");
1194 exit(5);
1195 }
1196
1197// const char *crash_log = GetCrashLogFilename();
1198// if (crash_log)
1199// {
1200// ParseCrashLog (crash_log);
1201// }
1202//
Greg Clayton63094e02010-06-23 01:19:29 +00001203 SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter();
Chris Lattner24943d22010-06-08 16:52:24 +00001204
1205 m_io_channel_ap.reset (new IOChannel(m_editline_slave_fh, stdout, stderr, this));
1206
1207 struct winsize window_size;
1208 if (isatty (STDIN_FILENO)
1209 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
1210 {
Caroline Tice6e4c5ce2010-09-04 00:03:46 +00001211 if (window_size.ws_col > 0)
Greg Clayton238c0a12010-09-18 01:14:36 +00001212 m_debugger.SetTerminalWidth (window_size.ws_col);
Chris Lattner24943d22010-06-08 16:52:24 +00001213 }
1214
1215 // Since input can be redirected by the debugger, we must insert our editline
1216 // input reader in the queue so we know when our reader should be active
1217 // and so we can receive bytes only when we are supposed to.
Greg Clayton63094e02010-06-23 01:19:29 +00001218 SBError err (m_editline_reader.Initialize (m_debugger,
1219 Driver::EditLineInputReaderCallback, // callback
Chris Lattner24943d22010-06-08 16:52:24 +00001220 this, // baton
1221 eInputReaderGranularityByte, // token_size
1222 NULL, // end token - NULL means never done
1223 NULL, // prompt - taken care of elsewhere
1224 false)); // echo input - don't need Debugger
1225 // to do this, we handle it elsewhere
1226
1227 if (err.Fail())
1228 {
1229 ::fprintf (stderr, "error: %s", err.GetCString());
1230 exit (6);
1231 }
1232
Greg Clayton63094e02010-06-23 01:19:29 +00001233 m_debugger.PushInputReader (m_editline_reader);
Chris Lattner24943d22010-06-08 16:52:24 +00001234
Greg Clayton63094e02010-06-23 01:19:29 +00001235 SBListener listener(m_debugger.GetListener());
Chris Lattner24943d22010-06-08 16:52:24 +00001236 if (listener.IsValid())
1237 {
1238
1239 listener.StartListeningForEvents (*m_io_channel_ap,
1240 IOChannel::eBroadcastBitHasUserInput |
1241 IOChannel::eBroadcastBitUserInterrupt |
1242 IOChannel::eBroadcastBitThreadShouldExit |
1243 IOChannel::eBroadcastBitThreadDidStart |
1244 IOChannel::eBroadcastBitThreadDidExit);
1245
1246 if (m_io_channel_ap->Start ())
1247 {
1248 bool iochannel_thread_exited = false;
1249
1250 listener.StartListeningForEvents (sb_interpreter.GetBroadcaster(),
1251 SBCommandInterpreter::eBroadcastBitQuitCommandReceived);
1252
1253 // Before we handle any options from the command line, we parse the
1254 // .lldbinit file in the user's home directory.
1255 SBCommandReturnObject result;
1256 sb_interpreter.SourceInitFileInHomeDirectory(result);
1257 if (GetDebugMode())
1258 {
Greg Clayton63094e02010-06-23 01:19:29 +00001259 result.PutError (m_debugger.GetErrorFileHandle());
1260 result.PutOutput (m_debugger.GetOutputFileHandle());
Chris Lattner24943d22010-06-08 16:52:24 +00001261 }
1262
1263 // Now we handle options we got from the command line
1264 char command_string[PATH_MAX * 2];
1265 const size_t num_source_command_files = GetNumSourceCommandFiles();
1266 if (num_source_command_files > 0)
1267 {
1268 for (size_t i=0; i < num_source_command_files; ++i)
1269 {
1270 const char *command_file = GetSourceCommandFileAtIndex(i);
Johnny Chen7c984242010-07-28 21:16:11 +00001271 ::snprintf (command_string, sizeof(command_string), "command source '%s'", command_file);
Greg Clayton63094e02010-06-23 01:19:29 +00001272 m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, false);
Chris Lattner24943d22010-06-08 16:52:24 +00001273 if (GetDebugMode())
1274 {
Greg Clayton63094e02010-06-23 01:19:29 +00001275 result.PutError (m_debugger.GetErrorFileHandle());
1276 result.PutOutput (m_debugger.GetOutputFileHandle());
Chris Lattner24943d22010-06-08 16:52:24 +00001277 }
1278 }
1279 }
1280
Greg Clayton4dc18922010-12-08 22:23:24 +00001281 const size_t num_args = m_option_data.m_args.size();
1282 if (num_args > 0)
Chris Lattner24943d22010-06-08 16:52:24 +00001283 {
1284 char arch_name[64];
Greg Clayton63094e02010-06-23 01:19:29 +00001285 if (m_debugger.GetDefaultArchitecture (arch_name, sizeof (arch_name)))
Greg Clayton4dc18922010-12-08 22:23:24 +00001286 ::snprintf (command_string,
1287 sizeof (command_string),
1288 "file --arch=%s '%s'",
1289 arch_name,
1290 m_option_data.m_args[0].c_str());
Chris Lattner24943d22010-06-08 16:52:24 +00001291 else
Greg Clayton4dc18922010-12-08 22:23:24 +00001292 ::snprintf (command_string,
1293 sizeof(command_string),
1294 "file '%s'",
1295 m_option_data.m_args[0].c_str());
Chris Lattner24943d22010-06-08 16:52:24 +00001296
Greg Clayton63094e02010-06-23 01:19:29 +00001297 m_debugger.HandleCommand (command_string);
Greg Clayton4dc18922010-12-08 22:23:24 +00001298
1299 if (num_args > 1)
1300 {
1301 m_debugger.HandleCommand ("settings clear target.process.run-args");
1302 char arg_cstr[1024];
1303 for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx)
1304 {
1305 ::snprintf (arg_cstr, sizeof(arg_cstr), "settings append target.process.run-args \"%s\"", m_option_data.m_args[arg_idx].c_str());
1306 m_debugger.HandleCommand (arg_cstr);
1307 }
1308 }
Chris Lattner24943d22010-06-08 16:52:24 +00001309 }
1310
1311 // Now that all option parsing is done, we try and parse the .lldbinit
1312 // file in the current working directory
1313 sb_interpreter.SourceInitFileInCurrentWorkingDirectory (result);
1314 if (GetDebugMode())
1315 {
Greg Clayton63094e02010-06-23 01:19:29 +00001316 result.PutError(m_debugger.GetErrorFileHandle());
1317 result.PutOutput(m_debugger.GetOutputFileHandle());
Chris Lattner24943d22010-06-08 16:52:24 +00001318 }
1319
1320 SBEvent event;
1321
1322 // Make sure the IO channel is started up before we try to tell it we
1323 // are ready for input
1324 listener.WaitForEventForBroadcasterWithType (UINT32_MAX,
1325 *m_io_channel_ap,
1326 IOChannel::eBroadcastBitThreadDidStart,
1327 event);
1328
1329 ReadyForCommand ();
1330
1331 bool done = false;
1332 while (!done)
1333 {
1334 listener.WaitForEvent (UINT32_MAX, event);
1335 if (event.IsValid())
1336 {
1337 if (event.GetBroadcaster().IsValid())
1338 {
1339 uint32_t event_type = event.GetType();
1340 if (event.BroadcasterMatchesRef (*m_io_channel_ap))
1341 {
1342 if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
1343 (event_type & IOChannel::eBroadcastBitThreadDidExit))
1344 {
1345 done = true;
1346 if (event_type & IOChannel::eBroadcastBitThreadDidExit)
1347 iochannel_thread_exited = true;
1348 break;
1349 }
1350 else
1351 done = HandleIOEvent (event);
1352 }
Jim Inghamc8332952010-08-26 21:32:51 +00001353 else if (event.BroadcasterMatchesRef (m_debugger.GetSelectedTarget().GetProcess().GetBroadcaster()))
Chris Lattner24943d22010-06-08 16:52:24 +00001354 {
1355 HandleProcessEvent (event);
1356 }
1357 else if (event.BroadcasterMatchesRef (sb_interpreter.GetBroadcaster()))
1358 {
1359 if (event_type & SBCommandInterpreter::eBroadcastBitQuitCommandReceived)
1360 done = true;
1361 }
1362 }
1363 }
1364 }
1365
1366 reset_stdin_termios ();
1367
1368 CloseIOChannelFile ();
1369
1370 if (!iochannel_thread_exited)
1371 {
Greg Claytonbef15832010-07-14 00:18:15 +00001372 event.Clear();
Chris Lattner24943d22010-06-08 16:52:24 +00001373 listener.GetNextEventForBroadcasterWithType (*m_io_channel_ap,
1374 IOChannel::eBroadcastBitThreadDidExit,
1375 event);
1376 if (!event.IsValid())
1377 {
1378 // Send end EOF to the driver file descriptor
1379 m_io_channel_ap->Stop();
1380 }
1381 }
1382
Jim Inghamc8332952010-08-26 21:32:51 +00001383 SBProcess process = m_debugger.GetSelectedTarget().GetProcess();
Chris Lattner24943d22010-06-08 16:52:24 +00001384 if (process.IsValid())
1385 process.Destroy();
1386 }
1387 }
1388}
1389
1390
1391void
1392Driver::ReadyForCommand ()
1393{
1394 if (m_waiting_for_command == false)
1395 {
1396 m_waiting_for_command = true;
1397 BroadcastEventByType (Driver::eBroadcastBitReadyForInput, true);
1398 }
1399}
1400
1401
Caroline Ticeb8314fe2010-09-09 17:45:09 +00001402void
1403sigwinch_handler (int signo)
1404{
1405 struct winsize window_size;
1406 if (isatty (STDIN_FILENO)
1407 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
1408 {
1409 if ((window_size.ws_col > 0) && (strlen (g_debugger_name) > 0))
1410 {
1411 char width_str_buffer[25];
1412 ::sprintf (width_str_buffer, "%d", window_size.ws_col);
1413 SBDebugger::SetInternalVariable ("term-width", width_str_buffer, g_debugger_name);
1414 }
1415 }
1416}
1417
Caroline Ticec4f55fe2010-11-19 20:47:54 +00001418void
1419sigint_handler (int signo)
1420{
1421 static bool g_interrupt_sent = false;
1422 if (g_driver)
1423 {
1424 if (!g_interrupt_sent)
1425 {
1426 g_interrupt_sent = true;
1427 g_driver->GetDebugger().DispatchInputInterrupt();
1428 g_interrupt_sent = false;
1429 return;
1430 }
1431 }
1432
1433 exit (signo);
1434}
1435
Chris Lattner24943d22010-06-08 16:52:24 +00001436int
Jim Inghamb2b604f2011-01-27 20:15:39 +00001437main (int argc, char const *argv[], const char *envp[])
Chris Lattner24943d22010-06-08 16:52:24 +00001438{
Chris Lattner24943d22010-06-08 16:52:24 +00001439 SBDebugger::Initialize();
1440
Greg Clayton95e33b72010-11-07 21:02:03 +00001441 SBHostOS::ThreadCreated ("<lldb.driver.main-thread>");
Chris Lattner24943d22010-06-08 16:52:24 +00001442
Greg Clayton36f63a92010-10-19 03:25:40 +00001443 signal (SIGPIPE, SIG_IGN);
Caroline Ticeb8314fe2010-09-09 17:45:09 +00001444 signal (SIGWINCH, sigwinch_handler);
Caroline Ticec4f55fe2010-11-19 20:47:54 +00001445 signal (SIGINT, sigint_handler);
Caroline Ticeb8314fe2010-09-09 17:45:09 +00001446
Greg Clayton63094e02010-06-23 01:19:29 +00001447 // Create a scope for driver so that the driver object will destroy itself
1448 // before SBDebugger::Terminate() is called.
Chris Lattner24943d22010-06-08 16:52:24 +00001449 {
Greg Clayton63094e02010-06-23 01:19:29 +00001450 Driver driver;
1451
1452 bool exit = false;
1453 SBError error (driver.ParseArgs (argc, argv, stdout, exit));
1454 if (error.Fail())
1455 {
1456 const char *error_cstr = error.GetCString ();
1457 if (error_cstr)
1458 ::fprintf (stderr, "error: %s\n", error_cstr);
1459 }
1460 else if (!exit)
1461 {
1462 driver.MainLoop ();
1463 }
Chris Lattner24943d22010-06-08 16:52:24 +00001464 }
1465
1466 SBDebugger::Terminate();
1467 return 0;
1468}