From 734ada9b573393022888bb4338f8772af198515e Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sat, 9 Jun 2018 07:52:28 +0100 Subject: [PATCH] gdb.py: add a 'memdump' command. This makes it easier for me to examine the contents of binary memory buffers, while debugging through code that does crypto or packet marshalling. --- contrib/gdb.py | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/contrib/gdb.py b/contrib/gdb.py index 14574bb2..a993cc89 100644 --- a/contrib/gdb.py +++ b/contrib/gdb.py @@ -35,3 +35,62 @@ rcpp.add_printer(PuTTYBignumPrettyPrinter.name, "^Bignum$", PuTTYBignumPrettyPrinter) gdb.printing.register_pretty_printer(None, rcpp) + +class MemDumpCommand(gdb.Command): + """Print a hex+ASCII dump of object EXP. + +EXP must be an expression whose value resides in memory. The +contents of the memory it occupies are printed in a standard hex +dump format, with each line showing an offset relative to the +address of EXP, then the hex byte values of the memory at that +offset, and then a translation into ASCII of the same bytes (with +values outside the printable ASCII range translated as '.'). + +To dump a number of bytes from a particular address, it's useful +to use the gdb expression extensions {TYPE} and @LENGTH. For +example, if 'ptr' and 'len' are variables giving an address and a +length in bytes, then the command + + memdump {char} ptr @ len + +will dump the range of memory described by those two variables.""" + + def __init__(self): + super(MemDumpCommand, self).__init__( + "memdump", gdb.COMMAND_DATA, gdb.COMPLETE_EXPRESSION) + + def invoke(self, cmdline, from_tty): + expr = gdb.parse_and_eval(cmdline) + try: + start, size = int(expr.address), expr.type.sizeof + except gdb.error as e: + sys.stderr.write(str(e)) + return + except (TypeError, AttributeError): + sys.stderr.write("expression must identify an object in memory") + return + + width = 16 + line_ptr_type = gdb.lookup_type( + "unsigned char").const().array(width).pointer() + + dumpaddr = 0 + while size > 0: + line = gdb.Value(start).cast(line_ptr_type).dereference() + thislinelen = min(size, width) + start += thislinelen + size -= thislinelen + + dumpline = [None, " "] + [" "] * width + [" "] + [""] * width + + dumpline[0] = "{:08x}".format(dumpaddr) + dumpaddr += thislinelen + + for i in range(thislinelen): + ch = int(line[i]) & 0xFF + dumpline[2+i] = " {:02x}".format(ch) + dumpline[3+width+i] = chr(ch) if 0x20 <= ch < 0x7F else "." + + sys.stdout.write("".join(dumpline) + "\n") + +MemDumpCommand()