[Lldb-commits] [lldb] [lldb] Fix CommandInterpreter::GetExecutionContext (PR #199922)

Pavel Labath via lldb-commits lldb-commits at lists.llvm.org
Wed May 27 03:36:40 PDT 2026


https://github.com/labath created https://github.com/llvm/llvm-project/pull/199922

Following up Jonas's comment in #198949, this patch changes the function to not ignore the override context in the adopt_dummy_target=false case.

However, I don't implement Jonas's suggestion exactly either. Instead of "bypassing" the override context if it contains the dummy target, this patch returns an empty context instead. I think this makes more sense, as the intention of the user may very well have been to run the command in the context of the dummy target. The test suite has no opinion either way, but this is sufficient to fix the regression that #198949 was trying to fix.

I also delete the test added in that PR, as the tests in this patch cover more cases, and the test has the potential of interfering with another process/test running on the same system.

>From f2286e0917327f5b6f97475f67c349d629cfb6ab Mon Sep 17 00:00:00 2001
From: Pavel Labath <pavel at labath.sk>
Date: Tue, 26 May 2026 17:30:42 +0000
Subject: [PATCH] [lldb] Fix CommandInterpreter::GetExecutionContext

Following up Jonas's comment in #198949, this patch changes the function
to not ignore the override context in the adopt_dummy_target=false case.

However, I don't implement Jonas's suggestion exactly either. Instead of
"bypassing" the override context if it contains the dummy target, this
patch returns an empty context instead. I think this makes more sense,
as the intention of the user may very well have been to run the command
in the context of the dummy target. The test suite has no opinion either
way, but this is sufficient to fix the regression that #198949 was
trying to fix.

I also delete the test added in that PR, as the tests in this patch
cover more cases, and the test has the potential of interfering with
another process/test running on the same system.
---
 .../source/Interpreter/CommandInterpreter.cpp | 12 +++++--
 .../interpreter/TestCommandInterpreterAPI.py  | 32 +++++++++++++++++++
 .../Shell/Commands/process-attach-dummy.test  | 22 -------------
 3 files changed, 41 insertions(+), 25 deletions(-)
 delete mode 100644 lldb/test/Shell/Commands/process-attach-dummy.test

diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp
index 64e2da1f0388b..0c5456c2c3b57 100644
--- a/lldb/source/Interpreter/CommandInterpreter.cpp
+++ b/lldb/source/Interpreter/CommandInterpreter.cpp
@@ -3284,9 +3284,15 @@ void CommandInterpreter::FindCommandsForApropos(llvm::StringRef search_word,
 
 ExecutionContext
 CommandInterpreter::GetExecutionContext(bool adopt_dummy_target) const {
-  return (m_overriden_exe_contexts.empty() || !adopt_dummy_target)
-             ? m_debugger.GetSelectedExecutionContext(adopt_dummy_target)
-             : m_overriden_exe_contexts.top();
+  if (m_overriden_exe_contexts.empty())
+    return m_debugger.GetSelectedExecutionContext(adopt_dummy_target);
+
+  ExecutionContext candidate_context = m_overriden_exe_contexts.top();
+  Target *candidate_target = candidate_context.GetTargetPtr();
+  if (!adopt_dummy_target && candidate_target &&
+      candidate_target->IsDummyTarget())
+    return ExecutionContext();
+  return candidate_context;
 }
 
 void CommandInterpreter::OverrideExecutionContext(
diff --git a/lldb/test/API/python_api/interpreter/TestCommandInterpreterAPI.py b/lldb/test/API/python_api/interpreter/TestCommandInterpreterAPI.py
index cb25df3b11425..9ee31885e36b8 100644
--- a/lldb/test/API/python_api/interpreter/TestCommandInterpreterAPI.py
+++ b/lldb/test/API/python_api/interpreter/TestCommandInterpreterAPI.py
@@ -292,3 +292,35 @@ def test_get_transcript_returns_copy(self):
             .GetStringValue(100),
             "version",
         )
+
+    def test_handle_command_with_execution_context_override(self):
+        """Test that HandleCommand with an override context works correctly and does not bypass non-dummy targets."""
+        self.build()
+        target, process, thread, _ = lldbutil.run_to_line_breakpoint(self, lldb.SBFileSpec("main.c"), self.line)
+        frame = thread.GetSelectedFrame()
+        self.assertTrue(frame.IsValid())
+        exe_ctx = lldb.SBExecutionContext(frame)
+
+        # With an dummy override target, the command should fail -- it should not use valid target selected in the debugger.
+        exe_ctx = lldb.SBExecutionContext(self.dbg.GetDummyTarget())
+        res = lldb.SBCommandReturnObject()
+        self.ci.HandleCommand("frame variable", exe_ctx, res)
+        self.assertFalse(res.Succeeded())
+        self.assertIn("invalid target", res.GetError())
+
+        # The same goes for a target which is not running.
+        exe = self.getBuildArtifact("a.out")
+        target2 = self.dbg.CreateTarget(exe)
+        self.assertTrue(target2.IsValid())
+        exe_ctx = lldb.SBExecutionContext(self.dbg.GetDummyTarget())
+        res = lldb.SBCommandReturnObject()
+        self.ci.HandleCommand("frame variable", exe_ctx, res)
+        self.assertFalse(res.Succeeded())
+        self.assertIn("invalid target", res.GetError())
+
+        # Now try vice-versa. The command should successfully use the target from the override context.
+        self.dbg.SetSelectedTarget(target)
+        exe_ctx = lldb.SBExecutionContext(frame)
+        res = lldb.SBCommandReturnObject()
+        self.ci.HandleCommand("frame variable", exe_ctx, res)
+        self.assertTrue(res.Succeeded(), "HandleCommand with override context succeeded")
diff --git a/lldb/test/Shell/Commands/process-attach-dummy.test b/lldb/test/Shell/Commands/process-attach-dummy.test
deleted file mode 100644
index 6ae5683f5c81f..0000000000000
--- a/lldb/test/Shell/Commands/process-attach-dummy.test
+++ /dev/null
@@ -1,22 +0,0 @@
-# Test that process attach correctly creates a real target instead of attaching
-# to the dummy target when executed inside a sourced script or command session.
-#
-# Sourced scripts run by the IOHandler override the execution context to contain
-# the dummy target by default (as a fallback target). When process attach runs,
-# it expects to bypass the dummy target (adopt_dummy_target = false).
-# CommandInterpreter::GetExecutionContext must respect this flag and clear the
-# dummy target from the overridden context, allowing process attach to create
-# and select a new real target.
-#
-# If the bug is present, process attach attaches directly to the dummy target,
-# leaving the main target list empty (target list outputs "No targets.").
-# If the bug is fixed, it successfully creates "target #0: <none>".
-
-# REQUIRES: python
-
-# RUN: %lldb -s %s 2>&1 | FileCheck %s
-
-script lldb.debugger.GetCommandInterpreter().HandleCommand("process attach -p 99999", lldb.SBCommandReturnObject())
-
-target list
-# CHECK: target #0: <none>



More information about the lldb-commits mailing list