Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 43 additions & 1 deletion cross-project-tests/debuginfo-tests/dexter/Commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -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])
Expand Down Expand Up @@ -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?
Comment on lines +420 to +421
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest creating two separate words for it. In debugger parlance, I think "hit_count=n" means after n hits, maybe we could replace the alternative form with "repeat_count"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DexFinishTest works in the hit_count sense, but other commands work in the repeat_count sense. Could we land this as-is and separately fix this inconsistency across all the commands?

Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# 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 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.
"""

from dex.command.CommandBase import CommandBase


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 = []
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:]]

# 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", None)
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.")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit, I don't know how I feel about this particular adjectivalisation, maybe we could avoid it by changing it to "Cannot eval DexContinue commands" or similar, or maybe you can just ignore this comment as being a matter of taste!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with you, but I copied this from other existing commands, so I'm inclined to keep it for uniformity.


@staticmethod
def get_name():
return __class__.__name__

@staticmethod
def get_subcommands() -> dict:
return None
Original file line number Diff line number Diff line change
@@ -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.function = str(args[0])
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.function

@staticmethod
def get_name():
return __class__.__name__

@staticmethod
def get_subcommands() -> dict:
return None
Loading