CLI: Support listing/clearing breakpoints in volshell

This commit is contained in:
Mike Auty
2025-05-18 20:18:29 +01:00
parent 5bb4cd90c1
commit 6269091be7
+42 -2
View File
@@ -187,6 +187,8 @@ class Volshell(interfaces.plugins.PluginInterface):
def construct_locals(self) -> List[Tuple[List[str], Any]]:
"""Returns a listing of the functions to be added to the environment."""
return [
(["bc", "breakpoint_clear"], self.breakpoint_clear),
(["bl", "breakpoint_list"], self.breakpoint_list),
(["bp", "breakpoint"], self.breakpoint),
(["dt", "display_type"], self.display_type),
(["db", "display_bytes"], self.display_bytes),
@@ -827,10 +829,13 @@ class Volshell(interfaces.plugins.PluginInterface):
original_read = getattr(wrapped_read, "original_read")
for breakpoint in getattr(wrapped_read, "breakpoints"):
if (offset <= breakpoint) and (breakpoint < offset + length):
print(
"Hit breakpoint, entering python debugger. To continue running without the debugger use the command continue"
)
import pdb
pdb.set_trace()
print("Hit breakpoint")
_ = "First statement after the breakpoint, use u(p), d(own) and list to navigate through the execution frames"
return original_read(offset, length, pad)
setattr(wrapped_read, "breakpoints", set())
@@ -838,11 +843,46 @@ class Volshell(interfaces.plugins.PluginInterface):
setattr(layer, "read", wrapped_read)
# Add the new breakpoint
print(f"Setting breakpoint {address:x} on {layer.name}")
print(f"Setting breakpoint {address:#x} on {layer.name}")
breakpoints = getattr(layer.read, "breakpoints")
breakpoints.add(address)
setattr(layer.read, "breakpoints", breakpoints)
def breakpoint_list(self, layer_names: Optional[List[str]] = None):
"""List available breakpoints for a set of layers"""
if not layer_names:
layer_names = [layer_name for layer_name in self.context.layers]
print("Listing breakpoints:")
for layer_name in layer_names:
print(f" {layer_name}")
layer = self.context.layers.get(layer_name, None)
if layer and hasattr(layer.read, "breakpoints"):
for breakpoint in layer.read.breakpoints:
print(f" {breakpoint:#x}")
def breakpoint_clear(
self, offset: Optional[int] = None, layer_name: Optional[str] = None
):
"""Clears a offset breakpoint on a layer (or all breakpoints if offset or layer not specified)
Args:
offset: Address of the breakpoint to clear (or all if None)
layer_name: Layer to clear breakpoints from (or all if None)
"""
print("Clearing breakpoints:")
for candidate_layer_name in self.context.layers:
candidate_layer = self.context.layers[candidate_layer_name]
if layer_name is None or layer_name == candidate_layer_name:
print(f" {candidate_layer_name}")
if hasattr(candidate_layer.read, "breakpoints"):
breakpoints_to_remove = set()
for breakpoint in candidate_layer.read.breakpoints:
if offset is None or offset == breakpoint:
print(f" clearing {breakpoint:#x}")
breakpoints_to_remove.add(breakpoint)
candidate_layer.read.breakpoints -= breakpoints_to_remove
class NullFileHandler(io.BytesIO, interfaces.plugins.FileHandlerInterface):
"""Null FileHandler that swallows files whole without consuming memory"""