blob: 0b5809c8355c85ac28adbe04356094caad783453 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- Driver.cpp ----------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "Driver.h"
11
Deepak Panickal429222c2013-10-15 15:46:40 +000012#include <stdio.h>
Eli Friedmana382d472010-06-09 09:50:17 +000013#include <string.h>
14#include <stdlib.h>
15#include <limits.h>
Eli Friedman07b16272010-06-09 19:11:30 +000016#include <fcntl.h>
Chris Lattner30fdc8d2010-06-08 16:52:24 +000017
Greg Clayton49668762014-08-01 18:32:07 +000018// Includes for pipe()
19#if defined(_WIN32)
20#include <io.h>
21#include <fcntl.h>
22#else
23#include <unistd.h>
24#endif
25
Chris Lattner30fdc8d2010-06-08 16:52:24 +000026#include <string>
27
Deepak Panickal429222c2013-10-15 15:46:40 +000028#include <thread>
Jim Inghame6bc6cb2012-02-08 05:23:15 +000029#include "lldb/API/SBBreakpoint.h"
Eli Friedmana382d472010-06-09 09:50:17 +000030#include "lldb/API/SBCommandInterpreter.h"
31#include "lldb/API/SBCommandReturnObject.h"
32#include "lldb/API/SBCommunication.h"
33#include "lldb/API/SBDebugger.h"
34#include "lldb/API/SBEvent.h"
35#include "lldb/API/SBHostOS.h"
36#include "lldb/API/SBListener.h"
Jim Ingham85e8b812011-02-19 02:53:09 +000037#include "lldb/API/SBStream.h"
Eli Friedmana382d472010-06-09 09:50:17 +000038#include "lldb/API/SBTarget.h"
39#include "lldb/API/SBThread.h"
40#include "lldb/API/SBProcess.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000041
Todd Fialab82ad2a2014-09-15 15:17:13 +000042#if !defined(__APPLE__)
Zachary Turner40a069a2014-09-11 20:26:49 +000043#include "llvm/Support/DataTypes.h"
Todd Fialab82ad2a2014-09-15 15:17:13 +000044#endif
Zachary Turner40a069a2014-09-11 20:26:49 +000045
Chris Lattner30fdc8d2010-06-08 16:52:24 +000046using namespace lldb;
47
48static void reset_stdin_termios ();
Greg Claytonf571b892012-02-02 19:28:31 +000049static bool g_old_stdin_termios_is_valid = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000050static struct termios g_old_stdin_termios;
51
Caroline Ticedd759852010-09-09 17:45:09 +000052static char *g_debugger_name = (char *) "";
Caroline Ticeefed6132010-11-19 20:47:54 +000053static Driver *g_driver = NULL;
Caroline Ticedd759852010-09-09 17:45:09 +000054
Chris Lattner30fdc8d2010-06-08 16:52:24 +000055// In the Driver::MainLoop, we change the terminal settings. This function is
56// added as an atexit handler to make sure we clean them up.
57static void
58reset_stdin_termios ()
59{
Greg Claytonf571b892012-02-02 19:28:31 +000060 if (g_old_stdin_termios_is_valid)
61 {
62 g_old_stdin_termios_is_valid = false;
63 ::tcsetattr (STDIN_FILENO, TCSANOW, &g_old_stdin_termios);
64 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +000065}
66
Greg Claytone0d378b2011-03-24 21:19:54 +000067typedef struct
Chris Lattner30fdc8d2010-06-08 16:52:24 +000068{
Greg Claytone0d378b2011-03-24 21:19:54 +000069 uint32_t usage_mask; // Used to mark options that can be used together. If (1 << n & usage_mask) != 0
70 // then this option belongs to option set n.
71 bool required; // This option is required (in the current usage level)
72 const char * long_option; // Full name for this option.
Greg Clayton3bcdfc02012-12-04 00:32:51 +000073 int short_option; // Single character for this option.
Greg Claytone0d378b2011-03-24 21:19:54 +000074 int option_has_arg; // no_argument, required_argument or optional_argument
Greg Claytonab65b342011-04-13 22:47:15 +000075 uint32_t completion_type; // Cookie the option class can use to do define the argument completion.
Greg Claytone0d378b2011-03-24 21:19:54 +000076 lldb::CommandArgumentType argument_type; // Type of argument this option takes
77 const char * usage_text; // Full text explaining what this options does and what (if any) argument to
78 // pass it.
79} OptionDefinition;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000080
Jim Inghame64f0dc2011-09-13 23:25:31 +000081#define LLDB_3_TO_5 LLDB_OPT_SET_3|LLDB_OPT_SET_4|LLDB_OPT_SET_5
82#define LLDB_4_TO_5 LLDB_OPT_SET_4|LLDB_OPT_SET_5
83
Greg Claytone0d378b2011-03-24 21:19:54 +000084static OptionDefinition g_options[] =
85{
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +000086 { LLDB_OPT_SET_1, true , "help" , 'h', no_argument , 0, eArgTypeNone,
Jim Ingham12e9a202011-09-15 21:30:02 +000087 "Prints out the usage information for the LLDB debugger." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +000088 { LLDB_OPT_SET_2, true , "version" , 'v', no_argument , 0, eArgTypeNone,
Jim Ingham12e9a202011-09-15 21:30:02 +000089 "Prints out the current version number of the LLDB debugger." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +000090 { LLDB_OPT_SET_3, true , "arch" , 'a', required_argument, 0, eArgTypeArchitecture,
Jim Ingham12e9a202011-09-15 21:30:02 +000091 "Tells the debugger to use the specified architecture when starting and running the program. <architecture> must "
92 "be one of the architectures for which the program was compiled." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +000093 { LLDB_OPT_SET_3, true , "file" , 'f', required_argument, 0, eArgTypeFilename,
Jim Ingham12e9a202011-09-15 21:30:02 +000094 "Tells the debugger to use the file <filename> as the program to be debugged." },
Jason Molenda67c3cf52012-10-24 03:29:40 +000095 { LLDB_OPT_SET_3, false, "core" , 'c', required_argument, 0, eArgTypeFilename,
Johnny Cheneb46f782012-08-15 22:10:42 +000096 "Tells the debugger to use the fullpath to <path> as the core file." },
Jim Inghamf0c63b92014-02-05 21:35:09 +000097 { LLDB_OPT_SET_5, true , "attach-pid" , 'p', required_argument, 0, eArgTypePid,
98 "Tells the debugger to attach to a process with the given pid." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +000099 { LLDB_OPT_SET_4, true , "attach-name" , 'n', required_argument, 0, eArgTypeProcessName,
Jim Ingham12e9a202011-09-15 21:30:02 +0000100 "Tells the debugger to attach to a process with the given name." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +0000101 { LLDB_OPT_SET_4, true , "wait-for" , 'w', no_argument , 0, eArgTypeNone,
Jim Ingham12e9a202011-09-15 21:30:02 +0000102 "Tells the debugger to wait for a process with the given pid or name to launch before attaching." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +0000103 { LLDB_3_TO_5, false, "source" , 's', required_argument, 0, eArgTypeFilename,
Jim Ingham47ea51f2013-09-17 01:53:35 +0000104 "Tells the debugger to read in and execute the lldb commands in the given file, after any file provided on the command line has been loaded." },
Jim Inghamed3252f2013-09-14 00:20:24 +0000105 { LLDB_3_TO_5, false, "one-line" , 'o', required_argument, 0, eArgTypeNone,
Jim Ingham47ea51f2013-09-17 01:53:35 +0000106 "Tells the debugger to execute this one-line lldb command after any file provided on the command line has been loaded." },
Jim Inghamed3252f2013-09-14 00:20:24 +0000107 { LLDB_3_TO_5, false, "source-before-file" , 'S', required_argument, 0, eArgTypeFilename,
Jim Ingham47ea51f2013-09-17 01:53:35 +0000108 "Tells the debugger to read in and execute the lldb commands in the given file, before any file provided on the command line has been loaded." },
Jim Inghamed3252f2013-09-14 00:20:24 +0000109 { LLDB_3_TO_5, false, "one-line-before-file" , 'O', required_argument, 0, eArgTypeNone,
Jim Ingham47ea51f2013-09-17 01:53:35 +0000110 "Tells the debugger to execute this one-line lldb command before any file provided on the command line has been loaded." },
Jim Inghamf0c63b92014-02-05 21:35:09 +0000111 { LLDB_3_TO_5, false, "source-quietly" , 'Q', no_argument , 0, eArgTypeNone,
112 "Tells the debugger suppress output from commands provided in the -s, -S, -O and -o commands." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +0000113 { LLDB_3_TO_5, false, "editor" , 'e', no_argument , 0, eArgTypeNone,
Jim Ingham12e9a202011-09-15 21:30:02 +0000114 "Tells the debugger to open source files using the host's \"external editor\" mechanism." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +0000115 { LLDB_3_TO_5, false, "no-lldbinit" , 'x', no_argument , 0, eArgTypeNone,
Jim Ingham12e9a202011-09-15 21:30:02 +0000116 "Do not automatically parse any '.lldbinit' files." },
Jim Inghamed3252f2013-09-14 00:20:24 +0000117 { LLDB_3_TO_5, false, "no-use-colors" , 'X', no_argument , 0, eArgTypeNone,
Michael Sartainc3ce7f272013-05-23 20:47:45 +0000118 "Do not use colors." },
119 { LLDB_OPT_SET_6, true , "python-path" , 'P', no_argument , 0, eArgTypeNone,
Jim Inghame2231ac2012-12-21 22:22:26 +0000120 "Prints out the path to the lldb.py file for this version of lldb." },
Jim Inghamf0c63b92014-02-05 21:35:09 +0000121 { LLDB_3_TO_5, false, "script-language", 'l', required_argument, 0, eArgTypeScriptLang,
122 "Tells the debugger to use the specified scripting language for user-defined scripts, rather than the default. "
123 "Valid scripting languages that can be specified include Python, Perl, Ruby and Tcl. Currently only the Python "
124 "extensions have been implemented." },
125 { LLDB_3_TO_5, false, "debug" , 'd', no_argument , 0, eArgTypeNone,
126 "Tells the debugger to print out extra information for debugging itself." },
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +0000127 { 0, false, NULL , 0 , 0 , 0, eArgTypeNone, NULL }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000128};
129
Jim Inghame64f0dc2011-09-13 23:25:31 +0000130static const uint32_t last_option_set_with_args = 2;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000131
132Driver::Driver () :
133 SBBroadcaster ("Driver"),
Jim Ingham06942692011-08-13 00:22:20 +0000134 m_debugger (SBDebugger::Create(false)),
Greg Clayton44d93782014-01-27 23:43:24 +0000135 m_option_data ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000136{
Greg Claytonfc3f0272011-05-29 04:06:55 +0000137 // We want to be able to handle CTRL+D in the terminal to have it terminate
138 // certain input
139 m_debugger.SetCloseInputOnEOF (false);
Caroline Ticedd759852010-09-09 17:45:09 +0000140 g_debugger_name = (char *) m_debugger.GetInstanceName();
141 if (g_debugger_name == NULL)
142 g_debugger_name = (char *) "";
Caroline Ticeefed6132010-11-19 20:47:54 +0000143 g_driver = this;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000144}
145
146Driver::~Driver ()
147{
Caroline Ticeefed6132010-11-19 20:47:54 +0000148 g_driver = NULL;
149 g_debugger_name = NULL;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000150}
151
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000152
Greg Claytonc982c762010-07-09 20:39:50 +0000153// This function takes INDENT, which tells how many spaces to output at the front
154// of each line; TEXT, which is the text that is to be output. It outputs the
155// text, on multiple lines if necessary, to RESULT, with INDENT spaces at the
156// front of each line. It breaks lines on spaces, tabs or newlines, shortening
157// the line if necessary to not break in the middle of a word. It assumes that
158// each output line should contain a maximum of OUTPUT_MAX_COLUMNS characters.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000159
160void
Greg Claytonc982c762010-07-09 20:39:50 +0000161OutputFormattedUsageText (FILE *out, int indent, const char *text, int output_max_columns)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000162{
163 int len = strlen (text);
164 std::string text_string (text);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000165
166 // Force indentation to be reasonable.
167 if (indent >= output_max_columns)
168 indent = 0;
169
170 // Will it all fit on one line?
171
172 if (len + indent < output_max_columns)
173 // Output as a single line
Greg Claytonc982c762010-07-09 20:39:50 +0000174 fprintf (out, "%*s%s\n", indent, "", text);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000175 else
176 {
177 // We need to break it up into multiple lines.
178 int text_width = output_max_columns - indent - 1;
179 int start = 0;
180 int end = start;
181 int final_end = len;
182 int sub_len;
183
184 while (end < final_end)
185 {
186 // Dont start the 'text' on a space, since we're already outputting the indentation.
187 while ((start < final_end) && (text[start] == ' '))
188 start++;
189
190 end = start + text_width;
191 if (end > final_end)
192 end = final_end;
193 else
194 {
195 // If we're not at the end of the text, make sure we break the line on white space.
196 while (end > start
197 && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
198 end--;
199 }
200 sub_len = end - start;
201 std::string substring = text_string.substr (start, sub_len);
Greg Claytonc982c762010-07-09 20:39:50 +0000202 fprintf (out, "%*s%s\n", indent, "", substring.c_str());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000203 start = end + 1;
204 }
205 }
206}
207
208void
Greg Claytone0d378b2011-03-24 21:19:54 +0000209ShowUsage (FILE *out, OptionDefinition *option_table, Driver::OptionData data)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000210{
211 uint32_t screen_width = 80;
212 uint32_t indent_level = 0;
213 const char *name = "lldb";
Jim Ingham86511212010-06-15 18:47:14 +0000214
Chris Lattner30fdc8d2010-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 Lattner30fdc8d2010-06-08 16:52:24 +0000224 uint32_t num_options;
Jim Ingham86511212010-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 Lattner30fdc8d2010-06-08 16:52:24 +0000228 {
Jim Ingham86511212010-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 Lattner30fdc8d2010-06-08 16:52:24 +0000231 {
Jim Ingham86511212010-06-15 18:47:14 +0000232 if (num_option_sets == 0)
233 num_option_sets = 1;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000234 }
235 else
236 {
Greg Claytonc982c762010-07-09 20:39:50 +0000237 for (uint32_t j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++)
Jim Ingham86511212010-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 Claytonc982c762010-07-09 20:39:50 +0000256 fprintf (out, "%*s%s", indent_level, "", name);
Jim Ingham556e6532011-08-16 23:15:02 +0000257 bool is_help_line = false;
Jim Ingham86511212010-06-15 18:47:14 +0000258
259 for (uint32_t i = 0; i < num_options; ++i)
260 {
261 if (option_table[i].usage_mask & opt_set_mask)
262 {
Caroline Ticedeaab222010-10-01 19:59:14 +0000263 CommandArgumentType arg_type = option_table[i].argument_type;
Greg Clayton9d0402b2011-02-20 02:15:07 +0000264 const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type);
Jim Ingham556e6532011-08-16 23:15:02 +0000265 // This is a bit of a hack, but there's no way to say certain options don't have arguments yet...
266 // so we do it by hand here.
267 if (option_table[i].short_option == 'h')
268 is_help_line = true;
269
Jim Ingham86511212010-06-15 18:47:14 +0000270 if (option_table[i].required)
271 {
272 if (option_table[i].option_has_arg == required_argument)
Greg Clayton9d0402b2011-02-20 02:15:07 +0000273 fprintf (out, " -%c <%s>", option_table[i].short_option, arg_name);
Jim Ingham86511212010-06-15 18:47:14 +0000274 else if (option_table[i].option_has_arg == optional_argument)
Greg Clayton9d0402b2011-02-20 02:15:07 +0000275 fprintf (out, " -%c [<%s>]", option_table[i].short_option, arg_name);
Jim Ingham86511212010-06-15 18:47:14 +0000276 else
277 fprintf (out, " -%c", option_table[i].short_option);
278 }
279 else
280 {
281 if (option_table[i].option_has_arg == required_argument)
Greg Clayton9d0402b2011-02-20 02:15:07 +0000282 fprintf (out, " [-%c <%s>]", option_table[i].short_option, arg_name);
Jim Ingham86511212010-06-15 18:47:14 +0000283 else if (option_table[i].option_has_arg == optional_argument)
Greg Clayton9d0402b2011-02-20 02:15:07 +0000284 fprintf (out, " [-%c [<%s>]]", option_table[i].short_option, arg_name);
Jim Ingham86511212010-06-15 18:47:14 +0000285 else
286 fprintf (out, " [-%c]", option_table[i].short_option);
287 }
288 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000289 }
Jim Inghame64f0dc2011-09-13 23:25:31 +0000290 if (!is_help_line && (opt_set <= last_option_set_with_args))
Jim Ingham556e6532011-08-16 23:15:02 +0000291 fprintf (out, " [[--] <PROGRAM-ARG-1> [<PROGRAM_ARG-2> ...]]");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000292 }
293
294 fprintf (out, "\n\n");
295
296 // Now print out all the detailed information about the various options: long form, short form and help text:
297 // -- long_name <argument>
298 // - short <argument>
299 // help text
300
301 // This variable is used to keep track of which options' info we've printed out, because some options can be in
302 // more than one usage level, but we only want to print the long form of its information once.
303
304 Driver::OptionData::OptionSet options_seen;
305 Driver::OptionData::OptionSet::iterator pos;
306
307 indent_level += 5;
308
Jim Ingham86511212010-06-15 18:47:14 +0000309 for (uint32_t i = 0; i < num_options; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000310 {
311 // Only print this option if we haven't already seen it.
312 pos = options_seen.find (option_table[i].short_option);
313 if (pos == options_seen.end())
314 {
Caroline Ticedeaab222010-10-01 19:59:14 +0000315 CommandArgumentType arg_type = option_table[i].argument_type;
Greg Clayton9d0402b2011-02-20 02:15:07 +0000316 const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type);
Caroline Ticedeaab222010-10-01 19:59:14 +0000317
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000318 options_seen.insert (option_table[i].short_option);
Greg Claytonc982c762010-07-09 20:39:50 +0000319 fprintf (out, "%*s-%c ", indent_level, "", option_table[i].short_option);
Caroline Ticedeaab222010-10-01 19:59:14 +0000320 if (arg_type != eArgTypeNone)
Greg Clayton9d0402b2011-02-20 02:15:07 +0000321 fprintf (out, "<%s>", arg_name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000322 fprintf (out, "\n");
Greg Claytonc982c762010-07-09 20:39:50 +0000323 fprintf (out, "%*s--%s ", indent_level, "", option_table[i].long_option);
Caroline Ticedeaab222010-10-01 19:59:14 +0000324 if (arg_type != eArgTypeNone)
Greg Clayton9d0402b2011-02-20 02:15:07 +0000325 fprintf (out, "<%s>", arg_name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000326 fprintf (out, "\n");
327 indent_level += 5;
Greg Claytonc982c762010-07-09 20:39:50 +0000328 OutputFormattedUsageText (out, indent_level, option_table[i].usage_text, screen_width);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000329 indent_level -= 5;
330 fprintf (out, "\n");
331 }
332 }
333
334 indent_level -= 5;
Jim Inghamf0c63b92014-02-05 21:35:09 +0000335
336 fprintf (out, "\n%*sNotes:\n",
337 indent_level, "");
338 indent_level += 5;
339
Jim Ingham47ea51f2013-09-17 01:53:35 +0000340 fprintf (out, "\n%*sMultiple \"-s\" and \"-o\" options can be provided. They will be processed from left to right in order, "
341 "\n%*swith the source files and commands interleaved. The same is true of the \"-S\" and \"-O\" options."
342 "\n%*sThe before file and after file sets can intermixed freely, the command parser will sort them out."
343 "\n%*sThe order of the file specifiers (\"-c\", \"-f\", etc.) is not significant in this regard.\n\n",
344 indent_level, "",
345 indent_level, "",
346 indent_level, "",
347 indent_level, "");
348
Jim Inghamf0c63b92014-02-05 21:35:09 +0000349 fprintf (out, "\n%*sIf you don't provide -f then the first argument will be the file to be debugged"
350 "\n%*swhich means that '%s -- <filename> [<ARG1> [<ARG2>]]' also works."
351 "\n%*sBut remember to end the options with \"--\" if any of your arguments have a \"-\" in them.\n\n",
Jim Inghama9deaf92011-08-16 23:57:58 +0000352 indent_level, "",
353 indent_level, "",
354 name,
355 indent_level, "");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000356}
357
358void
Greg Claytone0d378b2011-03-24 21:19:54 +0000359BuildGetOptTable (OptionDefinition *expanded_option_table, std::vector<struct option> &getopt_table,
Caroline Tice4ab31c92010-10-12 21:57:09 +0000360 uint32_t num_options)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000361{
362 if (num_options == 0)
363 return;
364
365 uint32_t i;
366 uint32_t j;
367 std::bitset<256> option_seen;
368
Caroline Tice4ab31c92010-10-12 21:57:09 +0000369 getopt_table.resize (num_options + 1);
370
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000371 for (i = 0, j = 0; i < num_options; ++i)
Greg Claytonc982c762010-07-09 20:39:50 +0000372 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000373 char short_opt = expanded_option_table[i].short_option;
Greg Claytonc982c762010-07-09 20:39:50 +0000374
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000375 if (option_seen.test(short_opt) == false)
Greg Claytonc982c762010-07-09 20:39:50 +0000376 {
Caroline Tice4ab31c92010-10-12 21:57:09 +0000377 getopt_table[j].name = expanded_option_table[i].long_option;
378 getopt_table[j].has_arg = expanded_option_table[i].option_has_arg;
379 getopt_table[j].flag = NULL;
380 getopt_table[j].val = expanded_option_table[i].short_option;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000381 option_seen.set(short_opt);
382 ++j;
Greg Claytonc982c762010-07-09 20:39:50 +0000383 }
384 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000385
Caroline Tice4ab31c92010-10-12 21:57:09 +0000386 getopt_table[j].name = NULL;
387 getopt_table[j].has_arg = 0;
388 getopt_table[j].flag = NULL;
389 getopt_table[j].val = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000390
391}
392
Greg Clayton66111032010-06-23 01:19:29 +0000393Driver::OptionData::OptionData () :
Greg Clayton8d846da2010-12-08 22:23:24 +0000394 m_args(),
Greg Clayton66111032010-06-23 01:19:29 +0000395 m_script_lang (lldb::eScriptLanguageDefault),
Johnny Cheneb46f782012-08-15 22:10:42 +0000396 m_core_file (),
Greg Claytonc982c762010-07-09 20:39:50 +0000397 m_crash_log (),
Jim Inghamed3252f2013-09-14 00:20:24 +0000398 m_initial_commands (),
399 m_after_file_commands (),
Greg Clayton66111032010-06-23 01:19:29 +0000400 m_debug_mode (false),
Jim Inghamed3252f2013-09-14 00:20:24 +0000401 m_source_quietly(false),
Greg Claytonc982c762010-07-09 20:39:50 +0000402 m_print_version (false),
Jim Inghame2231ac2012-12-21 22:22:26 +0000403 m_print_python_path (false),
Greg Clayton66111032010-06-23 01:19:29 +0000404 m_print_help (false),
Jim Inghame64f0dc2011-09-13 23:25:31 +0000405 m_wait_for(false),
406 m_process_name(),
407 m_process_pid(LLDB_INVALID_PROCESS_ID),
Daniel Dunbara08823f2011-10-31 22:50:49 +0000408 m_use_external_editor(false),
Stephen Wilson71c21d12011-04-11 19:41:40 +0000409 m_seen_options()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000410{
Greg Clayton66111032010-06-23 01:19:29 +0000411}
412
413Driver::OptionData::~OptionData ()
414{
415}
416
417void
418Driver::OptionData::Clear ()
419{
Greg Clayton8d846da2010-12-08 22:23:24 +0000420 m_args.clear ();
Greg Clayton66111032010-06-23 01:19:29 +0000421 m_script_lang = lldb::eScriptLanguageDefault;
Jim Inghamed3252f2013-09-14 00:20:24 +0000422 m_initial_commands.clear ();
423 m_after_file_commands.clear ();
Greg Clayton66111032010-06-23 01:19:29 +0000424 m_debug_mode = false;
Jim Inghamed3252f2013-09-14 00:20:24 +0000425 m_source_quietly = false;
Greg Clayton66111032010-06-23 01:19:29 +0000426 m_print_help = false;
427 m_print_version = false;
Jim Inghame2231ac2012-12-21 22:22:26 +0000428 m_print_python_path = false;
Jim Inghame40e4212010-08-30 19:44:40 +0000429 m_use_external_editor = false;
Jim Inghame64f0dc2011-09-13 23:25:31 +0000430 m_wait_for = false;
431 m_process_name.erase();
432 m_process_pid = LLDB_INVALID_PROCESS_ID;
Greg Clayton66111032010-06-23 01:19:29 +0000433}
434
435void
Jim Inghamed3252f2013-09-14 00:20:24 +0000436Driver::OptionData::AddInitialCommand (const char *command, bool before_file, bool is_file, SBError &error)
437{
438 std::vector<std::pair<bool, std::string> > *command_set;
439 if (before_file)
440 command_set = &(m_initial_commands);
441 else
442 command_set = &(m_after_file_commands);
443
444 if (is_file)
445 {
446 SBFileSpec file(command);
447 if (file.Exists())
448 command_set->push_back (std::pair<bool, std::string> (true, optarg));
449 else if (file.ResolveExecutableLocation())
450 {
451 char final_path[PATH_MAX];
452 file.GetPath (final_path, sizeof(final_path));
453 std::string path_str (final_path);
454 command_set->push_back (std::pair<bool, std::string> (true, path_str));
455 }
456 else
457 error.SetErrorStringWithFormat("file specified in --source (-s) option doesn't exist: '%s'", optarg);
458 }
459 else
460 command_set->push_back (std::pair<bool, std::string> (false, optarg));
461}
462
463void
Greg Clayton66111032010-06-23 01:19:29 +0000464Driver::ResetOptionValues ()
465{
466 m_option_data.Clear ();
467}
468
469const char *
470Driver::GetFilename() const
471{
Greg Clayton8d846da2010-12-08 22:23:24 +0000472 if (m_option_data.m_args.empty())
Greg Clayton66111032010-06-23 01:19:29 +0000473 return NULL;
Greg Clayton8d846da2010-12-08 22:23:24 +0000474 return m_option_data.m_args.front().c_str();
Greg Clayton66111032010-06-23 01:19:29 +0000475}
476
477const char *
478Driver::GetCrashLogFilename() const
479{
480 if (m_option_data.m_crash_log.empty())
481 return NULL;
482 return m_option_data.m_crash_log.c_str();
483}
484
485lldb::ScriptLanguage
486Driver::GetScriptLanguage() const
487{
488 return m_option_data.m_script_lang;
489}
490
Jim Inghamed3252f2013-09-14 00:20:24 +0000491void
Greg Clayton06357c92014-07-30 17:38:47 +0000492Driver::WriteInitialCommands (bool before_file, SBStream &strm)
Greg Clayton66111032010-06-23 01:19:29 +0000493{
Greg Clayton06357c92014-07-30 17:38:47 +0000494 std::vector<std::pair<bool, std::string> > &command_set = before_file ? m_option_data.m_initial_commands :
495 m_option_data.m_after_file_commands;
Jim Inghamed3252f2013-09-14 00:20:24 +0000496
Greg Clayton06357c92014-07-30 17:38:47 +0000497 for (const auto &command_pair : command_set)
Jim Inghamed3252f2013-09-14 00:20:24 +0000498 {
Greg Clayton06357c92014-07-30 17:38:47 +0000499 const char *command = command_pair.second.c_str();
500 if (command_pair.first)
501 strm.Printf("command source -s %i '%s'\n", m_option_data.m_source_quietly, command);
502 else
503 strm.Printf("%s\n", command);
Jim Inghamed3252f2013-09-14 00:20:24 +0000504 }
Greg Clayton66111032010-06-23 01:19:29 +0000505}
506
507bool
508Driver::GetDebugMode() const
509{
510 return m_option_data.m_debug_mode;
511}
512
513
514// Check the arguments that were passed to this program to make sure they are valid and to get their
515// argument values (if any). Return a boolean value indicating whether or not to start up the full
516// debugger (i.e. the Command Interpreter) or not. Return FALSE if the arguments were invalid OR
517// if the user only wanted help or version information.
518
519SBError
Deepak Panickal429222c2013-10-15 15:46:40 +0000520Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exiting)
Greg Clayton66111032010-06-23 01:19:29 +0000521{
522 ResetOptionValues ();
523
524 SBCommandReturnObject result;
525
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000526 SBError error;
527 std::string option_string;
528 struct option *long_options = NULL;
Caroline Tice4ab31c92010-10-12 21:57:09 +0000529 std::vector<struct option> long_options_vector;
Greg Claytonc982c762010-07-09 20:39:50 +0000530 uint32_t num_options;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000531
Greg Claytonc982c762010-07-09 20:39:50 +0000532 for (num_options = 0; g_options[num_options].long_option != NULL; ++num_options)
533 /* Do Nothing. */;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000534
535 if (num_options == 0)
536 {
537 if (argc > 1)
538 error.SetErrorStringWithFormat ("invalid number of options");
539 return error;
540 }
541
Caroline Tice4ab31c92010-10-12 21:57:09 +0000542 BuildGetOptTable (g_options, long_options_vector, num_options);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000543
Caroline Tice4ab31c92010-10-12 21:57:09 +0000544 if (long_options_vector.empty())
545 long_options = NULL;
546 else
547 long_options = &long_options_vector.front();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000548
549 if (long_options == NULL)
550 {
551 error.SetErrorStringWithFormat ("invalid long options");
552 return error;
553 }
554
Greg Claytonb7ad58a2013-04-04 20:35:24 +0000555 // Build the option_string argument for call to getopt_long_only.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000556
557 for (int i = 0; long_options[i].name != NULL; ++i)
558 {
559 if (long_options[i].flag == NULL)
560 {
561 option_string.push_back ((char) long_options[i].val);
562 switch (long_options[i].has_arg)
563 {
564 default:
565 case no_argument:
566 break;
567 case required_argument:
568 option_string.push_back (':');
569 break;
570 case optional_argument:
571 option_string.append ("::");
572 break;
573 }
574 }
575 }
576
Jim Ingham06942692011-08-13 00:22:20 +0000577 // This is kind of a pain, but since we make the debugger in the Driver's constructor, we can't
578 // know at that point whether we should read in init files yet. So we don't read them in in the
579 // Driver constructor, then set the flags back to "read them in" here, and then if we see the
580 // "-n" flag, we'll turn it off again. Finally we have to read them in by hand later in the
581 // main loop.
582
583 m_debugger.SkipLLDBInitFiles (false);
584 m_debugger.SkipAppInitFiles (false);
585
Greg Claytonb7ad58a2013-04-04 20:35:24 +0000586 // Prepare for & make calls to getopt_long_only.
Eli Friedmanadb35022010-06-13 19:18:49 +0000587#if __GLIBC__
588 optind = 0;
589#else
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000590 optreset = 1;
591 optind = 1;
Eli Friedmanadb35022010-06-13 19:18:49 +0000592#endif
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000593 int val;
594 while (1)
595 {
596 int long_options_index = -1;
Greg Claytonb7ad58a2013-04-04 20:35:24 +0000597 val = ::getopt_long_only (argc, const_cast<char **>(argv), option_string.c_str(), long_options, &long_options_index);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000598
599 if (val == -1)
600 break;
601 else if (val == '?')
602 {
Greg Clayton66111032010-06-23 01:19:29 +0000603 m_option_data.m_print_help = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000604 error.SetErrorStringWithFormat ("unknown or ambiguous option");
605 break;
606 }
607 else if (val == 0)
608 continue;
609 else
610 {
Greg Clayton66111032010-06-23 01:19:29 +0000611 m_option_data.m_seen_options.insert ((char) val);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000612 if (long_options_index == -1)
613 {
614 for (int i = 0;
615 long_options[i].name || long_options[i].has_arg || long_options[i].flag || long_options[i].val;
616 ++i)
617 {
618 if (long_options[i].val == val)
619 {
620 long_options_index = i;
621 break;
622 }
623 }
624 }
625
626 if (long_options_index >= 0)
627 {
Greg Clayton3bcdfc02012-12-04 00:32:51 +0000628 const int short_option = g_options[long_options_index].short_option;
Greg Clayton66111032010-06-23 01:19:29 +0000629
630 switch (short_option)
631 {
632 case 'h':
633 m_option_data.m_print_help = true;
634 break;
635
636 case 'v':
637 m_option_data.m_print_version = true;
638 break;
639
Jim Inghame2231ac2012-12-21 22:22:26 +0000640 case 'P':
641 m_option_data.m_print_python_path = true;
642 break;
643
Greg Clayton66111032010-06-23 01:19:29 +0000644 case 'c':
Johnny Cheneb46f782012-08-15 22:10:42 +0000645 {
646 SBFileSpec file(optarg);
647 if (file.Exists())
648 {
649 m_option_data.m_core_file = optarg;
650 }
651 else
652 error.SetErrorStringWithFormat("file specified in --core (-c) option doesn't exist: '%s'", optarg);
653 }
Greg Clayton66111032010-06-23 01:19:29 +0000654 break;
Johnny Cheneb46f782012-08-15 22:10:42 +0000655
Jim Inghame40e4212010-08-30 19:44:40 +0000656 case 'e':
657 m_option_data.m_use_external_editor = true;
658 break;
Greg Clayton6eee5aa2010-10-11 01:05:37 +0000659
Jim Inghame64f0dc2011-09-13 23:25:31 +0000660 case 'x':
Greg Clayton6eee5aa2010-10-11 01:05:37 +0000661 m_debugger.SkipLLDBInitFiles (true);
Jim Ingham06942692011-08-13 00:22:20 +0000662 m_debugger.SkipAppInitFiles (true);
Greg Clayton6eee5aa2010-10-11 01:05:37 +0000663 break;
664
Jim Inghamed3252f2013-09-14 00:20:24 +0000665 case 'X':
Michael Sartainc3ce7f272013-05-23 20:47:45 +0000666 m_debugger.SetUseColor (false);
667 break;
668
Greg Clayton66111032010-06-23 01:19:29 +0000669 case 'f':
670 {
671 SBFileSpec file(optarg);
672 if (file.Exists())
Greg Clayton8d846da2010-12-08 22:23:24 +0000673 {
674 m_option_data.m_args.push_back (optarg);
675 }
Caroline Tice428a9a52010-09-10 04:48:55 +0000676 else if (file.ResolveExecutableLocation())
677 {
678 char path[PATH_MAX];
Johnny Chen25f3a3c2011-08-10 22:06:24 +0000679 file.GetPath (path, sizeof(path));
Greg Clayton8d846da2010-12-08 22:23:24 +0000680 m_option_data.m_args.push_back (path);
Caroline Tice428a9a52010-09-10 04:48:55 +0000681 }
Greg Clayton66111032010-06-23 01:19:29 +0000682 else
683 error.SetErrorStringWithFormat("file specified in --file (-f) option doesn't exist: '%s'", optarg);
684 }
685 break;
686
687 case 'a':
688 if (!m_debugger.SetDefaultArchitecture (optarg))
689 error.SetErrorStringWithFormat("invalid architecture in the -a or --arch option: '%s'", optarg);
690 break;
691
692 case 'l':
693 m_option_data.m_script_lang = m_debugger.GetScriptingLanguage (optarg);
694 break;
695
696 case 'd':
697 m_option_data.m_debug_mode = true;
698 break;
699
Jim Inghamf0c63b92014-02-05 21:35:09 +0000700 case 'Q':
Jim Inghamed3252f2013-09-14 00:20:24 +0000701 m_option_data.m_source_quietly = true;
702 break;
703
Jim Inghame64f0dc2011-09-13 23:25:31 +0000704 case 'n':
705 m_option_data.m_process_name = optarg;
706 break;
707
708 case 'w':
709 m_option_data.m_wait_for = true;
710 break;
711
712 case 'p':
713 {
714 char *remainder;
715 m_option_data.m_process_pid = strtol (optarg, &remainder, 0);
716 if (remainder == optarg || *remainder != '\0')
717 error.SetErrorStringWithFormat ("Could not convert process PID: \"%s\" into a pid.",
718 optarg);
719 }
720 break;
Greg Clayton66111032010-06-23 01:19:29 +0000721 case 's':
Jim Inghamed3252f2013-09-14 00:20:24 +0000722 m_option_data.AddInitialCommand(optarg, false, true, error);
Greg Clayton66111032010-06-23 01:19:29 +0000723 break;
Jim Inghamed3252f2013-09-14 00:20:24 +0000724 case 'o':
725 m_option_data.AddInitialCommand(optarg, false, false, error);
726 break;
727 case 'S':
728 m_option_data.AddInitialCommand(optarg, true, true, error);
729 break;
730 case 'O':
731 m_option_data.AddInitialCommand(optarg, true, false, error);
732 break;
Greg Clayton66111032010-06-23 01:19:29 +0000733 default:
734 m_option_data.m_print_help = true;
735 error.SetErrorStringWithFormat ("unrecognized option %c", short_option);
736 break;
737 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000738 }
739 else
740 {
741 error.SetErrorStringWithFormat ("invalid option with value %i", val);
742 }
743 if (error.Fail())
Caroline Tice4ab31c92010-10-12 21:57:09 +0000744 {
Greg Clayton66111032010-06-23 01:19:29 +0000745 return error;
Caroline Tice4ab31c92010-10-12 21:57:09 +0000746 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000747 }
748 }
Jim Ingham86511212010-06-15 18:47:14 +0000749
Greg Clayton66111032010-06-23 01:19:29 +0000750 if (error.Fail() || m_option_data.m_print_help)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000751 {
752 ShowUsage (out_fh, g_options, m_option_data);
Deepak Panickal429222c2013-10-15 15:46:40 +0000753 exiting = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000754 }
755 else if (m_option_data.m_print_version)
756 {
Greg Clayton66111032010-06-23 01:19:29 +0000757 ::fprintf (out_fh, "%s\n", m_debugger.GetVersionString());
Deepak Panickal429222c2013-10-15 15:46:40 +0000758 exiting = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000759 }
Jim Inghame2231ac2012-12-21 22:22:26 +0000760 else if (m_option_data.m_print_python_path)
761 {
762 SBFileSpec python_file_spec = SBHostOS::GetLLDBPythonPath();
763 if (python_file_spec.IsValid())
764 {
765 char python_path[PATH_MAX];
766 size_t num_chars = python_file_spec.GetPath(python_path, PATH_MAX);
767 if (num_chars < PATH_MAX)
768 {
769 ::fprintf (out_fh, "%s\n", python_path);
770 }
771 else
772 ::fprintf (out_fh, "<PATH TOO LONG>\n");
773 }
774 else
775 ::fprintf (out_fh, "<COULD NOT FIND PATH>\n");
Deepak Panickal429222c2013-10-15 15:46:40 +0000776 exiting = true;
Jim Inghame2231ac2012-12-21 22:22:26 +0000777 }
Jim Inghame64f0dc2011-09-13 23:25:31 +0000778 else if (m_option_data.m_process_name.empty() && m_option_data.m_process_pid == LLDB_INVALID_PROCESS_ID)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000779 {
Greg Clayton8d846da2010-12-08 22:23:24 +0000780 // Any arguments that are left over after option parsing are for
781 // the program. If a file was specified with -f then the filename
782 // is already in the m_option_data.m_args array, and any remaining args
783 // are arguments for the inferior program. If no file was specified with
784 // -f, then what is left is the program name followed by any arguments.
785
Greg Claytonb7ad58a2013-04-04 20:35:24 +0000786 // Skip any options we consumed with getopt_long_only
Greg Clayton8d846da2010-12-08 22:23:24 +0000787 argc -= optind;
788 argv += optind;
789
790 if (argc > 0)
791 {
792 for (int arg_idx=0; arg_idx<argc; ++arg_idx)
793 {
794 const char *arg = argv[arg_idx];
795 if (arg)
796 m_option_data.m_args.push_back (arg);
797 }
798 }
799
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000800 }
Jim Inghame64f0dc2011-09-13 23:25:31 +0000801 else
802 {
Greg Claytonb7ad58a2013-04-04 20:35:24 +0000803 // Skip any options we consumed with getopt_long_only
Jim Inghame64f0dc2011-09-13 23:25:31 +0000804 argc -= optind;
Greg Clayton23f59502012-07-17 03:23:13 +0000805 //argv += optind; // Commented out to keep static analyzer happy
Jim Inghame64f0dc2011-09-13 23:25:31 +0000806
807 if (argc > 0)
808 ::fprintf (out_fh, "Warning: program arguments are ignored when attaching.\n");
809 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000810
Greg Clayton66111032010-06-23 01:19:29 +0000811 return error;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000812}
813
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000814void
815Driver::MainLoop ()
816{
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000817 if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0)
Greg Claytonf571b892012-02-02 19:28:31 +0000818 {
819 g_old_stdin_termios_is_valid = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000820 atexit (reset_stdin_termios);
Greg Claytonf571b892012-02-02 19:28:31 +0000821 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000822
823 ::setbuf (stdin, NULL);
824 ::setbuf (stdout, NULL);
825
Greg Clayton66111032010-06-23 01:19:29 +0000826 m_debugger.SetErrorFileHandle (stderr, false);
827 m_debugger.SetOutputFileHandle (stdout, false);
Greg Clayton06357c92014-07-30 17:38:47 +0000828 m_debugger.SetInputFileHandle (stdin, false); // Don't take ownership of STDIN yet...
829
Jim Inghame40e4212010-08-30 19:44:40 +0000830 m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000831
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000832 struct winsize window_size;
833 if (isatty (STDIN_FILENO)
834 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
835 {
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000836 if (window_size.ws_col > 0)
Greg Claytona7015092010-09-18 01:14:36 +0000837 m_debugger.SetTerminalWidth (window_size.ws_col);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000838 }
839
Greg Clayton44d93782014-01-27 23:43:24 +0000840 SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000841
Greg Clayton44d93782014-01-27 23:43:24 +0000842 // Before we handle any options from the command line, we parse the
843 // .lldbinit file in the user's home directory.
844 SBCommandReturnObject result;
845 sb_interpreter.SourceInitFileInHomeDirectory(result);
846 if (GetDebugMode())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000847 {
Greg Clayton44d93782014-01-27 23:43:24 +0000848 result.PutError (m_debugger.GetErrorFileHandle());
849 result.PutOutput (m_debugger.GetOutputFileHandle());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000850 }
Greg Clayton44d93782014-01-27 23:43:24 +0000851
852 // Now we handle options we got from the command line
Ed Mastef8314532014-07-30 19:26:11 +0000853 SBStream commands_stream;
Greg Clayton06357c92014-07-30 17:38:47 +0000854
Greg Clayton44d93782014-01-27 23:43:24 +0000855 // First source in the commands specified to be run before the file arguments are processed.
Greg Clayton06357c92014-07-30 17:38:47 +0000856 WriteInitialCommands(true, commands_stream);
857
Greg Clayton44d93782014-01-27 23:43:24 +0000858 const size_t num_args = m_option_data.m_args.size();
859 if (num_args > 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000860 {
Jim Ingham5b1fe952014-08-07 23:01:31 +0000861 char arch_name[64];
862 if (m_debugger.GetDefaultArchitecture (arch_name, sizeof (arch_name)))
863 commands_stream.Printf("target create --arch=%s \"%s\"", arch_name, m_option_data.m_args[0].c_str());
864 else
865 commands_stream.Printf("target create \"%s\"", m_option_data.m_args[0].c_str());
866
Greg Clayton06357c92014-07-30 17:38:47 +0000867 if (!m_option_data.m_core_file.empty())
868 {
869 commands_stream.Printf(" --core \"%s\"", m_option_data.m_core_file.c_str());
870 }
871 commands_stream.Printf("\n");
Greg Clayton44d93782014-01-27 23:43:24 +0000872
873 if (num_args > 1)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000874 {
Greg Clayton06357c92014-07-30 17:38:47 +0000875 commands_stream.Printf ("settings set -- target.run-args ");
Greg Clayton44d93782014-01-27 23:43:24 +0000876 for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000877 {
Greg Clayton06357c92014-07-30 17:38:47 +0000878 const char *arg_cstr = m_option_data.m_args[arg_idx].c_str();
879 if (strchr(arg_cstr, '"') == NULL)
880 commands_stream.Printf(" \"%s\"", arg_cstr);
881 else
882 commands_stream.Printf(" '%s'", arg_cstr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000883 }
Greg Clayton06357c92014-07-30 17:38:47 +0000884 commands_stream.Printf("\n");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000885 }
886 }
Greg Clayton06357c92014-07-30 17:38:47 +0000887 else if (!m_option_data.m_core_file.empty())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000888 {
Greg Clayton06357c92014-07-30 17:38:47 +0000889 commands_stream.Printf("target create --core \"%s\"\n", m_option_data.m_core_file.c_str());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000890 }
Greg Clayton9c0b64c2014-02-06 18:22:44 +0000891 else if (!m_option_data.m_process_name.empty())
892 {
Greg Clayton06357c92014-07-30 17:38:47 +0000893 commands_stream.Printf ("process attach --name \"%s\"", m_option_data.m_process_name.c_str());
894
895 if (m_option_data.m_wait_for)
896 commands_stream.Printf(" --waitfor");
897
898 commands_stream.Printf("\n");
899
Greg Clayton9c0b64c2014-02-06 18:22:44 +0000900 }
901 else if (LLDB_INVALID_PROCESS_ID != m_option_data.m_process_pid)
902 {
Greg Clayton06357c92014-07-30 17:38:47 +0000903 commands_stream.Printf ("process attach --pid %" PRIu64 "\n", m_option_data.m_process_pid);
Greg Clayton9c0b64c2014-02-06 18:22:44 +0000904 }
Greg Clayton44d93782014-01-27 23:43:24 +0000905
Greg Clayton06357c92014-07-30 17:38:47 +0000906 WriteInitialCommands(false, commands_stream);
907
Greg Clayton44d93782014-01-27 23:43:24 +0000908 // Now that all option parsing is done, we try and parse the .lldbinit
909 // file in the current working directory
910 sb_interpreter.SourceInitFileInCurrentWorkingDirectory (result);
911 if (GetDebugMode())
912 {
913 result.PutError(m_debugger.GetErrorFileHandle());
914 result.PutOutput(m_debugger.GetOutputFileHandle());
915 }
916
917 bool handle_events = true;
918 bool spawn_thread = false;
Greg Clayton06357c92014-07-30 17:38:47 +0000919
920 // Check if we have any data in the commands stream, and if so, save it to a temp file
Greg Clayton49668762014-08-01 18:32:07 +0000921 // so we can then run the command interpreter using the file contents.
922 const char *commands_data = commands_stream.GetData();
923 const size_t commands_size = commands_stream.GetSize();
924 if (commands_data && commands_size)
Greg Clayton06357c92014-07-30 17:38:47 +0000925 {
Greg Clayton49668762014-08-01 18:32:07 +0000926 enum PIPES { READ, WRITE }; // Constants 0 and 1 for READ and WRITE
Greg Clayton06357c92014-07-30 17:38:47 +0000927
Greg Clayton49668762014-08-01 18:32:07 +0000928 bool success = true;
929 int fds[2] = { -1, -1 };
930 int err = 0;
931#ifdef _WIN32
932 err = _pipe(fds, commands_size, O_BINARY);
933#else
934 err = pipe(fds);
935#endif
936 if (err == 0)
937 {
Saleem Abdulrasool9e5b4982014-09-08 02:47:13 +0000938 ssize_t nrwr = write(fds[WRITE], commands_data, commands_size);
939 if (nrwr < 0)
940 {
941 fprintf(stderr, "error: write(%i, %p, %zd) failed (errno = %i) "
942 "when trying to open LLDB commands pipe\n",
943 fds[WRITE], commands_data, commands_size, errno);
944 success = false;
945 }
946 else if (static_cast<size_t>(nrwr) == commands_size)
Greg Clayton06357c92014-07-30 17:38:47 +0000947 {
Greg Clayton49668762014-08-01 18:32:07 +0000948 // Close the write end of the pipe so when we give the read end to
949 // the debugger/command interpreter it will exit when it consumes all
950 // of the data
951#ifdef _WIN32
952 _close(fds[WRITE]); fds[WRITE] = -1;
953#else
954 close(fds[WRITE]); fds[WRITE] = -1;
955#endif
956 // Now open the read file descriptor in a FILE * that we can give to
957 // the debugger as an input handle
958 FILE *commands_file = fdopen(fds[READ], "r");
959 if (commands_file)
960 {
961 fds[READ] = -1; // The FILE * 'commands_file' now owns the read descriptor
962 // Hand ownership if the FILE * over to the debugger for "commands_file".
963 m_debugger.SetInputFileHandle (commands_file, true);
964 m_debugger.RunCommandInterpreter(handle_events, spawn_thread);
965 }
966 else
967 {
Saleem Abdulrasool9e5b4982014-09-08 02:47:13 +0000968 fprintf(stderr,
969 "error: fdopen(%i, \"r\") failed (errno = %i) when "
970 "trying to open LLDB commands pipe\n",
971 fds[READ], errno);
Greg Clayton49668762014-08-01 18:32:07 +0000972 success = false;
973 }
Greg Clayton06357c92014-07-30 17:38:47 +0000974 }
Saleem Abdulrasool9e5b4982014-09-08 02:47:13 +0000975 else
976 {
977 assert(!"partial writes not handled");
978 success = false;
979 }
Greg Clayton06357c92014-07-30 17:38:47 +0000980 }
Greg Clayton49668762014-08-01 18:32:07 +0000981 else
982 {
983 fprintf(stderr, "error: can't create pipe file descriptors for LLDB commands\n");
984 success = false;
985 }
986
987 // Close any pipes that we still have ownership of
988 if ( fds[WRITE] != -1)
989 {
990#ifdef _WIN32
991 _close(fds[WRITE]); fds[WRITE] = -1;
992#else
993 close(fds[WRITE]); fds[WRITE] = -1;
994#endif
995
996 }
997
998 if ( fds[READ] != -1)
999 {
1000#ifdef _WIN32
1001 _close(fds[READ]); fds[READ] = -1;
1002#else
1003 close(fds[READ]); fds[READ] = -1;
1004#endif
1005 }
1006
1007 // Something went wrong with command pipe
1008 if (!success)
1009 {
1010 exit(1);
1011 }
1012
Greg Clayton06357c92014-07-30 17:38:47 +00001013 }
1014
1015 // Now set the input file handle to STDIN and run the command
1016 // interpreter again in interactive mode and let the debugger
1017 // take ownership of stdin
1018 m_debugger.SetInputFileHandle (stdin, true);
Greg Clayton44d93782014-01-27 23:43:24 +00001019 m_debugger.RunCommandInterpreter(handle_events, spawn_thread);
1020
1021 reset_stdin_termios();
1022 fclose (stdin);
1023
1024 SBDebugger::Destroy (m_debugger);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001025}
1026
Greg Clayton44d93782014-01-27 23:43:24 +00001027
Jim Inghamc46fe7c2013-02-22 22:56:55 +00001028void
1029Driver::ResizeWindow (unsigned short col)
1030{
1031 GetDebugger().SetTerminalWidth (col);
Jim Inghamc46fe7c2013-02-22 22:56:55 +00001032}
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001033
Caroline Ticedd759852010-09-09 17:45:09 +00001034void
1035sigwinch_handler (int signo)
1036{
1037 struct winsize window_size;
1038 if (isatty (STDIN_FILENO)
1039 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
1040 {
Jim Ingham57190ba2012-04-26 21:39:32 +00001041 if ((window_size.ws_col > 0) && g_driver != NULL)
Caroline Ticedd759852010-09-09 17:45:09 +00001042 {
Jim Inghamc46fe7c2013-02-22 22:56:55 +00001043 g_driver->ResizeWindow (window_size.ws_col);
Caroline Ticedd759852010-09-09 17:45:09 +00001044 }
1045 }
1046}
1047
Caroline Ticeefed6132010-11-19 20:47:54 +00001048void
1049sigint_handler (int signo)
1050{
1051 static bool g_interrupt_sent = false;
1052 if (g_driver)
1053 {
1054 if (!g_interrupt_sent)
1055 {
1056 g_interrupt_sent = true;
1057 g_driver->GetDebugger().DispatchInputInterrupt();
1058 g_interrupt_sent = false;
1059 return;
1060 }
1061 }
1062
1063 exit (signo);
1064}
1065
Jim Inghamc5917d92012-11-30 20:23:19 +00001066void
1067sigtstp_handler (int signo)
1068{
1069 g_driver->GetDebugger().SaveInputTerminalState();
1070 signal (signo, SIG_DFL);
1071 kill (getpid(), signo);
1072 signal (signo, sigtstp_handler);
1073}
1074
1075void
1076sigcont_handler (int signo)
1077{
1078 g_driver->GetDebugger().RestoreInputTerminalState();
1079 signal (signo, SIG_DFL);
1080 kill (getpid(), signo);
1081 signal (signo, sigcont_handler);
1082}
1083
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001084int
Jim Inghama462f5c2011-01-27 20:15:39 +00001085main (int argc, char const *argv[], const char *envp[])
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001086{
Deepak Panickal99fbc072014-03-03 15:39:47 +00001087#ifdef _MSC_VER
1088 // disable buffering on windows
1089 setvbuf(stdout, NULL, _IONBF, 0);
1090 setvbuf(stdin , NULL, _IONBF, 0);
1091#endif
1092
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001093 SBDebugger::Initialize();
1094
Greg Clayton2ccf8cf2010-11-07 21:02:03 +00001095 SBHostOS::ThreadCreated ("<lldb.driver.main-thread>");
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001096
Greg Clayton3fcbed62010-10-19 03:25:40 +00001097 signal (SIGPIPE, SIG_IGN);
Caroline Ticedd759852010-09-09 17:45:09 +00001098 signal (SIGWINCH, sigwinch_handler);
Caroline Ticeefed6132010-11-19 20:47:54 +00001099 signal (SIGINT, sigint_handler);
Jim Inghamc5917d92012-11-30 20:23:19 +00001100 signal (SIGTSTP, sigtstp_handler);
1101 signal (SIGCONT, sigcont_handler);
Caroline Ticedd759852010-09-09 17:45:09 +00001102
Greg Clayton66111032010-06-23 01:19:29 +00001103 // Create a scope for driver so that the driver object will destroy itself
1104 // before SBDebugger::Terminate() is called.
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001105 {
Greg Clayton66111032010-06-23 01:19:29 +00001106 Driver driver;
1107
Deepak Panickal429222c2013-10-15 15:46:40 +00001108 bool exiting = false;
1109 SBError error (driver.ParseArgs (argc, argv, stdout, exiting));
Greg Clayton66111032010-06-23 01:19:29 +00001110 if (error.Fail())
1111 {
1112 const char *error_cstr = error.GetCString ();
1113 if (error_cstr)
1114 ::fprintf (stderr, "error: %s\n", error_cstr);
1115 }
Deepak Panickal429222c2013-10-15 15:46:40 +00001116 else if (!exiting)
Greg Clayton66111032010-06-23 01:19:29 +00001117 {
1118 driver.MainLoop ();
1119 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001120 }
1121
1122 SBDebugger::Terminate();
1123 return 0;
1124}