]> git.wh0rd.org - home.git/blob - .gdbinit.py
cros-board: update
[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()