[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