]> git.wh0rd.org - home.git/blobdiff - .gdbinit.py
gdbinit: split up & migrate some to python
[home.git] / .gdbinit.py
diff --git a/.gdbinit.py b/.gdbinit.py
new file mode 100644 (file)
index 0000000..f7e5134
--- /dev/null
@@ -0,0 +1,373 @@
+#!/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()