[llvm] [Dexter] Add DexStepFunction and DexContinue skeletons (PR #152720)

Orlando Cazalet-Hyams via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 27 09:06:53 PDT 2025


https://github.com/OCHyams updated https://github.com/llvm/llvm-project/pull/152720

>From f20b541939ca2f543ffa6917a142b2b640fc48f2 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Thu, 7 Aug 2025 15:38:28 +0100
Subject: [PATCH 1/5] [Dexter] Add DexStepFunction and DexContinue skeletons

---
 .../debuginfo-tests/dexter/Commands.md        | 44 ++++++++++++++++++-
 .../dex/command/commands/DexContinue.py       | 44 +++++++++++++++++++
 .../dex/command/commands/DexStepFunction.py   | 38 ++++++++++++++++
 3 files changed, 125 insertions(+), 1 deletion(-)
 create mode 100644 cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexContinue.py
 create mode 100644 cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexStepFunction.py

diff --git a/cross-project-tests/debuginfo-tests/dexter/Commands.md b/cross-project-tests/debuginfo-tests/dexter/Commands.md
index a98261a500094..9ef2d7199d24d 100644
--- a/cross-project-tests/debuginfo-tests/dexter/Commands.md
+++ b/cross-project-tests/debuginfo-tests/dexter/Commands.md
@@ -13,7 +13,8 @@
 * [DexDeclareFile](Commands.md#DexDeclareFile)
 * [DexFinishTest](Commands.md#DexFinishTest)
 * [DexCommandLine](Commands.md#DexCommandLine)
-
+* [DexStepFunction](Commands.md#DexStepFunction)
+* [DexContinue](Commands.md#DexContinue)
 ---
 ## DexExpectProgramState
     DexExpectProgramState(state [,**times])
@@ -377,3 +378,44 @@ line this command is found on.
 
 ### Heuristic
 [Deprecated]
+
+
+---
+## DexStepFunction
+    DexStepFunction(function_name[, **hit_count=0])
+
+    Arg list:
+        function_name (str): function to step through.
+        hit_count (int): If provided, limit the number of times the command
+                         triggers.
+
+### Description
+NOTE: Only supported for DAP based debuggers.
+
+This command controls stepping behaviour: Tell dexter to set a function
+breakpoint and step through the function after hitting it. Composes well with
+itself (you can may a callstack with multiple targets to step through) and
+`DexContinue`.
+
+---
+## DexContinue
+    DexContinue(*[expr, *values], **from_line[, **to_line, **hit_count])
+
+    Arg list:
+        function_name (str): function to step through.
+        hit_count (int): If provided, limit the number of times the command
+                         triggers.
+
+### Description
+NOTE: Only supported for DAP based debuggers.
+
+This command controls stepping behaviour: Tell dexter to set a breakpoint on
+`from_line`. When it is hit and optionally '(expr) == (values[n])' is true,
+optionally set a breakpoint on `to_line`. Then 'continue' (tell the debugger to
+run freely until a breakpoint is hit). Composed with `DexStepFunction` this
+lets you avoid stepping over certain regions (many loop iterations, for
+example). Continue-ing off the end of a `DexStepFunction` is well defined;
+stepping will resume in `DexStepFunction` targets deeper in the callstack.
+
+FIXME: hit_count should probably be inverted, like `DexLimitSteps`, to trigger
+AFTER that many hits?
diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexContinue.py b/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexContinue.py
new file mode 100644
index 0000000000000..6b52cecd241c4
--- /dev/null
+++ b/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexContinue.py
@@ -0,0 +1,44 @@
+# DExTer : Debugging Experience Tester
+# ~~~~~~   ~         ~~         ~   ~~
+#
+# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+# See https://llvm.org/LICENSE.txt for license information.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+"""A Command that tells dexter to set a breakpoint which, after hitting,
+signals that the debugger shuold 'continue' until another is hit. Continuing
+out of a function being stepped through with DexStepFunction is well defined:
+stepping will resume in other functions tracked further down the stacktrace.
+
+NOTE: Only supported for DAP based debuggers.
+"""
+
+from dex.command.CommandBase import CommandBase
+
+
+class DexContinue(CommandBase):
+    def __init__(self, *args, **kwargs):
+        if len(args) == 0:
+            self.expression = None
+            self.values = []
+        elif len(args) == 1:
+            raise TypeError("expected 0 or at least 2 positional arguments")
+        else:
+            self.expression = args[0]
+            self.values = [str(arg) for arg in args[1:]]
+        self.from_line = kwargs.pop("from_line", 1)
+        self.to_line = kwargs.pop("to_line", 999999)
+        self.hit_count = kwargs.pop("hit_count", None)
+        if kwargs:
+            raise TypeError("unexpected named args: {}".format(", ".join(kwargs)))
+        super(DexContinue, self).__init__()
+
+    def eval(self):
+        raise NotImplementedError("DexContinue commands cannot be evaled.")
+
+    @staticmethod
+    def get_name():
+        return __class__.__name__
+
+    @staticmethod
+    def get_subcommands() -> dict:
+        return None
diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexStepFunction.py b/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexStepFunction.py
new file mode 100644
index 0000000000000..eb8eeeb51e595
--- /dev/null
+++ b/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexStepFunction.py
@@ -0,0 +1,38 @@
+# DExTer : Debugging Experience Tester
+# ~~~~~~   ~         ~~         ~   ~~
+#
+# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+# See https://llvm.org/LICENSE.txt for license information.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+"""A Command that tells dexter to set a function breakpoint and step through
+the function after hitting it.
+
+NOTE: Only supported for DAP based debuggers.
+"""
+
+from dex.command.CommandBase import CommandBase
+
+
+class DexStepFunction(CommandBase):
+    def __init__(self, *args, **kwargs):
+        if len(args) < 1:
+            raise TypeError("expected 1 positional argument")
+        self.expression = str(args[0]) # Function name.
+        self.hit_count = kwargs.pop("hit_count", None)
+        if kwargs:
+            raise TypeError(f"unexpected named args: {', '.join(kwargs)}")
+        super(DexStepFunction, self).__init__()
+
+    def eval(self):
+        raise NotImplementedError("DexStepFunction commands cannot be evaled.")
+
+    def get_function(self):
+        return self.expression
+
+    @staticmethod
+    def get_name():
+        return __class__.__name__
+
+    @staticmethod
+    def get_subcommands() -> dict:
+        return None

>From fff10777b0c7bd0670aef92e613d6fa8947b5f8f Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Tue, 12 Aug 2025 11:41:49 +0100
Subject: [PATCH 2/5] address comments

---
 .../debuginfo-tests/dexter/Commands.md          |  4 ++--
 .../dexter/dex/command/commands/DexContinue.py  | 17 ++++++++++++++---
 .../dex/command/commands/DexStepFunction.py     |  2 +-
 3 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/cross-project-tests/debuginfo-tests/dexter/Commands.md b/cross-project-tests/debuginfo-tests/dexter/Commands.md
index 9ef2d7199d24d..afec3e6bbd002 100644
--- a/cross-project-tests/debuginfo-tests/dexter/Commands.md
+++ b/cross-project-tests/debuginfo-tests/dexter/Commands.md
@@ -390,7 +390,7 @@ line this command is found on.
                          triggers.
 
 ### Description
-NOTE: Only supported for DAP based debuggers.
+NOTE: Only supported for DAP-based debuggers.
 
 This command controls stepping behaviour: Tell dexter to set a function
 breakpoint and step through the function after hitting it. Composes well with
@@ -407,7 +407,7 @@ itself (you can may a callstack with multiple targets to step through) and
                          triggers.
 
 ### Description
-NOTE: Only supported for DAP based debuggers.
+NOTE: Only supported for DAP-based debuggers.
 
 This command controls stepping behaviour: Tell dexter to set a breakpoint on
 `from_line`. When it is hit and optionally '(expr) == (values[n])' is true,
diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexContinue.py b/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexContinue.py
index 6b52cecd241c4..17e481a585e5e 100644
--- a/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexContinue.py
+++ b/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexContinue.py
@@ -5,11 +5,11 @@
 # See https://llvm.org/LICENSE.txt for license information.
 # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 """A Command that tells dexter to set a breakpoint which, after hitting,
-signals that the debugger shuold 'continue' until another is hit. Continuing
+signals that the debugger should 'continue' until another is hit. Continuing
 out of a function being stepped through with DexStepFunction is well defined:
 stepping will resume in other functions tracked further down the stacktrace.
 
-NOTE: Only supported for DAP based debuggers.
+NOTE: Only supported for DAP-based debuggers.
 """
 
 from dex.command.CommandBase import CommandBase
@@ -17,6 +17,9 @@
 
 class DexContinue(CommandBase):
     def __init__(self, *args, **kwargs):
+        # DexContinue(*[expr, *values], **from_line[, **to_line, **hit_count])
+
+        # Optional positional args: expr, values.
         if len(args) == 0:
             self.expression = None
             self.values = []
@@ -25,9 +28,17 @@ def __init__(self, *args, **kwargs):
         else:
             self.expression = args[0]
             self.values = [str(arg) for arg in args[1:]]
-        self.from_line = kwargs.pop("from_line", 1)
+
+        # Required keyword arg: from_line.
+        try:
+            self.from_line = kwargs.pop("from_line")
+        except:
+            raise TypeError("Missing from_line argument")
+
+        # Optional conditional args: to_line, hit_count.
         self.to_line = kwargs.pop("to_line", 999999)
         self.hit_count = kwargs.pop("hit_count", None)
+
         if kwargs:
             raise TypeError("unexpected named args: {}".format(", ".join(kwargs)))
         super(DexContinue, self).__init__()
diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexStepFunction.py b/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexStepFunction.py
index eb8eeeb51e595..44dd114f155af 100644
--- a/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexStepFunction.py
+++ b/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexStepFunction.py
@@ -7,7 +7,7 @@
 """A Command that tells dexter to set a function breakpoint and step through
 the function after hitting it.
 
-NOTE: Only supported for DAP based debuggers.
+NOTE: Only supported for DAP-based debuggers.
 """
 
 from dex.command.CommandBase import CommandBase

>From 4b5d4f82d515214151cae691cef0da08cf178bf8 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Tue, 12 Aug 2025 11:46:40 +0100
Subject: [PATCH 3/5] rename .expression -> .function

---
 .../dexter/dex/command/commands/DexStepFunction.py            | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexStepFunction.py b/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexStepFunction.py
index 44dd114f155af..5f55be607226d 100644
--- a/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexStepFunction.py
+++ b/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexStepFunction.py
@@ -17,7 +17,7 @@ class DexStepFunction(CommandBase):
     def __init__(self, *args, **kwargs):
         if len(args) < 1:
             raise TypeError("expected 1 positional argument")
-        self.expression = str(args[0]) # Function name.
+        self.function = str(args[0]) # Function name.
         self.hit_count = kwargs.pop("hit_count", None)
         if kwargs:
             raise TypeError(f"unexpected named args: {', '.join(kwargs)}")
@@ -27,7 +27,7 @@ def eval(self):
         raise NotImplementedError("DexStepFunction commands cannot be evaled.")
 
     def get_function(self):
-        return self.expression
+        return self.function
 
     @staticmethod
     def get_name():

>From 83608acaeeda65a53658ffe12bf8a8f174b84a0f Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Tue, 12 Aug 2025 11:49:27 +0100
Subject: [PATCH 4/5] fix fmt (by removing redundant comment)

---
 .../dexter/dex/command/commands/DexStepFunction.py              | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexStepFunction.py b/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexStepFunction.py
index 5f55be607226d..4b80de87a1bb2 100644
--- a/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexStepFunction.py
+++ b/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexStepFunction.py
@@ -17,7 +17,7 @@ class DexStepFunction(CommandBase):
     def __init__(self, *args, **kwargs):
         if len(args) < 1:
             raise TypeError("expected 1 positional argument")
-        self.function = str(args[0]) # Function name.
+        self.function = str(args[0])
         self.hit_count = kwargs.pop("hit_count", None)
         if kwargs:
             raise TypeError(f"unexpected named args: {', '.join(kwargs)}")

>From f9dbca40875aa4eb604942326ea676b7ae4313d8 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Wed, 27 Aug 2025 17:06:20 +0100
Subject: [PATCH 5/5] Change to_line default from <large num> to None

---
 .../debuginfo-tests/dexter/dex/command/commands/DexContinue.py  | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexContinue.py b/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexContinue.py
index 17e481a585e5e..113f34bedd131 100644
--- a/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexContinue.py
+++ b/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexContinue.py
@@ -36,7 +36,7 @@ def __init__(self, *args, **kwargs):
             raise TypeError("Missing from_line argument")
 
         # Optional conditional args: to_line, hit_count.
-        self.to_line = kwargs.pop("to_line", 999999)
+        self.to_line = kwargs.pop("to_line", None)
         self.hit_count = kwargs.pop("hit_count", None)
 
         if kwargs:



More information about the llvm-commits mailing list