From 06357c930cc13f084e20fe1950a2c849aad22e39 Mon Sep 17 00:00:00 2001 From: Greg Clayton Date: Wed, 30 Jul 2014 17:38:47 +0000 Subject: [PATCH] (no commit message) llvm-svn: 214319 --- lldb/include/lldb/API/SBHostOS.h | 3 + lldb/include/lldb/Host/Host.h | 2 +- lldb/include/lldb/lldb-enumerations.h | 17 ++ lldb/include/lldb/lldb-private-enumerations.h | 18 --- lldb/scripts/Python/interface/SBHostOS.i | 6 + lldb/source/API/SBHostOS.cpp | 11 ++ lldb/source/API/SBStream.cpp | 2 + lldb/source/Commands/CommandObjectProcess.cpp | 9 +- lldb/source/Expression/ClangExpressionParser.cpp | 2 +- lldb/source/Interpreter/CommandInterpreter.cpp | 13 +- lldb/source/Target/Process.cpp | 8 +- lldb/tools/driver/Driver.cpp | 195 +++++++++++------------ lldb/tools/driver/Driver.h | 2 +- 13 files changed, 159 insertions(+), 129 deletions(-) diff --git a/lldb/include/lldb/API/SBHostOS.h b/lldb/include/lldb/API/SBHostOS.h index 7c73d7d..7ab22ca 100644 --- a/lldb/include/lldb/API/SBHostOS.h +++ b/lldb/include/lldb/API/SBHostOS.h @@ -25,6 +25,9 @@ public: static lldb::SBFileSpec GetLLDBPythonPath (); + static lldb::SBFileSpec + GetLLDBPath (lldb::PathType path_type); + static void ThreadCreated (const char *name); diff --git a/lldb/include/lldb/Host/Host.h b/lldb/include/lldb/Host/Host.h index ab048f7..aa934d9 100644 --- a/lldb/include/lldb/Host/Host.h +++ b/lldb/include/lldb/Host/Host.h @@ -460,7 +460,7 @@ public: /// \b true if \a resource_path was resolved, \a false otherwise. //------------------------------------------------------------------ static bool - GetLLDBPath (PathType path_type, + GetLLDBPath (lldb::PathType path_type, FileSpec &file_spec); //------------------------------------------------------------------ diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h index ab7faa4..4138b5d 100644 --- a/lldb/include/lldb/lldb-enumerations.h +++ b/lldb/include/lldb/lldb-enumerations.h @@ -818,6 +818,23 @@ namespace lldb { eGdbSignalBreakpoint = 0x96 } GdbRemoteSignal; + //---------------------------------------------------------------------- + // Used with SBHost::GetPath (lldb::PathType) to find files that are + // related to LLDB on the current host machine. Most files are relative + // to LLDB or are in known locations. + //---------------------------------------------------------------------- + typedef enum PathType + { + ePathTypeLLDBShlibDir, // The directory where the lldb.so (unix) or LLDB mach-o file in LLDB.framework (MacOSX) exists + ePathTypeSupportExecutableDir, // Find LLDB support executable directory (debugserver, etc) + ePathTypeHeaderDir, // Find LLDB header file directory + ePathTypePythonDir, // Find Python modules (PYTHONPATH) directory + ePathTypeLLDBSystemPlugins, // System plug-ins directory + ePathTypeLLDBUserPlugins, // User plug-ins directory + ePathTypeLLDBTempSystemDir // The LLDB temp directory for this system that will be cleaned up on exit + + } PathType; + } // namespace lldb diff --git a/lldb/include/lldb/lldb-private-enumerations.h b/lldb/include/lldb/lldb-private-enumerations.h index 2728c45..ee1589f 100644 --- a/lldb/include/lldb/lldb-private-enumerations.h +++ b/lldb/include/lldb/lldb-private-enumerations.h @@ -105,24 +105,6 @@ typedef enum SortOrder eSortOrderByName } SortOrder; - -//---------------------------------------------------------------------- -// Used in conjunction with Host::GetLLDBPath () to find files that -// are related to -//---------------------------------------------------------------------- -typedef enum PathType -{ - ePathTypeLLDBShlibDir, // The directory where the lldb.so (unix) or LLDB mach-o file in LLDB.framework (MacOSX) exists - ePathTypeSupportExecutableDir, // Find LLDB support executable directory (debugserver, etc) - ePathTypeHeaderDir, // Find LLDB header file directory - ePathTypePythonDir, // Find Python modules (PYTHONPATH) directory - ePathTypeLLDBSystemPlugins, // System plug-ins directory - ePathTypeLLDBUserPlugins, // User plug-ins directory - ePathTypeLLDBTempSystemDir // The LLDB temp directory for this system that will be cleaned up on exit - -} PathType; - - typedef enum ObjCRuntimeVersions { eObjC_VersionUnknown = 0, eAppleObjC_V1 = 1, diff --git a/lldb/scripts/Python/interface/SBHostOS.i b/lldb/scripts/Python/interface/SBHostOS.i index 0352924..d9f4216 100644 --- a/lldb/scripts/Python/interface/SBHostOS.i +++ b/lldb/scripts/Python/interface/SBHostOS.i @@ -16,6 +16,12 @@ public: static lldb::SBFileSpec GetProgramFileSpec (); + static lldb::SBFileSpec + GetLLDBPythonPath (); + + static lldb::SBFileSpec + GetLLDBPath (lldb::PathType path_type); + static void ThreadCreated (const char *name); diff --git a/lldb/source/API/SBHostOS.cpp b/lldb/source/API/SBHostOS.cpp index 88ca952..b3c7bc5 100644 --- a/lldb/source/API/SBHostOS.cpp +++ b/lldb/source/API/SBHostOS.cpp @@ -38,6 +38,17 @@ SBHostOS::GetLLDBPythonPath () return sb_lldb_python_filespec; } + +SBFileSpec +SBHostOS::GetLLDBPath (lldb::PathType path_type) +{ + SBFileSpec sb_fspec; + FileSpec fspec; + if (Host::GetLLDBPath (path_type, fspec)) + sb_fspec.SetFileSpec (fspec); + return sb_fspec; +} + lldb::thread_t SBHostOS::ThreadCreate ( diff --git a/lldb/source/API/SBStream.cpp b/lldb/source/API/SBStream.cpp index 531ab9f..f5b5c08 100644 --- a/lldb/source/API/SBStream.cpp +++ b/lldb/source/API/SBStream.cpp @@ -82,6 +82,8 @@ SBStream::RedirectToFile (const char *path, bool append) uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate; if (append) open_options |= File::eOpenOptionAppend; + else + open_options |= File::eOpenOptionTruncate; stream_file->GetFile().Open (path, open_options, lldb::eFilePermissionsFileDefault); m_opaque_ap.reset (stream_file); diff --git a/lldb/source/Commands/CommandObjectProcess.cpp b/lldb/source/Commands/CommandObjectProcess.cpp index 3534df3..5dde4dd 100644 --- a/lldb/source/Commands/CommandObjectProcess.cpp +++ b/lldb/source/Commands/CommandObjectProcess.cpp @@ -536,6 +536,9 @@ protected: if (error.Success()) { + // Update the execution context so the current target and process are now selected + // in case we interrupt + m_interpreter.UpdateExecutionContext(NULL); ListenerSP listener_sp (new Listener("lldb.CommandObjectProcessAttach.DoExecute.attach.hijack")); m_options.attach_info.SetHijackListener(listener_sp); process->HijackProcessEvents(listener_sp.get()); @@ -557,7 +560,11 @@ protected: } else { - result.AppendError ("attach failed: process did not stop (no such process or permission problem?)"); + const char *exit_desc = process->GetExitDescription(); + if (exit_desc) + result.AppendErrorWithFormat ("attach failed: %s", exit_desc); + else + result.AppendError ("attach failed: process did not stop (no such process or permission problem?)"); process->Destroy(); result.SetStatus (eReturnStatusFailed); } diff --git a/lldb/source/Expression/ClangExpressionParser.cpp b/lldb/source/Expression/ClangExpressionParser.cpp index a01733d..05a45bc 100644 --- a/lldb/source/Expression/ClangExpressionParser.cpp +++ b/lldb/source/Expression/ClangExpressionParser.cpp @@ -309,7 +309,7 @@ ClangExpressionParser::Parse (Stream &stream) std::string temp_source_path; FileSpec tmpdir_file_spec; - if (Host::GetLLDBPath (ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) + if (Host::GetLLDBPath (lldb::ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) { tmpdir_file_spec.GetFilename().SetCString("expr.XXXXXX"); temp_source_path = std::move(tmpdir_file_spec.GetPath()); diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp index 33a0912..d47b708 100644 --- a/lldb/source/Interpreter/CommandInterpreter.cpp +++ b/lldb/source/Interpreter/CommandInterpreter.cpp @@ -3141,7 +3141,16 @@ CommandInterpreter::RunCommandInterpreter(bool auto_handle_events, bool spawn_thread) { const bool multiple_lines = false; // Only get one line at a time - if (!m_command_io_handler_sp) + if (m_command_io_handler_sp) + { + // Copy the current debugger file handles in case they changed. + m_command_io_handler_sp->GetInputStreamFile() = m_debugger.GetInputFile(); + m_command_io_handler_sp->GetOutputStreamFile() = m_debugger.GetOutputFile(); + m_command_io_handler_sp->GetErrorStreamFile() = m_debugger.GetErrorFile(); + m_command_io_handler_sp->SetIsDone(false); + } + else + { m_command_io_handler_sp.reset(new IOHandlerEditline (m_debugger, m_debugger.GetInputFile(), m_debugger.GetOutputFile(), @@ -3152,6 +3161,8 @@ CommandInterpreter::RunCommandInterpreter(bool auto_handle_events, multiple_lines, 0, // Don't show line numbers *this)); + } + m_debugger.PushIOHandler(m_command_io_handler_sp); if (auto_handle_events) diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index 7e09e7e..cdbbe8d 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -3243,6 +3243,7 @@ Process::Halt (bool clear_thread_plans) EventSP event_sp; Error error (WillHalt()); + bool restored_process_events = false; if (error.Success()) { @@ -3254,6 +3255,10 @@ Process::Halt (bool clear_thread_plans) { if (m_public_state.GetValue() == eStateAttaching) { + // Don't hijack and eat the eStateExited as the code that was doing + // the attach will be waiting for this event... + RestorePrivateProcessEvents(); + restored_process_events = true; SetExitStatus(SIGKILL, "Cancelled async attach."); Destroy (); } @@ -3302,7 +3307,8 @@ Process::Halt (bool clear_thread_plans) } } // Resume our private state thread before we post the event (if any) - RestorePrivateProcessEvents(); + if (!restored_process_events) + RestorePrivateProcessEvents(); // Post any event we might have consumed. If all goes well, we will have // stopped the process, intercepted the event and set the interrupted diff --git a/lldb/tools/driver/Driver.cpp b/lldb/tools/driver/Driver.cpp index 06814ea..9345a34 100644 --- a/lldb/tools/driver/Driver.cpp +++ b/lldb/tools/driver/Driver.cpp @@ -477,63 +477,19 @@ Driver::GetScriptLanguage() const } void -Driver::ExecuteInitialCommands (bool before_file) +Driver::WriteInitialCommands (bool before_file, SBStream &strm) { - size_t num_commands; - std::vector > *command_set; - if (before_file) - command_set = &(m_option_data.m_initial_commands); - else - command_set = &(m_option_data.m_after_file_commands); + std::vector > &command_set = before_file ? m_option_data.m_initial_commands : + 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++) + for (const auto &command_pair : command_set) { - 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 %i '%s'", m_option_data.m_source_quietly, 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) - { - const char *cstr = result.GetOutput(dump_stream_only_if_no_immediate); - if (cstr) - printf ("%s", cstr); - } - const size_t error_size = result.GetErrorSize(); - if (error_size > 0) - { - const char *cstr = result.GetError(dump_stream_only_if_no_immediate); - if (cstr) - printf ("%s", cstr); - } - } - - if (result.Succeeded() == false) - { - const char *type = before_file ? "before file" : "after_file"; - if (is_file) - ::fprintf(stderr, "Aborting %s command execution, command file: '%s' failed.\n", type, command); - else - ::fprintf(stderr, "Aborting %s command execution, command: '%s' failed.\n", type, command); - break; - } - result.Clear(); + const char *command = command_pair.second.c_str(); + if (command_pair.first) + strm.Printf("command source -s %i '%s'\n", m_option_data.m_source_quietly, command); + else + strm.Printf("%s\n", command); } - GetDebugger().SetAsync(old_async); } bool @@ -857,8 +813,8 @@ Driver::MainLoop () m_debugger.SetErrorFileHandle (stderr, false); m_debugger.SetOutputFileHandle (stdout, false); - m_debugger.SetInputFileHandle (stdin, true); - + m_debugger.SetInputFileHandle (stdin, false); // Don't take ownership of STDIN yet... + m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor); struct winsize window_size; @@ -882,77 +838,56 @@ Driver::MainLoop () } // Now we handle options we got from the command line - // 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); + SBStream commands_stream;./ - char command_string[PATH_MAX * 2]; + // First source in the commands specified to be run before the file arguments are processed. + WriteInitialCommands(true, commands_stream); + const size_t num_args = m_option_data.m_args.size(); if (num_args > 0) { - char arch_name[64]; - if (m_debugger.GetDefaultArchitecture (arch_name, sizeof (arch_name))) - ::snprintf (command_string, - sizeof (command_string), - "target create --arch=%s %s \"%s\"", - arch_name, - core_file_spec.c_str(), - m_option_data.m_args[0].c_str()); - else - ::snprintf (command_string, - sizeof(command_string), - "target create %s \"%s\"", - core_file_spec.c_str(), - m_option_data.m_args[0].c_str()); - - m_debugger.HandleCommand (command_string); + commands_stream.Printf("target create \"%s\"", m_option_data.m_args[0].c_str()); + if (!m_option_data.m_core_file.empty()) + { + commands_stream.Printf(" --core \"%s\"", m_option_data.m_core_file.c_str()); + } + commands_stream.Printf("\n"); if (num_args > 1) { - m_debugger.HandleCommand ("settings clear target.run-args"); - char arg_cstr[1024]; + commands_stream.Printf ("settings set -- target.run-args "); for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx) { - ::snprintf (arg_cstr, - sizeof(arg_cstr), - "settings append target.run-args \"%s\"", - m_option_data.m_args[arg_idx].c_str()); - m_debugger.HandleCommand (arg_cstr); + const char *arg_cstr = m_option_data.m_args[arg_idx].c_str(); + if (strchr(arg_cstr, '"') == NULL) + commands_stream.Printf(" \"%s\"", arg_cstr); + else + commands_stream.Printf(" '%s'", arg_cstr); } + commands_stream.Printf("\n"); } } - else if (!core_file_spec.empty()) + else if (!m_option_data.m_core_file.empty()) { - ::snprintf (command_string, - sizeof(command_string), - "target create %s", - core_file_spec.c_str()); - m_debugger.HandleCommand (command_string);; + commands_stream.Printf("target create --core \"%s\"\n", m_option_data.m_core_file.c_str()); } else if (!m_option_data.m_process_name.empty()) { - ::snprintf (command_string, - sizeof(command_string), - "process attach --name '%s'%s", - m_option_data.m_process_name.c_str(), - m_option_data.m_wait_for ? " --waitfor" : ""); - m_debugger.HandleCommand (command_string); + commands_stream.Printf ("process attach --name \"%s\"", m_option_data.m_process_name.c_str()); + + if (m_option_data.m_wait_for) + commands_stream.Printf(" --waitfor"); + + commands_stream.Printf("\n"); + } else if (LLDB_INVALID_PROCESS_ID != m_option_data.m_process_pid) { - ::snprintf (command_string, - sizeof(command_string), - "process attach --pid %" PRIu64, - m_option_data.m_process_pid); - m_debugger.HandleCommand (command_string); + commands_stream.Printf ("process attach --pid %" PRIu64 "\n", m_option_data.m_process_pid); } - ExecuteInitialCommands(false); - + WriteInitialCommands(false, commands_stream); + // Now that all option parsing is done, we try and parse the .lldbinit // file in the current working directory sb_interpreter.SourceInitFileInCurrentWorkingDirectory (result); @@ -964,6 +899,56 @@ Driver::MainLoop () bool handle_events = true; bool spawn_thread = false; + + // Check if we have any data in the commands stream, and if so, save it to a temp file + // so we can then run the command interpreter using the file contents. + if (commands_stream.GetData() && commands_stream.GetSize()) + { + char lldb_cmds_file[PATH_MAX]; + SBFileSpec lldb_temp_dir_spec = SBHostOS::GetLLDBPath (lldb::ePathTypeLLDBTempSystemDir); + lldb_temp_dir_spec.SetFilename("lldb-cmds.XXXXXX"); + + if (lldb_temp_dir_spec.GetPath(lldb_cmds_file, sizeof(lldb_cmds_file))) + { + int fd = mkstemp(lldb_cmds_file); + if (fd == -1) + { + fprintf(stderr, "error: can't create temporary file for LLDB commands\n"); + exit (1); + } + FILE *file = fdopen(fd, "r+"); + if (file == NULL) + { + fprintf(stderr, "error: fdopen(%i, \"r+\") failed (errno = %i)\n", fd, errno); + exit (2); + } + // Redirect the stream to a file and it will save its temp buffer out to the file on disk + commands_stream.RedirectToFileHandle(file, true); + + // Close the stream which will close the file and flush it to disk + commands_stream.Clear(); + + // Now re-open the file so we can use it as an input file handle for the real + // command interpreter + FILE *commands_file = ::fopen(lldb_cmds_file, "r"); + if (commands_file) + { + // Hand ownership over to the debugger for "commands_file". + m_debugger.SetInputFileHandle (commands_file, true); + m_debugger.RunCommandInterpreter(handle_events, spawn_thread); + } + else + { + fprintf(stderr, "error: fopen(\"%s\", \"r\") failed (errno = %i) when trying to open LLDB commands file\n", lldb_cmds_file, errno); + exit (3); + } + } + } + + // Now set the input file handle to STDIN and run the command + // interpreter again in interactive mode and let the debugger + // take ownership of stdin + m_debugger.SetInputFileHandle (stdin, true); m_debugger.RunCommandInterpreter(handle_events, spawn_thread); reset_stdin_termios(); diff --git a/lldb/tools/driver/Driver.h b/lldb/tools/driver/Driver.h index 9185489..8b6c6ee 100644 --- a/lldb/tools/driver/Driver.h +++ b/lldb/tools/driver/Driver.h @@ -52,7 +52,7 @@ public: GetScriptLanguage() const; void - ExecuteInitialCommands (bool before_file); + WriteInitialCommands (bool before_file, lldb::SBStream &strm); bool GetDebugMode() const; -- 2.7.4