From b5da3e8237f3ba220c6d8fe28f1e1230a3568d4e Mon Sep 17 00:00:00 2001 From: "E. Rivas" <224161+erivas@users.noreply.github.com> Date: Thu, 13 Oct 2022 19:07:02 -0300 Subject: [PATCH] Add ignore command (from #1257) (#1276) * Add ignore command (from #1257) * Fix lint * Apply changes suggested by disconnect3d on ignore command * Add tests for ignore command --- pwndbg/commands/__init__.py | 3 +- pwndbg/commands/ignore.py | 44 +++++++++++++++++++++++++++ tests/test_command_ignore.py | 58 ++++++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 pwndbg/commands/ignore.py create mode 100644 tests/test_command_ignore.py diff --git a/pwndbg/commands/__init__.py b/pwndbg/commands/__init__.py index 004db620..a4de6601 100644 --- a/pwndbg/commands/__init__.py +++ b/pwndbg/commands/__init__.py @@ -54,7 +54,7 @@ GDB_BUILTIN_COMMANDS = list_current_commands() class Command(gdb.Command): """Generic command wrapper""" - builtin_override_whitelist = {"up", "down", "search", "pwd", "start"} + builtin_override_whitelist = {"up", "down", "search", "pwd", "start", "ignore"} history = {} # type: Dict[int,str] def __init__(self, function, prefix=False, command_name=None, shell=False): @@ -476,6 +476,7 @@ def load_commands(): import pwndbg.commands.heap import pwndbg.commands.hexdump import pwndbg.commands.ida + import pwndbg.commands.ignore import pwndbg.commands.ipython_interactive import pwndbg.commands.leakfind import pwndbg.commands.memoize diff --git a/pwndbg/commands/ignore.py b/pwndbg/commands/ignore.py new file mode 100644 index 00000000..5a114d91 --- /dev/null +++ b/pwndbg/commands/ignore.py @@ -0,0 +1,44 @@ +""" +Ignoring a breakpoint +""" + +import argparse + +import gdb + +import pwndbg.color.message as message +import pwndbg.commands + +parser = argparse.ArgumentParser() +parser.description = """Set ignore-count of breakpoint number N to COUNT. + +While the ignore count is positive, execution will not stop on the breakpoint. + +By default, if `N' is ommitted, the last breakpoint (i.e. greatest breakpoint number) will be used.""" +parser.formatter_class = argparse.RawDescriptionHelpFormatter +parser.add_argument( + "bpnum", metavar="N", type=int, default=None, nargs="?", help="The breakpoint number N." +) +parser.add_argument("count", metavar="COUNT", type=int, help="The number to set COUNT.") + + +@pwndbg.commands.ArgparsedCommand(parser) +def ignore(bpnum, count): + bps = gdb.breakpoints() + + if not bps: + print(message.error("No breakpoints set.")) + return + + if bpnum is None: + bp = max(bps, key=lambda bp: bp.number) + else: + bp = next((bp for bp in bps if bp.number == bpnum), None) + + if bp is None: + print(message.error("No breakpoint number %d." % bpnum)) + return + + count = max(0, int(count)) + bp.ignore_count = count + print("Will ignore next %d crossings of breakpoint %d." % (count, bp.number)) diff --git a/tests/test_command_ignore.py b/tests/test_command_ignore.py new file mode 100644 index 00000000..7b257a17 --- /dev/null +++ b/tests/test_command_ignore.py @@ -0,0 +1,58 @@ +import gdb + +import pwndbg +import tests + +REFERENCE_BINARY = tests.binaries.get("reference-binary.out") + + +def test_command_ignore_no_breakpoint_set(): + out = gdb.execute("ignore 1001", to_string=True) + assert out == "No breakpoints set.\n" + + +def test_command_ignore_no_breakpoint_set_remove(): + gdb.execute("file " + REFERENCE_BINARY) + gdb.execute("break break_here") + gdb.execute("delete 1") + out = gdb.execute("ignore 1001", to_string=True) + assert out == "No breakpoints set.\n" + + +def test_command_ignore_no_breakpoint_found(start_binary): + start_binary(REFERENCE_BINARY) + + gdb.execute("break main") + out = gdb.execute("ignore 2 1001", to_string=True) + assert out == "No breakpoint number 2.\n" + + +def test_command_ignore_breakpoint_last_found_one(): + gdb.execute("file " + REFERENCE_BINARY) + gdb.execute("break break_here") + + out = gdb.execute("ignore 1", to_string=True) + assert out == "Will ignore next 1 crossings of breakpoint 1.\n" + + gdb.execute("run") + assert not pwndbg.gdblib.proc.alive + + gdb.execute("run") + assert pwndbg.gdblib.proc.alive + + +def test_command_ignore_breakpoint_last_found_two(): + gdb.execute("file " + REFERENCE_BINARY) + gdb.execute("break break_here") + gdb.execute("break main") + + out = gdb.execute("ignore 15", to_string=True) + assert out == "Will ignore next 15 crossings of breakpoint 2.\n" + + +def test_command_ignore_breakpoint_last_negative(): + gdb.execute("file " + REFERENCE_BINARY) + gdb.execute("break break_here") + + out = gdb.execute("ignore -100", to_string=True) + assert out == "Will ignore next 0 crossings of breakpoint 1.\n"