--- /dev/null
+#!/usr/bin/python3
+
+import inspect
+import os
+from pathlib import Path
+import sys
+
+import gdb
+
+
+#
+# Load frameworks if available.
+#
+
+if False:
+ PWNDBG = Path('/usr/local/src/pwndbg/gdbinit.py')
+ GDB_DASHBOARD = Path('/usr/local/src/gdb-dashboard/.gdbinit')
+ if PWNDBG.exists():
+ gdb.execute(f'source {PWNDBG}')
+ elif GDB_DASHBOARD.exists():
+ gdb.execute(f'source {GDB_DASHBOARD}')
+
+
+#
+# Random helpers.
+#
+
+TRACE = False
+
+class VapierCommand(gdb.Command):
+ """Base class for my custom commands."""
+
+ CMD_INIT = ()
+ CATCH_INVOKE_ERROR = True
+
+ def __init__(self):
+ gdb.Command.__init__(self, *self.CMD_INIT)
+
+ def invoke(self, arg, from_tty):
+ try:
+ if hasattr(self, 'v_invoke_argv'):
+ argv = gdb.string_to_argv(arg)
+ self.v_invoke_argv(argv, from_tty)
+ else:
+ self.v_invoke(arg, from_tty)
+ except gdb.error as e:
+ if self.CATCH_INVOKE_ERROR:
+ print(e, file=sys.stderr)
+ else:
+ raise
+
+ def v_exec(self, cmd):
+ if TRACE:
+ print(f'+ {cmd}')
+ gdb.execute(cmd)
+
+ def v_parse_int(self, arg):
+ try:
+ return int(arg)
+ except ValueError:
+ pass
+
+ try:
+ return int(arg, 16)
+ except ValueError as e:
+ raise gdb.error(f'Not a decimal or hex integer: {arg}')
+
+
+class VapierTraceCommand(VapierCommand):
+ """Toggle tracing of helpers."""
+
+ CMD_INIT = ('vapier-trace', gdb.COMMAND_SUPPORT)
+
+ def v_invoke(self, arg, from_tty):
+ global TRACE
+ if arg:
+ TRACE = bool(arg)
+ else:
+ TRACE = not TRACE
+ print(f'Tracing of vapier helpers is now {"on" if TRACE else "off"}')
+
+
+class ExitCommand(VapierCommand):
+ """Exit gdb.
+Alias to 'quit'.\
+"""
+ CMD_INIT = ('exit', gdb.COMMAND_SUPPORT)
+
+ def v_invoke(self, arg, from_tty):
+ self.dont_repeat()
+ self.v_exec(f'quit {arg}')
+
+
+class LoadBlackfinCommands(VapierCommand):
+ """Load Blackfin specific commands."""
+
+ BFIN_CONFIG = Path('~/.gdbinit.bfin').expanduser()
+ CMD_INIT = ('blackfin-commands', gdb.COMMAND_SUPPORT)
+
+ def v_invoke(self, arg, from_tty):
+ self.dont_repeat()
+ self.v_exec(f'source {self.BFIN_CONFIG}')
+
+
+class GoCommand(VapierCommand):
+ """A simple goto-like helper.
+Basically an alias to 'jump *<addr>'.\
+"""
+
+ CMD_INIT = ('go', gdb.COMMAND_RUNNING)
+
+ def v_invoke(self, arg, from_tty):
+ self.v_exec(f'jump *{arg}')
+
+
+class DiCommand(VapierCommand):
+
+ CMD_INIT = ('di', gdb.COMMAND_DATA)
+
+ def v_invoke_argv(self, argv, from_tty):
+ self.dont_repeat()
+ if not argv:
+ base = '$pc'
+ elif len(argv) == 1:
+ base = argv[0]
+ else:
+ raise gdb.error('di takes 0 or 1 arguments')
+ self.v_exec(f'disassemble {base} ({base} + 0x40)')
+
+
+class DisCommand(VapierCommand):
+
+ CMD_INIT = ('dis', gdb.COMMAND_DATA)
+
+ def v_invoke_argv(self, argv, from_tty):
+ self.dont_repeat()
+ if not argv:
+ base = '$pc'
+ elif len(argv) == 1:
+ base = argv[0]
+ else:
+ raise gdb.error('dis takes 0 or 1 arguments')
+ self.v_exec(f'disassemble {base},+0x40')
+
+
+class UBootMdCommand(VapierCommand):
+ """Display memory.
+Usage: md <unit type> <address> [count=64]
+Display [count] <unit type> starting at <address>.\
+"""
+
+ CMD_INIT = ('md', gdb.COMMAND_DATA)
+
+ def v_invoke_argv(self, argv, from_tty):
+ self.dont_repeat()
+ if len(argv) == 2:
+ count = 64
+ unit, addr = argv
+ elif len(argv) == 3:
+ unit, addr, count = argv
+ else:
+ raise gdb.error('usage: <unit> <addr> [count]')
+ self.v_exec(f'x/{count}x{unit} {addr}')
+
+
+class UBootMemoryDisplayCommand(VapierCommand):
+ """Display memory.
+Usage: md[cbwlq] <address> [count=64]
+Display [count] <chars|bytes|words|longs|quads> starting at <address>.\
+"""
+
+ UNIT = None
+ RADIX = 16
+
+ def v_invoke_argv(self, argv, from_tty):
+ assert self.UNIT
+ self.dont_repeat()
+
+ if len(argv) == 1:
+ count = 64
+ addr, = argv
+ elif len(argv) == 2:
+ addr, count = argv
+ else:
+ raise gdb.error('usage: <addr> [count]')
+
+ if self.RADIX != 16:
+ self.v_exec(f'set output-radix {self.RADIX}')
+ self.v_exec(f'md {self.UNIT} {addr} {count}')
+ if self.RADIX != 16:
+ self.v_exec(f'set output-radix 16')
+
+class UBootMdb(UBootMemoryDisplayCommand):
+ __doc__ = UBootMemoryDisplayCommand.__doc__
+ CMD_INIT = ('mdb', gdb.COMMAND_DATA)
+ UNIT = 'b'
+
+class UBootMdw(UBootMemoryDisplayCommand):
+ __doc__ = UBootMemoryDisplayCommand.__doc__
+ CMD_INIT = ('mdw', gdb.COMMAND_DATA)
+ UNIT = 'h'
+
+class UBootMdl(UBootMemoryDisplayCommand):
+ __doc__ = UBootMemoryDisplayCommand.__doc__
+ CMD_INIT = ('mdl', gdb.COMMAND_DATA)
+ UNIT = 'w'
+
+class UBootMdq(UBootMemoryDisplayCommand):
+ __doc__ = UBootMemoryDisplayCommand.__doc__
+ CMD_INIT = ('mdq', gdb.COMMAND_DATA)
+ UNIT = 'g'
+
+class UBootMdc(UBootMemoryDisplayCommand):
+ __doc__ = UBootMemoryDisplayCommand.__doc__
+ CMD_INIT = ('mdc', gdb.COMMAND_DATA)
+ UNIT = 'c'
+ RADIX = 10
+
+
+class UBootMemoryWriteCommand(VapierCommand):
+ """Write memory.
+Usage: mw[bwlq] <address> <value> <count>
+Set <count> <bytes|words|longs|quads> at <address> to <value>.\
+"""
+
+ UNIT = None
+
+ def v_invoke_argv(self, argv, from_tty):
+ assert self.UNIT
+ self.dont_repeat()
+
+ if len(argv) == 3:
+ addr, val, count = argv
+ else:
+ raise gdb.error('usage: <addr> <val> <count>')
+ count = self.v_parse_int(count)
+
+ offset = 0
+ while count > 0:
+ self.v_exec(f'set *(({self.UNIT}*){addr} + {offset}) = {val}')
+ offset += 1
+ count -= 1
+
+class UBootMwb(UBootMemoryWriteCommand):
+ __doc__ = UBootMemoryWriteCommand.__doc__
+ CMD_INIT = ('mwb', gdb.COMMAND_DATA)
+ UNIT = 'unsigned char'
+
+class UBootMww(UBootMemoryWriteCommand):
+ __doc__ = UBootMemoryWriteCommand.__doc__
+ CMD_INIT = ('mww', gdb.COMMAND_DATA)
+ UNIT = 'unsigned short'
+
+class UBootMwl(UBootMemoryWriteCommand):
+ __doc__ = UBootMemoryWriteCommand.__doc__
+ CMD_INIT = ('mwl', gdb.COMMAND_DATA)
+ UNIT = 'unsigned int'
+
+class UBootMwq(UBootMemoryWriteCommand):
+ __doc__ = UBootMemoryWriteCommand.__doc__
+ CMD_INIT = ('mwq', gdb.COMMAND_DATA)
+ UNIT = 'unsigned long long'
+
+
+#class UBootCompareCommand(VapierCommand):
+# """Compare memory regions.
+#Usage: cmp[bwlq] <address> <address> <count>
+#Compare <count> <bytes|words|longs|quads> between <address> and <address>.\
+#"""
+#
+# UNIT = None
+#
+# def v_invoke_argv(self, argv, from_tty):
+# assert self.UNIT
+# self.dont_repeat()
+#
+# if len(argv) == 3:
+# addr1, addr2, count = argv
+# else:
+# raise gdb.error('usage: <addr1> <addr2> <count>')
+# count = self.v_parse_int(count)
+#
+# set $$addr1 = $arg0
+# set $$addr2 = $arg1
+# set $$count = $arg2
+# while $$count-- > 0
+# if (*$$addr1 != *$$addr2)
+# printf "Data mismatch at %#x units (@%#x != @%#x)\n", $arg2, $$addr1, $$addr2
+# set $$count = -100
+# end
+# set $$addr1 += 1
+# set $$addr2 += 1
+# end
+# if $$count == -1
+# printf "Data matches for %#x units\n", $arg2
+# end
+#
+#class UBootCmpb(UBootCompareCommand):
+# __doc__ = UBootCompareCommand.__doc__
+# CMD_INIT = ('cmpb', gdb.COMMAND_DATA)
+# UNIT = 'unsigned char'
+#
+#class UBootCmpw(UBootCompareCommand):
+# __doc__ = UBootCompareCommand.__doc__
+# CMD_INIT = ('cmpw', gdb.COMMAND_DATA)
+# UNIT = 'unsigned short'
+#
+#class UBootCmpl(UBootCompareCommand):
+# __doc__ = UBootCompareCommand.__doc__
+# CMD_INIT = ('cmpl', gdb.COMMAND_DATA)
+# UNIT = 'unsigned int'
+#
+#class UBootCmpq(UBootCompareCommand):
+# __doc__ = UBootCompareCommand.__doc__
+# CMD_INIT = ('cmpq', gdb.COMMAND_DATA)
+# UNIT = 'unsigned long long'
+#
+#
+#class UBootCopyCommand(VapierCommand):
+# """Copy memory regions.
+#Usage: cp[bwlq] <src> <dst> <count>
+#Copy <count> <bytes|words|longs|quads> from <src> to <dst>.\
+#"""
+#
+# UNIT = None
+#
+# def v_invoke_argv(self, argv, from_tty):
+# assert self.UNIT
+# self.dont_repeat()
+#
+# if len(argv) == 3:
+# src, dst, count = argv
+# else:
+# raise gdb.error('usage: <addr1> <addr2> <count>')
+# count = self.v_parse_int(count)
+#
+# offset = 0
+# while count > 0:
+# self.v_exec(f'set *(({self.UNIT}*){addr} + {offset}) = {val}')
+# count -= 1
+# offset += 1
+# set *$$dst = *$$src
+# set $$src += 1
+# set $$dst += 1
+# print(f'Copied {argv[2]} units from {addr1} to {addr2}')
+#
+#class UBootCpb(UBootCopyCommand):
+# __doc__ = UBootCopyCommand.__doc__
+# CMD_INIT = ('cpb', gdb.COMMAND_DATA)
+# UNIT = 'unsigned char'
+#
+#class UBootCpw(UBootCopyCommand):
+# __doc__ = UBootCopyCommand.__doc__
+# CMD_INIT = ('cpw', gdb.COMMAND_DATA)
+# UNIT = 'unsigned short'
+#
+#class UBootCpl(UBootCopyCommand):
+# __doc__ = UBootCopyCommand.__doc__
+# CMD_INIT = ('cpl', gdb.COMMAND_DATA)
+# UNIT = 'unsigned int'
+#
+#class UBootCpq(UBootCopyCommand):
+# __doc__ = UBootCopyCommand.__doc__
+# CMD_INIT = ('cpq', gdb.COMMAND_DATA)
+# UNIT = 'unsigned long long'
+
+
+# Probe & load all commands registered.
+for cls in list(globals().values()):
+ if (inspect.isclass(cls) and
+ issubclass(cls, VapierCommand) and
+ cls.CMD_INIT):
+ cls()