diff options
Diffstat (limited to 'tools/driver/Driver.cpp')
-rw-r--r-- | tools/driver/Driver.cpp | 227 |
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 (); } |