blob: 1bc314882f6d72a64a8666c1bc5378d1d8373a20 [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 *) "";
43
Chris Lattner24943d22010-06-08 16:52:24 +000044// In the Driver::MainLoop, we change the terminal settings. This function is
45// added as an atexit handler to make sure we clean them up.
46static void
47reset_stdin_termios ()
48{
49 ::tcsetattr (STDIN_FILENO, TCSANOW, &g_old_stdin_termios);
50}
51
52static lldb::OptionDefinition g_options[] =
53{
Caroline Tice4d6675c2010-10-01 19:59:14 +000054 { LLDB_OPT_SET_1, true, "help", 'h', no_argument, NULL, NULL, eArgTypeNone,
Chris Lattner24943d22010-06-08 16:52:24 +000055 "Prints out the usage information for the LLDB debugger." },
56
Caroline Tice4d6675c2010-10-01 19:59:14 +000057 { LLDB_OPT_SET_2, true, "version", 'v', no_argument, NULL, NULL, eArgTypeNone,
Chris Lattner24943d22010-06-08 16:52:24 +000058 "Prints out the current version number of the LLDB debugger." },
59
Caroline Tice4d6675c2010-10-01 19:59:14 +000060 { LLDB_OPT_SET_3, true, "arch", 'a', required_argument, NULL, NULL, eArgTypeArchitecture,
Chris Lattner24943d22010-06-08 16:52:24 +000061 "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." },
62
Caroline Tice4d6675c2010-10-01 19:59:14 +000063 { LLDB_OPT_SET_3 | LLDB_OPT_SET_4, false, "script-language",'l', required_argument, NULL, NULL, eArgTypeScriptLang,
Chris Lattner24943d22010-06-08 16:52:24 +000064 "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." },
65
Caroline Tice4d6675c2010-10-01 19:59:14 +000066 { LLDB_OPT_SET_3 | LLDB_OPT_SET_4, false, "debug", 'd', no_argument, NULL, NULL, eArgTypeNone,
Chris Lattner24943d22010-06-08 16:52:24 +000067 "Tells the debugger to print out extra information for debugging itself." },
68
Caroline Tice4d6675c2010-10-01 19:59:14 +000069 { LLDB_OPT_SET_3 | LLDB_OPT_SET_4, false, "source", 's', required_argument, NULL, NULL, eArgTypeFilename,
Chris Lattner24943d22010-06-08 16:52:24 +000070 "Tells the debugger to read in and execute the file <file>, which should contain lldb commands." },
71
Caroline Tice4d6675c2010-10-01 19:59:14 +000072 { LLDB_OPT_SET_3, true, "file", 'f', required_argument, NULL, NULL, eArgTypeFilename,
Jim Ingham34e9a982010-06-15 18:47:14 +000073 "Tells the debugger to use the file <filename> as the program to be debugged." },
74
Caroline Tice4d6675c2010-10-01 19:59:14 +000075 { LLDB_OPT_SET_ALL, false, "editor", 'e', no_argument, NULL, NULL, eArgTypeNone,
Jim Ingham74989e82010-08-30 19:44:40 +000076 "Tells the debugger to open source files using the host's \"external editor\" mechanism." },
77
Greg Clayton887aa282010-10-11 01:05:37 +000078 { LLDB_OPT_SET_ALL, false, "no-lldbinit", 'n', no_argument, NULL, NULL, eArgTypeNone,
79 "Do not automatically parse any '.lldbinit' files." },
80
Caroline Tice4d6675c2010-10-01 19:59:14 +000081// { LLDB_OPT_SET_4, true, "crash-log", 'c', required_argument, NULL, NULL, eArgTypeFilename,
Greg Clayton12bec712010-06-28 21:30:43 +000082// "Load executable images from a crash log for symbolication." },
Chris Lattner24943d22010-06-08 16:52:24 +000083
Caroline Tice4d6675c2010-10-01 19:59:14 +000084 { 0, false, NULL, 0, 0, NULL, NULL, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +000085};
86
87
88Driver::Driver () :
89 SBBroadcaster ("Driver"),
Greg Clayton63094e02010-06-23 01:19:29 +000090 m_debugger (SBDebugger::Create()),
Chris Lattner24943d22010-06-08 16:52:24 +000091 m_editline_pty (),
92 m_editline_slave_fh (NULL),
93 m_editline_reader (),
94 m_io_channel_ap (),
95 m_option_data (),
96 m_waiting_for_command (false)
97{
Caroline Ticeb8314fe2010-09-09 17:45:09 +000098 g_debugger_name = (char *) m_debugger.GetInstanceName();
99 if (g_debugger_name == NULL)
100 g_debugger_name = (char *) "";
Chris Lattner24943d22010-06-08 16:52:24 +0000101}
102
103Driver::~Driver ()
104{
105}
106
107void
108Driver::CloseIOChannelFile ()
109{
110 // Write and End of File sequence to the file descriptor to ensure any
111 // read functions can exit.
112 char eof_str[] = "\x04";
113 ::write (m_editline_pty.GetMasterFileDescriptor(), eof_str, strlen(eof_str));
114
115 m_editline_pty.CloseMasterFileDescriptor();
116
117 if (m_editline_slave_fh)
118 {
119 ::fclose (m_editline_slave_fh);
120 m_editline_slave_fh = NULL;
121 }
122}
123
Greg Clayton54e7afa2010-07-09 20:39:50 +0000124// This function takes INDENT, which tells how many spaces to output at the front
125// of each line; TEXT, which is the text that is to be output. It outputs the
126// text, on multiple lines if necessary, to RESULT, with INDENT spaces at the
127// front of each line. It breaks lines on spaces, tabs or newlines, shortening
128// the line if necessary to not break in the middle of a word. It assumes that
129// each output line should contain a maximum of OUTPUT_MAX_COLUMNS characters.
Chris Lattner24943d22010-06-08 16:52:24 +0000130
131void
Greg Clayton54e7afa2010-07-09 20:39:50 +0000132OutputFormattedUsageText (FILE *out, int indent, const char *text, int output_max_columns)
Chris Lattner24943d22010-06-08 16:52:24 +0000133{
134 int len = strlen (text);
135 std::string text_string (text);
Chris Lattner24943d22010-06-08 16:52:24 +0000136
137 // Force indentation to be reasonable.
138 if (indent >= output_max_columns)
139 indent = 0;
140
141 // Will it all fit on one line?
142
143 if (len + indent < output_max_columns)
144 // Output as a single line
Greg Clayton54e7afa2010-07-09 20:39:50 +0000145 fprintf (out, "%*s%s\n", indent, "", text);
Chris Lattner24943d22010-06-08 16:52:24 +0000146 else
147 {
148 // We need to break it up into multiple lines.
149 int text_width = output_max_columns - indent - 1;
150 int start = 0;
151 int end = start;
152 int final_end = len;
153 int sub_len;
154
155 while (end < final_end)
156 {
157 // Dont start the 'text' on a space, since we're already outputting the indentation.
158 while ((start < final_end) && (text[start] == ' '))
159 start++;
160
161 end = start + text_width;
162 if (end > final_end)
163 end = final_end;
164 else
165 {
166 // If we're not at the end of the text, make sure we break the line on white space.
167 while (end > start
168 && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
169 end--;
170 }
171 sub_len = end - start;
172 std::string substring = text_string.substr (start, sub_len);
Greg Clayton54e7afa2010-07-09 20:39:50 +0000173 fprintf (out, "%*s%s\n", indent, "", substring.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000174 start = end + 1;
175 }
176 }
177}
178
Caroline Tice4d6675c2010-10-01 19:59:14 +0000179void
180GetArgumentName (const CommandArgumentType arg_type, std::string &arg_name)
181{
182 //Fudge this function here, since we can't call the "real" version in lldb_private::CommandObject...
183
184 switch (arg_type)
185 {
186 // Make cases for all the arg_types used in Driver.cpp
187
188 case eArgTypeNone:
189 arg_name = "";
190 break;
191
192 case eArgTypeArchitecture:
193 arg_name = "architecture";
194 break;
195
196 case eArgTypeScriptLang:
197 arg_name = "script-language";
198 break;
199
200 case eArgTypeFilename:
201 arg_name = "filename";
202 break;
203 }
204 return;
205}
206
207
Chris Lattner24943d22010-06-08 16:52:24 +0000208void
209ShowUsage (FILE *out, lldb::OptionDefinition *option_table, Driver::OptionData data)
210{
211 uint32_t screen_width = 80;
212 uint32_t indent_level = 0;
213 const char *name = "lldb";
Jim Ingham34e9a982010-06-15 18:47:14 +0000214
Chris Lattner24943d22010-06-08 16:52:24 +0000215 fprintf (out, "\nUsage:\n\n");
216
217 indent_level += 2;
218
219
220 // First, show each usage level set of options, e.g. <cmd> [options-for-level-0]
221 // <cmd> [options-for-level-1]
222 // etc.
223
Chris Lattner24943d22010-06-08 16:52:24 +0000224 uint32_t num_options;
Jim Ingham34e9a982010-06-15 18:47:14 +0000225 uint32_t num_option_sets = 0;
226
227 for (num_options = 0; option_table[num_options].long_option != NULL; ++num_options)
Chris Lattner24943d22010-06-08 16:52:24 +0000228 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000229 uint32_t this_usage_mask = option_table[num_options].usage_mask;
230 if (this_usage_mask == LLDB_OPT_SET_ALL)
Chris Lattner24943d22010-06-08 16:52:24 +0000231 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000232 if (num_option_sets == 0)
233 num_option_sets = 1;
Chris Lattner24943d22010-06-08 16:52:24 +0000234 }
235 else
236 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000237 for (uint32_t j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++)
Jim Ingham34e9a982010-06-15 18:47:14 +0000238 {
239 if (this_usage_mask & 1 << j)
240 {
241 if (num_option_sets <= j)
242 num_option_sets = j + 1;
243 }
244 }
245 }
246 }
247
248 for (uint32_t opt_set = 0; opt_set < num_option_sets; opt_set++)
249 {
250 uint32_t opt_set_mask;
251
252 opt_set_mask = 1 << opt_set;
253
254 if (opt_set > 0)
255 fprintf (out, "\n");
Greg Clayton54e7afa2010-07-09 20:39:50 +0000256 fprintf (out, "%*s%s", indent_level, "", name);
Jim Ingham34e9a982010-06-15 18:47:14 +0000257
258 for (uint32_t i = 0; i < num_options; ++i)
259 {
260 if (option_table[i].usage_mask & opt_set_mask)
261 {
Caroline Tice4d6675c2010-10-01 19:59:14 +0000262 CommandArgumentType arg_type = option_table[i].argument_type;
263 std::string arg_name;
264 GetArgumentName (arg_type, arg_name);
Jim Ingham34e9a982010-06-15 18:47:14 +0000265 if (option_table[i].required)
266 {
267 if (option_table[i].option_has_arg == required_argument)
Caroline Tice4d6675c2010-10-01 19:59:14 +0000268 fprintf (out, " -%c <%s>", option_table[i].short_option, arg_name.c_str());
Jim Ingham34e9a982010-06-15 18:47:14 +0000269 else if (option_table[i].option_has_arg == optional_argument)
Caroline Tice4d6675c2010-10-01 19:59:14 +0000270 fprintf (out, " -%c [<%s>]", option_table[i].short_option, arg_name.c_str());
Jim Ingham34e9a982010-06-15 18:47:14 +0000271 else
272 fprintf (out, " -%c", option_table[i].short_option);
273 }
274 else
275 {
276 if (option_table[i].option_has_arg == required_argument)
Caroline Tice4d6675c2010-10-01 19:59:14 +0000277 fprintf (out, " [-%c <%s>]", option_table[i].short_option, arg_name.c_str());
Jim Ingham34e9a982010-06-15 18:47:14 +0000278 else if (option_table[i].option_has_arg == optional_argument)
Caroline Tice4d6675c2010-10-01 19:59:14 +0000279 fprintf (out, " [-%c [<%s>]]", option_table[i].short_option, arg_name.c_str());
Jim Ingham34e9a982010-06-15 18:47:14 +0000280 else
281 fprintf (out, " [-%c]", option_table[i].short_option);
282 }
283 }
Chris Lattner24943d22010-06-08 16:52:24 +0000284 }
285 }
286
287 fprintf (out, "\n\n");
288
289 // Now print out all the detailed information about the various options: long form, short form and help text:
290 // -- long_name <argument>
291 // - short <argument>
292 // help text
293
294 // This variable is used to keep track of which options' info we've printed out, because some options can be in
295 // more than one usage level, but we only want to print the long form of its information once.
296
297 Driver::OptionData::OptionSet options_seen;
298 Driver::OptionData::OptionSet::iterator pos;
299
300 indent_level += 5;
301
Jim Ingham34e9a982010-06-15 18:47:14 +0000302 for (uint32_t i = 0; i < num_options; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000303 {
304 // Only print this option if we haven't already seen it.
305 pos = options_seen.find (option_table[i].short_option);
306 if (pos == options_seen.end())
307 {
Caroline Tice4d6675c2010-10-01 19:59:14 +0000308 CommandArgumentType arg_type = option_table[i].argument_type;
309 std::string arg_name;
310 GetArgumentName (arg_type, arg_name);
311
Chris Lattner24943d22010-06-08 16:52:24 +0000312 options_seen.insert (option_table[i].short_option);
Greg Clayton54e7afa2010-07-09 20:39:50 +0000313 fprintf (out, "%*s-%c ", indent_level, "", option_table[i].short_option);
Caroline Tice4d6675c2010-10-01 19:59:14 +0000314 if (arg_type != eArgTypeNone)
315 fprintf (out, "<%s>", arg_name.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000316 fprintf (out, "\n");
Greg Clayton54e7afa2010-07-09 20:39:50 +0000317 fprintf (out, "%*s--%s ", indent_level, "", option_table[i].long_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");
321 indent_level += 5;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000322 OutputFormattedUsageText (out, indent_level, option_table[i].usage_text, screen_width);
Chris Lattner24943d22010-06-08 16:52:24 +0000323 indent_level -= 5;
324 fprintf (out, "\n");
325 }
326 }
327
328 indent_level -= 5;
329
Greg Clayton54e7afa2010-07-09 20:39:50 +0000330 fprintf (out, "\n%*s('%s <filename>' also works, to specify the file to be debugged.)\n\n",
331 indent_level, "", name);
Chris Lattner24943d22010-06-08 16:52:24 +0000332}
333
334void
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000335BuildGetOptTable (lldb::OptionDefinition *expanded_option_table, std::vector<struct option> &getopt_table,
336 uint32_t num_options)
Chris Lattner24943d22010-06-08 16:52:24 +0000337{
338 if (num_options == 0)
339 return;
340
341 uint32_t i;
342 uint32_t j;
343 std::bitset<256> option_seen;
344
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000345 getopt_table.resize (num_options + 1);
346
Chris Lattner24943d22010-06-08 16:52:24 +0000347 for (i = 0, j = 0; i < num_options; ++i)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000348 {
Chris Lattner24943d22010-06-08 16:52:24 +0000349 char short_opt = expanded_option_table[i].short_option;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000350
Chris Lattner24943d22010-06-08 16:52:24 +0000351 if (option_seen.test(short_opt) == false)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000352 {
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000353 getopt_table[j].name = expanded_option_table[i].long_option;
354 getopt_table[j].has_arg = expanded_option_table[i].option_has_arg;
355 getopt_table[j].flag = NULL;
356 getopt_table[j].val = expanded_option_table[i].short_option;
Chris Lattner24943d22010-06-08 16:52:24 +0000357 option_seen.set(short_opt);
358 ++j;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000359 }
360 }
Chris Lattner24943d22010-06-08 16:52:24 +0000361
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000362 getopt_table[j].name = NULL;
363 getopt_table[j].has_arg = 0;
364 getopt_table[j].flag = NULL;
365 getopt_table[j].val = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000366
367}
368
Greg Clayton63094e02010-06-23 01:19:29 +0000369Driver::OptionData::OptionData () :
370 m_filename(),
371 m_script_lang (lldb::eScriptLanguageDefault),
Greg Clayton54e7afa2010-07-09 20:39:50 +0000372 m_crash_log (),
Greg Clayton63094e02010-06-23 01:19:29 +0000373 m_source_command_files (),
374 m_debug_mode (false),
Greg Clayton54e7afa2010-07-09 20:39:50 +0000375 m_print_version (false),
Greg Clayton63094e02010-06-23 01:19:29 +0000376 m_print_help (false),
Jim Ingham74989e82010-08-30 19:44:40 +0000377 m_seen_options(),
378 m_use_external_editor(false)
Chris Lattner24943d22010-06-08 16:52:24 +0000379{
Greg Clayton63094e02010-06-23 01:19:29 +0000380}
381
382Driver::OptionData::~OptionData ()
383{
384}
385
386void
387Driver::OptionData::Clear ()
388{
389 m_filename.clear ();
390 m_script_lang = lldb::eScriptLanguageDefault;
391 m_source_command_files.clear ();
392 m_debug_mode = false;
393 m_print_help = false;
394 m_print_version = false;
Jim Ingham74989e82010-08-30 19:44:40 +0000395 m_use_external_editor = false;
Greg Clayton63094e02010-06-23 01:19:29 +0000396}
397
398void
399Driver::ResetOptionValues ()
400{
401 m_option_data.Clear ();
402}
403
404const char *
405Driver::GetFilename() const
406{
407 if (m_option_data.m_filename.empty())
408 return NULL;
409 return m_option_data.m_filename.c_str();
410}
411
412const char *
413Driver::GetCrashLogFilename() const
414{
415 if (m_option_data.m_crash_log.empty())
416 return NULL;
417 return m_option_data.m_crash_log.c_str();
418}
419
420lldb::ScriptLanguage
421Driver::GetScriptLanguage() const
422{
423 return m_option_data.m_script_lang;
424}
425
426size_t
427Driver::GetNumSourceCommandFiles () const
428{
429 return m_option_data.m_source_command_files.size();
430}
431
432const char *
433Driver::GetSourceCommandFileAtIndex (uint32_t idx) const
434{
435 if (idx < m_option_data.m_source_command_files.size())
436 return m_option_data.m_source_command_files[idx].c_str();
437 return NULL;
438}
439
440bool
441Driver::GetDebugMode() const
442{
443 return m_option_data.m_debug_mode;
444}
445
446
447// Check the arguments that were passed to this program to make sure they are valid and to get their
448// argument values (if any). Return a boolean value indicating whether or not to start up the full
449// debugger (i.e. the Command Interpreter) or not. Return FALSE if the arguments were invalid OR
450// if the user only wanted help or version information.
451
452SBError
453Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exit)
454{
455 ResetOptionValues ();
456
457 SBCommandReturnObject result;
458
Chris Lattner24943d22010-06-08 16:52:24 +0000459 SBError error;
460 std::string option_string;
461 struct option *long_options = NULL;
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000462 std::vector<struct option> long_options_vector;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000463 uint32_t num_options;
Chris Lattner24943d22010-06-08 16:52:24 +0000464
Greg Clayton54e7afa2010-07-09 20:39:50 +0000465 for (num_options = 0; g_options[num_options].long_option != NULL; ++num_options)
466 /* Do Nothing. */;
Chris Lattner24943d22010-06-08 16:52:24 +0000467
468 if (num_options == 0)
469 {
470 if (argc > 1)
471 error.SetErrorStringWithFormat ("invalid number of options");
472 return error;
473 }
474
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000475 BuildGetOptTable (g_options, long_options_vector, num_options);
Chris Lattner24943d22010-06-08 16:52:24 +0000476
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000477 if (long_options_vector.empty())
478 long_options = NULL;
479 else
480 long_options = &long_options_vector.front();
Chris Lattner24943d22010-06-08 16:52:24 +0000481
482 if (long_options == NULL)
483 {
484 error.SetErrorStringWithFormat ("invalid long options");
485 return error;
486 }
487
488 // Build the option_string argument for call to getopt_long.
489
490 for (int i = 0; long_options[i].name != NULL; ++i)
491 {
492 if (long_options[i].flag == NULL)
493 {
494 option_string.push_back ((char) long_options[i].val);
495 switch (long_options[i].has_arg)
496 {
497 default:
498 case no_argument:
499 break;
500 case required_argument:
501 option_string.push_back (':');
502 break;
503 case optional_argument:
504 option_string.append ("::");
505 break;
506 }
507 }
508 }
509
510 // Prepare for & make calls to getopt_long.
Eli Friedmanef2bc872010-06-13 19:18:49 +0000511#if __GLIBC__
512 optind = 0;
513#else
Chris Lattner24943d22010-06-08 16:52:24 +0000514 optreset = 1;
515 optind = 1;
Eli Friedmanef2bc872010-06-13 19:18:49 +0000516#endif
Chris Lattner24943d22010-06-08 16:52:24 +0000517 int val;
518 while (1)
519 {
520 int long_options_index = -1;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000521 val = ::getopt_long (argc, const_cast<char **>(argv), option_string.c_str(), long_options, &long_options_index);
Chris Lattner24943d22010-06-08 16:52:24 +0000522
523 if (val == -1)
524 break;
525 else if (val == '?')
526 {
Greg Clayton63094e02010-06-23 01:19:29 +0000527 m_option_data.m_print_help = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000528 error.SetErrorStringWithFormat ("unknown or ambiguous option");
529 break;
530 }
531 else if (val == 0)
532 continue;
533 else
534 {
Greg Clayton63094e02010-06-23 01:19:29 +0000535 m_option_data.m_seen_options.insert ((char) val);
Chris Lattner24943d22010-06-08 16:52:24 +0000536 if (long_options_index == -1)
537 {
538 for (int i = 0;
539 long_options[i].name || long_options[i].has_arg || long_options[i].flag || long_options[i].val;
540 ++i)
541 {
542 if (long_options[i].val == val)
543 {
544 long_options_index = i;
545 break;
546 }
547 }
548 }
549
550 if (long_options_index >= 0)
551 {
Greg Clayton63094e02010-06-23 01:19:29 +0000552 const char short_option = (char) g_options[long_options_index].short_option;
553
554 switch (short_option)
555 {
556 case 'h':
557 m_option_data.m_print_help = true;
558 break;
559
560 case 'v':
561 m_option_data.m_print_version = true;
562 break;
563
564 case 'c':
565 m_option_data.m_crash_log = optarg;
566 break;
Greg Clayton887aa282010-10-11 01:05:37 +0000567
Jim Ingham74989e82010-08-30 19:44:40 +0000568 case 'e':
569 m_option_data.m_use_external_editor = true;
570 break;
Greg Clayton887aa282010-10-11 01:05:37 +0000571
572 case 'n':
573 m_debugger.SkipLLDBInitFiles (true);
574 break;
575
Greg Clayton63094e02010-06-23 01:19:29 +0000576 case 'f':
577 {
578 SBFileSpec file(optarg);
579 if (file.Exists())
580 m_option_data.m_filename = optarg;
Caroline Ticeeddffe92010-09-10 04:48:55 +0000581 else if (file.ResolveExecutableLocation())
582 {
583 char path[PATH_MAX];
584 int path_len;
585 file.GetPath (path, path_len);
586 m_option_data.m_filename = path;
587 }
Greg Clayton63094e02010-06-23 01:19:29 +0000588 else
589 error.SetErrorStringWithFormat("file specified in --file (-f) option doesn't exist: '%s'", optarg);
590 }
591 break;
592
593 case 'a':
594 if (!m_debugger.SetDefaultArchitecture (optarg))
595 error.SetErrorStringWithFormat("invalid architecture in the -a or --arch option: '%s'", optarg);
596 break;
597
598 case 'l':
599 m_option_data.m_script_lang = m_debugger.GetScriptingLanguage (optarg);
600 break;
601
602 case 'd':
603 m_option_data.m_debug_mode = true;
604 break;
605
606 case 's':
607 {
608 SBFileSpec file(optarg);
609 if (file.Exists())
610 m_option_data.m_source_command_files.push_back (optarg);
Caroline Ticeeddffe92010-09-10 04:48:55 +0000611 else if (file.ResolveExecutableLocation())
612 {
613 char final_path[PATH_MAX];
614 size_t path_len;
615 file.GetPath (final_path, path_len);
616 std::string path_str (final_path);
617 m_option_data.m_source_command_files.push_back (path_str);
618 }
Greg Clayton63094e02010-06-23 01:19:29 +0000619 else
620 error.SetErrorStringWithFormat("file specified in --source (-s) option doesn't exist: '%s'", optarg);
621 }
622 break;
623
624 default:
625 m_option_data.m_print_help = true;
626 error.SetErrorStringWithFormat ("unrecognized option %c", short_option);
627 break;
628 }
Chris Lattner24943d22010-06-08 16:52:24 +0000629 }
630 else
631 {
632 error.SetErrorStringWithFormat ("invalid option with value %i", val);
633 }
634 if (error.Fail())
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000635 {
Greg Clayton63094e02010-06-23 01:19:29 +0000636 return error;
Caroline Ticebd5c63e2010-10-12 21:57:09 +0000637 }
Chris Lattner24943d22010-06-08 16:52:24 +0000638 }
639 }
Jim Ingham34e9a982010-06-15 18:47:14 +0000640
641 // If there is a trailing argument, it is the filename.
642 if (optind == argc - 1)
643 {
644 if (m_option_data.m_filename.empty())
Chris Lattner24943d22010-06-08 16:52:24 +0000645 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000646 m_option_data.m_filename = argv[optind];
Chris Lattner24943d22010-06-08 16:52:24 +0000647 }
Jim Ingham34e9a982010-06-15 18:47:14 +0000648 else
649 {
Greg Clayton63094e02010-06-23 01:19:29 +0000650 error.SetErrorStringWithFormat ("error: don't provide a file both on in the -f option and as an argument.");
Jim Ingham34e9a982010-06-15 18:47:14 +0000651 }
652
Chris Lattner24943d22010-06-08 16:52:24 +0000653 }
Jim Ingham34e9a982010-06-15 18:47:14 +0000654 else if (optind < argc - 1)
655 {
656 // Trailing extra arguments...
Greg Clayton63094e02010-06-23 01:19:29 +0000657 error.SetErrorStringWithFormat ("error: trailing extra arguments - only one the filename is allowed.");
Jim Ingham34e9a982010-06-15 18:47:14 +0000658 }
659
Greg Clayton63094e02010-06-23 01:19:29 +0000660 if (error.Fail() || m_option_data.m_print_help)
Chris Lattner24943d22010-06-08 16:52:24 +0000661 {
662 ShowUsage (out_fh, g_options, m_option_data);
Greg Clayton9caa9462010-10-11 01:13:37 +0000663 exit = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000664 }
665 else if (m_option_data.m_print_version)
666 {
Greg Clayton63094e02010-06-23 01:19:29 +0000667 ::fprintf (out_fh, "%s\n", m_debugger.GetVersionString());
668 exit = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000669 }
670 else if (! m_option_data.m_crash_log.empty())
671 {
672 // Handle crash log stuff here.
673 }
674 else
675 {
676 // All other combinations are valid; do nothing more here.
677 }
678
Greg Clayton63094e02010-06-23 01:19:29 +0000679 return error;
Chris Lattner24943d22010-06-08 16:52:24 +0000680}
681
Caroline Tice757500e2010-09-29 18:35:42 +0000682size_t
Chris Lattner24943d22010-06-08 16:52:24 +0000683Driver::GetProcessSTDOUT ()
684{
685 // The process has stuff waiting for stdout; get it and write it out to the appropriate place.
686 char stdio_buffer[1024];
687 size_t len;
Caroline Tice757500e2010-09-29 18:35:42 +0000688 size_t total_bytes = 0;
Jim Inghamc8332952010-08-26 21:32:51 +0000689 while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0)
Caroline Tice757500e2010-09-29 18:35:42 +0000690 {
Chris Lattner24943d22010-06-08 16:52:24 +0000691 m_io_channel_ap->OutWrite (stdio_buffer, len);
Caroline Tice757500e2010-09-29 18:35:42 +0000692 total_bytes += len;
693 }
694 return total_bytes;
Chris Lattner24943d22010-06-08 16:52:24 +0000695}
696
Caroline Tice757500e2010-09-29 18:35:42 +0000697size_t
Chris Lattner24943d22010-06-08 16:52:24 +0000698Driver::GetProcessSTDERR ()
699{
700 // The process has stuff waiting for stderr; get it and write it out to the appropriate place.
701 char stdio_buffer[1024];
702 size_t len;
Caroline Tice757500e2010-09-29 18:35:42 +0000703 size_t total_bytes = 0;
Jim Inghamc8332952010-08-26 21:32:51 +0000704 while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0)
Caroline Tice757500e2010-09-29 18:35:42 +0000705 {
Chris Lattner24943d22010-06-08 16:52:24 +0000706 m_io_channel_ap->ErrWrite (stdio_buffer, len);
Caroline Tice757500e2010-09-29 18:35:42 +0000707 total_bytes += len;
708 }
709 return total_bytes;
Chris Lattner24943d22010-06-08 16:52:24 +0000710}
711
712void
Jim Inghamc8332952010-08-26 21:32:51 +0000713Driver::UpdateSelectedThread ()
Chris Lattner24943d22010-06-08 16:52:24 +0000714{
715 using namespace lldb;
Jim Inghamc8332952010-08-26 21:32:51 +0000716 SBProcess process(m_debugger.GetSelectedTarget().GetProcess());
Chris Lattner24943d22010-06-08 16:52:24 +0000717 if (process.IsValid())
718 {
Jim Inghamc8332952010-08-26 21:32:51 +0000719 SBThread curr_thread (process.GetSelectedThread());
Chris Lattner24943d22010-06-08 16:52:24 +0000720 SBThread thread;
721 StopReason curr_thread_stop_reason = eStopReasonInvalid;
722 curr_thread_stop_reason = curr_thread.GetStopReason();
723
724 if (!curr_thread.IsValid() ||
725 curr_thread_stop_reason == eStopReasonInvalid ||
726 curr_thread_stop_reason == eStopReasonNone)
727 {
728 // Prefer a thread that has just completed its plan over another thread as current thread.
729 SBThread plan_thread;
730 SBThread other_thread;
731 const size_t num_threads = process.GetNumThreads();
732 size_t i;
733 for (i = 0; i < num_threads; ++i)
734 {
735 thread = process.GetThreadAtIndex(i);
736 StopReason thread_stop_reason = thread.GetStopReason();
737 switch (thread_stop_reason)
738 {
739 default:
740 case eStopReasonInvalid:
741 case eStopReasonNone:
742 break;
743
744 case eStopReasonTrace:
745 case eStopReasonBreakpoint:
746 case eStopReasonWatchpoint:
747 case eStopReasonSignal:
748 case eStopReasonException:
749 if (!other_thread.IsValid())
750 other_thread = thread;
751 break;
752 case eStopReasonPlanComplete:
753 if (!plan_thread.IsValid())
754 plan_thread = thread;
755 break;
756 }
757 }
758 if (plan_thread.IsValid())
Jim Inghamc8332952010-08-26 21:32:51 +0000759 process.SetSelectedThread (plan_thread);
Chris Lattner24943d22010-06-08 16:52:24 +0000760 else if (other_thread.IsValid())
Jim Inghamc8332952010-08-26 21:32:51 +0000761 process.SetSelectedThread (other_thread);
Chris Lattner24943d22010-06-08 16:52:24 +0000762 else
763 {
764 if (curr_thread.IsValid())
765 thread = curr_thread;
766 else
767 thread = process.GetThreadAtIndex(0);
768
769 if (thread.IsValid())
Jim Inghamc8332952010-08-26 21:32:51 +0000770 process.SetSelectedThread (thread);
Chris Lattner24943d22010-06-08 16:52:24 +0000771 }
772 }
773 }
774}
775
776
777// This function handles events that were broadcast by the process.
778void
779Driver::HandleProcessEvent (const SBEvent &event)
780{
781 using namespace lldb;
782 const uint32_t event_type = event.GetType();
783
784 if (event_type & SBProcess::eBroadcastBitSTDOUT)
785 {
786 // The process has stdout available, get it and write it out to the
787 // appropriate place.
Caroline Tice757500e2010-09-29 18:35:42 +0000788 if (GetProcessSTDOUT ())
789 m_io_channel_ap->RefreshPrompt();
Chris Lattner24943d22010-06-08 16:52:24 +0000790 }
791 else if (event_type & SBProcess::eBroadcastBitSTDERR)
792 {
793 // The process has stderr available, get it and write it out to the
794 // appropriate place.
Caroline Tice757500e2010-09-29 18:35:42 +0000795 if (GetProcessSTDERR ())
796 m_io_channel_ap->RefreshPrompt();
Chris Lattner24943d22010-06-08 16:52:24 +0000797 }
798 else if (event_type & SBProcess::eBroadcastBitStateChanged)
799 {
800 // Drain all stout and stderr so we don't see any output come after
801 // we print our prompts
Caroline Tice757500e2010-09-29 18:35:42 +0000802 if (GetProcessSTDOUT ()
803 || GetProcessSTDERR ())
804 m_io_channel_ap->RefreshPrompt();
Chris Lattner24943d22010-06-08 16:52:24 +0000805
806 // Something changed in the process; get the event and report the process's current status and location to
807 // the user.
808 StateType event_state = SBProcess::GetStateFromEvent (event);
809 if (event_state == eStateInvalid)
810 return;
811
812 SBProcess process (SBProcess::GetProcessFromEvent (event));
813 assert (process.IsValid());
814
815 switch (event_state)
816 {
817 case eStateInvalid:
818 case eStateUnloaded:
819 case eStateAttaching:
820 case eStateLaunching:
821 case eStateStepping:
822 case eStateDetached:
823 {
824 char message[1024];
825 int message_len = ::snprintf (message, sizeof(message), "Process %d %s\n", process.GetProcessID(),
Greg Clayton63094e02010-06-23 01:19:29 +0000826 m_debugger.StateAsCString (event_state));
Chris Lattner24943d22010-06-08 16:52:24 +0000827 m_io_channel_ap->OutWrite(message, message_len);
828 }
829 break;
830
831 case eStateRunning:
832 // Don't be chatty when we run...
833 break;
834
835 case eStateExited:
Caroline Tice757500e2010-09-29 18:35:42 +0000836 {
837 SBCommandReturnObject result;
838 m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
839 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize());
840 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize());
841 m_io_channel_ap->RefreshPrompt();
842 }
Chris Lattner24943d22010-06-08 16:52:24 +0000843 break;
844
845 case eStateStopped:
846 case eStateCrashed:
847 case eStateSuspended:
848 // Make sure the program hasn't been auto-restarted:
849 if (SBProcess::GetRestartedFromEvent (event))
850 {
851 // FIXME: Do we want to report this, or would that just be annoyingly chatty?
852 char message[1024];
853 int message_len = ::snprintf (message, sizeof(message), "Process %d stopped and was programmatically restarted.\n",
854 process.GetProcessID());
855 m_io_channel_ap->OutWrite(message, message_len);
Caroline Tice757500e2010-09-29 18:35:42 +0000856 m_io_channel_ap->RefreshPrompt ();
Chris Lattner24943d22010-06-08 16:52:24 +0000857 }
858 else
859 {
Caroline Tice757500e2010-09-29 18:35:42 +0000860 SBCommandReturnObject result;
Jim Inghamc8332952010-08-26 21:32:51 +0000861 UpdateSelectedThread ();
Caroline Tice757500e2010-09-29 18:35:42 +0000862 m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
863 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize());
864 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize());
865 m_io_channel_ap->RefreshPrompt ();
Chris Lattner24943d22010-06-08 16:52:24 +0000866 }
867 break;
868 }
869 }
870}
871
872// This function handles events broadcast by the IOChannel (HasInput, UserInterrupt, or ThreadShouldExit).
873
874bool
875Driver::HandleIOEvent (const SBEvent &event)
876{
877 bool quit = false;
878
879 const uint32_t event_type = event.GetType();
880
881 if (event_type & IOChannel::eBroadcastBitHasUserInput)
882 {
883 // We got some input (i.e. a command string) from the user; pass it off to the command interpreter for
884 // handling.
885
886 const char *command_string = SBEvent::GetCStringFromEvent(event);
887 if (command_string == NULL)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000888 command_string = "";
Chris Lattner24943d22010-06-08 16:52:24 +0000889 SBCommandReturnObject result;
Greg Clayton63094e02010-06-23 01:19:29 +0000890 if (m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, true) != lldb::eReturnStatusQuit)
Chris Lattner24943d22010-06-08 16:52:24 +0000891 {
892 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize());
893 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize());
894 }
895 // We are done getting and running our command, we can now clear the
896 // m_waiting_for_command so we can get another one.
897 m_waiting_for_command = false;
898
899 // If our editline input reader is active, it means another input reader
900 // got pushed onto the input reader and caused us to become deactivated.
901 // When the input reader above us gets popped, we will get re-activated
902 // and our prompt will refresh in our callback
903 if (m_editline_reader.IsActive())
904 {
905 ReadyForCommand ();
906 }
907 }
908 else if (event_type & IOChannel::eBroadcastBitUserInterrupt)
909 {
910 // This is here to handle control-c interrupts from the user. It has not yet really been implemented.
911 // TO BE DONE: PROPERLY HANDLE CONTROL-C FROM USER
912 //m_io_channel_ap->CancelInput();
913 // Anything else? Send Interrupt to process?
914 }
915 else if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
916 (event_type & IOChannel::eBroadcastBitThreadDidExit))
917 {
918 // If the IOChannel thread is trying to go away, then it is definitely
919 // time to end the debugging session.
920 quit = true;
921 }
922
923 return quit;
924}
925
926
927//struct CrashImageInfo
928//{
929// std::string path;
930// VMRange text_range;
931// UUID uuid;
932//};
933//
934//void
935//Driver::ParseCrashLog (const char *crash_log)
936//{
937// printf("Parsing crash log: %s\n", crash_log);
938//
939// char image_path[PATH_MAX];
940// std::vector<CrashImageInfo> crash_infos;
941// if (crash_log && crash_log[0])
942// {
943// FileSpec crash_log_file (crash_log);
944// STLStringArray crash_log_lines;
945// if (crash_log_file.ReadFileLines (crash_log_lines))
946// {
947// const size_t num_crash_log_lines = crash_log_lines.size();
948// size_t i;
949// for (i=0; i<num_crash_log_lines; ++i)
950// {
951// const char *line = crash_log_lines[i].c_str();
952// if (strstr (line, "Code Type:"))
953// {
954// char arch_string[256];
955// if (sscanf(line, "%s", arch_string))
956// {
957// if (strcmp(arch_string, "X86-64"))
958// lldb::GetDefaultArchitecture ().SetArch ("x86_64");
959// else if (strcmp(arch_string, "X86"))
960// lldb::GetDefaultArchitecture ().SetArch ("i386");
961// else
962// {
963// ArchSpec arch(arch_string);
964// if (arch.IsValid ())
965// lldb::GetDefaultArchitecture () = arch;
966// else
967// fprintf(stderr, "Unrecognized architecture: %s\n", arch_string);
968// }
969// }
970// }
971// else
972// if (strstr(line, "Path:"))
973// {
974// const char *p = line + strlen("Path:");
975// while (isspace(*p))
976// ++p;
977//
978// m_option_data.m_filename.assign (p);
979// }
980// else
981// if (strstr(line, "Binary Images:"))
982// {
983// while (++i < num_crash_log_lines)
984// {
985// if (crash_log_lines[i].empty())
986// break;
987//
988// line = crash_log_lines[i].c_str();
989// uint64_t text_start_addr;
990// uint64_t text_end_addr;
991// char uuid_cstr[64];
992// int bytes_consumed_before_uuid = 0;
993// int bytes_consumed_after_uuid = 0;
994//
995// int items_parsed = ::sscanf (line,
996// "%llx - %llx %*s %*s %*s %n%s %n",
997// &text_start_addr,
998// &text_end_addr,
999// &bytes_consumed_before_uuid,
1000// uuid_cstr,
1001// &bytes_consumed_after_uuid);
1002//
1003// if (items_parsed == 3)
1004// {
1005//
1006// CrashImageInfo info;
1007// info.text_range.SetBaseAddress(text_start_addr);
1008// info.text_range.SetEndAddress(text_end_addr);
1009//
1010// if (uuid_cstr[0] == '<')
1011// {
1012// if (info.uuid.SetfromCString (&uuid_cstr[1]) == 0)
1013// info.uuid.Clear();
1014//
1015// ::strncpy (image_path, line + bytes_consumed_after_uuid, sizeof(image_path));
1016// }
1017// else
1018// {
1019// ::strncpy (image_path, line + bytes_consumed_before_uuid, sizeof(image_path));
1020// }
1021//
1022// info.path = image_path;
1023//
1024// crash_infos.push_back (info);
1025//
1026// info.uuid.GetAsCString(uuid_cstr, sizeof(uuid_cstr));
1027//
1028// printf("0x%16.16llx - 0x%16.16llx <%s> %s\n",
1029// text_start_addr,
1030// text_end_addr,
1031// uuid_cstr,
1032// image_path);
1033// }
1034// }
1035// }
1036// }
1037// }
1038//
1039// if (crash_infos.size())
1040// {
Greg Clayton63094e02010-06-23 01:19:29 +00001041// SBTarget target (m_debugger.CreateTarget (crash_infos.front().path.c_str(),
Chris Lattner24943d22010-06-08 16:52:24 +00001042// lldb::GetDefaultArchitecture().AsCString (),
1043// false));
1044// if (target.IsValid())
1045// {
1046//
1047// }
1048// }
1049// }
1050//}
1051//
1052
1053void
1054Driver::MasterThreadBytesReceived (void *baton, const void *src, size_t src_len)
1055{
1056 Driver *driver = (Driver*)baton;
1057 driver->GetFromMaster ((const char *)src, src_len);
1058}
1059
1060void
1061Driver::GetFromMaster (const char *src, size_t src_len)
1062{
1063 // Echo the characters back to the Debugger's stdout, that way if you
1064 // type characters while a command is running, you'll see what you've typed.
Greg Clayton63094e02010-06-23 01:19:29 +00001065 FILE *out_fh = m_debugger.GetOutputFileHandle();
Chris Lattner24943d22010-06-08 16:52:24 +00001066 if (out_fh)
1067 ::fwrite (src, 1, src_len, out_fh);
1068}
1069
1070size_t
1071Driver::EditLineInputReaderCallback
1072(
1073 void *baton,
1074 SBInputReader *reader,
1075 InputReaderAction notification,
1076 const char *bytes,
1077 size_t bytes_len
1078)
1079{
1080 Driver *driver = (Driver *)baton;
1081
1082 switch (notification)
1083 {
1084 case eInputReaderActivate:
1085 break;
1086
1087 case eInputReaderReactivate:
1088 driver->ReadyForCommand();
1089 break;
1090
1091 case eInputReaderDeactivate:
1092 break;
1093
1094 case eInputReaderGotToken:
1095 write (driver->m_editline_pty.GetMasterFileDescriptor(), bytes, bytes_len);
1096 break;
1097
1098 case eInputReaderDone:
1099 break;
1100 }
1101 return bytes_len;
1102}
1103
1104void
1105Driver::MainLoop ()
1106{
1107 char error_str[1024];
1108 if (m_editline_pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, error_str, sizeof(error_str)) == false)
1109 {
1110 ::fprintf (stderr, "error: failed to open driver pseudo terminal : %s", error_str);
1111 exit(1);
1112 }
1113 else
1114 {
1115 const char *driver_slave_name = m_editline_pty.GetSlaveName (error_str, sizeof(error_str));
1116 if (driver_slave_name == NULL)
1117 {
1118 ::fprintf (stderr, "error: failed to get slave name for driver pseudo terminal : %s", error_str);
1119 exit(2);
1120 }
1121 else
1122 {
1123 m_editline_slave_fh = ::fopen (driver_slave_name, "r+");
1124 if (m_editline_slave_fh == NULL)
1125 {
1126 SBError error;
1127 error.SetErrorToErrno();
1128 ::fprintf (stderr, "error: failed to get open slave for driver pseudo terminal : %s",
1129 error.GetCString());
1130 exit(3);
1131 }
1132
1133 ::setbuf (m_editline_slave_fh, NULL);
1134 }
1135 }
1136
1137
1138 // struct termios stdin_termios;
1139
1140 if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0)
1141 atexit (reset_stdin_termios);
1142
1143 ::setbuf (stdin, NULL);
1144 ::setbuf (stdout, NULL);
1145
Greg Clayton63094e02010-06-23 01:19:29 +00001146 m_debugger.SetErrorFileHandle (stderr, false);
1147 m_debugger.SetOutputFileHandle (stdout, false);
1148 m_debugger.SetInputFileHandle (stdin, true);
Jim Ingham74989e82010-08-30 19:44:40 +00001149
1150 m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor);
Chris Lattner24943d22010-06-08 16:52:24 +00001151
1152 // You have to drain anything that comes to the master side of the PTY. master_out_comm is
1153 // for that purpose. The reason you need to do this is a curious reason... editline will echo
1154 // characters to the PTY when it gets characters while el_gets is not running, and then when
1155 // you call el_gets (or el_getc) it will try to reset the terminal back to raw mode which blocks
1156 // if there are unconsumed characters in the out buffer.
1157 // However, you don't need to do anything with the characters, since editline will dump these
1158 // unconsumed characters after printing the prompt again in el_gets.
1159
1160 SBCommunication master_out_comm("driver.editline");
1161 master_out_comm.AdoptFileDesriptor(m_editline_pty.GetMasterFileDescriptor(), false);
1162 master_out_comm.SetReadThreadBytesReceivedCallback(Driver::MasterThreadBytesReceived, this);
1163
1164 if (master_out_comm.ReadThreadStart () == false)
1165 {
1166 ::fprintf (stderr, "error: failed to start master out read thread");
1167 exit(5);
1168 }
1169
1170// const char *crash_log = GetCrashLogFilename();
1171// if (crash_log)
1172// {
1173// ParseCrashLog (crash_log);
1174// }
1175//
Greg Clayton63094e02010-06-23 01:19:29 +00001176 SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter();
Chris Lattner24943d22010-06-08 16:52:24 +00001177
1178 m_io_channel_ap.reset (new IOChannel(m_editline_slave_fh, stdout, stderr, this));
1179
1180 struct winsize window_size;
1181 if (isatty (STDIN_FILENO)
1182 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
1183 {
Caroline Tice6e4c5ce2010-09-04 00:03:46 +00001184 if (window_size.ws_col > 0)
Greg Clayton238c0a12010-09-18 01:14:36 +00001185 m_debugger.SetTerminalWidth (window_size.ws_col);
Chris Lattner24943d22010-06-08 16:52:24 +00001186 }
1187
1188 // Since input can be redirected by the debugger, we must insert our editline
1189 // input reader in the queue so we know when our reader should be active
1190 // and so we can receive bytes only when we are supposed to.
Greg Clayton63094e02010-06-23 01:19:29 +00001191 SBError err (m_editline_reader.Initialize (m_debugger,
1192 Driver::EditLineInputReaderCallback, // callback
Chris Lattner24943d22010-06-08 16:52:24 +00001193 this, // baton
1194 eInputReaderGranularityByte, // token_size
1195 NULL, // end token - NULL means never done
1196 NULL, // prompt - taken care of elsewhere
1197 false)); // echo input - don't need Debugger
1198 // to do this, we handle it elsewhere
1199
1200 if (err.Fail())
1201 {
1202 ::fprintf (stderr, "error: %s", err.GetCString());
1203 exit (6);
1204 }
1205
Greg Clayton63094e02010-06-23 01:19:29 +00001206 m_debugger.PushInputReader (m_editline_reader);
Chris Lattner24943d22010-06-08 16:52:24 +00001207
Greg Clayton63094e02010-06-23 01:19:29 +00001208 SBListener listener(m_debugger.GetListener());
Chris Lattner24943d22010-06-08 16:52:24 +00001209 if (listener.IsValid())
1210 {
1211
1212 listener.StartListeningForEvents (*m_io_channel_ap,
1213 IOChannel::eBroadcastBitHasUserInput |
1214 IOChannel::eBroadcastBitUserInterrupt |
1215 IOChannel::eBroadcastBitThreadShouldExit |
1216 IOChannel::eBroadcastBitThreadDidStart |
1217 IOChannel::eBroadcastBitThreadDidExit);
1218
1219 if (m_io_channel_ap->Start ())
1220 {
1221 bool iochannel_thread_exited = false;
1222
1223 listener.StartListeningForEvents (sb_interpreter.GetBroadcaster(),
1224 SBCommandInterpreter::eBroadcastBitQuitCommandReceived);
1225
1226 // Before we handle any options from the command line, we parse the
1227 // .lldbinit file in the user's home directory.
1228 SBCommandReturnObject result;
1229 sb_interpreter.SourceInitFileInHomeDirectory(result);
1230 if (GetDebugMode())
1231 {
Greg Clayton63094e02010-06-23 01:19:29 +00001232 result.PutError (m_debugger.GetErrorFileHandle());
1233 result.PutOutput (m_debugger.GetOutputFileHandle());
Chris Lattner24943d22010-06-08 16:52:24 +00001234 }
1235
1236 // Now we handle options we got from the command line
1237 char command_string[PATH_MAX * 2];
1238 const size_t num_source_command_files = GetNumSourceCommandFiles();
1239 if (num_source_command_files > 0)
1240 {
1241 for (size_t i=0; i < num_source_command_files; ++i)
1242 {
1243 const char *command_file = GetSourceCommandFileAtIndex(i);
Johnny Chen7c984242010-07-28 21:16:11 +00001244 ::snprintf (command_string, sizeof(command_string), "command source '%s'", command_file);
Greg Clayton63094e02010-06-23 01:19:29 +00001245 m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, false);
Chris Lattner24943d22010-06-08 16:52:24 +00001246 if (GetDebugMode())
1247 {
Greg Clayton63094e02010-06-23 01:19:29 +00001248 result.PutError (m_debugger.GetErrorFileHandle());
1249 result.PutOutput (m_debugger.GetOutputFileHandle());
Chris Lattner24943d22010-06-08 16:52:24 +00001250 }
1251 }
1252 }
1253
1254 if (!m_option_data.m_filename.empty())
1255 {
1256 char arch_name[64];
Greg Clayton63094e02010-06-23 01:19:29 +00001257 if (m_debugger.GetDefaultArchitecture (arch_name, sizeof (arch_name)))
Chris Lattner24943d22010-06-08 16:52:24 +00001258 ::snprintf (command_string, sizeof (command_string), "file --arch=%s '%s'", arch_name,
1259 m_option_data.m_filename.c_str());
1260 else
1261 ::snprintf (command_string, sizeof(command_string), "file '%s'", m_option_data.m_filename.c_str());
1262
Greg Clayton63094e02010-06-23 01:19:29 +00001263 m_debugger.HandleCommand (command_string);
Chris Lattner24943d22010-06-08 16:52:24 +00001264 }
1265
1266 // Now that all option parsing is done, we try and parse the .lldbinit
1267 // file in the current working directory
1268 sb_interpreter.SourceInitFileInCurrentWorkingDirectory (result);
1269 if (GetDebugMode())
1270 {
Greg Clayton63094e02010-06-23 01:19:29 +00001271 result.PutError(m_debugger.GetErrorFileHandle());
1272 result.PutOutput(m_debugger.GetOutputFileHandle());
Chris Lattner24943d22010-06-08 16:52:24 +00001273 }
1274
1275 SBEvent event;
1276
1277 // Make sure the IO channel is started up before we try to tell it we
1278 // are ready for input
1279 listener.WaitForEventForBroadcasterWithType (UINT32_MAX,
1280 *m_io_channel_ap,
1281 IOChannel::eBroadcastBitThreadDidStart,
1282 event);
1283
1284 ReadyForCommand ();
1285
1286 bool done = false;
1287 while (!done)
1288 {
1289 listener.WaitForEvent (UINT32_MAX, event);
1290 if (event.IsValid())
1291 {
1292 if (event.GetBroadcaster().IsValid())
1293 {
1294 uint32_t event_type = event.GetType();
1295 if (event.BroadcasterMatchesRef (*m_io_channel_ap))
1296 {
1297 if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
1298 (event_type & IOChannel::eBroadcastBitThreadDidExit))
1299 {
1300 done = true;
1301 if (event_type & IOChannel::eBroadcastBitThreadDidExit)
1302 iochannel_thread_exited = true;
1303 break;
1304 }
1305 else
1306 done = HandleIOEvent (event);
1307 }
Jim Inghamc8332952010-08-26 21:32:51 +00001308 else if (event.BroadcasterMatchesRef (m_debugger.GetSelectedTarget().GetProcess().GetBroadcaster()))
Chris Lattner24943d22010-06-08 16:52:24 +00001309 {
1310 HandleProcessEvent (event);
1311 }
1312 else if (event.BroadcasterMatchesRef (sb_interpreter.GetBroadcaster()))
1313 {
1314 if (event_type & SBCommandInterpreter::eBroadcastBitQuitCommandReceived)
1315 done = true;
1316 }
1317 }
1318 }
1319 }
1320
1321 reset_stdin_termios ();
1322
1323 CloseIOChannelFile ();
1324
1325 if (!iochannel_thread_exited)
1326 {
Greg Claytonbef15832010-07-14 00:18:15 +00001327 event.Clear();
Chris Lattner24943d22010-06-08 16:52:24 +00001328 listener.GetNextEventForBroadcasterWithType (*m_io_channel_ap,
1329 IOChannel::eBroadcastBitThreadDidExit,
1330 event);
1331 if (!event.IsValid())
1332 {
1333 // Send end EOF to the driver file descriptor
1334 m_io_channel_ap->Stop();
1335 }
1336 }
1337
Jim Inghamc8332952010-08-26 21:32:51 +00001338 SBProcess process = m_debugger.GetSelectedTarget().GetProcess();
Chris Lattner24943d22010-06-08 16:52:24 +00001339 if (process.IsValid())
1340 process.Destroy();
1341 }
1342 }
1343}
1344
1345
1346void
1347Driver::ReadyForCommand ()
1348{
1349 if (m_waiting_for_command == false)
1350 {
1351 m_waiting_for_command = true;
1352 BroadcastEventByType (Driver::eBroadcastBitReadyForInput, true);
1353 }
1354}
1355
1356
Caroline Ticeb8314fe2010-09-09 17:45:09 +00001357void
1358sigwinch_handler (int signo)
1359{
1360 struct winsize window_size;
1361 if (isatty (STDIN_FILENO)
1362 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
1363 {
1364 if ((window_size.ws_col > 0) && (strlen (g_debugger_name) > 0))
1365 {
1366 char width_str_buffer[25];
1367 ::sprintf (width_str_buffer, "%d", window_size.ws_col);
1368 SBDebugger::SetInternalVariable ("term-width", width_str_buffer, g_debugger_name);
1369 }
1370 }
1371}
1372
Chris Lattner24943d22010-06-08 16:52:24 +00001373int
1374main (int argc, char const *argv[])
1375{
Chris Lattner24943d22010-06-08 16:52:24 +00001376 SBDebugger::Initialize();
1377
Greg Clayton95e33b72010-11-07 21:02:03 +00001378 SBHostOS::ThreadCreated ("<lldb.driver.main-thread>");
Chris Lattner24943d22010-06-08 16:52:24 +00001379
Greg Clayton36f63a92010-10-19 03:25:40 +00001380 signal (SIGPIPE, SIG_IGN);
Caroline Ticeb8314fe2010-09-09 17:45:09 +00001381 signal (SIGWINCH, sigwinch_handler);
1382
Greg Clayton63094e02010-06-23 01:19:29 +00001383 // Create a scope for driver so that the driver object will destroy itself
1384 // before SBDebugger::Terminate() is called.
Chris Lattner24943d22010-06-08 16:52:24 +00001385 {
Greg Clayton63094e02010-06-23 01:19:29 +00001386 Driver driver;
1387
1388 bool exit = false;
1389 SBError error (driver.ParseArgs (argc, argv, stdout, exit));
1390 if (error.Fail())
1391 {
1392 const char *error_cstr = error.GetCString ();
1393 if (error_cstr)
1394 ::fprintf (stderr, "error: %s\n", error_cstr);
1395 }
1396 else if (!exit)
1397 {
1398 driver.MainLoop ();
1399 }
Chris Lattner24943d22010-06-08 16:52:24 +00001400 }
1401
1402 SBDebugger::Terminate();
1403 return 0;
1404}