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