diff options
-rw-r--r-- | lldb/include/lldb/API/SBCommandInterpreter.h | 11 | ||||
-rw-r--r-- | lldb/include/lldb/API/SBDebugger.h | 3 | ||||
-rw-r--r-- | lldb/include/lldb/API/SBExecutionContext.h | 2 | ||||
-rw-r--r-- | lldb/include/lldb/API/SBFileSpec.h | 1 | ||||
-rw-r--r-- | lldb/include/lldb/Interpreter/CommandInterpreter.h | 7 | ||||
-rw-r--r-- | lldb/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme | 2 | ||||
-rw-r--r-- | lldb/scripts/Python/interface/SBCommandInterpreter.i | 9 | ||||
-rw-r--r-- | lldb/scripts/Python/interface/SBDebugger.i | 3 | ||||
-rw-r--r-- | lldb/source/API/SBCommandInterpreter.cpp | 68 | ||||
-rw-r--r-- | lldb/source/API/SBDebugger.cpp | 4 | ||||
-rw-r--r-- | lldb/source/API/SBExecutionContext.cpp | 6 | ||||
-rw-r--r-- | lldb/source/Interpreter/CommandInterpreter.cpp | 99 | ||||
-rw-r--r-- | lldb/tools/driver/Driver.cpp | 31 | ||||
-rw-r--r-- | lldb/tools/driver/Driver.h | 1 |
14 files changed, 236 insertions, 11 deletions
diff --git a/lldb/include/lldb/API/SBCommandInterpreter.h b/lldb/include/lldb/API/SBCommandInterpreter.h index 6f9295bf740..947e3916414 100644 --- a/lldb/include/lldb/API/SBCommandInterpreter.h +++ b/lldb/include/lldb/API/SBCommandInterpreter.h @@ -18,6 +18,8 @@ namespace lldb { class SBCommandInterpreterRunOptions { friend class SBDebugger; +friend class SBCommandInterpreter; + public: SBCommandInterpreterRunOptions(); ~SBCommandInterpreterRunOptions(); @@ -138,6 +140,15 @@ public: lldb::ReturnStatus HandleCommand (const char *command_line, lldb::SBCommandReturnObject &result, bool add_to_history = false); + lldb::ReturnStatus + HandleCommand (const char *command_line, SBExecutionContext &exe_ctx, SBCommandReturnObject &result, bool add_to_history = false); + + void + HandleCommandsFromFile (lldb::SBFileSpec &file, + lldb::SBExecutionContext &override_context, + lldb::SBCommandInterpreterRunOptions &options, + lldb::SBCommandReturnObject result); + // The pointer based interface is not useful in SWIG, since the cursor & last_char arguments are string pointers INTO current_line // and you can't do that in a scripting language interface in general... diff --git a/lldb/include/lldb/API/SBDebugger.h b/lldb/include/lldb/API/SBDebugger.h index de7d1a1c23b..6e43e12f7b1 100644 --- a/lldb/include/lldb/API/SBDebugger.h +++ b/lldb/include/lldb/API/SBDebugger.h @@ -327,7 +327,8 @@ public: bool spawn_thread, SBCommandInterpreterRunOptions &options, int &num_errors, - bool &quit_requested); + bool &quit_requested, + bool &stopped_for_crash); private: friend class SBCommandInterpreter; diff --git a/lldb/include/lldb/API/SBExecutionContext.h b/lldb/include/lldb/API/SBExecutionContext.h index e5cac1afe91..9d889139f5c 100644 --- a/lldb/include/lldb/API/SBExecutionContext.h +++ b/lldb/include/lldb/API/SBExecutionContext.h @@ -20,6 +20,8 @@ namespace lldb { class SBExecutionContext { +friend class SBCommandInterpreter; + public: SBExecutionContext(); diff --git a/lldb/include/lldb/API/SBFileSpec.h b/lldb/include/lldb/API/SBFileSpec.h index d262b98d0fd..1eee3d10367 100644 --- a/lldb/include/lldb/API/SBFileSpec.h +++ b/lldb/include/lldb/API/SBFileSpec.h @@ -63,6 +63,7 @@ public: private: friend class SBAttachInfo; friend class SBBlock; + friend class SBCommandInterpreter; friend class SBCompileUnit; friend class SBDeclaration; friend class SBFileSpecList; diff --git a/lldb/include/lldb/Interpreter/CommandInterpreter.h b/lldb/include/lldb/Interpreter/CommandInterpreter.h index 7047f21e716..ddc4dbab4c1 100644 --- a/lldb/include/lldb/Interpreter/CommandInterpreter.h +++ b/lldb/include/lldb/Interpreter/CommandInterpreter.h @@ -628,6 +628,12 @@ public: { return m_quit_requested; } + + bool + GetStoppedForCrash () const + { + return m_stopped_for_crash; + } protected: friend class Debugger; @@ -685,6 +691,7 @@ private: std::vector<uint32_t> m_command_source_flags; uint32_t m_num_errors; bool m_quit_requested; + bool m_stopped_for_crash; }; diff --git a/lldb/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme b/lldb/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme index 34560feaaeb..bd7c34c49d2 100644 --- a/lldb/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme +++ b/lldb/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme @@ -84,7 +84,7 @@ <LaunchAction selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - launchStyle = "0" + launchStyle = "1" useCustomWorkingDirectory = "NO" customWorkingDirectory = "/Volumes/work/gclayton/Documents/devb/attach" buildConfiguration = "Debug" diff --git a/lldb/scripts/Python/interface/SBCommandInterpreter.i b/lldb/scripts/Python/interface/SBCommandInterpreter.i index 856038094f7..0a795adb038 100644 --- a/lldb/scripts/Python/interface/SBCommandInterpreter.i +++ b/lldb/scripts/Python/interface/SBCommandInterpreter.i @@ -182,6 +182,15 @@ public: lldb::ReturnStatus HandleCommand (const char *command_line, lldb::SBCommandReturnObject &result, bool add_to_history = false); + lldb::ReturnStatus + HandleCommand (const char *command_line, SBExecutionContext &exe_ctx, SBCommandReturnObject &result, bool add_to_history = false); + + void + HandleCommandsFromFile (lldb::SBFileSpec &file, + lldb::SBExecutionContext &override_context, + lldb::SBCommandInterpreterRunOptions &options, + lldb::SBCommandReturnObject result); + int HandleCompletion (const char *current_line, uint32_t cursor_pos, diff --git a/lldb/scripts/Python/interface/SBDebugger.i b/lldb/scripts/Python/interface/SBDebugger.i index fb63fc362dc..48e0d5db638 100644 --- a/lldb/scripts/Python/interface/SBDebugger.i +++ b/lldb/scripts/Python/interface/SBDebugger.i @@ -369,7 +369,8 @@ public: bool spawn_thread, SBCommandInterpreterRunOptions &options, int &num_errors, - bool &quit_requested); + bool &quit_requested, + bool &stopped_for_crash); }; // class SBDebugger } // namespace lldb diff --git a/lldb/source/API/SBCommandInterpreter.cpp b/lldb/source/API/SBCommandInterpreter.cpp index bc8d6d34aa9..4e65c4f857c 100644 --- a/lldb/source/API/SBCommandInterpreter.cpp +++ b/lldb/source/API/SBCommandInterpreter.cpp @@ -20,6 +20,7 @@ #include "lldb/API/SBBroadcaster.h" #include "lldb/API/SBCommandReturnObject.h" #include "lldb/API/SBCommandInterpreter.h" +#include "lldb/API/SBExecutionContext.h" #include "lldb/API/SBProcess.h" #include "lldb/API/SBTarget.h" #include "lldb/API/SBListener.h" @@ -222,6 +223,13 @@ SBCommandInterpreter::GetIOHandlerControlSequence(char ch) lldb::ReturnStatus SBCommandInterpreter::HandleCommand (const char *command_line, SBCommandReturnObject &result, bool add_to_history) { + SBExecutionContext sb_exe_ctx; + return HandleCommand (command_line, sb_exe_ctx, result, add_to_history); +} + +lldb::ReturnStatus +SBCommandInterpreter::HandleCommand (const char *command_line, SBExecutionContext &override_context, SBCommandReturnObject &result, bool add_to_history) +{ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); if (log) @@ -229,11 +237,21 @@ SBCommandInterpreter::HandleCommand (const char *command_line, SBCommandReturnOb static_cast<void*>(m_opaque_ptr), command_line, static_cast<void*>(result.get()), add_to_history); + ExecutionContext ctx, *ctx_ptr; + if (override_context.get()) + { + ctx = override_context.get()->Lock(true); + ctx_ptr = &ctx; + } + else + ctx_ptr = nullptr; + + result.Clear(); if (command_line && m_opaque_ptr) { result.ref().SetInteractive(false); - m_opaque_ptr->HandleCommand (command_line, add_to_history ? eLazyBoolYes : eLazyBoolNo, result.ref()); + m_opaque_ptr->HandleCommand (command_line, add_to_history ? eLazyBoolYes : eLazyBoolNo, result.ref(), ctx_ptr); } else { @@ -256,6 +274,54 @@ SBCommandInterpreter::HandleCommand (const char *command_line, SBCommandReturnOb return result.GetStatus(); } +void +SBCommandInterpreter::HandleCommandsFromFile (lldb::SBFileSpec &file, + lldb::SBExecutionContext &override_context, + lldb::SBCommandInterpreterRunOptions &options, + lldb::SBCommandReturnObject result) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + + if (log) + { + SBStream s; + file.GetDescription (s); + log->Printf ("SBCommandInterpreter(%p)::HandleCommandsFromFile (file=\"%s\", SBCommandReturnObject(%p))", + static_cast<void*>(m_opaque_ptr), s.GetData(), + static_cast<void*>(result.get())); + } + + if (!m_opaque_ptr) + { + result->AppendError ("SBCommandInterpreter is not valid."); + result->SetStatus (eReturnStatusFailed); + return; + } + + if (!file.IsValid()) + { + SBStream s; + file.GetDescription (s); + result->AppendErrorWithFormat ("File is not valid: %s.", s.GetData()); + result->SetStatus (eReturnStatusFailed); + } + + FileSpec tmp_spec = file.ref(); + ExecutionContext ctx, *ctx_ptr; + if (override_context.get()) + { + ctx = override_context.get()->Lock(true); + ctx_ptr = &ctx; + } + else + ctx_ptr = nullptr; + + + m_opaque_ptr->HandleCommandsFromFile (tmp_spec, ctx_ptr, options.ref(), result.ref()); + +} + + int SBCommandInterpreter::HandleCompletion (const char *current_line, const char *cursor, diff --git a/lldb/source/API/SBDebugger.cpp b/lldb/source/API/SBDebugger.cpp index a655950926f..4b00f19d22a 100644 --- a/lldb/source/API/SBDebugger.cpp +++ b/lldb/source/API/SBDebugger.cpp @@ -986,7 +986,8 @@ SBDebugger::RunCommandInterpreter (bool auto_handle_events, bool spawn_thread, SBCommandInterpreterRunOptions &options, int &num_errors, - bool &quit_requested) + bool &quit_requested, + bool &stopped_for_crash) { if (m_opaque_sp) @@ -995,6 +996,7 @@ SBDebugger::RunCommandInterpreter (bool auto_handle_events, interp.RunCommandInterpreter(auto_handle_events, spawn_thread, options.ref()); num_errors = interp.GetNumErrors(); quit_requested = interp.GetQuitRequested(); + stopped_for_crash = interp.GetStoppedForCrash(); } } diff --git a/lldb/source/API/SBExecutionContext.cpp b/lldb/source/API/SBExecutionContext.cpp index d1c21eccb72..dc20c609213 100644 --- a/lldb/source/API/SBExecutionContext.cpp +++ b/lldb/source/API/SBExecutionContext.cpp @@ -69,6 +69,12 @@ SBExecutionContext::operator = (const lldb::SBExecutionContext &rhs) return *this; } +ExecutionContextRef * +SBExecutionContext::get () const +{ + return m_exe_ctx_sp.get(); +} + SBTarget SBExecutionContext::GetTarget () const { diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp index 28eafcbd1d9..b281bf1954c 100644 --- a/lldb/source/Interpreter/CommandInterpreter.cpp +++ b/lldb/source/Interpreter/CommandInterpreter.cpp @@ -121,7 +121,8 @@ CommandInterpreter::CommandInterpreter m_truncation_warning(eNoTruncation), m_command_source_depth (0), m_num_errors(0), - m_quit_requested(false) + m_quit_requested(false), + m_stopped_for_crash(false) { debugger.SetScriptLanguage (script_language); @@ -2568,6 +2569,42 @@ CommandInterpreter::HandleCommands (const StringList &commands, return; } } + + // Also check for "stop on crash here: + bool should_stop = false; + if (tmp_result.GetDidChangeProcessState() && options.GetStopOnCrash()) + { + TargetSP target_sp (m_debugger.GetTargetList().GetSelectedTarget()); + if (target_sp) + { + ProcessSP process_sp (target_sp->GetProcessSP()); + if (process_sp) + { + for (ThreadSP thread_sp : process_sp->GetThreadList().Threads()) + { + StopReason reason = thread_sp->GetStopReason(); + if (reason == eStopReasonSignal || reason == eStopReasonException || reason == eStopReasonInstrumentation) + { + should_stop = true; + break; + } + } + } + } + if (should_stop) + { + if (idx != num_lines - 1) + result.AppendErrorWithFormat("Aborting reading of commands after command #%" PRIu64 ": '%s' stopped with a signal or exception.\n", + (uint64_t)idx + 1, cmd); + else + result.AppendMessageWithFormat("Command #%" PRIu64 " '%s' stopped with a signal or exception.\n", (uint64_t)idx + 1, cmd); + + result.SetStatus(tmp_result.GetStatus()); + m_debugger.SetAsyncExecution (old_async_execution); + + return; + } + } } @@ -2639,6 +2676,19 @@ CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file, flags |= eHandleCommandFlagStopOnError; } + if (options.GetStopOnCrash()) + { + if (m_command_source_flags.empty()) + { + // Echo command by default + flags |= eHandleCommandFlagStopOnCrash; + } + else if (m_command_source_flags.back() & eHandleCommandFlagStopOnCrash) + { + flags |= eHandleCommandFlagStopOnCrash; + } + } + if (options.m_echo_commands == eLazyBoolCalculate) { if (m_command_source_flags.empty()) @@ -2694,7 +2744,7 @@ CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file, *this)); const bool old_async_execution = debugger.GetAsyncExecution(); - // Set synchronous execution if we not stopping when we continue + // Set synchronous execution if we are not stopping on continue if ((flags & eHandleCommandFlagStopOnContinue) == 0) debugger.SetAsyncExecution (false); @@ -3069,6 +3119,50 @@ CommandInterpreter::IOHandlerInputComplete (IOHandler &io_handler, std::string & io_handler.SetIsDone(true); break; } + + // Finally, if we're going to stop on crash, check that here: + if (!m_quit_requested + && result.GetDidChangeProcessState() + && io_handler.GetFlags().Test(eHandleCommandFlagStopOnCrash)) + { + bool should_stop = false; + TargetSP target_sp (m_debugger.GetTargetList().GetSelectedTarget()); + if (target_sp) + { + ProcessSP process_sp (target_sp->GetProcessSP()); + if (process_sp) + { + for (ThreadSP thread_sp : process_sp->GetThreadList().Threads()) + { + StopReason reason = thread_sp->GetStopReason(); + if (reason == eStopReasonSignal || reason == eStopReasonException || reason == eStopReasonInstrumentation) + { + // If we are printing results, we ought to show the resaon why we are stopping here: + if (io_handler.GetFlags().Test(eHandleCommandFlagPrintResult)) + { + if (!result.GetImmediateOutputStream()) + { + const uint32_t start_frame = 0; + const uint32_t num_frames = 1; + const uint32_t num_frames_with_source = 1; + thread_sp->GetStatus (*io_handler.GetOutputStreamFile().get(), + start_frame, + num_frames, + num_frames_with_source); + } + } + should_stop = true; + break; + } + } + } + } + if (should_stop) + { + io_handler.SetIsDone(true); + m_stopped_for_crash = true; + } + } } bool @@ -3155,6 +3249,7 @@ CommandInterpreter::RunCommandInterpreter(bool auto_handle_events, const bool multiple_lines = false; m_num_errors = 0; m_quit_requested = false; + m_stopped_for_crash = false; // Always re-create the IOHandlerEditline in case the input // changed. The old instance might have had a non-interactive diff --git a/lldb/tools/driver/Driver.cpp b/lldb/tools/driver/Driver.cpp index e4fdc77caea..cec56b4cb47 100644 --- a/lldb/tools/driver/Driver.cpp +++ b/lldb/tools/driver/Driver.cpp @@ -109,7 +109,10 @@ static OptionDefinition g_options[] = { 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, "source-quietly" , 'Q', no_argument , 0, eArgTypeNone, - "Tells the debugger suppress output from commands provided in the -s, -S, -O and -o commands." }, + "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, "batch" , 'b', no_argument , 0, eArgTypeNone, + "Tells the debugger to running the commands from -s, -S, -o & -O, and then quit. However if any run command stopped due to a signal or crash, " + "the debugger will return to the interactive prompt at the place of the crash." }, { 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, @@ -406,6 +409,7 @@ Driver::OptionData::OptionData () : m_process_name(), m_process_pid(LLDB_INVALID_PROCESS_ID), m_use_external_editor(false), + m_batch(false), m_seen_options() { } @@ -429,6 +433,7 @@ Driver::OptionData::Clear () m_use_external_editor = false; m_wait_for = false; m_process_name.erase(); + m_batch = false; m_process_pid = LLDB_INVALID_PROCESS_ID; } @@ -641,6 +646,10 @@ Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exiting) m_option_data.m_print_python_path = true; break; + case 'b': + m_option_data.m_batch = true; + break; + case 'c': { SBFileSpec file(optarg); @@ -924,6 +933,7 @@ Driver::MainLoop () // The command file might have requested that we quit, this variable will track that. bool quit_requested = false; + bool stopped_for_crash = false; if (commands_data && commands_size) { enum PIPES { READ, WRITE }; // Constants 0 and 1 for READ and WRITE @@ -973,8 +983,15 @@ Driver::MainLoop () SBCommandInterpreterRunOptions options; options.SetStopOnError (true); - - m_debugger.RunCommandInterpreter(handle_events, spawn_thread, options, num_errors, quit_requested); + if (m_option_data.m_batch) + options.SetStopOnCrash (true); + + m_debugger.RunCommandInterpreter(handle_events, + spawn_thread, + options, + num_errors, + quit_requested, + stopped_for_crash); m_debugger.SetAsync(old_async); } else @@ -1030,7 +1047,13 @@ Driver::MainLoop () // interpreter again in interactive mode and let the debugger // take ownership of stdin - if (!quit_requested) + bool go_interactive = true; + if (quit_requested) + go_interactive = false; + else if (m_option_data.m_batch && !stopped_for_crash) + go_interactive = false; + + if (go_interactive) { m_debugger.SetInputFileHandle (stdin, true); m_debugger.RunCommandInterpreter(handle_events, spawn_thread); diff --git a/lldb/tools/driver/Driver.h b/lldb/tools/driver/Driver.h index 8b6c6eebdd5..c4faac16b52 100644 --- a/lldb/tools/driver/Driver.h +++ b/lldb/tools/driver/Driver.h @@ -87,6 +87,7 @@ public: std::string m_process_name; lldb::pid_t m_process_pid; bool m_use_external_editor; // FIXME: When we have set/show variables we can remove this from here. + bool m_batch; typedef std::set<char> OptionSet; OptionSet m_seen_options; }; |