]> git.wh0rd.org Git - home.git/blob - .gdbinit.py
git-rewrite-authors: minor style tweak
[home.git] / .gdbinit.py
1 #!/usr/bin/python3
2
3 import inspect
4 import os
5 from pathlib import Path
6 import sys
7
8 import gdb
9
10
11 #
12 # Load frameworks if available.
13 #
14
15 if False:
16     PWNDBG = Path('/usr/local/src/pwndbg/gdbinit.py')
17     GDB_DASHBOARD = Path('/usr/local/src/gdb-dashboard/.gdbinit')
18     if PWNDBG.exists():
19         gdb.execute(f'source {PWNDBG}')
20     elif GDB_DASHBOARD.exists():
21         gdb.execute(f'source {GDB_DASHBOARD}')
22
23
24 #
25 # Random helpers.
26 #
27
28 TRACE = False
29
30 class VapierCommand(gdb.Command):
31     """Base class for my custom commands."""
32
33     CMD_INIT = ()
34     CATCH_INVOKE_ERROR = True
35
36     def __init__(self):
37         gdb.Command.__init__(self, *self.CMD_INIT)
38
39     def invoke(self, arg, from_tty):
40         try:
41             if hasattr(self, 'v_invoke_argv'):
42                 argv = gdb.string_to_argv(arg)
43                 self.v_invoke_argv(argv, from_tty)
44             else:
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)
49             else:
50                 raise
51
52     def v_exec(self, cmd):
53         if TRACE:
54             print(f'+ {cmd}')
55         gdb.execute(cmd)
56
57     def v_parse_int(self, arg):
58        try:
59            return int(arg)
60        except ValueError:
61            pass
62
63        try:
64            return int(arg, 16)
65        except ValueError as e:
66            raise gdb.error(f'Not a decimal or hex integer: {arg}')
67
68
69 class VapierTraceCommand(VapierCommand):
70     """Toggle tracing of helpers."""
71
72     CMD_INIT = ('vapier-trace', gdb.COMMAND_SUPPORT)
73
74     def v_invoke(self, arg, from_tty):
75        global TRACE
76        if arg:
77           TRACE = bool(arg)
78        else:
79           TRACE = not TRACE
80        print(f'Tracing of vapier helpers is now {"on" if TRACE else "off"}')
81
82
83 class ExitCommand(VapierCommand):
84     """Exit gdb.
85 Alias to 'quit'.\
86 """
87     CMD_INIT = ('exit', gdb.COMMAND_SUPPORT)
88
89     def v_invoke(self, arg, from_tty):
90         self.dont_repeat()
91         self.v_exec(f'quit {arg}')
92
93
94 class LoadBlackfinCommands(VapierCommand):
95     """Load Blackfin specific commands."""
96
97     BFIN_CONFIG = Path('~/.gdbinit.bfin').expanduser()
98     CMD_INIT = ('blackfin-commands', gdb.COMMAND_SUPPORT)
99
100     def v_invoke(self, arg, from_tty):
101         self.dont_repeat()
102         self.v_exec(f'source {self.BFIN_CONFIG}')
103
104
105 class GoCommand(VapierCommand):
106     """A simple goto-like helper.
107 Basically an alias to 'jump *<addr>'.\
108 """
109
110     CMD_INIT = ('go', gdb.COMMAND_RUNNING)
111
112     def v_invoke(self, arg, from_tty):
113         self.v_exec(f'jump *{arg}')
114
115
116 class DiCommand(VapierCommand):
117
118     CMD_INIT = ('di', gdb.COMMAND_DATA)
119
120     def v_invoke_argv(self, argv, from_tty):
121         self.dont_repeat()
122         if not argv:
123             base = '$pc'
124         elif len(argv) == 1:
125             base = argv[0]
126         else:
127             raise gdb.error('di takes 0 or 1 arguments')
128         self.v_exec(f'disassemble {base} ({base} + 0x40)')
129
130
131 class DisCommand(VapierCommand):
132
133     CMD_INIT = ('dis', gdb.COMMAND_DATA)
134
135     def v_invoke_argv(self, argv, from_tty):
136         self.dont_repeat()
137         if not argv:
138             base = '$pc'
139         elif len(argv) == 1:
140             base = argv[0]
141         else:
142             raise gdb.error('dis takes 0 or 1 arguments')
143         self.v_exec(f'disassemble {base},+0x40')
144
145
146 class UBootMdCommand(VapierCommand):
147     """Display memory.
148 Usage: md <unit type> <address> [count=64]
149 Display [count] <unit type> starting at <address>.\
150 """
151
152     CMD_INIT = ('md', gdb.COMMAND_DATA)
153
154     def v_invoke_argv(self, argv, from_tty):
155         self.dont_repeat()
156         if len(argv) == 2:
157             count = 64
158             unit, addr = argv
159         elif len(argv) == 3:
160             unit, addr, count = argv
161         else:
162             raise gdb.error('usage: <unit> <addr> [count]')
163         self.v_exec(f'x/{count}x{unit} {addr}')
164
165
166 class UBootMemoryDisplayCommand(VapierCommand):
167     """Display memory.
168 Usage: md[cbwlq] <address> [count=64]
169 Display [count] <chars|bytes|words|longs|quads> starting at <address>.\
170 """
171
172     UNIT = None
173     RADIX = 16
174
175     def v_invoke_argv(self, argv, from_tty):
176         assert self.UNIT
177         self.dont_repeat()
178
179         if len(argv) == 1:
180             count = 64
181             addr, = argv
182         elif len(argv) == 2:
183             addr, count = argv
184         else:
185             raise gdb.error('usage: <addr> [count]')
186
187         if self.RADIX != 16:
188             self.v_exec(f'set output-radix {self.RADIX}')
189         self.v_exec(f'md {self.UNIT} {addr} {count}')
190         if self.RADIX != 16:
191             self.v_exec(f'set output-radix 16')
192
193 class UBootMdb(UBootMemoryDisplayCommand):
194     __doc__ = UBootMemoryDisplayCommand.__doc__
195     CMD_INIT = ('mdb', gdb.COMMAND_DATA)
196     UNIT = 'b'
197
198 class UBootMdw(UBootMemoryDisplayCommand):
199     __doc__ = UBootMemoryDisplayCommand.__doc__
200     CMD_INIT = ('mdw', gdb.COMMAND_DATA)
201     UNIT = 'h'
202
203 class UBootMdl(UBootMemoryDisplayCommand):
204     __doc__ = UBootMemoryDisplayCommand.__doc__
205     CMD_INIT = ('mdl', gdb.COMMAND_DATA)
206     UNIT = 'w'
207
208 class UBootMdq(UBootMemoryDisplayCommand):
209     __doc__ = UBootMemoryDisplayCommand.__doc__
210     CMD_INIT = ('mdq', gdb.COMMAND_DATA)
211     UNIT = 'g'
212
213 class UBootMdc(UBootMemoryDisplayCommand):
214     __doc__ = UBootMemoryDisplayCommand.__doc__
215     CMD_INIT = ('mdc', gdb.COMMAND_DATA)
216     UNIT = 'c'
217     RADIX = 10
218
219
220 class UBootMemoryWriteCommand(VapierCommand):
221     """Write memory.
222 Usage: mw[bwlq] <address> <value> <count>
223 Set <count> <bytes|words|longs|quads> at <address> to <value>.\
224 """
225
226     UNIT = None
227
228     def v_invoke_argv(self, argv, from_tty):
229         assert self.UNIT
230         self.dont_repeat()
231
232         if len(argv) == 3:
233             addr, val, count = argv
234         else:
235             raise gdb.error('usage: <addr> <val> <count>')
236         count = self.v_parse_int(count)
237
238         offset = 0
239         while count > 0:
240             self.v_exec(f'set *(({self.UNIT}*){addr} + {offset}) = {val}')
241             offset += 1
242             count -= 1
243
244 class UBootMwb(UBootMemoryWriteCommand):
245     __doc__ = UBootMemoryWriteCommand.__doc__
246     CMD_INIT = ('mwb', gdb.COMMAND_DATA)
247     UNIT = 'unsigned char'
248
249 class UBootMww(UBootMemoryWriteCommand):
250     __doc__ = UBootMemoryWriteCommand.__doc__
251     CMD_INIT = ('mww', gdb.COMMAND_DATA)
252     UNIT = 'unsigned short'
253
254 class UBootMwl(UBootMemoryWriteCommand):
255     __doc__ = UBootMemoryWriteCommand.__doc__
256     CMD_INIT = ('mwl', gdb.COMMAND_DATA)
257     UNIT = 'unsigned int'
258
259 class UBootMwq(UBootMemoryWriteCommand):
260     __doc__ = UBootMemoryWriteCommand.__doc__
261     CMD_INIT = ('mwq', gdb.COMMAND_DATA)
262     UNIT = 'unsigned long long'
263
264
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>.\
269 #"""
270 #
271 #    UNIT = None
272 #
273 #    def v_invoke_argv(self, argv, from_tty):
274 #        assert self.UNIT
275 #        self.dont_repeat()
276 #
277 #        if len(argv) == 3:
278 #            addr1, addr2, count = argv
279 #        else:
280 #            raise gdb.error('usage: <addr1> <addr2> <count>')
281 #        count = self.v_parse_int(count)
282 #
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
289 #                       set $$count = -100
290 #               end
291 #               set $$addr1 += 1
292 #               set $$addr2 += 1
293 #       end
294 #       if $$count == -1
295 #               printf "Data matches for %#x units\n", $arg2
296 #       end
297 #
298 #class UBootCmpb(UBootCompareCommand):
299 #    __doc__ = UBootCompareCommand.__doc__
300 #    CMD_INIT = ('cmpb', gdb.COMMAND_DATA)
301 #    UNIT = 'unsigned char'
302 #
303 #class UBootCmpw(UBootCompareCommand):
304 #    __doc__ = UBootCompareCommand.__doc__
305 #    CMD_INIT = ('cmpw', gdb.COMMAND_DATA)
306 #    UNIT = 'unsigned short'
307 #
308 #class UBootCmpl(UBootCompareCommand):
309 #    __doc__ = UBootCompareCommand.__doc__
310 #    CMD_INIT = ('cmpl', gdb.COMMAND_DATA)
311 #    UNIT = 'unsigned int'
312 #
313 #class UBootCmpq(UBootCompareCommand):
314 #    __doc__ = UBootCompareCommand.__doc__
315 #    CMD_INIT = ('cmpq', gdb.COMMAND_DATA)
316 #    UNIT = 'unsigned long long'
317 #
318 #
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>.\
323 #"""
324 #
325 #    UNIT = None
326 #
327 #    def v_invoke_argv(self, argv, from_tty):
328 #        assert self.UNIT
329 #        self.dont_repeat()
330 #
331 #        if len(argv) == 3:
332 #            src, dst, count = argv
333 #        else:
334 #            raise gdb.error('usage: <addr1> <addr2> <count>')
335 #        count = self.v_parse_int(count)
336 #
337 #        offset = 0
338 #        while count > 0:
339 #            self.v_exec(f'set *(({self.UNIT}*){addr} + {offset}) = {val}')
340 #            count -= 1
341 #            offset += 1
342 #               set *$$dst = *$$src
343 #               set $$src += 1
344 #               set $$dst += 1
345 #        print(f'Copied {argv[2]} units from {addr1} to {addr2}')
346 #
347 #class UBootCpb(UBootCopyCommand):
348 #    __doc__ = UBootCopyCommand.__doc__
349 #    CMD_INIT = ('cpb', gdb.COMMAND_DATA)
350 #    UNIT = 'unsigned char'
351 #
352 #class UBootCpw(UBootCopyCommand):
353 #    __doc__ = UBootCopyCommand.__doc__
354 #    CMD_INIT = ('cpw', gdb.COMMAND_DATA)
355 #    UNIT = 'unsigned short'
356 #
357 #class UBootCpl(UBootCopyCommand):
358 #    __doc__ = UBootCopyCommand.__doc__
359 #    CMD_INIT = ('cpl', gdb.COMMAND_DATA)
360 #    UNIT = 'unsigned int'
361 #
362 #class UBootCpq(UBootCopyCommand):
363 #    __doc__ = UBootCopyCommand.__doc__
364 #    CMD_INIT = ('cpq', gdb.COMMAND_DATA)
365 #    UNIT = 'unsigned long long'
366
367
368 # Probe & load all commands registered.
369 for cls in list(globals().values()):
370     if (inspect.isclass(cls) and
371             issubclass(cls, VapierCommand) and
372             cls.CMD_INIT):
373         cls()