5 from pathlib import Path
12 # Load frameworks if available.
16 PWNDBG = Path('/usr/local/src/pwndbg/gdbinit.py')
17 GDB_DASHBOARD = Path('/usr/local/src/gdb-dashboard/.gdbinit')
19 gdb.execute(f'source {PWNDBG}')
20 elif GDB_DASHBOARD.exists():
21 gdb.execute(f'source {GDB_DASHBOARD}')
30 class VapierCommand(gdb.Command):
31 """Base class for my custom commands."""
34 CATCH_INVOKE_ERROR = True
37 gdb.Command.__init__(self, *self.CMD_INIT)
39 def invoke(self, arg, from_tty):
41 if hasattr(self, 'v_invoke_argv'):
42 argv = gdb.string_to_argv(arg)
43 self.v_invoke_argv(argv, from_tty)
45 self.v_invoke(arg, from_tty)
46 except gdb.error as e:
47 if self.CATCH_INVOKE_ERROR:
48 print(e, file=sys.stderr)
52 def v_exec(self, cmd):
57 def v_parse_int(self, arg):
65 except ValueError as e:
66 raise gdb.error(f'Not a decimal or hex integer: {arg}')
69 class VapierTraceCommand(VapierCommand):
70 """Toggle tracing of helpers."""
72 CMD_INIT = ('vapier-trace', gdb.COMMAND_SUPPORT)
74 def v_invoke(self, arg, from_tty):
80 print(f'Tracing of vapier helpers is now {"on" if TRACE else "off"}')
83 class ExitCommand(VapierCommand):
87 CMD_INIT = ('exit', gdb.COMMAND_SUPPORT)
89 def v_invoke(self, arg, from_tty):
91 self.v_exec(f'quit {arg}')
94 class LoadBlackfinCommands(VapierCommand):
95 """Load Blackfin specific commands."""
97 BFIN_CONFIG = Path('~/.gdbinit.bfin').expanduser()
98 CMD_INIT = ('blackfin-commands', gdb.COMMAND_SUPPORT)
100 def v_invoke(self, arg, from_tty):
102 self.v_exec(f'source {self.BFIN_CONFIG}')
105 class GoCommand(VapierCommand):
106 """A simple goto-like helper.
107 Basically an alias to 'jump *<addr>'.\
110 CMD_INIT = ('go', gdb.COMMAND_RUNNING)
112 def v_invoke(self, arg, from_tty):
113 self.v_exec(f'jump *{arg}')
116 class DiCommand(VapierCommand):
118 CMD_INIT = ('di', gdb.COMMAND_DATA)
120 def v_invoke_argv(self, argv, from_tty):
127 raise gdb.error('di takes 0 or 1 arguments')
128 self.v_exec(f'disassemble {base} ({base} + 0x40)')
131 class DisCommand(VapierCommand):
133 CMD_INIT = ('dis', gdb.COMMAND_DATA)
135 def v_invoke_argv(self, argv, from_tty):
142 raise gdb.error('dis takes 0 or 1 arguments')
143 self.v_exec(f'disassemble {base},+0x40')
146 class UBootMdCommand(VapierCommand):
148 Usage: md <unit type> <address> [count=64]
149 Display [count] <unit type> starting at <address>.\
152 CMD_INIT = ('md', gdb.COMMAND_DATA)
154 def v_invoke_argv(self, argv, from_tty):
160 unit, addr, count = argv
162 raise gdb.error('usage: <unit> <addr> [count]')
163 self.v_exec(f'x/{count}x{unit} {addr}')
166 class UBootMemoryDisplayCommand(VapierCommand):
168 Usage: md[cbwlq] <address> [count=64]
169 Display [count] <chars|bytes|words|longs|quads> starting at <address>.\
175 def v_invoke_argv(self, argv, from_tty):
185 raise gdb.error('usage: <addr> [count]')
188 self.v_exec(f'set output-radix {self.RADIX}')
189 self.v_exec(f'md {self.UNIT} {addr} {count}')
191 self.v_exec(f'set output-radix 16')
193 class UBootMdb(UBootMemoryDisplayCommand):
194 __doc__ = UBootMemoryDisplayCommand.__doc__
195 CMD_INIT = ('mdb', gdb.COMMAND_DATA)
198 class UBootMdw(UBootMemoryDisplayCommand):
199 __doc__ = UBootMemoryDisplayCommand.__doc__
200 CMD_INIT = ('mdw', gdb.COMMAND_DATA)
203 class UBootMdl(UBootMemoryDisplayCommand):
204 __doc__ = UBootMemoryDisplayCommand.__doc__
205 CMD_INIT = ('mdl', gdb.COMMAND_DATA)
208 class UBootMdq(UBootMemoryDisplayCommand):
209 __doc__ = UBootMemoryDisplayCommand.__doc__
210 CMD_INIT = ('mdq', gdb.COMMAND_DATA)
213 class UBootMdc(UBootMemoryDisplayCommand):
214 __doc__ = UBootMemoryDisplayCommand.__doc__
215 CMD_INIT = ('mdc', gdb.COMMAND_DATA)
220 class UBootMemoryWriteCommand(VapierCommand):
222 Usage: mw[bwlq] <address> <value> <count>
223 Set <count> <bytes|words|longs|quads> at <address> to <value>.\
228 def v_invoke_argv(self, argv, from_tty):
233 addr, val, count = argv
235 raise gdb.error('usage: <addr> <val> <count>')
236 count = self.v_parse_int(count)
240 self.v_exec(f'set *(({self.UNIT}*){addr} + {offset}) = {val}')
244 class UBootMwb(UBootMemoryWriteCommand):
245 __doc__ = UBootMemoryWriteCommand.__doc__
246 CMD_INIT = ('mwb', gdb.COMMAND_DATA)
247 UNIT = 'unsigned char'
249 class UBootMww(UBootMemoryWriteCommand):
250 __doc__ = UBootMemoryWriteCommand.__doc__
251 CMD_INIT = ('mww', gdb.COMMAND_DATA)
252 UNIT = 'unsigned short'
254 class UBootMwl(UBootMemoryWriteCommand):
255 __doc__ = UBootMemoryWriteCommand.__doc__
256 CMD_INIT = ('mwl', gdb.COMMAND_DATA)
257 UNIT = 'unsigned int'
259 class UBootMwq(UBootMemoryWriteCommand):
260 __doc__ = UBootMemoryWriteCommand.__doc__
261 CMD_INIT = ('mwq', gdb.COMMAND_DATA)
262 UNIT = 'unsigned long long'
265 #class UBootCompareCommand(VapierCommand):
266 # """Compare memory regions.
267 #Usage: cmp[bwlq] <address> <address> <count>
268 #Compare <count> <bytes|words|longs|quads> between <address> and <address>.\
273 # def v_invoke_argv(self, argv, from_tty):
278 # addr1, addr2, count = argv
280 # raise gdb.error('usage: <addr1> <addr2> <count>')
281 # count = self.v_parse_int(count)
283 # set $$addr1 = $arg0
284 # set $$addr2 = $arg1
285 # set $$count = $arg2
286 # while $$count-- > 0
287 # if (*$$addr1 != *$$addr2)
288 # printf "Data mismatch at %#x units (@%#x != @%#x)\n", $arg2, $$addr1, $$addr2
295 # printf "Data matches for %#x units\n", $arg2
298 #class UBootCmpb(UBootCompareCommand):
299 # __doc__ = UBootCompareCommand.__doc__
300 # CMD_INIT = ('cmpb', gdb.COMMAND_DATA)
301 # UNIT = 'unsigned char'
303 #class UBootCmpw(UBootCompareCommand):
304 # __doc__ = UBootCompareCommand.__doc__
305 # CMD_INIT = ('cmpw', gdb.COMMAND_DATA)
306 # UNIT = 'unsigned short'
308 #class UBootCmpl(UBootCompareCommand):
309 # __doc__ = UBootCompareCommand.__doc__
310 # CMD_INIT = ('cmpl', gdb.COMMAND_DATA)
311 # UNIT = 'unsigned int'
313 #class UBootCmpq(UBootCompareCommand):
314 # __doc__ = UBootCompareCommand.__doc__
315 # CMD_INIT = ('cmpq', gdb.COMMAND_DATA)
316 # UNIT = 'unsigned long long'
319 #class UBootCopyCommand(VapierCommand):
320 # """Copy memory regions.
321 #Usage: cp[bwlq] <src> <dst> <count>
322 #Copy <count> <bytes|words|longs|quads> from <src> to <dst>.\
327 # def v_invoke_argv(self, argv, from_tty):
332 # src, dst, count = argv
334 # raise gdb.error('usage: <addr1> <addr2> <count>')
335 # count = self.v_parse_int(count)
339 # self.v_exec(f'set *(({self.UNIT}*){addr} + {offset}) = {val}')
342 # set *$$dst = *$$src
345 # print(f'Copied {argv[2]} units from {addr1} to {addr2}')
347 #class UBootCpb(UBootCopyCommand):
348 # __doc__ = UBootCopyCommand.__doc__
349 # CMD_INIT = ('cpb', gdb.COMMAND_DATA)
350 # UNIT = 'unsigned char'
352 #class UBootCpw(UBootCopyCommand):
353 # __doc__ = UBootCopyCommand.__doc__
354 # CMD_INIT = ('cpw', gdb.COMMAND_DATA)
355 # UNIT = 'unsigned short'
357 #class UBootCpl(UBootCopyCommand):
358 # __doc__ = UBootCopyCommand.__doc__
359 # CMD_INIT = ('cpl', gdb.COMMAND_DATA)
360 # UNIT = 'unsigned int'
362 #class UBootCpq(UBootCopyCommand):
363 # __doc__ = UBootCopyCommand.__doc__
364 # CMD_INIT = ('cpq', gdb.COMMAND_DATA)
365 # UNIT = 'unsigned long long'
368 # Probe & load all commands registered.
369 for cls in list(globals().values()):
370 if (inspect.isclass(cls) and
371 issubclass(cls, VapierCommand) and