Add Command.repeat property for repeated commands (#272)

* Add Command.repeat property for repeated commands

* Support repeated invocations of the "hexdump" command

The output now looks like:

    pwndbg> hexdump $rsp 0x20
    +0000 0x7fffffffdb38  30 18 60 f7  ff 7f 00 00  00 00 00 00  00 00 00 00  │0.`.│....│....│....│
    +0010 0x7fffffffdb48  18 dc ff ff  ff 7f 00 00  00 00 00 00  01 00 00 00  │....│....│....│....│
    +0020 0x7fffffffdb58
    pwndbg>
    +0000 0x7fffffffdb58  d0 ee 41 00  00 00 00 00  00 00 00 00  00 00 00 00  │..A.│....│....│....│
    +0010 0x7fffffffdb68  23 ff 3e ed  14 92 d9 c6  60 05 42 00  00 00 00 00  │#.>.│....│`.B.│....│
    +0020 0x7fffffffdb78
    pwndbg>
    +0000 0x7fffffffdb78  10 dc ff ff  ff 7f 00 00  00 00 00 00  00 00 00 00  │....│....│....│....│
    +0010 0x7fffffffdb88  00 00 00 00  00 00 00 00  23 ff de 19  7c 6d 26 39  │....│....│#...│|m&9│
    +0020 0x7fffffffdb98
pull/261/merge
Zach Riggle 9 years ago committed by GitHub
parent 94730a1b17
commit 5861c6a675

@ -27,6 +27,7 @@ class _Command(gdb.Command):
"""Generic command wrapper""" """Generic command wrapper"""
count = 0 count = 0
commands = [] commands = []
history = {}
def __init__(self, function, inc=True, prefix=False): def __init__(self, function, inc=True, prefix=False):
super(_Command, self).__init__(function.__name__, gdb.COMMAND_USER, gdb.COMPLETE_EXPRESSION, prefix=prefix) super(_Command, self).__init__(function.__name__, gdb.COMMAND_USER, gdb.COMPLETE_EXPRESSION, prefix=prefix)
@ -44,11 +45,46 @@ class _Command(gdb.Command):
def invoke(self, argument, from_tty): def invoke(self, argument, from_tty):
argv = self.split_args(argument) argv = self.split_args(argument)
try: try:
self.repeat = self.check_repeated(argument, from_tty)
return self(*argv) return self(*argv)
except TypeError: except TypeError:
if debug: if debug:
print(traceback.format_exc()) print(traceback.format_exc())
raise raise
finally:
self.repeat = False
def check_repeated(self, argument, from_tty):
"""Keep a record of all commands which come from the TTY.
Returns:
True if this command was executed by the user just hitting "enter".
"""
# Don't care unless it's interactive use
if not from_tty:
return False
lines = gdb.execute('show commands', from_tty=False, to_string=True)
lines = lines.splitlines()
# No history
if not lines:
return False
last_line = lines[-1]
number, command = last_line.split(None, 1)
number = int(number)
# A new command was entered by the user
if number not in _Command.history:
_Command.history[number] = command
return False
# Somehow the command is different than we got before?
if not command.endswith(argument):
return False
return True
def __call__(self, *args, **kwargs): def __call__(self, *args, **kwargs):
try: try:

@ -23,14 +23,18 @@ pwndbg.config.Parameter('hexdump-bytes',
'number of bytes printed by hexdump command') 'number of bytes printed by hexdump command')
parser = argparse.ArgumentParser(description='Hexdumps data at the specified address (or at $sp)') parser = argparse.ArgumentParser(description='Hexdumps data at the specified address (or at $sp)')
parser.add_argument('address', nargs='?', default='$sp', parser.add_argument('address', nargs='?', default='$sp',
help='Address to dump') help='Address to dump')
parser.add_argument('count', nargs='?', default=pwndbg.config.hexdump_bytes, parser.add_argument('count', nargs='?', default=pwndbg.config.hexdump_bytes,
help='Number of bytes to dump') help='Number of bytes to dump')
@pwndbg.commands.ArgparsedCommand(parser) @pwndbg.commands.ArgparsedCommand(parser)
@pwndbg.commands.OnlyWhenRunning @pwndbg.commands.OnlyWhenRunning
def hexdump(address=None, count=pwndbg.config.hexdump_bytes): def hexdump(address=None, count=pwndbg.config.hexdump_bytes):
if hexdump.repeat:
address = hexdump.last_address
address = int(address) address = int(address)
address &= pwndbg.arch.ptrmask address &= pwndbg.arch.ptrmask
count = max(int(count), 0) count = max(int(count), 0)
@ -41,9 +45,12 @@ def hexdump(address=None, count=pwndbg.config.hexdump_bytes):
try: try:
data = pwndbg.memory.read(address, count, partial=True) data = pwndbg.memory.read(address, count, partial=True)
hexdump.last_address = (address + count)
except gdb.error as e: except gdb.error as e:
print(e) print(e)
return return
for line in pwndbg.hexdump.hexdump(data, address=address, width=width): for line in pwndbg.hexdump.hexdump(data, address=address, width=width):
print(line) print(line)
hexdump.last_address = 0

Loading…
Cancel
Save