Skip to content

Commit e2dcb8b

Browse files
authored
[Dexter] Add DexStepFunction and DexContinue skeletons (#152720)
1 parent e491647 commit e2dcb8b

File tree

3 files changed

+136
-1
lines changed

3 files changed

+136
-1
lines changed

cross-project-tests/debuginfo-tests/dexter/Commands.md

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
* [DexDeclareFile](Commands.md#DexDeclareFile)
1414
* [DexFinishTest](Commands.md#DexFinishTest)
1515
* [DexCommandLine](Commands.md#DexCommandLine)
16-
16+
* [DexStepFunction](Commands.md#DexStepFunction)
17+
* [DexContinue](Commands.md#DexContinue)
1718
---
1819
## DexExpectProgramState
1920
DexExpectProgramState(state [,**times])
@@ -377,3 +378,44 @@ line this command is found on.
377378

378379
### Heuristic
379380
[Deprecated]
381+
382+
383+
---
384+
## DexStepFunction
385+
DexStepFunction(function_name[, **hit_count=0])
386+
387+
Arg list:
388+
function_name (str): function to step through.
389+
hit_count (int): If provided, limit the number of times the command
390+
triggers.
391+
392+
### Description
393+
NOTE: Only supported for DAP-based debuggers.
394+
395+
This command controls stepping behaviour: Tell dexter to set a function
396+
breakpoint and step through the function after hitting it. Composes well with
397+
itself (you can may a callstack with multiple targets to step through) and
398+
`DexContinue`.
399+
400+
---
401+
## DexContinue
402+
DexContinue(*[expr, *values], **from_line[, **to_line, **hit_count])
403+
404+
Arg list:
405+
function_name (str): function to step through.
406+
hit_count (int): If provided, limit the number of times the command
407+
triggers.
408+
409+
### Description
410+
NOTE: Only supported for DAP-based debuggers.
411+
412+
This command controls stepping behaviour: Tell dexter to set a breakpoint on
413+
`from_line`. When it is hit and optionally '(expr) == (values[n])' is true,
414+
optionally set a breakpoint on `to_line`. Then 'continue' (tell the debugger to
415+
run freely until a breakpoint is hit). Composed with `DexStepFunction` this
416+
lets you avoid stepping over certain regions (many loop iterations, for
417+
example). Continue-ing off the end of a `DexStepFunction` is well defined;
418+
stepping will resume in `DexStepFunction` targets deeper in the callstack.
419+
420+
FIXME: hit_count should probably be inverted, like `DexLimitSteps`, to trigger
421+
AFTER that many hits?
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# DExTer : Debugging Experience Tester
2+
# ~~~~~~ ~ ~~ ~ ~~
3+
#
4+
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
# See https://llvm.org/LICENSE.txt for license information.
6+
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
"""A Command that tells dexter to set a breakpoint which, after hitting,
8+
signals that the debugger should 'continue' until another is hit. Continuing
9+
out of a function being stepped through with DexStepFunction is well defined:
10+
stepping will resume in other functions tracked further down the stacktrace.
11+
12+
NOTE: Only supported for DAP-based debuggers.
13+
"""
14+
15+
from dex.command.CommandBase import CommandBase
16+
17+
18+
class DexContinue(CommandBase):
19+
def __init__(self, *args, **kwargs):
20+
# DexContinue(*[expr, *values], **from_line[, **to_line, **hit_count])
21+
22+
# Optional positional args: expr, values.
23+
if len(args) == 0:
24+
self.expression = None
25+
self.values = []
26+
elif len(args) == 1:
27+
raise TypeError("expected 0 or at least 2 positional arguments")
28+
else:
29+
self.expression = args[0]
30+
self.values = [str(arg) for arg in args[1:]]
31+
32+
# Required keyword arg: from_line.
33+
try:
34+
self.from_line = kwargs.pop("from_line")
35+
except:
36+
raise TypeError("Missing from_line argument")
37+
38+
# Optional conditional args: to_line, hit_count.
39+
self.to_line = kwargs.pop("to_line", None)
40+
self.hit_count = kwargs.pop("hit_count", None)
41+
42+
if kwargs:
43+
raise TypeError("unexpected named args: {}".format(", ".join(kwargs)))
44+
super(DexContinue, self).__init__()
45+
46+
def eval(self):
47+
raise NotImplementedError("DexContinue commands cannot be evaled.")
48+
49+
@staticmethod
50+
def get_name():
51+
return __class__.__name__
52+
53+
@staticmethod
54+
def get_subcommands() -> dict:
55+
return None
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# DExTer : Debugging Experience Tester
2+
# ~~~~~~ ~ ~~ ~ ~~
3+
#
4+
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
# See https://llvm.org/LICENSE.txt for license information.
6+
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
"""A Command that tells dexter to set a function breakpoint and step through
8+
the function after hitting it.
9+
10+
NOTE: Only supported for DAP-based debuggers.
11+
"""
12+
13+
from dex.command.CommandBase import CommandBase
14+
15+
16+
class DexStepFunction(CommandBase):
17+
def __init__(self, *args, **kwargs):
18+
if len(args) < 1:
19+
raise TypeError("expected 1 positional argument")
20+
self.function = str(args[0])
21+
self.hit_count = kwargs.pop("hit_count", None)
22+
if kwargs:
23+
raise TypeError(f"unexpected named args: {', '.join(kwargs)}")
24+
super(DexStepFunction, self).__init__()
25+
26+
def eval(self):
27+
raise NotImplementedError("DexStepFunction commands cannot be evaled.")
28+
29+
def get_function(self):
30+
return self.function
31+
32+
@staticmethod
33+
def get_name():
34+
return __class__.__name__
35+
36+
@staticmethod
37+
def get_subcommands() -> dict:
38+
return None

0 commit comments

Comments
 (0)