Author: Tatyana Krasnukha Date: 2021-02-08T15:09:09+03:00 New Revision: 36de94cf54efbad967a9a0fa41329a8b59bc35c4
URL: https://github.com/llvm/llvm-project/commit/36de94cf54efbad967a9a0fa41329a8b59bc35c4 DIFF: https://github.com/llvm/llvm-project/commit/36de94cf54efbad967a9a0fa41329a8b59bc35c4.diff LOG: Reland "[lldb] Make CommandInterpreter's execution context the same as debugger's one" Added: lldb/test/API/python_api/debugger/Makefile lldb/test/API/python_api/debugger/main.cpp Modified: lldb/include/lldb/Interpreter/CommandInterpreter.h lldb/source/API/SBCommandInterpreter.cpp lldb/source/Breakpoint/BreakpointOptions.cpp lldb/source/Commands/CommandObjectCommands.cpp lldb/source/Commands/CommandObjectExpression.cpp lldb/source/Commands/CommandObjectProcess.cpp lldb/source/Commands/CommandObjectRegexCommand.cpp lldb/source/Commands/CommandObjectSettings.cpp lldb/source/Commands/CommandObjectWatchpointCommand.cpp lldb/source/Core/IOHandlerCursesGUI.cpp lldb/source/Interpreter/CommandInterpreter.cpp lldb/source/Target/Target.cpp lldb/test/API/python_api/debugger/TestDebuggerAPI.py Removed: ################################################################################ diff --git a/lldb/include/lldb/Interpreter/CommandInterpreter.h b/lldb/include/lldb/Interpreter/CommandInterpreter.h index c4f9dd2fdb37..7f897bf20185 100644 --- a/lldb/include/lldb/Interpreter/CommandInterpreter.h +++ b/lldb/include/lldb/Interpreter/CommandInterpreter.h @@ -24,7 +24,9 @@ #include "lldb/Utility/StringList.h" #include "lldb/lldb-forward.h" #include "lldb/lldb-private.h" + #include <mutex> +#include <stack> namespace lldb_private { class CommandInterpreter; @@ -245,7 +247,7 @@ class CommandInterpreter : public Broadcaster, CommandInterpreter(Debugger &debugger, bool synchronous_execution); - ~CommandInterpreter() override; + ~CommandInterpreter() override = default; // These two functions fill out the Broadcaster interface: @@ -300,10 +302,11 @@ class CommandInterpreter : public Broadcaster, CommandReturnObject &result); bool HandleCommand(const char *command_line, LazyBool add_to_history, - CommandReturnObject &result, - ExecutionContext *override_context = nullptr, - bool repeat_on_empty_command = true, - bool no_context_switching = false); + const ExecutionContext &override_context, + CommandReturnObject &result); + + bool HandleCommand(const char *command_line, LazyBool add_to_history, + CommandReturnObject &result); bool WasInterrupted() const; @@ -312,9 +315,7 @@ class CommandInterpreter : public Broadcaster, /// \param[in] commands /// The list of commands to execute. /// \param[in,out] context - /// The execution context in which to run the commands. Can be nullptr in - /// which case the default - /// context will be used. + /// The execution context in which to run the commands. /// \param[in] options /// This object holds the options used to control when to stop, whether to /// execute commands, @@ -324,8 +325,13 @@ class CommandInterpreter : public Broadcaster, /// safely, /// and failed with some explanation if we aborted executing the commands /// at some point. - void HandleCommands(const StringList &commands, ExecutionContext *context, - CommandInterpreterRunOptions &options, + void HandleCommands(const StringList &commands, + const ExecutionContext &context, + const CommandInterpreterRunOptions &options, + CommandReturnObject &result); + + void HandleCommands(const StringList &commands, + const CommandInterpreterRunOptions &options, CommandReturnObject &result); /// Execute a list of commands from a file. @@ -333,9 +339,7 @@ class CommandInterpreter : public Broadcaster, /// \param[in] file /// The file from which to read in commands. /// \param[in,out] context - /// The execution context in which to run the commands. Can be nullptr in - /// which case the default - /// context will be used. + /// The execution context in which to run the commands. /// \param[in] options /// This object holds the options used to control when to stop, whether to /// execute commands, @@ -345,8 +349,12 @@ class CommandInterpreter : public Broadcaster, /// safely, /// and failed with some explanation if we aborted executing the commands /// at some point. - void HandleCommandsFromFile(FileSpec &file, ExecutionContext *context, - CommandInterpreterRunOptions &options, + void HandleCommandsFromFile(FileSpec &file, const ExecutionContext &context, + const CommandInterpreterRunOptions &options, + CommandReturnObject &result); + + void HandleCommandsFromFile(FileSpec &file, + const CommandInterpreterRunOptions &options, CommandReturnObject &result); CommandObject *GetCommandObjectForCommand(llvm::StringRef &command_line); @@ -391,12 +399,7 @@ class CommandInterpreter : public Broadcaster, Debugger &GetDebugger() { return m_debugger; } - ExecutionContext GetExecutionContext() { - const bool thread_and_frame_only_if_stopped = true; - return m_exe_ctx_ref.Lock(thread_and_frame_only_if_stopped); - } - - void UpdateExecutionContext(ExecutionContext *override_context); + ExecutionContext GetExecutionContext() const; lldb::PlatformSP GetPlatform(bool prefer_target_platform); @@ -581,6 +584,10 @@ class CommandInterpreter : public Broadcaster, StringList *descriptions = nullptr) const; private: + void OverrideExecutionContext(const ExecutionContext &override_context); + + void RestoreExecutionContext(); + Status PreprocessCommand(std::string &command); void SourceInitFile(FileSpec file, CommandReturnObject &result); @@ -619,8 +626,9 @@ class CommandInterpreter : public Broadcaster, Debugger &m_debugger; // The debugger session that this interpreter is // associated with - ExecutionContextRef m_exe_ctx_ref; // The current execution context to use - // when handling commands + // Execution contexts that were temporarily set by some of HandleCommand* + // overloads. + std::stack<ExecutionContext> m_overriden_exe_contexts; bool m_synchronous_execution; bool m_skip_lldbinit_files; bool m_skip_app_init_files; diff --git a/lldb/source/API/SBCommandInterpreter.cpp b/lldb/source/API/SBCommandInterpreter.cpp index 31e7da8323b8..d28bc411042c 100644 --- a/lldb/source/API/SBCommandInterpreter.cpp +++ b/lldb/source/API/SBCommandInterpreter.cpp @@ -171,27 +171,23 @@ lldb::ReturnStatus SBCommandInterpreter::HandleCommand( lldb::SBCommandReturnObject &, bool), command_line, override_context, result, 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 && IsValid()) { result.ref().SetInteractive(false); - m_opaque_ptr->HandleCommand(command_line, - add_to_history ? eLazyBoolYes : eLazyBoolNo, - result.ref(), ctx_ptr); + auto do_add_to_history = add_to_history ? eLazyBoolYes : eLazyBoolNo; + if (override_context.get()) + m_opaque_ptr->HandleCommand(command_line, do_add_to_history, + override_context.get()->Lock(true), + result.ref()); + else + m_opaque_ptr->HandleCommand(command_line, do_add_to_history, + result.ref()); } else { result->AppendError( "SBCommandInterpreter or the command line is not valid"); result->SetStatus(eReturnStatusFailed); } - return result.GetStatus(); } @@ -219,15 +215,14 @@ void SBCommandInterpreter::HandleCommandsFromFile( } 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()); + if (override_context.get()) + m_opaque_ptr->HandleCommandsFromFile(tmp_spec, + override_context.get()->Lock(true), + options.ref(), + result.ref()); + + else + m_opaque_ptr->HandleCommandsFromFile(tmp_spec, options.ref(), result.ref()); } int SBCommandInterpreter::HandleCompletion( diff --git a/lldb/source/Breakpoint/BreakpointOptions.cpp b/lldb/source/Breakpoint/BreakpointOptions.cpp index f6bb7633d0a9..2fdb53e52723 100644 --- a/lldb/source/Breakpoint/BreakpointOptions.cpp +++ b/lldb/source/Breakpoint/BreakpointOptions.cpp @@ -649,7 +649,7 @@ bool BreakpointOptions::BreakpointOptionsCallbackFunction( options.SetPrintErrors(true); options.SetAddToHistory(false); - debugger.GetCommandInterpreter().HandleCommands(commands, &exe_ctx, + debugger.GetCommandInterpreter().HandleCommands(commands, exe_ctx, options, result); result.GetImmediateOutputStream()->Flush(); result.GetImmediateErrorStream()->Flush(); diff --git a/lldb/source/Commands/CommandObjectCommands.cpp b/lldb/source/Commands/CommandObjectCommands.cpp index 3b3cdde6ab9a..74b16a613ffa 100644 --- a/lldb/source/Commands/CommandObjectCommands.cpp +++ b/lldb/source/Commands/CommandObjectCommands.cpp @@ -134,15 +134,12 @@ class CommandObjectCommandsSource : public CommandObjectParsed { FileSpec cmd_file(command[0].ref()); FileSystem::Instance().Resolve(cmd_file); - ExecutionContext *exe_ctx = nullptr; // Just use the default context. + CommandInterpreterRunOptions options; // If any options were set, then use them if (m_options.m_stop_on_error.OptionWasSet() || m_options.m_silent_run.OptionWasSet() || m_options.m_stop_on_continue.OptionWasSet()) { - // Use user set settings - CommandInterpreterRunOptions options; - if (m_options.m_stop_on_continue.OptionWasSet()) options.SetStopOnContinue( m_options.m_stop_on_continue.GetCurrentValue()); @@ -159,14 +156,9 @@ class CommandObjectCommandsSource : public CommandObjectParsed { options.SetEchoCommands(m_interpreter.GetEchoCommands()); options.SetEchoCommentCommands(m_interpreter.GetEchoCommentCommands()); } - - m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options, result); - } else { - // No options were set, inherit any settings from nested "command source" - // commands, or set to sane default settings... - CommandInterpreterRunOptions options; - m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options, result); } + + m_interpreter.HandleCommandsFromFile(cmd_file, options, result); return result.Succeeded(); } diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp index 58eaa3f973cb..c7866f966569 100644 --- a/lldb/source/Commands/CommandObjectExpression.cpp +++ b/lldb/source/Commands/CommandObjectExpression.cpp @@ -292,18 +292,12 @@ void CommandObjectExpression::HandleCompletion(CompletionRequest &request) { options.SetAutoApplyFixIts(false); options.SetGenerateDebugInfo(false); - // We need a valid execution context with a frame pointer for this - // completion, so if we don't have one we should try to make a valid - // execution context. - if (m_interpreter.GetExecutionContext().GetFramePtr() == nullptr) - m_interpreter.UpdateExecutionContext(nullptr); - - // This didn't work, so let's get out before we start doing things that - // expect a valid frame pointer. - if (m_interpreter.GetExecutionContext().GetFramePtr() == nullptr) + ExecutionContext exe_ctx(m_interpreter.GetExecutionContext()); + + // Get out before we start doing things that expect a valid frame pointer. + if (exe_ctx.GetFramePtr() == nullptr) return; - ExecutionContext exe_ctx(m_interpreter.GetExecutionContext()); Target *exe_target = exe_ctx.GetTargetPtr(); Target &target = exe_target ? *exe_target : GetDummyTarget(); diff --git a/lldb/source/Commands/CommandObjectProcess.cpp b/lldb/source/Commands/CommandObjectProcess.cpp index 35835f638557..c21c499536f2 100644 --- a/lldb/source/Commands/CommandObjectProcess.cpp +++ b/lldb/source/Commands/CommandObjectProcess.cpp @@ -381,7 +381,6 @@ class CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach { return false; } - m_interpreter.UpdateExecutionContext(nullptr); StreamString stream; const auto error = target->Attach(m_options.attach_info, &stream); if (error.Success()) { diff --git a/lldb/source/Commands/CommandObjectRegexCommand.cpp b/lldb/source/Commands/CommandObjectRegexCommand.cpp index 1bf29d3c047b..dcd05a12cd6a 100644 --- a/lldb/source/Commands/CommandObjectRegexCommand.cpp +++ b/lldb/source/Commands/CommandObjectRegexCommand.cpp @@ -53,8 +53,8 @@ bool CommandObjectRegexCommand::DoExecute(llvm::StringRef command, // Pass in true for "no context switching". The command that called us // should have set up the context appropriately, we shouldn't have to // redo that. - return m_interpreter.HandleCommand( - new_command.c_str(), eLazyBoolCalculate, result, nullptr, true, true); + return m_interpreter.HandleCommand(new_command.c_str(), + eLazyBoolCalculate, result); } } result.SetStatus(eReturnStatusFailed); diff --git a/lldb/source/Commands/CommandObjectSettings.cpp b/lldb/source/Commands/CommandObjectSettings.cpp index 87e0352636e1..d869377c578c 100644 --- a/lldb/source/Commands/CommandObjectSettings.cpp +++ b/lldb/source/Commands/CommandObjectSettings.cpp @@ -469,14 +469,13 @@ class CommandObjectSettingsRead : public CommandObjectParsed { bool DoExecute(Args &command, CommandReturnObject &result) override { FileSpec file(m_options.m_filename); FileSystem::Instance().Resolve(file); - ExecutionContext clean_ctx; CommandInterpreterRunOptions options; options.SetAddToHistory(false); options.SetEchoCommands(false); options.SetPrintResults(true); options.SetPrintErrors(true); options.SetStopOnError(false); - m_interpreter.HandleCommandsFromFile(file, &clean_ctx, options, result); + m_interpreter.HandleCommandsFromFile(file, options, result); return result.Succeeded(); } diff --git a/lldb/source/Commands/CommandObjectWatchpointCommand.cpp b/lldb/source/Commands/CommandObjectWatchpointCommand.cpp index fe3052a775a2..3df17a0c17f3 100644 --- a/lldb/source/Commands/CommandObjectWatchpointCommand.cpp +++ b/lldb/source/Commands/CommandObjectWatchpointCommand.cpp @@ -301,7 +301,7 @@ are no syntax errors may indicate that a function was declared but never called. options.SetPrintErrors(true); options.SetAddToHistory(false); - debugger.GetCommandInterpreter().HandleCommands(commands, &exe_ctx, + debugger.GetCommandInterpreter().HandleCommands(commands, exe_ctx, options, result); result.GetImmediateOutputStream()->Flush(); result.GetImmediateErrorStream()->Flush(); diff --git a/lldb/source/Core/IOHandlerCursesGUI.cpp b/lldb/source/Core/IOHandlerCursesGUI.cpp index 19066e6be623..af9fb29bd6bb 100644 --- a/lldb/source/Core/IOHandlerCursesGUI.cpp +++ b/lldb/source/Core/IOHandlerCursesGUI.cpp @@ -1390,8 +1390,6 @@ class Application { ConstString broadcaster_class( broadcaster->GetBroadcasterClass()); if (broadcaster_class == broadcaster_class_process) { - debugger.GetCommandInterpreter().UpdateExecutionContext( - nullptr); m_update_screen = true; continue; // Don't get any key, just update our view } @@ -1403,7 +1401,6 @@ class Application { HandleCharResult key_result = m_window_sp->HandleChar(ch); switch (key_result) { case eKeyHandled: - debugger.GetCommandInterpreter().UpdateExecutionContext(nullptr); m_update_screen = true; break; case eKeyNotHandled: diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp index fb503fe0afb0..0b25abc9cdea 100644 --- a/lldb/source/Interpreter/CommandInterpreter.cpp +++ b/lldb/source/Interpreter/CommandInterpreter.cpp @@ -76,6 +76,7 @@ #include "lldb/Target/UnixSignals.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/FormatAdapters.h" #include "llvm/Support/Path.h" @@ -1631,12 +1632,18 @@ Status CommandInterpreter::PreprocessCommand(std::string &command) { bool CommandInterpreter::HandleCommand(const char *command_line, LazyBool lazy_add_to_history, - CommandReturnObject &result, - ExecutionContext *override_context, - bool repeat_on_empty_command, - bool no_context_switching) + const ExecutionContext &override_context, + CommandReturnObject &result) { + + OverrideExecutionContext(override_context); + bool status = HandleCommand(command_line, lazy_add_to_history, result); + RestoreExecutionContext(); + return status; +} -{ +bool CommandInterpreter::HandleCommand(const char *command_line, + LazyBool lazy_add_to_history, + CommandReturnObject &result) { std::string command_string(command_line); std::string original_command_string(command_line); @@ -1648,9 +1655,6 @@ bool CommandInterpreter::HandleCommand(const char *command_line, LLDB_LOGF(log, "Processing command: %s", command_line); LLDB_SCOPED_TIMERF("Processing command: %s.", command_line); - if (!no_context_switching) - UpdateExecutionContext(override_context); - if (WasInterrupted()) { result.AppendError("interrupted"); result.SetStatus(eReturnStatusFailed); @@ -1696,26 +1700,22 @@ bool CommandInterpreter::HandleCommand(const char *command_line, } if (empty_command) { - if (repeat_on_empty_command) { - if (m_command_history.IsEmpty()) { - result.AppendError("empty command"); - result.SetStatus(eReturnStatusFailed); - return false; - } else { - command_line = m_repeat_command.c_str(); - command_string = command_line; - original_command_string = command_line; - if (m_repeat_command.empty()) { - result.AppendError("No auto repeat."); - result.SetStatus(eReturnStatusFailed); - return false; - } - } - add_to_history = false; - } else { - result.SetStatus(eReturnStatusSuccessFinishNoResult); - return true; + if (m_command_history.IsEmpty()) { + result.AppendError("empty command"); + result.SetStatus(eReturnStatusFailed); + return false; + } + + command_line = m_repeat_command.c_str(); + command_string = command_line; + original_command_string = command_line; + if (m_repeat_command.empty()) { + result.AppendError("No auto repeat."); + result.SetStatus(eReturnStatusFailed); + return false; } + + add_to_history = false; } else if (comment_command) { result.SetStatus(eReturnStatusSuccessFinishNoResult); return true; @@ -1852,8 +1852,6 @@ void CommandInterpreter::HandleCompletionMatches(CompletionRequest &request) { void CommandInterpreter::HandleCompletion(CompletionRequest &request) { - UpdateExecutionContext(nullptr); - // Don't complete comments, and if the line we are completing is just the // history repeat character, substitute the appropriate history line. llvm::StringRef first_arg = request.GetParsedLine().GetArgumentAtIndex(0); @@ -1885,8 +1883,6 @@ CommandInterpreter::GetAutoSuggestionForCommand(llvm::StringRef line) { return llvm::None; } -CommandInterpreter::~CommandInterpreter() {} - void CommandInterpreter::UpdatePrompt(llvm::StringRef new_prompt) { EventSP prompt_change_event_sp( new Event(eBroadcastBitResetPrompt, new EventDataBytes(new_prompt))); @@ -2128,13 +2124,12 @@ void CommandInterpreter::SourceInitFile(FileSpec file, // broadcasting of the commands back to any appropriate listener (see // CommandObjectSource::Execute for more details). const bool saved_batch = SetBatchCommandMode(true); - ExecutionContext *ctx = nullptr; CommandInterpreterRunOptions options; options.SetSilent(true); options.SetPrintErrors(true); options.SetStopOnError(false); options.SetStopOnContinue(true); - HandleCommandsFromFile(file, ctx, options, result); + HandleCommandsFromFile(file, options, result); SetBatchCommandMode(saved_batch); } @@ -2225,7 +2220,8 @@ PlatformSP CommandInterpreter::GetPlatform(bool prefer_target_platform) { } bool CommandInterpreter::DidProcessStopAbnormally() const { - TargetSP target_sp = m_debugger.GetTargetList().GetSelectedTarget(); + auto exe_ctx = GetExecutionContext(); + TargetSP target_sp = exe_ctx.GetTargetSP(); if (!target_sp) return false; @@ -2263,9 +2259,19 @@ bool CommandInterpreter::DidProcessStopAbnormally() const { return false; } +void +CommandInterpreter::HandleCommands(const StringList &commands, + const ExecutionContext &override_context, + const CommandInterpreterRunOptions &options, + CommandReturnObject &result) { + + OverrideExecutionContext(override_context); + HandleCommands(commands, options, result); + RestoreExecutionContext(); +} + void CommandInterpreter::HandleCommands(const StringList &commands, - ExecutionContext *override_context, - CommandInterpreterRunOptions &options, + const CommandInterpreterRunOptions &options, CommandReturnObject &result) { size_t num_lines = commands.GetSize(); @@ -2275,13 +2281,6 @@ void CommandInterpreter::HandleCommands(const StringList &commands, bool old_async_execution = m_debugger.GetAsyncExecution(); - // If we've been given an execution context, set it at the start, but don't - // keep resetting it or we will cause series of commands that change the - // context, then do an operation that relies on that context to fail. - - if (override_context != nullptr) - UpdateExecutionContext(override_context); - if (!options.GetStopOnContinue()) { m_debugger.SetAsyncExecution(false); } @@ -2300,19 +2299,12 @@ void CommandInterpreter::HandleCommands(const StringList &commands, CommandReturnObject tmp_result(m_debugger.GetUseColor()); tmp_result.SetInteractive(result.GetInteractive()); - // If override_context is not NULL, pass no_context_switching = true for - // HandleCommand() since we updated our context already. - // We might call into a regex or alias command, in which case the // add_to_history will get lost. This m_command_source_depth dingus is the // way we turn off adding to the history in that case, so set it up here. if (!options.GetAddToHistory()) m_command_source_depth++; - bool success = - HandleCommand(cmd, options.m_add_to_history, tmp_result, - nullptr, /* override_context */ - true, /* repeat_on_empty_command */ - override_context != nullptr /* no_context_switching */); + bool success = HandleCommand(cmd, options.m_add_to_history, tmp_result); if (!options.GetAddToHistory()) m_command_source_depth--; @@ -2413,8 +2405,15 @@ enum { }; void CommandInterpreter::HandleCommandsFromFile( - FileSpec &cmd_file, ExecutionContext *context, - CommandInterpreterRunOptions &options, CommandReturnObject &result) { + FileSpec &cmd_file, const ExecutionContext &context, + const CommandInterpreterRunOptions &options, CommandReturnObject &result) { + OverrideExecutionContext(context); + HandleCommandsFromFile(cmd_file, options, result); + RestoreExecutionContext(); +} + +void CommandInterpreter::HandleCommandsFromFile(FileSpec &cmd_file, + const CommandInterpreterRunOptions &options, CommandReturnObject &result) { if (!FileSystem::Instance().Exists(cmd_file)) { result.AppendErrorWithFormat( "Error reading commands from file %s - file not found.\n", @@ -2715,23 +2714,24 @@ void CommandInterpreter::FindCommandsForApropos(llvm::StringRef search_word, m_alias_dict); } -void CommandInterpreter::UpdateExecutionContext( - ExecutionContext *override_context) { - if (override_context != nullptr) { - m_exe_ctx_ref = *override_context; - } else { - const bool adopt_selected = true; - m_exe_ctx_ref.SetTargetPtr(m_debugger.GetSelectedTarget().get(), - adopt_selected); - } +ExecutionContext CommandInterpreter::GetExecutionContext() const { + return !m_overriden_exe_contexts.empty() + ? m_overriden_exe_contexts.top() + : m_debugger.GetSelectedExecutionContext(); } -void CommandInterpreter::GetProcessOutput() { - TargetSP target_sp(m_debugger.GetTargetList().GetSelectedTarget()); - if (!target_sp) - return; +void CommandInterpreter::OverrideExecutionContext( + const ExecutionContext &override_context) { + m_overriden_exe_contexts.push(override_context); +} + +void CommandInterpreter::RestoreExecutionContext() { + if (!m_overriden_exe_contexts.empty()) + m_overriden_exe_contexts.pop(); +} - if (ProcessSP process_sp = target_sp->GetProcessSP()) +void CommandInterpreter::GetProcessOutput() { + if (ProcessSP process_sp = GetExecutionContext().GetProcessSP()) m_debugger.FlushProcessOutput(*process_sp, /*flush_stdout*/ true, /*flush_stderr*/ true); } @@ -2831,6 +2831,9 @@ void CommandInterpreter::IOHandlerInputComplete(IOHandler &io_handler, StartHandlingCommand(); + OverrideExecutionContext(m_debugger.GetSelectedExecutionContext()); + llvm::make_scope_exit([this]() { RestoreExecutionContext(); }); + lldb_private::CommandReturnObject result(m_debugger.GetUseColor()); HandleCommand(line.c_str(), eLazyBoolCalculate, result); diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index 736864e021bb..da47d8eeac62 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -3349,7 +3349,7 @@ Target::StopHookCommandLine::HandleStop(ExecutionContext &exc_ctx, // Force Async: bool old_async = debugger.GetAsyncExecution(); debugger.SetAsyncExecution(true); - debugger.GetCommandInterpreter().HandleCommands(GetCommands(), &exc_ctx, + debugger.GetCommandInterpreter().HandleCommands(GetCommands(), exc_ctx, options, result); debugger.SetAsyncExecution(old_async); lldb::ReturnStatus status = result.GetStatus(); diff --git a/lldb/test/API/python_api/debugger/Makefile b/lldb/test/API/python_api/debugger/Makefile new file mode 100644 index 000000000000..bfad5f33e867 --- /dev/null +++ b/lldb/test/API/python_api/debugger/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/lldb/test/API/python_api/debugger/TestDebuggerAPI.py b/lldb/test/API/python_api/debugger/TestDebuggerAPI.py index 32202acbe072..15597146c5b4 100644 --- a/lldb/test/API/python_api/debugger/TestDebuggerAPI.py +++ b/lldb/test/API/python_api/debugger/TestDebuggerAPI.py @@ -43,3 +43,54 @@ def test_debugger_delete_invalid_target(self): target = lldb.SBTarget() self.assertFalse(target.IsValid()) self.dbg.DeleteTarget(target) + + def test_debugger_internal_variables(self): + """Ensure that SBDebugger reachs the same instance of properties + regardless CommandInterpreter's context initialization""" + self.build() + exe = self.getBuildArtifact("a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + property_name = "target.process.memory-cache-line-size" + + def get_cache_line_size(): + value_list = lldb.SBStringList() + value_list = self.dbg.GetInternalVariableValue(property_name, + self.dbg.GetInstanceName()) + + self.assertEqual(value_list.GetSize(), 1) + try: + return int(value_list.GetStringAtIndex(0)) + except ValueError as error: + self.fail("Value is not a number: " + error) + + # Get global property value while there are no processes. + global_cache_line_size = get_cache_line_size() + + # Run a process via SB interface. CommandInterpreter's execution context + # remains empty. + error = lldb.SBError() + launch_info = lldb.SBLaunchInfo(None) + launch_info.SetLaunchFlags(lldb.eLaunchFlagStopAtEntry) + process = target.Launch(launch_info, error) + self.assertTrue(process, PROCESS_IS_VALID) + + # This should change the value of a process's local property. + new_cache_line_size = global_cache_line_size + 512 + error = self.dbg.SetInternalVariable(property_name, + str(new_cache_line_size), + self.dbg.GetInstanceName()) + self.assertTrue(error.Success(), + property_name + " value was changed successfully") + + # Check that it was set actually. + self.assertEqual(get_cache_line_size(), new_cache_line_size) + + # Run any command to initialize CommandInterpreter's execution context. + self.runCmd("target list") + + # Test the local property again, is it set to new_cache_line_size? + self.assertEqual(get_cache_line_size(), new_cache_line_size) diff --git a/lldb/test/API/python_api/debugger/main.cpp b/lldb/test/API/python_api/debugger/main.cpp new file mode 100644 index 000000000000..4b4ca68ab87d --- /dev/null +++ b/lldb/test/API/python_api/debugger/main.cpp @@ -0,0 +1,9 @@ +// This simple program is to test the lldb Python API SBDebugger. + +int func(int val) { + return val - 1; +} + +int main (int argc, char const *argv[]) { + return func(argc); +} _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits