[Lldb-commits] [lldb] 36de94c - Reland "[lldb] Make CommandInterpreter's execution context the same as debugger's one"
Tatyana Krasnukha via lldb-commits
lldb-commits at lists.llvm.org
Mon Feb 8 04:13:04 PST 2021
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);
+}
More information about the lldb-commits
mailing list