aboutsummaryrefslogtreecommitdiff
path: root/tools/driver/Driver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/driver/Driver.cpp')
-rw-r--r--tools/driver/Driver.cpp227
1 files changed, 151 insertions, 76 deletions
diff --git a/tools/driver/Driver.cpp b/tools/driver/Driver.cpp
index 875adc22283a..e2742425dd4c 100644
--- a/tools/driver/Driver.cpp
+++ b/tools/driver/Driver.cpp
@@ -9,19 +9,15 @@
#include "Driver.h"
-#include <getopt.h>
-#include <libgen.h>
-#include <sys/ioctl.h>
-#include <termios.h>
-#include <unistd.h>
+#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <fcntl.h>
-#include <inttypes.h>
#include <string>
+#include <thread>
#include "IOChannel.h"
#include "lldb/API/SBBreakpoint.h"
#include "lldb/API/SBCommandInterpreter.h"
@@ -99,13 +95,21 @@ static OptionDefinition g_options[] =
"extensions have been implemented." },
{ LLDB_3_TO_5, false, "debug" , 'd', no_argument , 0, eArgTypeNone,
"Tells the debugger to print out extra information for debugging itself." },
+ { LLDB_3_TO_5, false, "source-quietly" , 'b', no_argument , 0, eArgTypeNone,
+ "Tells the debugger to print out extra information for debugging itself." },
{ LLDB_3_TO_5, false, "source" , 's', required_argument, 0, eArgTypeFilename,
- "Tells the debugger to read in and execute the file <file>, which should contain lldb commands." },
+ "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." },
+ { LLDB_3_TO_5, false, "one-line" , 'o', required_argument, 0, eArgTypeNone,
+ "Tells the debugger to execute this one-line lldb command after any file provided on the command line has been loaded." },
+ { LLDB_3_TO_5, false, "source-before-file" , 'S', required_argument, 0, eArgTypeFilename,
+ "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." },
+ { LLDB_3_TO_5, false, "one-line-before-file" , 'O', required_argument, 0, eArgTypeNone,
+ "Tells the debugger to execute this one-line lldb command before any file provided on the command line has been loaded." },
{ LLDB_3_TO_5, false, "editor" , 'e', no_argument , 0, eArgTypeNone,
"Tells the debugger to open source files using the host's \"external editor\" mechanism." },
{ LLDB_3_TO_5, false, "no-lldbinit" , 'x', no_argument , 0, eArgTypeNone,
"Do not automatically parse any '.lldbinit' files." },
- { LLDB_3_TO_5, false, "no-use-colors" , 'o', no_argument , 0, eArgTypeNone,
+ { LLDB_3_TO_5, false, "no-use-colors" , 'X', no_argument , 0, eArgTypeNone,
"Do not use colors." },
{ LLDB_OPT_SET_6, true , "python-path" , 'P', no_argument , 0, eArgTypeNone,
"Prints out the path to the lldb.py file for this version of lldb." },
@@ -147,7 +151,9 @@ Driver::CloseIOChannelFile ()
// Write an End of File sequence to the file descriptor to ensure any
// read functions can exit.
char eof_str[] = "\x04";
- ::write (m_editline_pty.GetMasterFileDescriptor(), eof_str, strlen(eof_str));
+ int mfd = m_editline_pty.GetMasterFileDescriptor();
+ if (mfd != -1)
+ ::write (m_editline_pty.GetMasterFileDescriptor(), eof_str, strlen(eof_str));
m_editline_pty.CloseMasterFileDescriptor();
@@ -341,6 +347,15 @@ ShowUsage (FILE *out, OptionDefinition *option_table, Driver::OptionData data)
indent_level -= 5;
+ fprintf (out, "\n%*sMultiple \"-s\" and \"-o\" options can be provided. They will be processed from left to right in order, "
+ "\n%*swith the source files and commands interleaved. The same is true of the \"-S\" and \"-O\" options."
+ "\n%*sThe before file and after file sets can intermixed freely, the command parser will sort them out."
+ "\n%*sThe order of the file specifiers (\"-c\", \"-f\", etc.) is not significant in this regard.\n\n",
+ indent_level, "",
+ indent_level, "",
+ indent_level, "",
+ indent_level, "");
+
fprintf (out, "\n%*s(If you don't provide -f then the first argument will be the file to be debugged"
"\n%*s so '%s -- <filename> [<ARG1> [<ARG2>]]' also works."
"\n%*s Remember to end the options with \"--\" if any of your arguments have a \"-\" in them.)\n\n",
@@ -390,8 +405,10 @@ Driver::OptionData::OptionData () :
m_script_lang (lldb::eScriptLanguageDefault),
m_core_file (),
m_crash_log (),
- m_source_command_files (),
+ m_initial_commands (),
+ m_after_file_commands (),
m_debug_mode (false),
+ m_source_quietly(false),
m_print_version (false),
m_print_python_path (false),
m_print_help (false),
@@ -412,8 +429,10 @@ Driver::OptionData::Clear ()
{
m_args.clear ();
m_script_lang = lldb::eScriptLanguageDefault;
- m_source_command_files.clear ();
+ m_initial_commands.clear ();
+ m_after_file_commands.clear ();
m_debug_mode = false;
+ m_source_quietly = false;
m_print_help = false;
m_print_version = false;
m_print_python_path = false;
@@ -424,6 +443,34 @@ Driver::OptionData::Clear ()
}
void
+Driver::OptionData::AddInitialCommand (const char *command, bool before_file, bool is_file, SBError &error)
+{
+ std::vector<std::pair<bool, std::string> > *command_set;
+ if (before_file)
+ command_set = &(m_initial_commands);
+ else
+ command_set = &(m_after_file_commands);
+
+ if (is_file)
+ {
+ SBFileSpec file(command);
+ if (file.Exists())
+ command_set->push_back (std::pair<bool, std::string> (true, optarg));
+ else if (file.ResolveExecutableLocation())
+ {
+ char final_path[PATH_MAX];
+ file.GetPath (final_path, sizeof(final_path));
+ std::string path_str (final_path);
+ command_set->push_back (std::pair<bool, std::string> (true, path_str));
+ }
+ else
+ error.SetErrorStringWithFormat("file specified in --source (-s) option doesn't exist: '%s'", optarg);
+ }
+ else
+ command_set->push_back (std::pair<bool, std::string> (false, optarg));
+}
+
+void
Driver::ResetOptionValues ()
{
m_option_data.Clear ();
@@ -451,18 +498,60 @@ Driver::GetScriptLanguage() const
return m_option_data.m_script_lang;
}
-size_t
-Driver::GetNumSourceCommandFiles () const
-{
- return m_option_data.m_source_command_files.size();
-}
-
-const char *
-Driver::GetSourceCommandFileAtIndex (uint32_t idx) const
+void
+Driver::ExecuteInitialCommands (bool before_file)
{
- if (idx < m_option_data.m_source_command_files.size())
- return m_option_data.m_source_command_files[idx].c_str();
- return NULL;
+ size_t num_commands;
+ std::vector<std::pair<bool, std::string> > *command_set;
+ if (before_file)
+ command_set = &(m_option_data.m_initial_commands);
+ else
+ command_set = &(m_option_data.m_after_file_commands);
+
+ num_commands = command_set->size();
+ SBCommandReturnObject result;
+ bool old_async = GetDebugger().GetAsync();
+ GetDebugger().SetAsync(false);
+ for (size_t idx = 0; idx < num_commands; idx++)
+ {
+ bool is_file = (*command_set)[idx].first;
+ const char *command = (*command_set)[idx].second.c_str();
+ char command_string[PATH_MAX * 2];
+ const bool dump_stream_only_if_no_immediate = true;
+ const char *executed_command = command;
+ if (is_file)
+ {
+ ::snprintf (command_string, sizeof(command_string), "command source '%s'", command);
+ executed_command = command_string;
+ }
+
+ m_debugger.GetCommandInterpreter().HandleCommand (executed_command, result, false);
+ if (!m_option_data.m_source_quietly || result.Succeeded() == false)
+ {
+ const size_t output_size = result.GetOutputSize();
+ if (output_size > 0)
+ m_io_channel_ap->OutWrite (result.GetOutput(dump_stream_only_if_no_immediate), output_size, NO_ASYNC);
+ const size_t error_size = result.GetErrorSize();
+ if (error_size > 0)
+ m_io_channel_ap->OutWrite (result.GetError(dump_stream_only_if_no_immediate), error_size, NO_ASYNC);
+ }
+
+ if (result.Succeeded() == false)
+ {
+ char error_buffer[1024];
+ size_t error_size;
+ const char *type = before_file ? "before file" : "after_file";
+ if (is_file)
+ error_size = ::snprintf(error_buffer, sizeof(error_buffer), "Aborting %s command execution, command file: '%s' failed.\n", type, command);
+ else
+ error_size = ::snprintf(error_buffer, sizeof(error_buffer), "Aborting %s command execution, command: '%s' failed.\n", type, command);
+
+ m_io_channel_ap->OutWrite(error_buffer, error_size, NO_ASYNC);
+ break;
+ }
+ result.Clear();
+ }
+ GetDebugger().SetAsync(old_async);
}
bool
@@ -478,7 +567,7 @@ Driver::GetDebugMode() const
// if the user only wanted help or version information.
SBError
-Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exit)
+Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exiting)
{
ResetOptionValues ();
@@ -623,7 +712,7 @@ Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exit)
m_debugger.SkipAppInitFiles (true);
break;
- case 'o':
+ case 'X':
m_debugger.SetUseColor (false);
break;
@@ -658,6 +747,10 @@ Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exit)
m_option_data.m_debug_mode = true;
break;
+ case 'q':
+ m_option_data.m_source_quietly = true;
+ break;
+
case 'n':
m_option_data.m_process_name = optarg;
break;
@@ -676,22 +769,17 @@ Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exit)
}
break;
case 's':
- {
- SBFileSpec file(optarg);
- if (file.Exists())
- m_option_data.m_source_command_files.push_back (optarg);
- else if (file.ResolveExecutableLocation())
- {
- char final_path[PATH_MAX];
- file.GetPath (final_path, sizeof(final_path));
- std::string path_str (final_path);
- m_option_data.m_source_command_files.push_back (path_str);
- }
- else
- error.SetErrorStringWithFormat("file specified in --source (-s) option doesn't exist: '%s'", optarg);
- }
+ m_option_data.AddInitialCommand(optarg, false, true, error);
+ break;
+ case 'o':
+ m_option_data.AddInitialCommand(optarg, false, false, error);
+ break;
+ case 'S':
+ m_option_data.AddInitialCommand(optarg, true, true, error);
+ break;
+ case 'O':
+ m_option_data.AddInitialCommand(optarg, true, false, error);
break;
-
default:
m_option_data.m_print_help = true;
error.SetErrorStringWithFormat ("unrecognized option %c", short_option);
@@ -712,12 +800,12 @@ Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exit)
if (error.Fail() || m_option_data.m_print_help)
{
ShowUsage (out_fh, g_options, m_option_data);
- exit = true;
+ exiting = true;
}
else if (m_option_data.m_print_version)
{
::fprintf (out_fh, "%s\n", m_debugger.GetVersionString());
- exit = true;
+ exiting = true;
}
else if (m_option_data.m_print_python_path)
{
@@ -735,7 +823,7 @@ Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exit)
}
else
::fprintf (out_fh, "<COULD NOT FIND PATH>\n");
- exit = true;
+ exiting = true;
}
else if (m_option_data.m_process_name.empty() && m_option_data.m_process_pid == LLDB_INVALID_PROCESS_ID)
{
@@ -1221,6 +1309,12 @@ Driver::EditLineInputReaderCallback
void
Driver::MainLoop ()
{
+#if defined(_MSC_VER)
+ m_editline_slave_fh = stdin;
+ FILE *editline_output_slave_fh = stdout;
+ lldb_utility::PseudoTerminal editline_output_pty;
+#else
+
char error_str[1024];
if (m_editline_pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, error_str, sizeof(error_str)) == false)
{
@@ -1281,6 +1375,7 @@ Driver::MainLoop ()
::setbuf (editline_output_slave_fh, NULL);
}
}
+#endif
// struct termios stdin_termios;
@@ -1322,6 +1417,7 @@ Driver::MainLoop ()
m_io_channel_ap.reset (new IOChannel(m_editline_slave_fh, editline_output_slave_fh, stdout, stderr, this));
+#if !defined (_MSC_VER)
SBCommunication out_comm_2("driver.editline_output");
out_comm_2.SetCloseOnEOF (false);
out_comm_2.AdoptFileDesriptor (editline_output_pty.GetMasterFileDescriptor(), false);
@@ -1332,6 +1428,7 @@ Driver::MainLoop ()
::fprintf (stderr, "error: failed to start libedit output read thread");
exit (5);
}
+#endif
struct winsize window_size;
@@ -1400,42 +1497,15 @@ Driver::MainLoop ()
}
// Now we handle options we got from the command line
- char command_string[PATH_MAX * 2];
- const size_t num_source_command_files = GetNumSourceCommandFiles();
- const bool dump_stream_only_if_no_immediate = true;
- if (num_source_command_files > 0)
- {
- for (size_t i=0; i < num_source_command_files; ++i)
- {
- const char *command_file = GetSourceCommandFileAtIndex(i);
- ::snprintf (command_string, sizeof(command_string), "command source '%s'", command_file);
- m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, false);
- if (GetDebugMode())
- {
- result.PutError (m_debugger.GetErrorFileHandle());
- result.PutOutput (m_debugger.GetOutputFileHandle());
- }
-
- // if the command sourcing generated an error - dump the result object
- if (result.Succeeded() == false)
- {
- const size_t output_size = result.GetOutputSize();
- if (output_size > 0)
- m_io_channel_ap->OutWrite (result.GetOutput(dump_stream_only_if_no_immediate), output_size, NO_ASYNC);
- const size_t error_size = result.GetErrorSize();
- if (error_size > 0)
- m_io_channel_ap->OutWrite (result.GetError(dump_stream_only_if_no_immediate), error_size, NO_ASYNC);
- }
-
- result.Clear();
- }
- }
-
+ // First source in the commands specified to be run before the file arguments are processed.
+ ExecuteInitialCommands(true);
+
// Was there a core file specified?
std::string core_file_spec("");
if (!m_option_data.m_core_file.empty())
core_file_spec.append("--core ").append(m_option_data.m_core_file);
+ char command_string[PATH_MAX * 2];
const size_t num_args = m_option_data.m_args.size();
if (num_args > 0)
{
@@ -1487,6 +1557,9 @@ Driver::MainLoop ()
result.PutError(m_debugger.GetErrorFileHandle());
result.PutOutput(m_debugger.GetOutputFileHandle());
}
+
+ // Now execute the commands specified for after the file arguments are processed.
+ ExecuteInitialCommands(false);
SBEvent event;
@@ -1597,9 +1670,11 @@ Driver::MainLoop ()
master_out_comm.Disconnect();
master_out_comm.ReadThreadStop();
+#if !defined(_MSC_VER)
out_comm_2.SetReadThreadBytesReceivedCallback(NULL, NULL);
out_comm_2.Disconnect();
out_comm_2.ReadThreadStop();
+#endif
editline_output_pty.CloseMasterFileDescriptor();
reset_stdin_termios();
@@ -1714,15 +1789,15 @@ main (int argc, char const *argv[], const char *envp[])
{
Driver driver;
- bool exit = false;
- SBError error (driver.ParseArgs (argc, argv, stdout, exit));
+ bool exiting = false;
+ SBError error (driver.ParseArgs (argc, argv, stdout, exiting));
if (error.Fail())
{
const char *error_cstr = error.GetCString ();
if (error_cstr)
::fprintf (stderr, "error: %s\n", error_cstr);
}
- else if (!exit)
+ else if (!exiting)
{
driver.MainLoop ();
}