···11+function b --wrap bundle
22+ bundle $argv
33+end
44+
+3
fish/functions/be.fish
···11+function be --wrap 'bundle exec'
22+ bundle exec $argv
33+end
+3
fish/functions/e.fish
···11+function e --wraps "$EDITOR"
22+ eval "$EDITOR $argv"
33+end
+3
fish/functions/g.fish
···11+function g --description 'Less typing more work!' --wrap git
22+ git $argv
33+end
+4
fish/functions/work.fish
···11+function work
22+ set project (basename (command git rev-parse --show-toplevel))
33+ time -f '%E' -- tmux new -s $project; or time -f '%E' -- tmux attach -t $project
44+end
+12
fish/init.fish
···11+set fish_greeting (fortune zen)
22+# set fish_key_bindings fish_vi_key_bindings
33+44+set -gx PATH $HOME/.bin $PATH
55+66+if [ -z "$TMUX" ]
77+ set -gx TERM xterm-256color
88+else
99+ set -gx TERM screen-256color
1010+end
1111+1212+agnoster_powerline
···11-function work
22- set project (basename (git rev-parse --show-toplevel))
33- time -f '%E' -- tmux new -s $project ; or time -f '%E' -- tmux attach -t $project
44-end
+1093-3874
gdbinit
···11-# INSTALL INSTRUCTIONS: save as ~/.gdbinit
22-#
33-# DESCRIPTION: A user-friendly gdb configuration file, for x86/x86_64 and ARM platforms.
44-#
55-# REVISION : 8.0.5 (18/08/2013)
66-#
77-# CONTRIBUTORS: mammon_, elaine, pusillus, mong, zhang le, l0kit,
88-# truthix the cyberpunk, fG!, gln
99-#
1010-# FEEDBACK: http://reverse.put.as - reverser@put.as
1111-#
1212-# NOTES: 'help user' in gdb will list the commands/descriptions in this file
1313-# 'context on' now enables auto-display of context screen
1414-#
1515-# MAC OS X NOTES: If you are using this on Mac OS X, you must either attach gdb to a process
1616-# or launch gdb without any options and then load the binary file you want to analyse with "exec-file" option
1717-# If you load the binary from the command line, like $gdb binary-name, this will not work as it should
1818-# For more information, read it here http://reverse.put.as/2008/11/28/apples-gdb-bug/
1919-#
2020-# UPDATE: This bug can be fixed in gdb source. Refer to http://reverse.put.as/2009/08/10/fix-for-apples-gdb-bug-or-why-apple-forks-are-bad/
2121-# and http://reverse.put.as/2009/08/26/gdb-patches/ (if you want the fixed binary for i386)
2222-#
2323-# An updated version of the patch and binary is available at http://reverse.put.as/2011/02/21/update-to-gdb-patches-fix-a-new-bug/
2424-#
2525-# iOS NOTES: iOS gdb from Cydia (and Apple's) suffer from the same OS X bug.
2626-# If you are using this on Mac OS X or iOS, you must either attach gdb to a process
2727-# or launch gdb without any options and then load the binary file you want to analyse with "exec-file" option
2828-# If you load the binary from the command line, like $gdb binary-name, this will not work as it should
2929-# For more information, read it here http://reverse.put.as/2008/11/28/apples-gdb-bug/
3030-#
3131-# CHANGELOG: (older changes at the end of the file)
3232-#
3333-# Version 8.0.6 (05/09/2013)
3434-# - Add patch command to convert bytes to little-endian and patch memory
3535-#
3636-# Version 8.0.5 (18/08/2013)
3737-# - Add commands header and loadcmds to dump Mach-O header information
3838-# - Other fixes and additions from previous commits
3939-#
4040-# Version 8.0.4 (08/05/2013)
4141-# - Detect automatically 32 or 64 bits archs using sizeof(void*).
4242-# Thanks to Tyilo for the simple but very effective idea!
4343-# - Typo in hexdump command also fixed by vuquangtrong.
4444-# - Add shortcuts to attach to VMware kernel debugging gdb stub (kernel32 and kernel64)
4545-#
4646-# Version 8.0.3 (21/03/2013)
4747-# - Add option to colorize or not output (thanks to argp and skier for the request and ideas!)
4848-# - Convert the escape codes into functions so colors can be easily customized
4949-# - Other enhancements available at git commit logs
5050-# Thanks to Plouj, argp, xristos for their ideas and fixes!
5151-#
5252-# Version 8.0.2 (31/07/2012)
5353-# - Merge pull request from mheistermann to support local modifications in a .gdbinit.local file
5454-# - Add a missing opcode to the stepo command
5555-#
5656-# Version 8.0.1 (23/04/2012)
5757-# - Small bug fix to the attsyntax and intelsyntax commands (changing X86 flavor variable was missing)
5858-#
5959-# Version 8.0 (13/04/2012)
6060-# - Merged x86/x64 and ARM versions
6161-# - Added commands intelsyntax and attsyntax to switch between x86 disassembly flavors
6262-# - Added new configuration variables ARM, ARMOPCODES, and X86FLAVOR
6363-# - Code cleanups and fixes to the indentation
6464-# - Bug fixes to some ARM related code
6565-# - Added the dumpmacho command to memory dump the mach-o header to a file
6666-#
6767-# TODO:
6868-#
6969-7070-# __________________gdb options_________________
7171-7272-# set to 1 to have ARM target debugging as default, use the "arm" command to switch inside gdb
7373-set $ARM = 0
7474-# set to 0 if you have problems with the colorized prompt - reported by Plouj with Ubuntu gdb 7.2
7575-set $COLOREDPROMPT = 1
7676-# color the first line of the disassembly - default is green, if you want to change it search for
7777-# SETCOLOR1STLINE and modify it :-)
7878-set $SETCOLOR1STLINE = 0
7979-# set to 0 to remove display of objectivec messages (default is 1)
8080-set $SHOWOBJECTIVEC = 1
8181-# set to 0 to remove display of cpu registers (default is 1)
8282-set $SHOWCPUREGISTERS = 1
8383-# set to 1 to enable display of stack (default is 0)
8484-set $SHOWSTACK = 0
8585-# set to 1 to enable display of data window (default is 0)
8686-set $SHOWDATAWIN = 0
8787-# set to 0 to disable colored display of changed registers
8888-set $SHOWREGCHANGES = 1
8989-# set to 1 so skip command to execute the instruction at the new location
9090-# by default it EIP/RIP will be modified and update the new context but not execute the instruction
9191-set $SKIPEXECUTE = 0
9292-# if $SKIPEXECUTE is 1 configure the type of execution
9393-# 1 = use stepo (do not get into calls), 0 = use stepi (step into calls)
9494-set $SKIPSTEP = 1
9595-# show the ARM opcodes - change to 0 if you don't want such thing (in x/i command)
9696-set $ARMOPCODES = 1
9797-# x86 disassembly flavor: 0 for Intel, 1 for AT&T
9898-set $X86FLAVOR = 0
9999-# use colorized output or not
100100-set $USECOLOR = 1
101101-# to use with remote KDP
102102-set $KDP64BITS = -1
103103-set $64BITS = 0
104104-105105-set confirm off
106106-set verbose off
107107-set history filename ~/.gdb_history
108108-set history save
109109-110110-set output-radix 0x10
111111-set input-radix 0x10
112112-113113-# These make gdb never pause in its output
114114-set height 0
115115-set width 0
116116-117117-set $SHOW_CONTEXT = 1
118118-set $SHOW_NEST_INSN = 0
119119-120120-set $CONTEXTSIZE_STACK = 6
121121-set $CONTEXTSIZE_DATA = 8
122122-set $CONTEXTSIZE_CODE = 8
11+python
1232124124-# __________________end gdb options_________________
33+# GDB dashboard - Modular visual interface for GDB in Python.
1254#
55+# https://github.com/cyrus-and/gdb-dashboard
1266127127-# __________________color functions_________________
128128-#
129129-# color codes
130130-set $BLACK = 0
131131-set $RED = 1
132132-set $GREEN = 2
133133-set $YELLOW = 3
134134-set $BLUE = 4
135135-set $MAGENTA = 5
136136-set $CYAN = 6
137137-set $WHITE = 7
77+import ast
88+import fcntl
99+import os
1010+import re
1111+import struct
1212+import termios
13813139139-# CHANGME: If you want to modify the "theme" change the colors here
140140-# or just create a ~/.gdbinit.local and set these variables there
141141-set $COLOR_REGNAME = $GREEN
142142-set $COLOR_REGVAL = $BLACK
143143-set $COLOR_REGVAL_MODIFIED = $RED
144144-set $COLOR_SEPARATOR = $BLUE
145145-set $COLOR_CPUFLAGS = $RED
1414+# Common attributes ------------------------------------------------------------
14615147147-# this is ugly but there's no else if available :-(
148148-define color
149149- if $USECOLOR == 1
150150- # BLACK
151151- if $arg0 == 0
152152- echo \033[30m
153153- else
154154- # RED
155155- if $arg0 == 1
156156- echo \033[31m
157157- else
158158- # GREEN
159159- if $arg0 == 2
160160- echo \033[32m
161161- else
162162- # YELLOW
163163- if $arg0 == 3
164164- echo \033[33m
165165- else
166166- # BLUE
167167- if $arg0 == 4
168168- echo \033[34m
169169- else
170170- # MAGENTA
171171- if $arg0 == 5
172172- echo \033[35m
173173- else
174174- # CYAN
175175- if $arg0 == 6
176176- echo \033[36m
177177- else
178178- # WHITE
179179- if $arg0 == 7
180180- echo \033[37m
181181- end
182182- end
183183- end
184184- end
185185- end
186186- end
187187- end
188188- end
189189- end
190190-end
1616+class R():
19117192192-define color_reset
193193- if $USECOLOR == 1
194194- echo \033[0m
195195- end
196196-end
1818+ @staticmethod
1919+ def attributes():
2020+ return {
2121+ # miscellaneous
2222+ 'ansi': {
2323+ 'doc': 'Control the ANSI output of the dashboard.',
2424+ 'default': True,
2525+ 'type': bool
2626+ },
2727+ # prompt
2828+ 'prompt': {
2929+ 'doc': """Command prompt.
3030+This value is parsed as a Python format string in which `{status}` is expanded
3131+with the substitution of either `prompt_running` or `prompt_not_running`
3232+attributes, according to the target program status. The resulting string must be
3333+a valid GDB prompt, see the command `python print(gdb.prompt.prompt_help())`""",
3434+ 'default': '{status}'
3535+ },
3636+ 'prompt_running': {
3737+ 'doc': """`{status}` when the target program is running.
3838+See the `prompt` attribute. This value is parsed as a Python format string in
3939+which `{pid}` is expanded with the process identifier of the target program.""",
4040+ 'default': '\[\e[1;35m\]>>>\[\e[0m\]'
4141+ },
4242+ 'prompt_not_running': {
4343+ 'doc': '`{status}` when the target program is not running.',
4444+ 'default': '\[\e[1;30m\]>>>\[\e[0m\]'
4545+ },
4646+ # divider
4747+ 'divider_fill_char_primary': {
4848+ 'doc': 'Filler around the label for primary dividers',
4949+ 'default': '─'
5050+ },
5151+ 'divider_fill_char_secondary': {
5252+ 'doc': 'Filler around the label for secondary dividers',
5353+ 'default': '─'
5454+ },
5555+ 'divider_fill_style_primary': {
5656+ 'doc': 'Style for `divider_fill_char_primary`',
5757+ 'default': '36'
5858+ },
5959+ 'divider_fill_style_secondary': {
6060+ 'doc': 'Style for `divider_fill_char_secondary`',
6161+ 'default': '1;30'
6262+ },
6363+ 'divider_label_style_on_primary': {
6464+ 'doc': 'Label style for non-empty primary dividers',
6565+ 'default': '1;33'
6666+ },
6767+ 'divider_label_style_on_secondary': {
6868+ 'doc': 'Label style for non-empty secondary dividers',
6969+ 'default': '0'
7070+ },
7171+ 'divider_label_style_off_primary': {
7272+ 'doc': 'Label style for empty primary dividers',
7373+ 'default': '33'
7474+ },
7575+ 'divider_label_style_off_secondary': {
7676+ 'doc': 'Label style for empty secondary dividers',
7777+ 'default': '1;30'
7878+ },
7979+ 'divider_label_skip': {
8080+ 'doc': 'Gap between the aligning border and the label.',
8181+ 'default': 3,
8282+ 'type': int,
8383+ 'check': check_ge_zero
8484+ },
8585+ 'divider_label_margin': {
8686+ 'doc': 'Number of spaces around the label.',
8787+ 'default': 1,
8888+ 'type': int,
8989+ 'check': check_ge_zero
9090+ },
9191+ 'divider_label_align_right': {
9292+ 'doc': 'Label alignment flag.',
9393+ 'default': False,
9494+ 'type': bool
9595+ },
9696+ # common styles
9797+ 'style_selected_1': {
9898+ 'default': '1;32'
9999+ },
100100+ 'style_selected_2': {
101101+ 'default': '32'
102102+ },
103103+ 'style_low': {
104104+ 'default': '1;30'
105105+ },
106106+ 'style_high': {
107107+ 'default': '1;37'
108108+ },
109109+ 'style_error': {
110110+ 'default': '31'
111111+ }
112112+ }
197113198198-define color_bold
199199- if $USECOLOR == 1
200200- echo \033[1m
201201- end
202202-end
114114+# Common -----------------------------------------------------------------------
203115204204-define color_underline
205205- if $USECOLOR == 1
206206- echo \033[4m
207207- end
208208-end
116116+def run(command):
117117+ return gdb.execute(command, to_string=True)
209118210210-# this way anyone can have their custom prompt - argp's idea :-)
211211-# can also be used to redefine anything else in particular the colors aka theming
212212-# just remap the color variables defined above
213213-source ~/.gdbinit.local
119119+def ansi(string, style):
120120+ if R.ansi:
121121+ return '\x1b[{}m{}\x1b[0m'.format(style, string)
122122+ else:
123123+ return string
214124215215-# can't use the color functions because we are using the set command
216216-if $COLOREDPROMPT == 1
217217- set prompt \033[31mgdb$ \033[0m
218218-end
125125+def divider(label='', primary=False, active=True):
126126+ width = Dashboard.term_width
127127+ if primary:
128128+ divider_fill_style = R.divider_fill_style_primary
129129+ divider_fill_char = R.divider_fill_char_primary
130130+ divider_label_style_on = R.divider_label_style_on_primary
131131+ divider_label_style_off = R.divider_label_style_off_primary
132132+ else:
133133+ divider_fill_style = R.divider_fill_style_secondary
134134+ divider_fill_char = R.divider_fill_char_secondary
135135+ divider_label_style_on = R.divider_label_style_on_secondary
136136+ divider_label_style_off = R.divider_label_style_off_secondary
137137+ if label:
138138+ if active:
139139+ divider_label_style = divider_label_style_on
140140+ else:
141141+ divider_label_style = divider_label_style_off
142142+ skip = R.divider_label_skip
143143+ margin = R.divider_label_margin
144144+ before = ansi(divider_fill_char * skip, divider_fill_style)
145145+ middle = ansi(label, divider_label_style)
146146+ after_length = width - len(label) - skip - 2 * margin
147147+ after = ansi(divider_fill_char * after_length, divider_fill_style)
148148+ if R.divider_label_align_right:
149149+ before, after = after, before
150150+ return ''.join([before, ' ' * margin, middle, ' ' * margin, after])
151151+ else:
152152+ return ansi(divider_fill_char * width, divider_fill_style)
219153220220-# Initialize these variables else comparisons will fail for coloring
221221-# we must initialize all of them at once, 32 and 64 bits, and ARM.
222222-set $oldrax = 0
223223-set $oldrbx = 0
224224-set $oldrcx = 0
225225-set $oldrdx = 0
226226-set $oldrsi = 0
227227-set $oldrdi = 0
228228-set $oldrbp = 0
229229-set $oldrsp = 0
230230-set $oldr8 = 0
231231-set $oldr9 = 0
232232-set $oldr10 = 0
233233-set $oldr11 = 0
234234-set $oldr12 = 0
235235-set $oldr13 = 0
236236-set $oldr14 = 0
237237-set $oldr15 = 0
238238-set $oldeax = 0
239239-set $oldebx = 0
240240-set $oldecx = 0
241241-set $oldedx = 0
242242-set $oldesi = 0
243243-set $oldedi = 0
244244-set $oldebp = 0
245245-set $oldesp = 0
246246-set $oldr0 = 0
247247-set $oldr1 = 0
248248-set $oldr2 = 0
249249-set $oldr3 = 0
250250-set $oldr4 = 0
251251-set $oldr5 = 0
252252-set $oldr6 = 0
253253-set $oldr7 = 0
254254-set $oldsp = 0
255255-set $oldlr = 0
154154+def check_gt_zero(x):
155155+ return x > 0
256156257257-# used by ptraceme/rptraceme
258258-set $ptrace_bpnum = 0
157157+def check_ge_zero(x):
158158+ return x >= 0
259159260260-# ______________window size control___________
261261-define contextsize-stack
262262- if $argc != 1
263263- help contextsize-stack
264264- else
265265- set $CONTEXTSIZE_STACK = $arg0
266266- end
267267-end
268268-document contextsize-stack
269269-Syntax: contextsize-stack NUM
270270-| Set stack dump window size to NUM lines.
271271-end
160160+def to_unsigned(value, size=8):
161161+ # values from GDB can be used transparently but are not suitable for
162162+ # being printed as unsigned integers, so a conversion is needed
163163+ return int(value.cast(gdb.Value(0).type)) % (2 ** (size * 8))
272164165165+def to_string(value):
166166+ # attempt to convert an inferior value to string; OK when (Python 3 ||
167167+ # simple ASCII); otherwise (Python 2.7 && not ASCII) encode the string as
168168+ # utf8
169169+ try:
170170+ value_string = str(value)
171171+ except UnicodeEncodeError:
172172+ value_string = unicode(value).encode('utf8')
173173+ return value_string
273174274274-define contextsize-data
275275- if $argc != 1
276276- help contextsize-data
277277- else
278278- set $CONTEXTSIZE_DATA = $arg0
279279- end
280280-end
281281-document contextsize-data
282282-Syntax: contextsize-data NUM
283283-| Set data dump window size to NUM lines.
284284-end
175175+def format_address(address):
176176+ pointer_size = gdb.parse_and_eval('$pc').type.sizeof
177177+ return ('0x{{:0{}x}}').format(pointer_size * 2).format(address)
285178179179+# Dashboard --------------------------------------------------------------------
286180287287-define contextsize-code
288288- if $argc != 1
289289- help contextsize-code
290290- else
291291- set $CONTEXTSIZE_CODE = $arg0
292292- end
293293-end
294294-document contextsize-code
295295-Syntax: contextsize-code NUM
296296-| Set code window size to NUM lines.
297297-end
181181+class Dashboard(gdb.Command):
182182+ """Redisplay the dashboard."""
298183184184+ def __init__(self):
185185+ gdb.Command.__init__(self, 'dashboard',
186186+ gdb.COMMAND_USER, gdb.COMPLETE_NONE, True)
187187+ self.output = None # main terminal
188188+ self.enabled = True
189189+ # setup subcommands
190190+ Dashboard.OutputCommand(self)
191191+ Dashboard.EnabledCommand(self)
192192+ Dashboard.LayoutCommand(self)
193193+ # setup style commands
194194+ Dashboard.StyleCommand(self, 'dashboard', R, R.attributes())
195195+ # setup events
196196+ gdb.events.cont.connect(lambda _: self.on_continue())
197197+ gdb.events.stop.connect(lambda _: self.on_stop())
198198+ gdb.events.exited.connect(lambda _: self.on_exit())
299199300300-# _____________breakpoint aliases_____________
301301-define bpl
302302- info breakpoints
303303-end
304304-document bpl
305305-Syntax: bpl
306306-| List all breakpoints.
307307-end
200200+ def on_continue(self):
201201+ # try to contain the GDB messages is a specified are unless the
202202+ # dashboard is printed to a separate file
203203+ if self.enabled and self.is_running() and not self.output:
204204+ Dashboard.update_term_width()
205205+ gdb.write(Dashboard.clear_screen())
206206+ gdb.write(divider('Output/messages', True))
207207+ gdb.write('\n')
208208+ gdb.flush()
308209210210+ def on_stop(self):
211211+ # redisplay the dashboard when the target program stops (the screen is
212212+ # cleared by on_continue when the dashboard is printed to a separate
213213+ # file)
214214+ if self.enabled and self.is_running():
215215+ clear = Dashboard.clear_screen() if self.output else ''
216216+ self.display(clear, self.build(), '\n')
309217310310-define bp
311311- if $argc != 1
312312- help bp
313313- else
314314- break $arg0
315315- end
316316-end
317317-document bp
318318-Syntax: bp LOCATION
319319-| Set breakpoint.
320320-| LOCATION may be a line number, function name, or "*" and an address.
321321-| To break on a symbol you must enclose symbol name inside "".
322322-| Example:
323323-| bp "[NSControl stringValue]"
324324-| Or else you can use directly the break command (break [NSControl stringValue])
325325-end
218218+ def on_exit(self):
219219+ pass
326220221221+ def load_modules(self, modules):
222222+ self.modules = []
223223+ for module in modules:
224224+ info = Dashboard.ModuleInfo(self, module)
225225+ self.modules.append(info)
327226328328-define bpc
329329- if $argc != 1
330330- help bpc
331331- else
332332- clear $arg0
333333- end
334334-end
335335-document bpc
336336-Syntax: bpc LOCATION
337337-| Clear breakpoint.
338338-| LOCATION may be a line number, function name, or "*" and an address.
339339-end
227227+ def redisplay(self):
228228+ # manually redisplay the dashboard
229229+ if self.is_running():
230230+ self.display(Dashboard.clear_screen(), self.build(), '')
340231232232+ def inferior_pid(self):
233233+ return gdb.selected_inferior().pid
341234342342-define bpe
343343- if $argc != 1
344344- help bpe
345345- else
346346- enable $arg0
347347- end
348348-end
349349-document bpe
350350-Syntax: bpe NUM
351351-| Enable breakpoint with number NUM.
352352-end
235235+ def is_running(self):
236236+ return self.inferior_pid() != 0
353237238238+ def build(self):
239239+ # fetch the output width
240240+ try:
241241+ fd = self.output.fileno() if self.output else 1 # main terminal
242242+ Dashboard.update_term_width(fd)
243243+ except:
244244+ # fall back to the main terminal
245245+ Dashboard.update_term_width()
246246+ # fetch lines
247247+ lines = []
248248+ for module in self.modules:
249249+ if not module.enabled:
250250+ continue
251251+ module = module.instance
252252+ # active if more than zero lines
253253+ module_lines = module.lines()
254254+ lines.append(divider(module.label(), True, module_lines))
255255+ lines.extend(module_lines)
256256+ if len(lines) == 0:
257257+ lines.append(divider('Error', True))
258258+ if len(self.modules) == 0:
259259+ lines.append('No module loaded')
260260+ else:
261261+ lines.append('No module to display (see `help dashboard`)')
262262+ lines.append(divider(primary=True))
263263+ # print the dashboard
264264+ return '\n'.join(lines)
354265355355-define bpd
356356- if $argc != 1
357357- help bpd
358358- else
359359- disable $arg0
360360- end
361361-end
362362-document bpd
363363-Syntax: bpd NUM
364364-| Disable breakpoint with number NUM.
365365-end
266266+ def display(self, *data):
267267+ # gdb module has both write() and flush()
268268+ try:
269269+ output = self.output or gdb
270270+ for string in data:
271271+ output.write(string)
272272+ output.flush()
273273+ except:
274274+ Dashboard.err('Cannot write the dashboard')
366275276276+# Utility methods --------------------------------------------------------------
367277368368-define bpt
369369- if $argc != 1
370370- help bpt
371371- else
372372- tbreak $arg0
373373- end
374374-end
375375-document bpt
376376-Syntax: bpt LOCATION
377377-| Set a temporary breakpoint.
378378-| This breakpoint will be automatically deleted when hit!.
379379-| LOCATION may be a line number, function name, or "*" and an address.
380380-end
278278+ @staticmethod
279279+ def start():
280280+ # initialize the dashboard
281281+ dashboard = Dashboard()
282282+ Dashboard.set_custom_prompt(dashboard)
283283+ # parse Python inits, load modules then parse GDB inits
284284+ Dashboard.parse_inits(True)
285285+ modules = Dashboard.get_modules()
286286+ dashboard.load_modules(modules)
287287+ Dashboard.parse_inits(False)
288288+ # GDB overrides
289289+ run('set pagination off')
290290+ run('alias -a db = dashboard')
381291292292+ @staticmethod
293293+ def update_term_width(fd=1): # defaults to the main terminal
294294+ # first 2 shorts (4 byte) of struct winsize
295295+ raw = fcntl.ioctl(fd, termios.TIOCGWINSZ, ' ' * 4)
296296+ height, width = struct.unpack('hh', raw)
297297+ Dashboard.term_width = int(width)
382298383383-define bpm
384384- if $argc != 1
385385- help bpm
386386- else
387387- awatch $arg0
388388- end
389389-end
390390-document bpm
391391-Syntax: bpm EXPRESSION
392392-| Set a read/write breakpoint on EXPRESSION, e.g. *address.
393393-end
299299+ @staticmethod
300300+ def set_custom_prompt(dashboard):
301301+ def custom_prompt(_):
302302+ # render thread status indicator
303303+ if dashboard.is_running():
304304+ pid = dashboard.inferior_pid()
305305+ status = R.prompt_running.format(pid=pid)
306306+ else:
307307+ status = R.prompt_not_running
308308+ # build prompt
309309+ prompt = R.prompt.format(status=status)
310310+ prompt = gdb.prompt.substitute_prompt(prompt)
311311+ return prompt + ' ' # force trailing space
312312+ gdb.prompt_hook = custom_prompt
394313314314+ @staticmethod
315315+ def parse_inits(python):
316316+ for root, dirs, files in os.walk(os.path.expanduser('~/.gdbinit.d/')):
317317+ dirs.sort()
318318+ for init in sorted(files):
319319+ path = os.path.join(root, init)
320320+ _, ext = os.path.splitext(path)
321321+ # either load Python files or GDB
322322+ if python ^ (ext != '.py'):
323323+ gdb.execute('source ' + path)
395324396396-define bhb
397397- if $argc != 1
398398- help bhb
399399- else
400400- hb $arg0
401401- end
402402-end
403403-document bhb
404404-Syntax: bhb LOCATION
405405-| Set hardware assisted breakpoint.
406406-| LOCATION may be a line number, function name, or "*" and an address.
407407-end
325325+ @staticmethod
326326+ def get_modules():
327327+ # scan the scope for modules
328328+ modules = []
329329+ for name in globals():
330330+ obj = globals()[name]
331331+ try:
332332+ if issubclass(obj, Dashboard.Module):
333333+ modules.append(obj)
334334+ except TypeError:
335335+ continue
336336+ # sort modules alphabetically
337337+ modules.sort(key=lambda x: x.__name__)
338338+ return modules
408339340340+ @staticmethod
341341+ def create_command(name, invoke, doc, is_prefix, complete=None):
342342+ Class = type('', (gdb.Command,), {'invoke': invoke, '__doc__': doc})
343343+ Class(name, gdb.COMMAND_USER, complete or gdb.COMPLETE_NONE, is_prefix)
409344410410-define bht
411411- if $argc != 1
412412- help bht
413413- else
414414- thbreak $arg0
415415- end
416416-end
417417-document bht
418418-Usage: bht LOCATION
419419-| Set a temporary hardware breakpoint.
420420-| This breakpoint will be automatically deleted when hit!
421421-| LOCATION may be a line number, function name, or "*" and an address.
422422-end
345345+ @staticmethod
346346+ def err(string):
347347+ print(ansi(string, R.style_error))
423348349349+ @staticmethod
350350+ def complete(word, candidates):
351351+ matching = []
352352+ for candidate in candidates:
353353+ if candidate.startswith(word):
354354+ matching.append(candidate)
355355+ return matching
424356425425-# ______________process information____________
426426-define argv
427427- show args
428428-end
429429-document argv
430430-Syntax: argv
431431-| Print program arguments.
432432-end
357357+ @staticmethod
358358+ def parse_arg(arg):
359359+ # encode unicode GDB command arguments as utf8 in Python 2.7
360360+ if type(arg) is not str:
361361+ arg = arg.encode('utf8')
362362+ return arg
433363364364+ @staticmethod
365365+ def clear_screen():
366366+ return '\x1b[H\x1b[2J'
434367435435-define stack
436436- if $argc == 0
437437- info stack
438438- end
439439- if $argc == 1
440440- info stack $arg0
441441- end
442442- if $argc > 1
443443- help stack
444444- end
445445-end
446446-document stack
447447-Syntax: stack <COUNT>
448448-| Print backtrace of the call stack, or innermost COUNT frames.
449449-end
368368+# Module descriptor ------------------------------------------------------------
450369370370+ class ModuleInfo:
451371452452-define frame
453453- info frame
454454- info args
455455- info locals
456456-end
457457-document frame
458458-Syntax: frame
459459-| Print stack frame.
460460-end
372372+ def __init__(self, dashboard, module):
373373+ self.name = module.__name__.lower() # from class to module name
374374+ self.enabled = True
375375+ self.instance = module()
376376+ self.doc = self.instance.__doc__ or '(no documentation)'
377377+ self.prefix = 'dashboard {}'.format(self.name)
378378+ # add GDB commands
379379+ self.add_main_command(dashboard)
380380+ self.add_style_command(dashboard)
381381+ self.add_subcommands(dashboard)
461382383383+ def add_main_command(self, dashboard):
384384+ module = self
385385+ def invoke(self, arg, from_tty, info=self):
386386+ arg = Dashboard.parse_arg(arg)
387387+ if arg == '':
388388+ info.enabled ^= True
389389+ if dashboard.is_running():
390390+ dashboard.redisplay()
391391+ else:
392392+ status = 'enabled' if info.enabled else 'disabled'
393393+ print('{} module {}'.format(module.name, status))
394394+ else:
395395+ Dashboard.err('Wrong argument "{}"'.format(arg))
396396+ doc_brief = 'Configure the {} module.'.format(self.name)
397397+ doc_extended = 'Toggle the module visibility.'
398398+ doc = '{}\n{}\n\n{}'.format(doc_brief, doc_extended, self.doc)
399399+ Dashboard.create_command(self.prefix, invoke, doc, True)
462400463463-define flagsarm
464464-# conditional flags are
465465-# negative/less than (N), bit 31 of CPSR
466466-# zero (Z), bit 30
467467-# Carry/Borrow/Extend (C), bit 29
468468-# Overflow (V), bit 28
469469- # negative/less than (N), bit 31 of CPSR
470470- if (($cpsr >> 0x1f) & 1)
471471- printf "N "
472472- set $_n_flag = 1
473473- else
474474- printf "n "
475475- set $_n_flag = 0
476476- end
477477- # zero (Z), bit 30
478478- if (($cpsr >> 0x1e) & 1)
479479- printf "Z "
480480- set $_z_flag = 1
481481- else
482482- printf "z "
483483- set $_z_flag = 0
484484- end
485485- # Carry/Borrow/Extend (C), bit 29
486486- if (($cpsr >> 0x1d) & 1)
487487- printf "C "
488488- set $_c_flag = 1
489489- else
490490- printf "c "
491491- set $_c_flag = 0
492492- end
493493- # Overflow (V), bit 28
494494- if (($cpsr >> 0x1c) & 1)
495495- printf "V "
496496- set $_v_flag = 1
497497- else
498498- printf "v "
499499- set $_v_flag = 0
500500- end
501501- # Sticky overflow (Q), bit 27
502502- if (($cpsr >> 0x1b) & 1)
503503- printf "Q "
504504- set $_q_flag = 1
505505- else
506506- printf "q "
507507- set $_q_flag = 0
508508- end
509509- # Java state bit (J), bit 24
510510- # When T=1:
511511- # J = 0 The processor is in Thumb state.
512512- # J = 1 The processor is in ThumbEE state.
513513- if (($cpsr >> 0x18) & 1)
514514- printf "J "
515515- set $_j_flag = 1
516516- else
517517- printf "j "
518518- set $_j_flag = 0
519519- end
520520- # Data endianness bit (E), bit 9
521521- if (($cpsr >> 9) & 1)
522522- printf "E "
523523- set $_e_flag = 1
524524- else
525525- printf "e "
526526- set $_e_flag = 0
527527- end
528528- # Imprecise abort disable bit (A), bit 8
529529- # The A bit is set to 1 automatically. It is used to disable imprecise data aborts.
530530- # It might not be writable in the Nonsecure state if the AW bit in the SCR register is reset.
531531- if (($cpsr >> 8) & 1)
532532- printf "A "
533533- set $_a_flag = 1
534534- else
535535- printf "a "
536536- set $_a_flag = 0
537537- end
538538- # IRQ disable bit (I), bit 7
539539- # When the I bit is set to 1, IRQ interrupts are disabled.
540540- if (($cpsr >> 7) & 1)
541541- printf "I "
542542- set $_i_flag = 1
543543- else
544544- printf "i "
545545- set $_i_flag = 0
546546- end
547547- # FIQ disable bit (F), bit 6
548548- # When the F bit is set to 1, FIQ interrupts are disabled.
549549- # FIQ can be nonmaskable in the Nonsecure state if the FW bit in SCR register is reset.
550550- if (($cpsr >> 6) & 1)
551551- printf "F "
552552- set $_f_flag = 1
553553- else
554554- printf "f "
555555- set $_f_flag = 0
556556- end
557557- # Thumb state bit (F), bit 5
558558- # if 1 then the processor is executing in Thumb state or ThumbEE state depending on the J bit
559559- if (($cpsr >> 5) & 1)
560560- printf "T "
561561- set $_t_flag = 1
562562- else
563563- printf "t "
564564- set $_t_flag = 0
565565- end
566566- # TODO: GE bit ?
567567-end
568568-document flagsarm
569569-Syntax: flagsarm
570570-| Auxiliary function to set ARM cpu flags.
571571-end
401401+ def add_style_command(self, dashboard):
402402+ if 'attributes' in dir(self.instance):
403403+ Dashboard.StyleCommand(dashboard, self.prefix, self.instance,
404404+ self.instance.attributes())
572405406406+ def add_subcommands(self, dashboard):
407407+ if 'commands' in dir(self.instance):
408408+ for name, command in self.instance.commands().items():
409409+ self.add_subcommand(dashboard, name, command)
573410574574-define flagsx86
575575- # OF (overflow) flag
576576- if (((unsigned int)$eflags >> 0xB) & 1)
577577- printf "O "
578578- set $_of_flag = 1
579579- else
580580- printf "o "
581581- set $_of_flag = 0
582582- end
583583- # DF (direction) flag
584584- if (((unsigned int)$eflags >> 0xA) & 1)
585585- printf "D "
586586- else
587587- printf "d "
588588- end
589589- # IF (interrupt enable) flag
590590- if (((unsigned int)$eflags >> 9) & 1)
591591- printf "I "
592592- else
593593- printf "i "
594594- end
595595- # TF (trap) flag
596596- if (((unsigned int)$eflags >> 8) & 1)
597597- printf "T "
598598- else
599599- printf "t "
600600- end
601601- # SF (sign) flag
602602- if (((unsigned int)$eflags >> 7) & 1)
603603- printf "S "
604604- set $_sf_flag = 1
605605- else
606606- printf "s "
607607- set $_sf_flag = 0
608608- end
609609- # ZF (zero) flag
610610- if (((unsigned int)$eflags >> 6) & 1)
611611- printf "Z "
612612- set $_zf_flag = 1
613613- else
614614- printf "z "
615615- set $_zf_flag = 0
616616- end
617617- # AF (adjust) flag
618618- if (((unsigned int)$eflags >> 4) & 1)
619619- printf "A "
620620- else
621621- printf "a "
622622- end
623623- # PF (parity) flag
624624- if (((unsigned int)$eflags >> 2) & 1)
625625- printf "P "
626626- set $_pf_flag = 1
627627- else
628628- printf "p "
629629- set $_pf_flag = 0
630630- end
631631- # CF (carry) flag
632632- if ((unsigned int)$eflags & 1)
633633- printf "C "
634634- set $_cf_flag = 1
635635- else
636636- printf "c "
637637- set $_cf_flag = 0
638638- end
639639- printf "\n"
640640-end
641641-document flagsx86
642642-Syntax: flagsx86
643643-| Auxiliary function to set X86/X64 cpu flags.
644644-end
411411+ def add_subcommand(self, dashboard, name, command):
412412+ action = command['action']
413413+ doc = command['doc']
414414+ complete = command.get('complete')
415415+ def invoke(self, arg, from_tty, info=self):
416416+ arg = Dashboard.parse_arg(arg)
417417+ if info.enabled:
418418+ try:
419419+ action(arg)
420420+ except Exception as e:
421421+ Dashboard.err(e)
422422+ return
423423+ # don't catch redisplay errors
424424+ dashboard.redisplay()
425425+ else:
426426+ Dashboard.err('Module disabled')
427427+ prefix = '{} {}'.format(self.prefix, name)
428428+ Dashboard.create_command(prefix, invoke, doc, False, complete)
645429430430+# GDB commands -----------------------------------------------------------------
646431647647-define flags
648648- # call the auxiliary functions based on target cpu
649649- if $ARM == 1
650650- flagsarm
651651- else
652652- flagsx86
653653- end
654654-end
655655-document flags
656656-Syntax: flags
657657-| Print flags register.
658658-end
432432+ def invoke(self, arg, from_tty):
433433+ arg = Dashboard.parse_arg(arg)
434434+ if arg == '':
435435+ if self.is_running():
436436+ self.redisplay()
437437+ else:
438438+ Dashboard.err('Is the target program running?')
439439+ else:
440440+ Dashboard.err('Wrong argument "{}"'.format(arg))
659441442442+ class OutputCommand(gdb.Command):
443443+ """Set the dashboard output file/TTY.
444444+The dashboard will be appended to the specified file, which will be created if
445445+it does not exists. If the specified file identifies a terminal then its width
446446+will be used to format the dashboard, otherwise falls back to the width of the
447447+main GDB terminal. Without argument the dashboard will be printed on standard
448448+output (default)."""
660449661661-define eflags
662662- if $ARM == 1
663663- # http://www.heyrick.co.uk/armwiki/The_Status_register
664664- printf " N <%d> Z <%d> C <%d> V <%d>",\
665665- (($cpsr >> 0x1f) & 1), (($cpsr >> 0x1e) & 1), \
666666- (($cpsr >> 0x1d) & 1), (($cpsr >> 0x1c) & 1)
667667- printf " Q <%d> J <%d> GE <%d> E <%d> A <%d>",\
668668- (($cpsr >> 0x1b) & 1), (($cpsr >> 0x18) & 1),\
669669- (($cpsr >> 0x10) & 7), (($cpsr >> 9) & 1), (($cpsr >> 8) & 1)
670670- printf " I <%d> F <%d> T <%d> \n",\
671671- (($cpsr >> 7) & 1), (($cpsr >> 6) & 1), \
672672- (($cpsr >> 5) & 1)
673673- else
674674- printf " OF <%d> DF <%d> IF <%d> TF <%d>",\
675675- (((unsigned int)$eflags >> 0xB) & 1), (((unsigned int)$eflags >> 0xA) & 1), \
676676- (((unsigned int)$eflags >> 9) & 1), (((unsigned int)$eflags >> 8) & 1)
677677- printf " SF <%d> ZF <%d> AF <%d> PF <%d> CF <%d>\n",\
678678- (((unsigned int)$eflags >> 7) & 1), (((unsigned int)$eflags >> 6) & 1),\
679679- (((unsigned int)$eflags >> 4) & 1), (((unsigned int)$eflags >> 2) & 1), ((unsigned int)$eflags & 1)
680680- printf " ID <%d> VIP <%d> VIF <%d> AC <%d>",\
681681- (((unsigned int)$eflags >> 0x15) & 1), (((unsigned int)$eflags >> 0x14) & 1), \
682682- (((unsigned int)$eflags >> 0x13) & 1), (((unsigned int)$eflags >> 0x12) & 1)
683683- printf " VM <%d> RF <%d> NT <%d> IOPL <%d>\n",\
684684- (((unsigned int)$eflags >> 0x11) & 1), (((unsigned int)$eflags >> 0x10) & 1),\
685685- (((unsigned int)$eflags >> 0xE) & 1), (((unsigned int)$eflags >> 0xC) & 3)
686686- end
687687-end
688688-document eflags
689689-Syntax: eflags
690690-| Print eflags register.
691691-end
450450+ def __init__(self, dashboard):
451451+ gdb.Command.__init__(self, 'dashboard -output',
452452+ gdb.COMMAND_USER, gdb.COMPLETE_FILENAME)
453453+ self.dashboard = dashboard
692454455455+ def invoke(self, arg, from_tty):
456456+ arg = Dashboard.parse_arg(arg)
457457+ # close the previous output file, if any
458458+ if self.dashboard.output:
459459+ self.dashboard.output.close()
460460+ # set or open the output file
461461+ if arg == '':
462462+ self.dashboard.output = None
463463+ else:
464464+ try:
465465+ self.dashboard.output = open(arg, 'w')
466466+ except:
467467+ Dashboard.err('Cannot open "{}"'.format(arg))
468468+ # redisplay the dashboard in the new output
469469+ self.dashboard.redisplay()
693470694694-define cpsr
695695- eflags
696696-end
697697-document cpsr
698698-Syntax: cpsr
699699-| Print cpsr register.
700700-end
471471+ class EnabledCommand(gdb.Command):
472472+ """Enable or disable the dashboard [on|off].
473473+The current status is printed if no argument is present."""
701474702702-define regarm
703703- printf " "
704704- # R0
705705- color $COLOR_REGNAME
706706- printf "R0:"
707707- if ($r0 != $oldr0 && $SHOWREGCHANGES == 1)
708708- color $COLOR_REGVAL_MODIFIED
709709- else
710710- color $COLOR_REGVAL
711711- end
712712- printf " 0x%08X ", $r0
713713- # R1
714714- color $COLOR_REGNAME
715715- printf "R1:"
716716- if ($r1 != $oldr1 && $SHOWREGCHANGES == 1)
717717- color $COLOR_REGVAL_MODIFIED
718718- else
719719- color $COLOR_REGVAL
720720- end
721721- printf " 0x%08X ", $r1
722722- # R2
723723- color $COLOR_REGNAME
724724- printf "R2:"
725725- if ($r2 != $oldr2 && $SHOWREGCHANGES == 1)
726726- color $COLOR_REGVAL_MODIFIED
727727- else
728728- color $COLOR_REGVAL
729729- end
730730- printf " 0x%08X ", $r2
731731- # R3
732732- color $COLOR_REGNAME
733733- printf "R3:"
734734- if ($r3 != $oldr3 && $SHOWREGCHANGES == 1)
735735- color $COLOR_REGVAL_MODIFIED
736736- else
737737- color $COLOR_REGVAL
738738- end
739739- printf " 0x%08X\n", $r3
740740- printf " "
741741- # R4
742742- color $COLOR_REGNAME
743743- printf "R4:"
744744- if ($r4 != $oldr4 && $SHOWREGCHANGES == 1)
745745- color $COLOR_REGVAL_MODIFIED
746746- else
747747- color $COLOR_REGVAL
748748- end
749749- printf " 0x%08X ", $r4
750750- # R5
751751- color $COLOR_REGNAME
752752- printf "R5:"
753753- if ($r5 != $oldr5 && $SHOWREGCHANGES == 1)
754754- color $COLOR_REGVAL_MODIFIED
755755- else
756756- color $COLOR_REGVAL
757757- end
758758- printf " 0x%08X ", $r5
759759- # R6
760760- color $COLOR_REGNAME
761761- printf "R6:"
762762- if ($r6 != $oldr6 && $SHOWREGCHANGES == 1)
763763- color $COLOR_REGVAL_MODIFIED
764764- else
765765- color $COLOR_REGVAL
766766- end
767767- printf " 0x%08X ", $r6
768768- # R7
769769- color $COLOR_REGNAME
770770- printf "R7:"
771771- if ($r7 != $oldr7 && $SHOWREGCHANGES == 1)
772772- color $COLOR_REGVAL_MODIFIED
773773- else
774774- color $COLOR_REGVAL
775775- end
776776- printf " 0x%08X\n", $r7
777777- printf " "
778778- # R8
779779- color $COLOR_REGNAME
780780- printf "R8:"
781781- if ($r8 != $oldr8 && $SHOWREGCHANGES == 1)
782782- color $COLOR_REGVAL_MODIFIED
783783- else
784784- color $COLOR_REGVAL
785785- end
786786- printf " 0x%08X ", $r8
787787- # R9
788788- color $COLOR_REGNAME
789789- printf "R9:"
790790- if ($r9 != $oldr9 && $SHOWREGCHANGES == 1)
791791- color $COLOR_REGVAL_MODIFIED
792792- else
793793- color $COLOR_REGVAL
794794- end
795795- printf " 0x%08X ", $r9
796796- # R10
797797- color $COLOR_REGNAME
798798- printf "R10:"
799799- if ($r10 != $oldr10 && $SHOWREGCHANGES == 1)
800800- color $COLOR_REGVAL_MODIFIED
801801- else
802802- color $COLOR_REGVAL
803803- end
804804- printf " 0x%08X ", $r10
805805- # R11
806806- color $COLOR_REGNAME
807807- printf "R11:"
808808- if ($r11 != $oldr11 && $SHOWREGCHANGES == 1)
809809- color $COLOR_REGVAL_MODIFIED
810810- else
811811- color $COLOR_REGVAL
812812- end
813813- printf " 0x%08X ", $r11
814814- dumpjump
815815- printf "\n"
816816- # R12
817817- color $COLOR_REGNAME
818818- printf " R12:"
819819- if ($r12 != $oldr12 && $SHOWREGCHANGES == 1)
820820- color $COLOR_REGVAL_MODIFIED
821821- else
822822- color $COLOR_REGVAL
823823- end
824824- printf " 0x%08X", $r12
825825- printf " "
826826- # SP
827827- color $COLOR_REGNAME
828828- printf "SP:"
829829- if ($sp != $oldsp && $SHOWREGCHANGES == 1)
830830- color $COLOR_REGVAL_MODIFIED
831831- else
832832- color $COLOR_REGVAL
833833- end
834834- printf " 0x%08X ", $sp
835835- # LR
836836- color $COLOR_REGNAME
837837- printf "LR:"
838838- if ($lr != $oldlr && $SHOWREGCHANGES == 1)
839839- color $COLOR_REGVAL_MODIFIED
840840- else
841841- color $COLOR_REGVAL
842842- end
843843- printf " 0x%08X ", $lr
844844- # PC
845845- color $COLOR_REGNAME
846846- printf "PC:"
847847- color $COLOR_REGVAL_MODIFIED
848848- printf " 0x%08X ", $pc
849849- color_bold
850850- color_underline
851851- color $COLOR_CPUFLAGS
852852- flags
853853- color_reset
854854- printf "\n"
855855-end
856856-document regarm
857857-Syntax: regarm
858858-| Auxiliary function to display ARM registers.
859859-end
475475+ def __init__(self, dashboard):
476476+ gdb.Command.__init__(self, 'dashboard -enabled', gdb.COMMAND_USER)
477477+ self.dashboard = dashboard
860478861861-define regx64
862862- # 64bits stuff
863863- printf " "
864864- # RAX
865865- color $COLOR_REGNAME
866866- printf "RAX:"
867867- if ($rax != $oldrax && $SHOWREGCHANGES == 1)
868868- color $COLOR_REGVAL_MODIFIED
869869- else
870870- color $COLOR_REGVAL
871871- end
872872- printf " 0x%016lX ", $rax
873873- # RBX
874874- color $COLOR_REGNAME
875875- printf "RBX:"
876876- if ($rbx != $oldrbx && $SHOWREGCHANGES == 1)
877877- color $COLOR_REGVAL_MODIFIED
878878- else
879879- color $COLOR_REGVAL
880880- end
881881- printf " 0x%016lX ", $rbx
882882- # RBP
883883- color $COLOR_REGNAME
884884- printf "RBP:"
885885- if ($rbp != $oldrbp && $SHOWREGCHANGES == 1)
886886- color $COLOR_REGVAL_MODIFIED
887887- else
888888- color $COLOR_REGVAL
889889- end
890890- printf " 0x%016lX ", $rbp
891891- # RSP
892892- color $COLOR_REGNAME
893893- printf "RSP:"
894894- if ($rsp != $oldrsp && $SHOWREGCHANGES == 1)
895895- color $COLOR_REGVAL_MODIFIED
896896- else
897897- color $COLOR_REGVAL
898898- end
899899- printf " 0x%016lX ", $rsp
900900- color_bold
901901- color_underline
902902- color $COLOR_CPUFLAGS
903903- flags
904904- color_reset
905905- printf " "
906906- # RDI
907907- color $COLOR_REGNAME
908908- printf "RDI:"
909909- if ($rdi != $oldrdi && $SHOWREGCHANGES == 1)
910910- color $COLOR_REGVAL_MODIFIED
911911- else
912912- color $COLOR_REGVAL
913913- end
914914- printf " 0x%016lX ", $rdi
915915- # RSI
916916- color $COLOR_REGNAME
917917- printf "RSI:"
918918- if ($rsi != $oldrsi && $SHOWREGCHANGES == 1)
919919- color $COLOR_REGVAL_MODIFIED
920920- else
921921- color $COLOR_REGVAL
922922- end
923923- printf " 0x%016lX ", $rsi
924924- # RDX
925925- color $COLOR_REGNAME
926926- printf "RDX:"
927927- if ($rdx != $oldrdx && $SHOWREGCHANGES == 1)
928928- color $COLOR_REGVAL_MODIFIED
929929- else
930930- color $COLOR_REGVAL
931931- end
932932- printf " 0x%016lX ", $rdx
933933- # RCX
934934- color $COLOR_REGNAME
935935- printf "RCX:"
936936- if ($rcx != $oldrcx && $SHOWREGCHANGES == 1)
937937- color $COLOR_REGVAL_MODIFIED
938938- else
939939- color $COLOR_REGVAL
940940- end
941941- printf " 0x%016lX ", $rcx
942942- # RIP
943943- color $COLOR_REGNAME
944944- printf "RIP:"
945945- color $COLOR_REGVAL_MODIFIED
946946- printf " 0x%016lX\n ", $rip
947947- # R8
948948- color $COLOR_REGNAME
949949- printf "R8 :"
950950- if ($r8 != $oldr8 && $SHOWREGCHANGES == 1)
951951- color $COLOR_REGVAL_MODIFIED
952952- else
953953- color $COLOR_REGVAL
954954- end
955955- printf " 0x%016lX ", $r8
956956- # R9
957957- color $COLOR_REGNAME
958958- printf "R9 :"
959959- if ($r9 != $oldr9 && $SHOWREGCHANGES == 1)
960960- color $COLOR_REGVAL_MODIFIED
961961- else
962962- color $COLOR_REGVAL
963963- end
964964- printf " 0x%016lX ", $r9
965965- # R10
966966- color $COLOR_REGNAME
967967- printf "R10:"
968968- if ($r10 != $oldr10 && $SHOWREGCHANGES == 1)
969969- color $COLOR_REGVAL_MODIFIED
970970- else
971971- color $COLOR_REGVAL
972972- end
973973- printf " 0x%016lX ", $r10
974974- # R11
975975- color $COLOR_REGNAME
976976- printf "R11:"
977977- if ($r11 != $oldr11 && $SHOWREGCHANGES == 1)
978978- color $COLOR_REGVAL_MODIFIED
979979- else
980980- color $COLOR_REGVAL
981981- end
982982- printf " 0x%016lX ", $r11
983983- # R12
984984- color $COLOR_REGNAME
985985- printf "R12:"
986986- if ($r12 != $oldr12 && $SHOWREGCHANGES == 1)
987987- color $COLOR_REGVAL_MODIFIED
988988- else
989989- color $COLOR_REGVAL
990990- end
991991- printf " 0x%016lX\n ", $r12
992992- # R13
993993- color $COLOR_REGNAME
994994- printf "R13:"
995995- if ($r13 != $oldr13 && $SHOWREGCHANGES == 1)
996996- color $COLOR_REGVAL_MODIFIED
997997- else
998998- color $COLOR_REGVAL
999999- end
10001000- printf " 0x%016lX ", $r13
10011001- # R14
10021002- color $COLOR_REGNAME
10031003- printf "R14:"
10041004- if ($r14 != $oldr14 && $SHOWREGCHANGES == 1)
10051005- color $COLOR_REGVAL_MODIFIED
10061006- else
10071007- color $COLOR_REGVAL
10081008- end
10091009- printf " 0x%016lX ", $r14
10101010- # R15
10111011- color $COLOR_REGNAME
10121012- printf "R15:"
10131013- if ($r15 != $oldr15 && $SHOWREGCHANGES == 1)
10141014- color $COLOR_REGVAL_MODIFIED
10151015- else
10161016- color $COLOR_REGVAL
10171017- end
10181018- printf " 0x%016lX\n ", $r15
10191019- color $COLOR_REGNAME
10201020- printf "CS:"
10211021- color $COLOR_REGVAL
10221022- printf " %04X ", $cs
10231023- color $COLOR_REGNAME
10241024- printf "DS:"
10251025- color $COLOR_REGVAL
10261026- printf " %04X ", $ds
10271027- color $COLOR_REGNAME
10281028- printf "ES:"
10291029- color $COLOR_REGVAL
10301030- printf " %04X ", $es
10311031- color $COLOR_REGNAME
10321032- printf "FS:"
10331033- color $COLOR_REGVAL
10341034- printf " %04X ", $fs
10351035- color $COLOR_REGNAME
10361036- printf "GS:"
10371037- color $COLOR_REGVAL
10381038- printf " %04X ", $gs
10391039- color $COLOR_REGNAME
10401040- printf "SS:"
10411041- color $COLOR_REGVAL
10421042- printf " %04X", $ss
10431043- color_reset
10441044-end
10451045-document regx64
10461046-Syntax: regx64
10471047-| Auxiliary function to display X86_64 registers.
10481048-end
479479+ def invoke(self, arg, from_tty):
480480+ arg = Dashboard.parse_arg(arg)
481481+ if arg == '':
482482+ status = 'enabled' if self.dashboard.enabled else 'disabled'
483483+ print('The dashboard is {}'.format(status))
484484+ elif arg == 'on':
485485+ self.dashboard.enabled = True
486486+ self.dashboard.redisplay()
487487+ elif arg == 'off':
488488+ self.dashboard.enabled = False
489489+ else:
490490+ msg = 'Wrong argument "{}"; expecting "on" or "off"'
491491+ Dashboard.err(msg.format(arg))
1049492493493+ def complete(self, text, word):
494494+ return Dashboard.complete(word, ['on', 'off'])
105049510511051-define regx86
10521052- printf " "
10531053- # EAX
10541054- color $COLOR_REGNAME
10551055- printf "EAX:"
10561056- if ($eax != $oldeax && $SHOWREGCHANGES == 1)
10571057- color $COLOR_REGVAL_MODIFIED
10581058- else
10591059- color $COLOR_REGVAL
10601060- end
10611061- printf " 0x%08X ", $eax
10621062- # EBX
10631063- color $COLOR_REGNAME
10641064- printf "EBX:"
10651065- if ($ebx != $oldebx && $SHOWREGCHANGES == 1)
10661066- color $COLOR_REGVAL_MODIFIED
10671067- else
10681068- color $COLOR_REGVAL
10691069- end
10701070- printf " 0x%08X ", $ebx
10711071- # ECX
10721072- color $COLOR_REGNAME
10731073- printf "ECX:"
10741074- if ($ecx != $oldecx && $SHOWREGCHANGES == 1)
10751075- color $COLOR_REGVAL_MODIFIED
10761076- else
10771077- color $COLOR_REGVAL
10781078- end
10791079- printf " 0x%08X ", $ecx
10801080- # EDX
10811081- color $COLOR_REGNAME
10821082- printf "EDX:"
10831083- if ($edx != $oldedx && $SHOWREGCHANGES == 1)
10841084- color $COLOR_REGVAL_MODIFIED
10851085- else
10861086- color $COLOR_REGVAL
10871087- end
10881088- printf " 0x%08X ", $edx
10891089- color_bold
10901090- color_underline
10911091- color $COLOR_CPUFLAGS
10921092- flags
10931093- color_reset
10941094- printf " "
10951095- # ESI
10961096- color $COLOR_REGNAME
10971097- printf "ESI:"
10981098- if ($esi != $oldesi && $SHOWREGCHANGES == 1)
10991099- color $COLOR_REGVAL_MODIFIED
11001100- else
11011101- color $COLOR_REGVAL
11021102- end
11031103- printf " 0x%08X ", $esi
11041104- # EDI
11051105- color $COLOR_REGNAME
11061106- printf "EDI:"
11071107- if ($edi != $oldedi && $SHOWREGCHANGES == 1)
11081108- color $COLOR_REGVAL_MODIFIED
11091109- else
11101110- color $COLOR_REGVAL
11111111- end
11121112- printf " 0x%08X ", $edi
11131113- # EBP
11141114- color $COLOR_REGNAME
11151115- printf "EBP:"
11161116- if ($ebp != $oldebp && $SHOWREGCHANGES == 1)
11171117- color $COLOR_REGVAL_MODIFIED
11181118- else
11191119- color $COLOR_REGVAL
11201120- end
11211121- printf " 0x%08X ", $ebp
11221122- # ESP
11231123- color $COLOR_REGNAME
11241124- printf "ESP:"
11251125- if ($esp != $oldesp && $SHOWREGCHANGES == 1)
11261126- color $COLOR_REGVAL_MODIFIED
11271127- else
11281128- color $COLOR_REGVAL
11291129- end
11301130- printf " 0x%08X ", $esp
11311131- # EIP
11321132- color $COLOR_REGNAME
11331133- printf "EIP:"
11341134- color $COLOR_REGVAL_MODIFIED
11351135- printf " 0x%08X\n ", $eip
11361136- color $COLOR_REGNAME
11371137- printf "CS:"
11381138- color $COLOR_REGVAL
11391139- printf " %04X ", $cs
11401140- color $COLOR_REGNAME
11411141- printf "DS:"
11421142- color $COLOR_REGVAL
11431143- printf " %04X ", $ds
11441144- color $COLOR_REGNAME
11451145- printf "ES:"
11461146- color $COLOR_REGVAL
11471147- printf " %04X ", $es
11481148- color $COLOR_REGNAME
11491149- printf "FS:"
11501150- color $COLOR_REGVAL
11511151- printf " %04X ", $fs
11521152- color $COLOR_REGNAME
11531153- printf "GS:"
11541154- color $COLOR_REGVAL
11551155- printf " %04X ", $gs
11561156- color $COLOR_REGNAME
11571157- printf "SS:"
11581158- color $COLOR_REGVAL
11591159- printf " %04X", $ss
11601160- color_reset
11611161-end
11621162-document regx86
11631163-Syntax: regx86
11641164-| Auxiliary function to display X86 registers.
11651165-end
496496+ class LayoutCommand(gdb.Command):
497497+ """Set or show the dashboard layout.
498498+Accepts a space-separated list of directive. Each directive is in the form
499499+"[!]<module>". Modules in the list are placed in the dashboard in the same order
500500+as they appear and those prefixed by "!" are disabled by default. Omitted
501501+modules are hidden and placed at the bottom in alphabetical order. Without
502502+arguments the current layout is shown; enabled and disabled modules are properly
503503+marked."""
1166504505505+ def __init__(self, dashboard):
506506+ gdb.Command.__init__(self, 'dashboard -layout', gdb.COMMAND_USER)
507507+ self.dashboard = dashboard
116750811681168-define reg
11691169- if $ARM == 1
11701170- regarm
11711171- if ($SHOWREGCHANGES == 1)
11721172- set $oldr0 = $r0
11731173- set $oldr1 = $r1
11741174- set $oldr2 = $r2
11751175- set $oldr3 = $r3
11761176- set $oldr4 = $r4
11771177- set $oldr5 = $r5
11781178- set $oldr6 = $r6
11791179- set $oldr7 = $r7
11801180- set $oldr8 = $r8
11811181- set $oldr9 = $r9
11821182- set $oldr10 = $r10
11831183- set $oldr11 = $r11
11841184- set $oldr12 = $r12
11851185- set $oldsp = $sp
11861186- set $oldlr = $lr
11871187- end
11881188- else
11891189- if ($64BITS == 1)
11901190- regx64
11911191- else
11921192- regx86
11931193- end
11941194- # call smallregisters
11951195- smallregisters
11961196- # display conditional jump routine
11971197- if ($64BITS == 1)
11981198- printf "\t\t\t\t"
11991199- end
12001200- dumpjump
12011201- printf "\n"
12021202- if ($SHOWREGCHANGES == 1)
12031203- if ($64BITS == 1)
12041204- set $oldrax = $rax
12051205- set $oldrbx = $rbx
12061206- set $oldrcx = $rcx
12071207- set $oldrdx = $rdx
12081208- set $oldrsi = $rsi
12091209- set $oldrdi = $rdi
12101210- set $oldrbp = $rbp
12111211- set $oldrsp = $rsp
12121212- set $oldr8 = $r8
12131213- set $oldr9 = $r9
12141214- set $oldr10 = $r10
12151215- set $oldr11 = $r11
12161216- set $oldr12 = $r12
12171217- set $oldr13 = $r13
12181218- set $oldr14 = $r14
12191219- set $oldr15 = $r15
12201220- else
12211221- set $oldeax = $eax
12221222- set $oldebx = $ebx
12231223- set $oldecx = $ecx
12241224- set $oldedx = $edx
12251225- set $oldesi = $esi
12261226- set $oldedi = $edi
12271227- set $oldebp = $ebp
12281228- set $oldesp = $esp
12291229- end
12301230- end
12311231- end
12321232-end
12331233-document reg
12341234-Syntax: reg
12351235-| Print CPU registers.
12361236-end
509509+ def invoke(self, arg, from_tty):
510510+ arg = Dashboard.parse_arg(arg)
511511+ directives = str(arg).split()
512512+ if directives:
513513+ self.layout(directives)
514514+ if from_tty and not self.dashboard.is_running():
515515+ self.show()
516516+ else:
517517+ self.show()
1237518519519+ def show(self):
520520+ for module in self.dashboard.modules:
521521+ style = R.style_high if module.enabled else R.style_low
522522+ print(ansi(module.name, style))
123852312391239-define smallregisters
12401240- if ($64BITS == 1)
12411241- #64bits stuff
12421242- # from rax
12431243- set $eax = $rax & 0xffffffff
12441244- set $ax = $rax & 0xffff
12451245- set $al = $ax & 0xff
12461246- set $ah = $ax >> 8
12471247- # from rbx
12481248- set $ebx = $rbx & 0xffffffff
12491249- set $bx = $rbx & 0xffff
12501250- set $bl = $bx & 0xff
12511251- set $bh = $bx >> 8
12521252- # from rcx
12531253- set $ecx = $rcx & 0xffffffff
12541254- set $cx = $rcx & 0xffff
12551255- set $cl = $cx & 0xff
12561256- set $ch = $cx >> 8
12571257- # from rdx
12581258- set $edx = $rdx & 0xffffffff
12591259- set $dx = $rdx & 0xffff
12601260- set $dl = $dx & 0xff
12611261- set $dh = $dx >> 8
12621262- # from rsi
12631263- set $esi = $rsi & 0xffffffff
12641264- set $si = $rsi & 0xffff
12651265- # from rdi
12661266- set $edi = $rdi & 0xffffffff
12671267- set $di = $rdi & 0xffff
12681268- #32 bits stuff
12691269- else
12701270- # from eax
12711271- set $ax = $eax & 0xffff
12721272- set $al = $ax & 0xff
12731273- set $ah = $ax >> 8
12741274- # from ebx
12751275- set $bx = $ebx & 0xffff
12761276- set $bl = $bx & 0xff
12771277- set $bh = $bx >> 8
12781278- # from ecx
12791279- set $cx = $ecx & 0xffff
12801280- set $cl = $cx & 0xff
12811281- set $ch = $cx >> 8
12821282- # from edx
12831283- set $dx = $edx & 0xffff
12841284- set $dl = $dx & 0xff
12851285- set $dh = $dx >> 8
12861286- # from esi
12871287- set $si = $esi & 0xffff
12881288- # from edi
12891289- set $di = $edi & 0xffff
12901290- end
12911291-end
12921292-document smallregisters
12931293-Syntax: smallregisters
12941294-| Create the 16 and 8 bit cpu registers (gdb doesn't have them by default).
12951295-| And 32bits if we are dealing with 64bits binaries.
12961296-end
524524+ def layout(self, directives):
525525+ modules = self.dashboard.modules
526526+ # reset visibility
527527+ for module in modules:
528528+ module.enabled = False
529529+ # move and enable the selected modules on top
530530+ last = 0
531531+ n_enabled = 0
532532+ for directive in directives:
533533+ # parse next directive
534534+ enabled = (directive[0] != '!')
535535+ name = directive[not enabled:]
536536+ try:
537537+ # it may actually start from last, but in this way repeated
538538+ # modules can be handler transparently and without error
539539+ todo = enumerate(modules[last:], start=last)
540540+ index = next(i for i, m in todo if name == m.name)
541541+ modules[index].enabled = enabled
542542+ modules.insert(last, modules.pop(index))
543543+ last += 1
544544+ n_enabled += enabled
545545+ except StopIteration:
546546+ def find_module(x):
547547+ return x.name == name
548548+ first_part = modules[:last]
549549+ if len(filter(find_module, first_part)) == 0:
550550+ Dashboard.err('Cannot find module "{}"'.format(name))
551551+ else:
552552+ Dashboard.err('Module "{}" already set'.format(name))
553553+ continue
554554+ # redisplay the dashboard
555555+ if n_enabled:
556556+ self.dashboard.redisplay()
1297557558558+ def complete(self, text, word):
559559+ all_modules = (m.name for m in self.dashboard.modules)
560560+ return Dashboard.complete(word, all_modules)
129856112991299-define func
13001300- if $argc == 0
13011301- info functions
13021302- end
13031303- if $argc == 1
13041304- info functions $arg0
13051305- end
13061306- if $argc > 1
13071307- help func
13081308- end
13091309-end
13101310-document func
13111311-Syntax: func <REGEXP>
13121312-| Print all function names in target, or those matching REGEXP.
13131313-end
562562+ class StyleCommand(gdb.Command):
563563+ """Access the stylable attributes.
564564+Without arguments print all the stylable attributes. Subcommands are used to set
565565+or print (when the value is omitted) individual attributes."""
1314566567567+ def __init__(self, dashboard, prefix, obj, attributes):
568568+ self.prefix = prefix + ' -style'
569569+ gdb.Command.__init__(self, self.prefix,
570570+ gdb.COMMAND_USER, gdb.COMPLETE_NONE, True)
571571+ self.dashboard = dashboard
572572+ self.obj = obj
573573+ self.attributes = attributes
574574+ self.add_styles()
131557513161316-define var
13171317- if $argc == 0
13181318- info variables
13191319- end
13201320- if $argc == 1
13211321- info variables $arg0
13221322- end
13231323- if $argc > 1
13241324- help var
13251325- end
13261326-end
13271327-document var
13281328-Syntax: var <REGEXP>
13291329-| Print all global and static variable names (symbols), or those matching REGEXP.
13301330-end
576576+ def add_styles(self):
577577+ this = self
578578+ for name, attribute in self.attributes.items():
579579+ # fetch fields
580580+ attr_name = attribute.get('name', name)
581581+ attr_type = attribute.get('type', str)
582582+ attr_check = attribute.get('check', lambda _: True)
583583+ attr_default = attribute['default']
584584+ # set the default value (coerced to the type)
585585+ value = attr_type(attr_default)
586586+ setattr(self.obj, attr_name, value)
587587+ # create the command
588588+ def invoke(self, arg, from_tty, name=name, attr_name=attr_name,
589589+ attr_type=attr_type, attr_check=attr_check):
590590+ new_value = Dashboard.parse_arg(arg)
591591+ if new_value == '':
592592+ # print the current value
593593+ value = getattr(this.obj, attr_name)
594594+ print('{} = {!r}'.format(name, value))
595595+ else:
596596+ try:
597597+ # convert and check the new value
598598+ parsed = ast.literal_eval(new_value)
599599+ value = attr_type(parsed)
600600+ if not attr_check(value):
601601+ msg = 'Invalid value "{}" for "{}"'
602602+ raise Exception(msg.format(new_value, name))
603603+ except Exception as e:
604604+ Dashboard.err(e)
605605+ else:
606606+ # set and redisplay
607607+ setattr(this.obj, attr_name, value)
608608+ this.dashboard.redisplay()
609609+ prefix = self.prefix + ' ' + name
610610+ doc = attribute.get('doc', 'This style is self-documenting')
611611+ Dashboard.create_command(prefix, invoke, doc, False)
1331612613613+ def invoke(self, arg, from_tty):
614614+ # print all the pairs
615615+ for name, attribute in self.attributes.items():
616616+ attr_name = attribute.get('name', name)
617617+ value = getattr(self.obj, attr_name)
618618+ print('{} = {!r}'.format(name, value))
133261913331333-define lib
13341334- info sharedlibrary
13351335-end
13361336-document lib
13371337-Syntax: lib
13381338-| Print shared libraries linked to target.
13391339-end
620620+# Base module ------------------------------------------------------------------
1340621622622+ # just a tag
623623+ class Module():
624624+ pass
134162513421342-define sig
13431343- if $argc == 0
13441344- info signals
13451345- end
13461346- if $argc == 1
13471347- info signals $arg0
13481348- end
13491349- if $argc > 1
13501350- help sig
13511351- end
13521352-end
13531353-document sig
13541354-Syntax: sig <SIGNAL>
13551355-| Print what debugger does when program gets various signals.
13561356-| Specify a SIGNAL as argument to print info on that signal only.
13571357-end
626626+# Default modules --------------------------------------------------------------
1358627628628+class Source(Dashboard.Module):
629629+ """Show the program source code, if available."""
135963013601360-define threads
13611361- info threads
13621362-end
13631363-document threads
13641364-Syntax: threads
13651365-| Print threads in target.
13661366-end
631631+ def __init__(self):
632632+ self.file_name = None
633633+ self.source_lines = []
1367634635635+ def label(self):
636636+ return 'Source'
136863713691369-define dis
13701370- if $argc == 0
13711371- disassemble
13721372- end
13731373- if $argc == 1
13741374- disassemble $arg0
13751375- end
13761376- if $argc == 2
13771377- disassemble $arg0 $arg1
13781378- end
13791379- if $argc > 2
13801380- help dis
13811381- end
13821382-end
13831383-document dis
13841384-Syntax: dis <ADDR1> <ADDR2>
13851385-| Disassemble a specified section of memory.
13861386-| Default is to disassemble the function surrounding the PC (program counter) of selected frame.
13871387-| With one argument, ADDR1, the function surrounding this address is dumped.
13881388-| Two arguments are taken as a range of memory to dump.
13891389-end
638638+ def lines(self):
639639+ # try to fetch the current line (skip if no line information)
640640+ sal = gdb.selected_frame().find_sal()
641641+ current_line = sal.line
642642+ if current_line == 0:
643643+ return []
644644+ # reload the source file if changed
645645+ file_name = sal.symtab.fullname()
646646+ if file_name != self.file_name:
647647+ self.file_name = file_name
648648+ try:
649649+ with open(self.file_name) as source:
650650+ self.source_lines = source.readlines()
651651+ except:
652652+ msg = 'Cannot access "{}"'.format(self.file_name)
653653+ return [ansi(msg, R.style_error)]
654654+ # compute the line range
655655+ start = max(current_line - 1 - self.context, 0)
656656+ end = min(current_line - 1 + self.context, len(self.source_lines))
657657+ # return the source code listing
658658+ out = []
659659+ number_format = '{{:>{}}}'.format(len(str(end)))
660660+ for number, line in enumerate(self.source_lines[start:end], start + 1):
661661+ if int(number) == current_line:
662662+ line_format = ansi(number_format + ' {}', R.style_selected_1)
663663+ else:
664664+ line_format = ansi(number_format, R.style_low) + ' {}'
665665+ out.append(line_format.format(number, line.rstrip('\n')))
666666+ return out
1390667668668+ def set_context(self, arg):
669669+ msg = 'expecting a positive integer'
670670+ self.context = parse_value(arg, int, check_ge_zero, msg)
139167113921392-# __________hex/ascii dump an address_________
13931393-define ascii_char
13941394- if $argc != 1
13951395- help ascii_char
13961396- else
13971397- # thanks elaine :)
13981398- set $_c = *(unsigned char *)($arg0)
13991399- if ($_c < 0x20 || $_c > 0x7E)
14001400- printf "."
14011401- else
14021402- printf "%c", $_c
14031403- end
14041404- end
14051405-end
14061406-document ascii_char
14071407-Syntax: ascii_char ADDR
14081408-| Print ASCII value of byte at address ADDR.
14091409-| Print "." if the value is unprintable.
14101410-end
672672+ def attributes(self):
673673+ return {
674674+ 'context': {
675675+ 'doc': 'Number of context lines.',
676676+ 'default': 5,
677677+ 'type': int,
678678+ 'check': check_ge_zero
679679+ }
680680+ }
1411681682682+class Assembly(Dashboard.Module):
683683+ """Show the disassembled code surrounding the program counter. The
684684+instructions constituting the current statement are marked, if available."""
141268514131413-define hex_quad
14141414- if $argc != 1
14151415- help hex_quad
14161416- else
14171417- printf "%02X %02X %02X %02X %02X %02X %02X %02X", \
14181418- *(unsigned char*)($arg0), *(unsigned char*)($arg0 + 1), \
14191419- *(unsigned char*)($arg0 + 2), *(unsigned char*)($arg0 + 3), \
14201420- *(unsigned char*)($arg0 + 4), *(unsigned char*)($arg0 + 5), \
14211421- *(unsigned char*)($arg0 + 6), *(unsigned char*)($arg0 + 7)
14221422- end
14231423-end
14241424-document hex_quad
14251425-Syntax: hex_quad ADDR
14261426-| Print eight hexadecimal bytes starting at address ADDR.
14271427-end
686686+ def label(self):
687687+ return 'Assembly'
1428688689689+ def lines(self):
690690+ line_info = None
691691+ frame = gdb.selected_frame() # PC is here
692692+ disassemble = frame.architecture().disassemble
693693+ try:
694694+ # try to fetch the function boundaries using the disassemble command
695695+ output = run('disassemble').split('\n')
696696+ start = int(re.split('[ :]', output[1][3:], 1)[0], 16)
697697+ end = int(re.split('[ :]', output[-3][3:], 1)[0], 16)
698698+ asm = disassemble(start, end_pc=end)
699699+ # find the location of the PC
700700+ pc_index = next(index for index, instr in enumerate(asm)
701701+ if instr['addr'] == frame.pc())
702702+ start = max(pc_index - self.context, 0)
703703+ end = pc_index + self.context + 1
704704+ asm = asm[start:end]
705705+ # if there are line information then use it, it may be that
706706+ # line_info is not None but line_info.last is None
707707+ line_info = gdb.find_pc_line(frame.pc())
708708+ line_info = line_info if line_info.last else None
709709+ except gdb.error:
710710+ # if it is not possible (stripped binary) start from PC and end
711711+ # after twice the context
712712+ asm = disassemble(frame.pc(), count=2 * self.context + 1)
713713+ # fetch function start if available
714714+ func_start = None
715715+ if self.show_function and frame.name():
716716+ try:
717717+ value = gdb.parse_and_eval(frame.name()).address
718718+ func_start = to_unsigned(value)
719719+ except gdb.error:
720720+ pass # e.g., @plt
721721+ # return the machine code
722722+ max_length = max(instr['length'] for instr in asm)
723723+ inferior = gdb.selected_inferior()
724724+ out = []
725725+ for index, instr in enumerate(asm):
726726+ addr = instr['addr']
727727+ length = instr['length']
728728+ text = instr['asm']
729729+ addr_str = format_address(addr)
730730+ if self.show_opcodes:
731731+ # fetch and format opcode
732732+ region = inferior.read_memory(addr, length)
733733+ opcodes = (' '.join('{:02x}'.format(ord(byte))
734734+ for byte in region))
735735+ opcodes += (max_length - len(region)) * 3 * ' ' + ' '
736736+ else:
737737+ opcodes = ''
738738+ # compute the offset if available
739739+ if self.show_function:
740740+ if func_start:
741741+ max_offset = len(str(asm[-1]['addr'] - func_start))
742742+ offset = str(addr - func_start).ljust(max_offset)
743743+ func_info = '{}+{} '.format(frame.name(), offset)
744744+ else:
745745+ func_info = '? '
746746+ else:
747747+ func_info = ''
748748+ format_string = '{} {}{}{}'
749749+ if addr == frame.pc():
750750+ addr_str = ansi(addr_str, R.style_selected_1)
751751+ opcodes = ansi(opcodes, R.style_selected_1)
752752+ func_info = ansi(func_info, R.style_selected_1)
753753+ text = ansi(text, R.style_selected_1)
754754+ elif line_info and line_info.pc <= addr < line_info.last:
755755+ addr_str = ansi(addr_str, R.style_selected_2)
756756+ opcodes = ansi(opcodes, R.style_selected_2)
757757+ func_info = ansi(func_info, R.style_selected_2)
758758+ text = ansi(text, R.style_selected_2)
759759+ else:
760760+ addr_str = ansi(addr_str, R.style_low)
761761+ func_info = ansi(func_info, R.style_low)
762762+ out.append(format_string.format(addr_str, opcodes, func_info, text))
763763+ return out
142976414301430-define hexdump
14311431- if $argc == 1
14321432- hexdump_aux $arg0
14331433- else
14341434- if $argc == 2
14351435- set $_count = 0
14361436- while ($_count < $arg1)
14371437- set $_i = ($_count * 0x10)
14381438- hexdump_aux $arg0+$_i
14391439- set $_count++
14401440- end
14411441- else
14421442- help hexdump
14431443- end
14441444- end
14451445-end
14461446-document hexdump
14471447-Syntax: hexdump ADDR <NR_LINES>
14481448-| Display a 16-byte hex/ASCII dump of memory starting at address ADDR.
14491449-| Optional parameter is the number of lines to display if you want more than one.
14501450-end
765765+ def attributes(self):
766766+ return {
767767+ 'context': {
768768+ 'doc': 'Number of context instructions.',
769769+ 'default': 3,
770770+ 'type': int,
771771+ 'check': check_ge_zero
772772+ },
773773+ 'opcodes': {
774774+ 'doc': 'Opcodes visibility flag.',
775775+ 'default': False,
776776+ 'name': 'show_opcodes',
777777+ 'type': bool
778778+ },
779779+ 'function': {
780780+ 'doc': 'Function information visibility flag.',
781781+ 'default': True,
782782+ 'name': 'show_function',
783783+ 'type': bool
784784+ }
785785+ }
1451786787787+class Stack(Dashboard.Module):
788788+ """Show the current stack trace including the function name and the file
789789+location, if available. Optionally list the frame arguments and locals too."""
145279014531453-define hexdump_aux
14541454- if $argc != 1
14551455- help hexdump_aux
14561456- else
14571457- color_bold
14581458- if ($64BITS == 1)
14591459- printf "0x%016lX : ", $arg0
14601460- else
14611461- printf "0x%08X : ", $arg0
14621462- end
14631463- color_reset
14641464- hex_quad $arg0
14651465- color_bold
14661466- printf " - "
14671467- color_reset
14681468- hex_quad $arg0+8
14691469- printf " "
14701470- color_bold
14711471- ascii_char $arg0+0x0
14721472- ascii_char $arg0+0x1
14731473- ascii_char $arg0+0x2
14741474- ascii_char $arg0+0x3
14751475- ascii_char $arg0+0x4
14761476- ascii_char $arg0+0x5
14771477- ascii_char $arg0+0x6
14781478- ascii_char $arg0+0x7
14791479- ascii_char $arg0+0x8
14801480- ascii_char $arg0+0x9
14811481- ascii_char $arg0+0xA
14821482- ascii_char $arg0+0xB
14831483- ascii_char $arg0+0xC
14841484- ascii_char $arg0+0xD
14851485- ascii_char $arg0+0xE
14861486- ascii_char $arg0+0xF
14871487- color_reset
14881488- printf "\n"
14891489- end
14901490-end
14911491-document hexdump_aux
14921492-Syntax: hexdump_aux ADDR
14931493-| Display a 16-byte hex/ASCII dump of memory at address ADDR.
14941494-end
791791+ def label(self):
792792+ return 'Stack'
1495793794794+ def lines(self):
795795+ frames = []
796796+ number = 0
797797+ selected_index = 0
798798+ frame = gdb.newest_frame()
799799+ while frame:
800800+ frame_lines = []
801801+ # fetch frame info
802802+ selected = (frame == gdb.selected_frame())
803803+ if selected:
804804+ selected_index = number
805805+ style = R.style_selected_1 if selected else R.style_selected_2
806806+ frame_id = ansi(str(number), style)
807807+ info = Stack.get_pc_line(frame, style)
808808+ frame_lines.append('[{}] {}'.format(frame_id, info))
809809+ # fetch frame arguments and locals
810810+ decorator = gdb.FrameDecorator.FrameDecorator(frame)
811811+ if self.show_arguments:
812812+ frame_args = decorator.frame_args()
813813+ args_lines = self.fetch_frame_info(frame, frame_args, 'arg')
814814+ if args_lines:
815815+ frame_lines.extend(args_lines)
816816+ else:
817817+ frame_lines.append(ansi('(no arguments)', R.style_low))
818818+ if self.show_locals:
819819+ frame_locals = decorator.frame_locals()
820820+ locals_lines = self.fetch_frame_info(frame, frame_locals, 'loc')
821821+ if locals_lines:
822822+ frame_lines.extend(locals_lines)
823823+ else:
824824+ frame_lines.append(ansi('(no locals)', R.style_low))
825825+ # add frame
826826+ frames.append(frame_lines)
827827+ # next
828828+ frame = frame.older()
829829+ number += 1
830830+ # format the output
831831+ if not self.limit or self.limit >= len(frames):
832832+ start = 0
833833+ end = len(frames)
834834+ more = False
835835+ else:
836836+ start = selected_index
837837+ end = min(len(frames), start + self.limit)
838838+ more = (len(frames) - start > self.limit)
839839+ lines = []
840840+ for frame_lines in frames[start:end]:
841841+ lines.extend(frame_lines)
842842+ # add the placeholder
843843+ if more:
844844+ lines.append('[{}]'.format(ansi('+', R.style_selected_2)))
845845+ return lines
149684614971497-# _______________data window__________________
14981498-define ddump
14991499- if $argc != 1
15001500- help ddump
15011501- else
15021502- color $COLOR_SEPARATOR
15031503- if $ARM == 1
15041504- printf "[0x%08X]", $data_addr
15051505- else
15061506- if ($64BITS == 1)
15071507- printf "[0x%04X:0x%016lX]", $ds, $data_addr
15081508- else
15091509- printf "[0x%04X:0x%08X]", $ds, $data_addr
15101510- end
15111511- end
847847+ def fetch_frame_info(self, frame, data, prefix):
848848+ prefix = ansi(prefix, R.style_low)
849849+ lines = []
850850+ for elem in data or []:
851851+ name = elem.sym
852852+ value = to_string(elem.sym.value(frame))
853853+ lines.append('{} {} = {}'.format(prefix, name, value))
854854+ return lines
151285515131513- color $COLOR_SEPARATOR
15141514- printf "------------------------"
15151515- printf "-------------------------------"
15161516- if ($64BITS == 1)
15171517- printf "-------------------------------------"
15181518- end
15191519- color_bold
15201520- color $COLOR_SEPARATOR
15211521- printf "[data]\n"
15221522- color_reset
15231523- set $_count = 0
15241524- while ($_count < $arg0)
15251525- set $_i = ($_count * 0x10)
15261526- hexdump $data_addr+$_i
15271527- set $_count++
15281528- end
15291529- end
15301530-end
15311531-document ddump
15321532-Syntax: ddump NUM
15331533-| Display NUM lines of hexdump for address in $data_addr global variable.
15341534-end
856856+ @staticmethod
857857+ def get_pc_line(frame, style):
858858+ frame_pc = ansi(format_address(frame.pc()), style)
859859+ info = 'from {}'.format(frame_pc)
860860+ if frame.name():
861861+ frame_name = ansi(frame.name(), style)
862862+ try:
863863+ # try to compute the offset relative to the current function
864864+ value = gdb.parse_and_eval(frame.name()).address
865865+ # it can be None even if it is part of the "stack" (C++)
866866+ if value:
867867+ func_start = to_unsigned(value)
868868+ offset = frame.pc() - func_start
869869+ frame_name += '+' + ansi(str(offset), style)
870870+ except gdb.error:
871871+ pass # e.g., @plt
872872+ info += ' in {}'.format(frame_name)
873873+ sal = frame.find_sal()
874874+ if sal.symtab:
875875+ file_name = ansi(sal.symtab.filename, style)
876876+ file_line = ansi(str(sal.line), style)
877877+ info += ' at {}:{}'.format(file_name, file_line)
878878+ return info
1535879880880+ def attributes(self):
881881+ return {
882882+ 'limit': {
883883+ 'doc': 'Maximum number of displayed frames (0 means no limit).',
884884+ 'default': 2,
885885+ 'type': int,
886886+ 'check': check_ge_zero
887887+ },
888888+ 'arguments': {
889889+ 'doc': 'Frame arguments visibility flag.',
890890+ 'default': True,
891891+ 'name': 'show_arguments',
892892+ 'type': bool
893893+ },
894894+ 'locals': {
895895+ 'doc': 'Frame locals visibility flag.',
896896+ 'default': False,
897897+ 'name': 'show_locals',
898898+ 'type': bool
899899+ }
900900+ }
153690115371537-define dd
15381538- if $argc != 1
15391539- help dd
15401540- else
15411541- set $data_addr = $arg0
15421542- ddump 0x10
15431543- end
15441544-end
15451545-document dd
15461546-Syntax: dd ADDR
15471547-| Display 16 lines of a hex dump of address starting at ADDR.
15481548-end
902902+class History(Dashboard.Module):
903903+ """List the last entries of the value history."""
1549904905905+ def label(self):
906906+ return 'History'
155090715511551-define datawin
15521552- if $ARM == 1
15531553- if ((($r0 >> 0x18) == 0x40) || (($r0 >> 0x18) == 0x08) || (($r0 >> 0x18) == 0xBF))
15541554- set $data_addr = $r0
15551555- else
15561556- if ((($r1 >> 0x18) == 0x40) || (($r1 >> 0x18) == 0x08) || (($r1 >> 0x18) == 0xBF))
15571557- set $data_addr = $r1
15581558- else
15591559- if ((($r2 >> 0x18) == 0x40) || (($r2 >> 0x18) == 0x08) || (($r2 >> 0x18) == 0xBF))
15601560- set $data_addr = $r2
15611561- else
15621562- set $data_addr = $sp
15631563- end
15641564- end
15651565- end
15661566-################################# X86
15671567- else
15681568- if ($64BITS == 1)
15691569- if ((($rsi >> 0x18) == 0x40) || (($rsi >> 0x18) == 0x08) || (($rsi >> 0x18) == 0xBF))
15701570- set $data_addr = $rsi
15711571- else
15721572- if ((($rdi >> 0x18) == 0x40) || (($rdi >> 0x18) == 0x08) || (($rdi >> 0x18) == 0xBF))
15731573- set $data_addr = $rdi
15741574- else
15751575- if ((($rax >> 0x18) == 0x40) || (($rax >> 0x18) == 0x08) || (($rax >> 0x18) == 0xBF))
15761576- set $data_addr = $rax
15771577- else
15781578- set $data_addr = $rsp
15791579- end
15801580- end
15811581- end
15821582- else
15831583- if ((($esi >> 0x18) == 0x40) || (($esi >> 0x18) == 0x08) || (($esi >> 0x18) == 0xBF))
15841584- set $data_addr = $esi
15851585- else
15861586- if ((($edi >> 0x18) == 0x40) || (($edi >> 0x18) == 0x08) || (($edi >> 0x18) == 0xBF))
15871587- set $data_addr = $edi
15881588- else
15891589- if ((($eax >> 0x18) == 0x40) || (($eax >> 0x18) == 0x08) || (($eax >> 0x18) == 0xBF))
15901590- set $data_addr = $eax
15911591- else
15921592- set $data_addr = $esp
15931593- end
15941594- end
15951595- end
15961596- end
15971597- end
15981598- ddump $CONTEXTSIZE_DATA
15991599-end
16001600-document datawin
16011601-Syntax: datawin
16021602-| Display valid address from one register in data window.
16031603-| Registers to choose are: esi, edi, eax, or esp.
16041604-end
908908+ def lines(self):
909909+ out = []
910910+ # fetch last entries
911911+ for i in range(-self.limit + 1, 1):
912912+ try:
913913+ value = to_string(gdb.history(i))
914914+ value_id = ansi('$${}', R.style_low).format(abs(i))
915915+ line = '{} = {}'.format(value_id, value)
916916+ out.append(line)
917917+ except gdb.error:
918918+ continue
919919+ return out
1605920921921+ def attributes(self):
922922+ return {
923923+ 'limit': {
924924+ 'doc': 'Maximum number of values to show.',
925925+ 'default': 3,
926926+ 'type': int,
927927+ 'check': check_gt_zero
928928+ }
929929+ }
160693016071607-################################
16081608-##### ALERT ALERT ALERT ########
16091609-################################
16101610-# Huge mess going here :) HAHA #
16111611-################################
16121612-define dumpjump
16131613- if $ARM == 1
16141614- ## Most ARM and Thumb instructions are conditional!
16151615- # each instruction is 32 bits long
16161616- # 4 bits are for condition codes (16 in total) (bits 31:28 in ARM contain the condition or 1111 if instruction is unconditional)
16171617- # 2x4 bits for destination and first operand registers
16181618- # one for the set-status flag
16191619- # an assorted number for other stuff
16201620- # 12 bits for any immediate value
16211621- # $_t_flag == 0 => ARM mode
16221622- # $_t_flag == 1 => Thumb or ThumbEE
16231623- # State bit (T), bit 5
16241624- if (($cpsr >> 5) & 1)
16251625- set $_t_flag = 1
16261626- else
16271627- set $_t_flag = 0
16281628- end
931931+class Memory(Dashboard.Module):
932932+ """Allow to inspect memory regions."""
162993316301630- if $_t_flag == 0
16311631- set $_lastbyte = *(unsigned char *)($pc+3)
16321632- #set $_bit31 = ($_lastbyte >> 7) & 1
16331633- #set $_bit30 = ($_lastbyte >> 6) & 1
16341634- #set $_bit29 = ($_lastbyte >> 5) & 1
16351635- #set $_bit28 = ($_lastbyte >> 4) & 1
16361636- set $_conditional = $_lastbyte >> 4
16371637- dumpjumphelper
16381638- else
16391639- # if bits 15-12 (opcode in Thumb instructions) are equal to 1 1 0 1 (0xD) then we have a conditional branch
16401640- # bits 11-8 for the conditional execution code (check ARMv7 manual A8.3)
16411641- if ( (*(unsigned char *)($pc+1) >> 4) == 0xD )
16421642- set $_conditional = *(unsigned char *)($pc+1) ^ 0xD0
16431643- dumpjumphelper
16441644- end
16451645- end
16461646-##################### X86
16471647- else
16481648- ## grab the first two bytes from the instruction so we can determine the jump instruction
16491649- set $_byte1 = *(unsigned char *)$pc
16501650- set $_byte2 = *(unsigned char *)($pc+1)
16511651- ## and now check what kind of jump we have (in case it's a jump instruction)
16521652- ## I changed the flags routine to save the flag into a variable, so we don't need to repeat the process :) (search for "define flags")
934934+ @staticmethod
935935+ def format_byte(byte):
936936+ # `type(byte) is bytes` in Python 3
937937+ if byte.isspace():
938938+ return ' '
939939+ elif 0x20 < ord(byte) < 0x7e:
940940+ return chr(ord(byte))
941941+ else:
942942+ return '.'
165394316541654- ## opcode 0x77: JA, JNBE (jump if CF=0 and ZF=0)
16551655- ## opcode 0x0F87: JNBE, JA
16561656- if ( ($_byte1 == 0x77) || ($_byte1 == 0x0F && $_byte2 == 0x87) )
16571657- # cf=0 and zf=0
16581658- if ($_cf_flag == 0 && $_zf_flag == 0)
16591659- color $RED
16601660- printf " Jump is taken (c=0 and z=0)"
16611661- else
16621662- # cf != 0 or zf != 0
16631663- color $RED
16641664- printf " Jump is NOT taken (c!=0 or z!=0)"
16651665- end
16661666- end
16671667- ## opcode 0x73: JAE, JNB, JNC (jump if CF=0)
16681668- ## opcode 0x0F83: JNC, JNB, JAE (jump if CF=0)
16691669- if ( ($_byte1 == 0x73) || ($_byte1 == 0x0F && $_byte2 == 0x83) )
16701670- # cf=0
16711671- if ($_cf_flag == 0)
16721672- color $RED
16731673- printf " Jump is taken (c=0)"
16741674- else
16751675- # cf != 0
16761676- color $RED
16771677- printf " Jump is NOT taken (c!=0)"
16781678- end
16791679- end
16801680- ## opcode 0x72: JB, JC, JNAE (jump if CF=1)
16811681- ## opcode 0x0F82: JNAE, JB, JC
16821682- if ( ($_byte1 == 0x72) || ($_byte1 == 0x0F && $_byte2 == 0x82) )
16831683- # cf=1
16841684- if ($_cf_flag == 1)
16851685- color $RED
16861686- printf " Jump is taken (c=1)"
16871687- else
16881688- # cf != 1
16891689- color $RED
16901690- printf " Jump is NOT taken (c!=1)"
16911691- end
16921692- end
16931693- ## opcode 0x76: JBE, JNA (jump if CF=1 or ZF=1)
16941694- ## opcode 0x0F86: JBE, JNA
16951695- if ( ($_byte1 == 0x76) || ($_byte1 == 0x0F && $_byte2 == 0x86) )
16961696- # cf=1 or zf=1
16971697- if (($_cf_flag == 1) || ($_zf_flag == 1))
16981698- color $RED
16991699- printf " Jump is taken (c=1 or z=1)"
17001700- else
17011701- # cf != 1 or zf != 1
17021702- color $RED
17031703- printf " Jump is NOT taken (c!=1 or z!=1)"
17041704- end
17051705- end
17061706- ## opcode 0xE3: JCXZ, JECXZ, JRCXZ (jump if CX=0 or ECX=0 or RCX=0)
17071707- if ($_byte1 == 0xE3)
17081708- # cx=0 or ecx=0
17091709- if (($ecx == 0) || ($cx == 0))
17101710- color $RED
17111711- printf " Jump is taken (cx=0 or ecx=0)"
17121712- else
17131713- color $RED
17141714- printf " Jump is NOT taken (cx!=0 or ecx!=0)"
17151715- end
17161716- end
17171717- ## opcode 0x74: JE, JZ (jump if ZF=1)
17181718- ## opcode 0x0F84: JZ, JE, JZ (jump if ZF=1)
17191719- if ( ($_byte1 == 0x74) || ($_byte1 == 0x0F && $_byte2 == 0x84) )
17201720- # ZF = 1
17211721- if ($_zf_flag == 1)
17221722- color $RED
17231723- printf " Jump is taken (z=1)"
17241724- else
17251725- # ZF = 0
17261726- color $RED
17271727- printf " Jump is NOT taken (z!=1)"
17281728- end
17291729- end
17301730- ## opcode 0x7F: JG, JNLE (jump if ZF=0 and SF=OF)
17311731- ## opcode 0x0F8F: JNLE, JG (jump if ZF=0 and SF=OF)
17321732- if ( ($_byte1 == 0x7F) || ($_byte1 == 0x0F && $_byte2 == 0x8F) )
17331733- # zf = 0 and sf = of
17341734- if (($_zf_flag == 0) && ($_sf_flag == $_of_flag))
17351735- color $RED
17361736- printf " Jump is taken (z=0 and s=o)"
17371737- else
17381738- color $RED
17391739- printf " Jump is NOT taken (z!=0 or s!=o)"
17401740- end
17411741- end
17421742- ## opcode 0x7D: JGE, JNL (jump if SF=OF)
17431743- ## opcode 0x0F8D: JNL, JGE (jump if SF=OF)
17441744- if ( ($_byte1 == 0x7D) || ($_byte1 == 0x0F && $_byte2 == 0x8D) )
17451745- # sf = of
17461746- if ($_sf_flag == $_of_flag)
17471747- color $RED
17481748- printf " Jump is taken (s=o)"
17491749- else
17501750- color $RED
17511751- printf " Jump is NOT taken (s!=o)"
17521752- end
17531753- end
17541754- ## opcode: 0x7C: JL, JNGE (jump if SF != OF)
17551755- ## opcode: 0x0F8C: JNGE, JL (jump if SF != OF)
17561756- if ( ($_byte1 == 0x7C) || ($_byte1 == 0x0F && $_byte2 == 0x8C) )
17571757- # sf != of
17581758- if ($_sf_flag != $_of_flag)
17591759- color $RED
17601760- printf " Jump is taken (s!=o)"
17611761- else
17621762- color $RED
17631763- printf " Jump is NOT taken (s=o)"
17641764- end
17651765- end
17661766- ## opcode 0x7E: JLE, JNG (jump if ZF = 1 or SF != OF)
17671767- ## opcode 0x0F8E: JNG, JLE (jump if ZF = 1 or SF != OF)
17681768- if ( ($_byte1 == 0x7E) || ($_byte1 == 0x0F && $_byte2 == 0x8E) )
17691769- # zf = 1 or sf != of
17701770- if (($_zf_flag == 1) || ($_sf_flag != $_of_flag))
17711771- color $RED
17721772- printf " Jump is taken (zf=1 or sf!=of)"
17731773- else
17741774- color $RED
17751775- printf " Jump is NOT taken (zf!=1 or sf=of)"
17761776- end
17771777- end
17781778- ## opcode 0x75: JNE, JNZ (jump if ZF = 0)
17791779- ## opcode 0x0F85: JNE, JNZ (jump if ZF = 0)
17801780- if ( ($_byte1 == 0x75) || ($_byte1 == 0x0F && $_byte2 == 0x85) )
17811781- # ZF = 0
17821782- if ($_zf_flag == 0)
17831783- color $RED
17841784- printf " Jump is taken (z=0)"
17851785- else
17861786- # ZF = 1
17871787- color $RED
17881788- printf " Jump is NOT taken (z!=0)"
17891789- end
17901790- end
17911791- ## opcode 0x71: JNO (OF = 0)
17921792- ## opcode 0x0F81: JNO (OF = 0)
17931793- if ( ($_byte1 == 0x71) || ($_byte1 == 0x0F && $_byte2 == 0x81) )
17941794- # OF = 0
17951795- if ($_of_flag == 0)
17961796- color $RED
17971797- printf " Jump is taken (o=0)"
17981798- else
17991799- # OF != 0
18001800- color $RED
18011801- printf " Jump is NOT taken (o!=0)"
18021802- end
18031803- end
18041804- ## opcode 0x7B: JNP, JPO (jump if PF = 0)
18051805- ## opcode 0x0F8B: JPO (jump if PF = 0)
18061806- if ( ($_byte1 == 0x7B) || ($_byte1 == 0x0F && $_byte2 == 0x8B) )
18071807- # PF = 0
18081808- if ($_pf_flag == 0)
18091809- color $RED
18101810- printf " Jump is NOT taken (p=0)"
18111811- else
18121812- # PF != 0
18131813- color $RED
18141814- printf " Jump is taken (p!=0)"
18151815- end
18161816- end
18171817- ## opcode 0x79: JNS (jump if SF = 0)
18181818- ## opcode 0x0F89: JNS (jump if SF = 0)
18191819- if ( ($_byte1 == 0x79) || ($_byte1 == 0x0F && $_byte2 == 0x89) )
18201820- # SF = 0
18211821- if ($_sf_flag == 0)
18221822- color $RED
18231823- printf " Jump is taken (s=0)"
18241824- else
18251825- # SF != 0
18261826- color $RED
18271827- printf " Jump is NOT taken (s!=0)"
18281828- end
18291829- end
18301830- ## opcode 0x70: JO (jump if OF=1)
18311831- ## opcode 0x0F80: JO (jump if OF=1)
18321832- if ( ($_byte1 == 0x70) || ($_byte1 == 0x0F && $_byte2 == 0x80) )
18331833- # OF = 1
18341834- if ($_of_flag == 1)
18351835- color $RED
18361836- printf " Jump is taken (o=1)"
18371837- else
18381838- # OF != 1
18391839- color $RED
18401840- printf " Jump is NOT taken (o!=1)"
18411841- end
18421842- end
18431843- ## opcode 0x7A: JP, JPE (jump if PF=1)
18441844- ## opcode 0x0F8A: JP, JPE (jump if PF=1)
18451845- if ( ($_byte1 == 0x7A) || ($_byte1 == 0x0F && $_byte2 == 0x8A) )
18461846- # PF = 1
18471847- if ($_pf_flag == 1)
18481848- color $RED
18491849- printf " Jump is taken (p=1)"
18501850- else
18511851- # PF = 0
18521852- color $RED
18531853- printf " Jump is NOT taken (p!=1)"
18541854- end
18551855- end
18561856- ## opcode 0x78: JS (jump if SF=1)
18571857- ## opcode 0x0F88: JS (jump if SF=1)
18581858- if ( ($_byte1 == 0x78) || ($_byte1 == 0x0F && $_byte2 == 0x88) )
18591859- # SF = 1
18601860- if ($_sf_flag == 1)
18611861- color $RED
18621862- printf " Jump is taken (s=1)"
18631863- else
18641864- # SF != 1
18651865- color $RED
18661866- printf " Jump is NOT taken (s!=1)"
18671867- end
18681868- end
18691869- end
18701870-end
18711871-document dumpjump
18721872-Syntax: dumpjump
18731873-| Display if conditional jump will be taken or not.
18741874-end
944944+ @staticmethod
945945+ def parse_as_address(expression):
946946+ value = gdb.parse_and_eval(expression)
947947+ return to_unsigned(value)
187594818761876-define dumpjumphelper
18771877- # 0000 - EQ: Z == 1
18781878- if ($_conditional == 0x0)
18791879- if ($_z_flag == 1)
18801880- color $RED
18811881- printf " Jump is taken (z==1)"
18821882- else
18831883- color $RED
18841884- printf " Jump is NOT taken (z!=1)"
18851885- end
18861886- end
18871887- # 0001 - NE: Z == 0
18881888- if ($_conditional == 0x1)
18891889- if ($_z_flag == 0)
18901890- color $RED
18911891- printf " Jump is taken (z==0)"
18921892- else
18931893- color $RED
18941894- printf " Jump is NOT taken (z!=0)"
18951895- end
18961896- end
18971897- # 0010 - CS: C == 1
18981898- if ($_conditional == 0x2)
18991899- if ($_c_flag == 1)
19001900- color $RED
19011901- printf " Jump is taken (c==1)"
19021902- else
19031903- color $RED
19041904- printf " Jump is NOT taken (c!=1)"
19051905- end
19061906- end
19071907- # 0011 - CC: C == 0
19081908- if ($_conditional == 0x3)
19091909- if ($_c_flag == 0)
19101910- color $RED
19111911- printf " Jump is taken (c==0)"
19121912- else
19131913- color $RED
19141914- printf " Jump is NOT taken (c!=0)"
19151915- end
19161916- end
19171917- # 0100 - MI: N == 1
19181918- if ($_conditional == 0x4)
19191919- if ($_n_flag == 1)
19201920- color $RED
19211921- printf " Jump is taken (n==1)"
19221922- else
19231923- color $RED
19241924- printf " Jump is NOT taken (n!=1)"
19251925- end
19261926- end
19271927- # 0101 - PL: N == 0
19281928- if ($_conditional == 0x5)
19291929- if ($_n_flag == 0)
19301930- color $RED
19311931- printf " Jump is taken (n==0)"
19321932- else
19331933- color $RED
19341934- printf " Jump is NOT taken (n!=0)"
19351935- end
19361936- end
19371937- # 0110 - VS: V == 1
19381938- if ($_conditional == 0x6)
19391939- if ($_v_flag == 1)
19401940- color $RED
19411941- printf " Jump is taken (v==1)"
19421942- else
19431943- color $RED
19441944- printf " Jump is NOT taken (v!=1)"
19451945- end
19461946- end
19471947- # 0111 - VC: V == 0
19481948- if ($_conditional == 0x7)
19491949- if ($_v_flag == 0)
19501950- color $RED
19511951- printf " Jump is taken (v==0)"
19521952- else
19531953- color $RED
19541954- printf " Jump is NOT taken (v!=0)"
19551955- end
19561956- end
19571957- # 1000 - HI: C == 1 and Z == 0
19581958- if ($_conditional == 0x8)
19591959- if ($_c_flag == 1 && $_z_flag == 0)
19601960- color $RED
19611961- printf " Jump is taken (c==1 and z==0)"
19621962- else
19631963- color $RED
19641964- printf " Jump is NOT taken (c!=1 or z!=0)"
19651965- end
19661966- end
19671967- # 1001 - LS: C == 0 or Z == 1
19681968- if ($_conditional == 0x9)
19691969- if ($_c_flag == 0 || $_z_flag == 1)
19701970- color $RED
19711971- printf " Jump is taken (c==0 or z==1)"
19721972- else
19731973- color $RED
19741974- printf " Jump is NOT taken (c!=0 or z!=1)"
19751975- end
19761976- end
19771977- # 1010 - GE: N == V
19781978- if ($_conditional == 0xA)
19791979- if ($_n_flag == $_v_flag)
19801980- color $RED
19811981- printf " Jump is taken (n==v)"
19821982- else
19831983- color $RED
19841984- printf " Jump is NOT taken (n!=v)"
19851985- end
19861986- end
19871987- # 1011 - LT: N != V
19881988- if ($_conditional == 0xB)
19891989- if ($_n_flag != $_v_flag)
19901990- color $RED
19911991- printf " Jump is taken (n!=v)"
19921992- else
19931993- color $RED
19941994- printf " Jump is NOT taken (n==v)"
19951995- end
19961996- end
19971997- # 1100 - GT: Z == 0 and N == V
19981998- if ($_conditional == 0xC)
19991999- if ($_z_flag == 0 && $_n_flag == $_v_flag)
20002000- color $RED
20012001- printf " Jump is taken (z==0 and n==v)"
20022002- else
20032003- color $RED
20042004- printf " Jump is NOT taken (z!=0 or n!=v)"
20052005- end
20062006- end
20072007- # 1101 - LE: Z == 1 or N != V
20082008- if ($_conditional == 0xD)
20092009- if ($_z_flag == 1 || $_n_flag != $_v_flag)
20102010- color $RED
20112011- printf " Jump is taken (z==1 or n!=v)"
20122012- else
20132013- color $RED
20142014- printf " Jump is NOT taken (z!=1 or n==v)"
20152015- end
20162016- end
20172017-end
20182018-document dumpjumphelper
20192019-Syntax: dumpjumphelper
20202020-| Helper function to decide if conditional jump will be taken or not, for ARM and Thumb.
20212021-end
20222022-20232023-20242024-# _______________process context______________
20252025-# initialize variable
20262026-set $displayobjectivec = 0
20272027-20282028-define context
20292029- color $COLOR_SEPARATOR
20302030- if $SHOWCPUREGISTERS == 1
20312031- printf "----------------------------------------"
20322032- printf "----------------------------------"
20332033- if ($64BITS == 1)
20342034- printf "---------------------------------------------"
20352035- end
20362036- color $COLOR_SEPARATOR
20372037- color_bold
20382038- printf "[regs]\n"
20392039- color_reset
20402040- reg
20412041- color $CYAN
20422042- end
20432043- if $SHOWSTACK == 1
20442044- color $COLOR_SEPARATOR
20452045- if $ARM == 1
20462046- printf "[0x%08X]", $sp
20472047- else
20482048- if ($64BITS == 1)
20492049- printf "[0x%04X:0x%016lX]", $ss, $rsp
20502050- else
20512051- printf "[0x%04X:0x%08X]", $ss, $esp
20522052- end
20532053- end
20542054- color $COLOR_SEPARATOR
20552055- printf "-------------------------"
20562056- printf "-----------------------------"
20572057- if ($64BITS == 1)
20582058- printf "-------------------------------------"
20592059- end
20602060- color $COLOR_SEPARATOR
20612061- color_bold
20622062- printf "[stack]\n"
20632063- color_reset
20642064- set $context_i = $CONTEXTSIZE_STACK
20652065- while ($context_i > 0)
20662066- set $context_t = $sp + 0x10 * ($context_i - 1)
20672067- hexdump $context_t
20682068- set $context_i--
20692069- end
20702070- end
20712071- # show the objective C message being passed to msgSend
20722072- if $SHOWOBJECTIVEC == 1
20732073- #FIXME: X64 and ARM
20742074- # What a piece of crap that's going on here :)
20752075- # detect if it's the correct opcode we are searching for
20762076- if $ARM == 0
20772077- set $__byte1 = *(unsigned char *)$pc
20782078- set $__byte = *(int *)$pc
20792079- if ($__byte == 0x4244489)
20802080- set $objectivec = $eax
20812081- set $displayobjectivec = 1
20822082- end
20832083-20842084- if ($__byte == 0x4245489)
20852085- set $objectivec = $edx
20862086- set $displayobjectivec = 1
20872087- end
20882088-20892089- if ($__byte == 0x4244c89)
20902090- set $objectivec = $ecx
20912091- set $displayobjectivec = 1
20922092- end
20932093- else
20942094- set $__byte1 = 0
20952095- end
20962096- # and now display it or not (we have no interest in having the info displayed after the call)
20972097- if $__byte1 == 0xE8
20982098- if $displayobjectivec == 1
20992099- color $COLOR_SEPARATOR
21002100- printf "--------------------------------------------------------------------"
21012101- if ($64BITS == 1)
21022102- printf "---------------------------------------------"
21032103- end
21042104- color $COLOR_SEPARATOR
21052105- color_bold
21062106- printf "[ObjectiveC]\n"
21072107- color_reset
21082108- color $BLACK
21092109- x/s $objectivec
21102110- end
21112111- set $displayobjectivec = 0
21122112- end
21132113- if $displayobjectivec == 1
21142114- color $COLOR_SEPARATOR
21152115- printf "--------------------------------------------------------------------"
21162116- if ($64BITS == 1)
21172117- printf "---------------------------------------------"
21182118- end
21192119- color $COLOR_SEPARATOR
21202120- color_bold
21212121- printf "[ObjectiveC]\n"
21222122- color_reset
21232123- color $BLACK
21242124- x/s $objectivec
21252125- end
21262126- end
21272127- color_reset
21282128-# and this is the end of this little crap
21292129-21302130- if $SHOWDATAWIN == 1
21312131- datawin
21322132- end
21332133-21342134- color $COLOR_SEPARATOR
21352135- printf "--------------------------------------------------------------------------"
21362136- if ($64BITS == 1)
21372137- printf "---------------------------------------------"
21382138- end
21392139- color $COLOR_SEPARATOR
21402140- color_bold
21412141- printf "[code]\n"
21422142- color_reset
21432143- set $context_i = $CONTEXTSIZE_CODE
21442144- if ($context_i > 0)
21452145- if ($SETCOLOR1STLINE == 1)
21462146- color $GREEN
21472147- if ($ARM == 1)
21482148- # | $cpsr.t (Thumb flag)
21492149- x/i (unsigned int)$pc | (($cpsr >> 5) & 1)
21502150- else
21512151- x/i $pc
21522152- end
21532153- color_reset
21542154- else
21552155- if ($ARM == 1)
21562156- # | $cpsr.t (Thumb flag)
21572157- x/i (unsigned int)$pc | (($cpsr >> 5) & 1)
21582158- else
21592159- x/i $pc
21602160- end
21612161- end
21622162- set $context_i--
21632163- end
21642164- while ($context_i > 0)
21652165- x /i
21662166- set $context_i--
21672167- end
21682168- color $COLOR_SEPARATOR
21692169- printf "----------------------------------------"
21702170- printf "----------------------------------------"
21712171- if ($64BITS == 1)
21722172- printf "---------------------------------------------\n"
21732173- else
21742174- printf "\n"
21752175- end
21762176- color_reset
21772177-end
21782178-document context
21792179-Syntax: context
21802180-| Print context window, i.e. regs, stack, ds:esi and disassemble cs:eip.
21812181-end
21822182-21832183-21842184-define context-on
21852185- set $SHOW_CONTEXT = 1
21862186- printf "Displaying of context is now ON\n"
21872187-end
21882188-document context-on
21892189-Syntax: context-on
21902190-| Enable display of context on every program break.
21912191-end
21922192-21932193-21942194-define context-off
21952195- set $SHOW_CONTEXT = 0
21962196- printf "Displaying of context is now OFF\n"
21972197-end
21982198-document context-off
21992199-Syntax: context-off
22002200-| Disable display of context on every program break.
22012201-end
22022202-22032203-22042204-# _______________process control______________
22052205-define n
22062206- if $argc == 0
22072207- nexti
22082208- end
22092209- if $argc == 1
22102210- nexti $arg0
22112211- end
22122212- if $argc > 1
22132213- help n
22142214- end
22152215-end
22162216-document n
22172217-Syntax: n <NUM>
22182218-| Step one instruction, but proceed through subroutine calls.
22192219-| If NUM is given, then repeat it NUM times or till program stops.
22202220-| This is alias for nexti.
22212221-end
22222222-22232223-22242224-define go
22252225- if $argc == 0
22262226- stepi
22272227- end
22282228- if $argc == 1
22292229- stepi $arg0
22302230- end
22312231- if $argc > 1
22322232- help go
22332233- end
22342234-end
22352235-document go
22362236-Syntax: go <NUM>
22372237-| Step one instruction exactly.
22382238-| If NUM is given, then repeat it NUM times or till program stops.
22392239-| This is alias for stepi.
22402240-end
22412241-22422242-22432243-define pret
22442244- finish
22452245-end
22462246-document pret
22472247-Syntax: pret
22482248-| Execute until selected stack frame returns (step out of current call).
22492249-| Upon return, the value returned is printed and put in the value history.
22502250-end
22512251-22522252-22532253-define init
22542254- set $SHOW_NEST_INSN = 0
22552255- tbreak _init
22562256- r
22572257-end
22582258-document init
22592259-Syntax: init
22602260-| Run program and break on _init().
22612261-end
22622262-22632263-22642264-define start
22652265- set $SHOW_NEST_INSN = 0
22662266- tbreak _start
22672267- r
22682268-end
22692269-document start
22702270-Syntax: start
22712271-| Run program and break on _start().
22722272-end
22732273-22742274-22752275-define sstart
22762276- set $SHOW_NEST_INSN = 0
22772277- tbreak __libc_start_main
22782278- r
22792279-end
22802280-document sstart
22812281-Syntax: sstart
22822282-| Run program and break on __libc_start_main().
22832283-| Useful for stripped executables.
22842284-end
22852285-22862286-22872287-define main
22882288- set $SHOW_NEST_INSN = 0
22892289- tbreak main
22902290- r
22912291-end
22922292-document main
22932293-Syntax: main
22942294-| Run program and break on main().
22952295-end
22962296-22972297-22982298-# FIXME64
22992299-#### WARNING ! WARNING !!
23002300-#### More more messy stuff starting !!!
23012301-#### I was thinking about how to do this and then it ocurred me that it could be as simple as this ! :)
23022302-define stepoframework
23032303- if $ARM == 1
23042304- # bl and bx opcodes
23052305- # bx Rn => ARM bits 27-20: 0 0 0 1 0 0 1 0 , bits 7-4: 0 0 0 1 ; Thumb bits: 15-7: 0 1 0 0 0 1 1 1 0
23062306- # blx Rn => ARM bits 27-20: 0 0 0 1 0 0 1 0 , bits 7-4: 0 0 1 1 ; Thumb bits: 15-7: 0 1 0 0 0 1 1 1 1
23072307- # bl # => ARM bits 27-24: 1 0 1 1 ; Thumb bits: 15-11: 1 1 1 1 0
23082308- # blx # => ARM bits 31-25: 1 1 1 1 1 0 1 ; Thumb bits: 15-11: 1 1 1 1 0
23092309- set $_nextaddress = 0
23102310-23112311- # ARM Mode
23122312- if ($_t_flag == 0)
23132313- set $_branchesint = *(unsigned int*)$pc
23142314- set $_bit31 = ($_branchesint >> 0x1F) & 1
23152315- set $_bit30 = ($_branchesint >> 0x1E) & 1
23162316- set $_bit29 = ($_branchesint >> 0x1D) & 1
23172317- set $_bit28 = ($_branchesint >> 0x1C) & 1
23182318- set $_bit27 = ($_branchesint >> 0x1B) & 1
23192319- set $_bit26 = ($_branchesint >> 0x1A) & 1
23202320- set $_bit25 = ($_branchesint >> 0x19) & 1
23212321- set $_bit24 = ($_branchesint >> 0x18) & 1
23222322- set $_bit23 = ($_branchesint >> 0x17) & 1
23232323- set $_bit22 = ($_branchesint >> 0x16) & 1
23242324- set $_bit21 = ($_branchesint >> 0x15) & 1
23252325- set $_bit20 = ($_branchesint >> 0x14) & 1
23262326- set $_bit7 = ($_branchesint >> 0x7) & 1
23272327- set $_bit6 = ($_branchesint >> 0x6) & 1
23282328- set $_bit5 = ($_branchesint >> 0x5) & 1
23292329- set $_bit4 = ($_branchesint >> 0x4) & 1
23302330-23312331- # set $_lastbyte = *(unsigned char *)($pc+3)
23322332- # set $_bits2724 = $_lastbyte & 0x1
23332333- # set $_bits3128 = $_lastbyte >> 4
23342334- # if ($_bits3128 == 0xF)
23352335- # set $_bits2724 = $_lastbyte & 0xA
23362336- # set $_bits2724 = $_bits2724 >> 1
23372337- # end
23382338- # set $_previousbyte = *(unsigned char *)($pc+2)
23392339- # set $_bits2320 = $_previousbyte >> 4
23402340- # printf "bits2724: %x bits2320: %x\n", $_bits2724, $_bits2320
949949+ def __init__(self):
950950+ self.row_length = 16
951951+ self.table = {}
234195223422342- if ($_bit27 == 0 && $_bit26 == 0 && $_bit25 == 0 && $_bit24 == 1 && $_bit23 == 0 && $_bit22 == 0 && $_bit21 == 1 && $_bit20 == 0 && $_bit7 == 0 && $_bit6 == 0 && $_bit5 == 0 && $_bit4 == 1)
23432343- printf "Found a bx Rn\n"
23442344- set $_nextaddress = $pc+0x4
23452345- end
23462346- if ($_bit27 == 0 && $_bit26 == 0 && $_bit25 == 0 && $_bit24 == 1 && $_bit23 == 0 && $_bit22 == 0 && $_bit21 == 1 && $_bit20 == 0 && $_bit7 == 0 && $_bit6 == 0 && $_bit5 == 1 && $_bit4 == 1)
23472347- printf "Found a blx Rn\n"
23482348- set $_nextaddress = $pc+0x4
23492349- end
23502350- if ($_bit27 == 1 && $_bit26 == 0 && $_bit25 == 1 && $_bit24 == 1)
23512351- printf "Found a bl #\n"
23522352- set $_nextaddress = $pc+0x4
23532353- end
23542354- if ($_bit31 == 1 && $_bit30 == 1 && $_bit29 == 1 && $_bit28 == 1 && $_bit27 == 1 && $_bit26 == 0 && $_bit25 == 1)
23552355- printf "Found a blx #\n"
23562356- set $_nextaddress = $pc+0x4
23572357- end
23582358- # Thumb Mode
23592359- else
23602360- # 32 bits instructions in Thumb are divided into two half words
23612361- set $_hw1 = *(unsigned short*)($pc)
23622362- set $_hw2 = *(unsigned short*)($pc+2)
953953+ def format_memory(self, start, memory):
954954+ out = []
955955+ for i in range(0, len(memory), self.row_length):
956956+ region = memory[i:i + self.row_length]
957957+ pad = self.row_length - len(region)
958958+ address = format_address(start + i)
959959+ hexa = (' '.join('{:02x}'.format(ord(byte)) for byte in region))
960960+ text = (''.join(Memory.format_byte(byte) for byte in region))
961961+ out.append('{} {}{} {}{}'.format(ansi(address, R.style_low),
962962+ hexa,
963963+ ansi(pad * ' --', R.style_low),
964964+ ansi(text, R.style_high),
965965+ ansi(pad * '.', R.style_low)))
966966+ return out
236396723642364- # bl/blx (immediate)
23652365- # hw1: bits 15-11: 1 1 1 1 0
23662366- # hw2: bits 15-14: 1 1 ; BL bit 12: 1 ; BLX bit 12: 0
23672367- if ( ($_hw1 >> 0xC) == 0xF && (($_hw1 >> 0xB) & 1) == 0)
23682368- if ( ((($_hw2 >> 0xF) & 1) == 1) && ((($_hw2 >> 0xE) & 1) == 1) )
23692369- set $_nextaddress = $pc+0x4
23702370- end
23712371- end
23722372- end
23732373- # if we have found a call to bypass we set a temporary breakpoint on next instruction and continue
23742374- if ($_nextaddress != 0)
23752375- tbreak *$_nextaddress
23762376- continue
23772377- printf "[StepO] Next address will be %x\n", $_nextaddress
23782378- # else we just single step
23792379- else
23802380- nexti
23812381- end
23822382-###################################### X86
23832383- else
23842384- ## we know that an opcode starting by 0xE8 has a fixed length
23852385- ## for the 0xFF opcodes, we can enumerate what is possible to have
23862386- # first we grab the first 3 bytes from the current program counter
23872387- set $_byte1 = *(unsigned char *)$pc
23882388- set $_byte2 = *(unsigned char *)($pc+1)
23892389- set $_byte3 = *(unsigned char *)($pc+2)
23902390- # and start the fun
23912391- # if it's a 0xE8 opcode, the total instruction size will be 5 bytes
23922392- # so we can simply calculate the next address and use a temporary breakpoint ! Voila :)
23932393- set $_nextaddress = 0
23942394- # this one is the must useful for us !!!
23952395- if ($_byte1 == 0xE8)
23962396- set $_nextaddress = $pc + 0x5
23972397- else
23982398- # just other cases we might be interested in... maybe this should be removed since the 0xE8 opcode is the one we will use more
23992399- # this is a big fucking mess and can be improved for sure :) I don't like the way it is ehehehe
24002400- if ($_byte1 == 0xFF)
24012401- # call *%eax (0xFFD0) || call *%edx (0xFFD2) || call *(%ecx) (0xFFD1) || call (%eax) (0xFF10) || call *%esi (0xFFD6) || call *%ebx (0xFFD3) || call DWORD PTR [edx] (0xFF12)
24022402- if ($_byte2 == 0xD0 || $_byte2 == 0xD1 || $_byte2 == 0xD2 || $_byte2 == 0xD3 || $_byte2 == 0xD6 || $_byte2 == 0x10 || $_byte2 == 0x11 || $_byte2 == 0xD7 || $_byte2 == 0x12)
24032403- set $_nextaddress = $pc + 0x2
24042404- end
24052405- # call *0x??(%ebp) (0xFF55??) || call *0x??(%esi) (0xFF56??) || call *0x??(%edi) (0xFF5F??) || call *0x??(%ebx)
24062406- # call *0x??(%edx) (0xFF52??) || call *0x??(%ecx) (0xFF51??) || call *0x??(%edi) (0xFF57??) || call *0x??(%eax) (0xFF50??)
24072407- if ($_byte2 == 0x55 || $_byte2 == 0x56 || $_byte2 == 0x5F || $_byte2 == 0x53 || $_byte2 == 0x52 || $_byte2 == 0x51 || $_byte2 == 0x57 || $_byte2 == 0x50)
24082408- set $_nextaddress = $pc + 0x3
24092409- end
24102410- # call *0x????????(%ebx) (0xFF93????????) ||
24112411- if ($_byte2 == 0x93 || $_byte2 == 0x94 || $_byte2 == 0x90 || $_byte2 == 0x92 || $_byte2 == 0x95 || $_byte2 == 0x15)
24122412- set $_nextaddress = $pc + 6
24132413- end
24142414- # call *0x????????(%ebx,%eax,4) (0xFF94??????????)
24152415- if ($_byte2 == 0x94)
24162416- set $_nextaddress = $pc + 7
24172417- end
24182418- end
24192419- # FIXME: still missing a few?
24202420- if ($_byte1 == 0x41 || $_byte1 == 0x40)
24212421- if ($_byte2 == 0xFF)
24222422- if ($_byte3 == 0xD0 || $_byte3 == 0xD1 || $_byte3 == 0xD2 || $_byte3 == 0xD3 || $_byte3 == 0xD4 || $_byte3 == 0xD5 || $_byte3 == 0xD6 || $_byte3 == 0xD7)
24232423- set $_nextaddress = $pc + 0x3
24242424- end
24252425- end
24262426- end
24272427- end
24282428- # if we have found a call to bypass we set a temporary breakpoint on next instruction and continue
24292429- if ($_nextaddress != 0)
24302430- if ($arg0 == 1)
24312431- thbreak *$_nextaddress
24322432- else
24332433- tbreak *$_nextaddress
24342434- end
24352435- continue
24362436- # else we just single step
24372437- else
24382438- nexti
24392439- end
24402440- end
24412441-end
24422442-document stepoframework
24432443-Syntax: stepoframework
24442444-| Auxiliary function to stepo command.
24452445-end
968968+ def label(self):
969969+ return 'Memory'
244697024472447-define stepo
24482448- stepoframework 0
24492449-end
24502450-document stepo
24512451-Syntax: stepo
24522452-| Step over calls (interesting to bypass the ones to msgSend).
24532453-| This function will set a temporary breakpoint on next instruction after the call so the call will be bypassed.
24542454-| You can safely use it instead nexti or n since it will single step code if it's not a call instruction (unless you want to go into the call function).
24552455-end
971971+ def lines(self):
972972+ out = []
973973+ inferior = gdb.selected_inferior()
974974+ for address, length in sorted(self.table.items()):
975975+ try:
976976+ memory = inferior.read_memory(address, length)
977977+ out.extend(self.format_memory(address, memory))
978978+ except gdb.error:
979979+ msg = 'Cannot access {} bytes starting at {}'
980980+ msg = msg.format(length, format_address(address))
981981+ out.append(ansi(msg, R.style_error))
982982+ out.append(divider())
983983+ # drop last divider
984984+ if out:
985985+ del out[-1]
986986+ return out
2456987988988+ def watch(self, arg):
989989+ if arg:
990990+ address, _, length = arg.partition(' ')
991991+ address = Memory.parse_as_address(address)
992992+ if length:
993993+ length = Memory.parse_as_address(length)
994994+ else:
995995+ length = self.row_length
996996+ self.table[address] = length
997997+ else:
998998+ raise Exception('Specify an address')
245799924582458-define stepoh
24592459- stepoframework 1
24602460-end
24612461-document stepoh
24622462-Syntax: stepoh
24632463-| Same as stepo command but uses temporary hardware breakpoints.
24642464-end
10001000+ def unwatch(self, arg):
10011001+ if arg:
10021002+ try:
10031003+ del self.table[Memory.parse_as_address(arg)]
10041004+ except KeyError:
10051005+ raise Exception('Memory region not watched')
10061006+ else:
10071007+ raise Exception('Specify an address')
2465100810091009+ def clear(self, arg):
10101010+ self.table.clear()
2466101124672467-# FIXME: ARM
24682468-define skip
24692469- x/2i $pc
24702470- set $instruction_size = (int)($_ - $pc)
24712471- set $pc = $pc + $instruction_size
24722472- if ($SKIPEXECUTE == 1)
24732473- if ($SKIPSTEP == 1)
24742474- stepo
24752475- else
24762476- stepi
24772477- end
24782478- else
24792479- context
24802480- end
24812481-end
24822482-document skip
24832483-Syntax: skip
24842484-| Skip over the instruction located at EIP/RIP. By default, the instruction will not be executed!
24852485-| Some configurable options are available on top of gdbinit to override this.
24862486-end
10121012+ def commands(self):
10131013+ return {
10141014+ 'watch': {
10151015+ 'action': self.watch,
10161016+ 'doc': 'Watch a memory region by address and length.\n'
10171017+ 'The length defaults to 16 byte.',
10181018+ 'complete': gdb.COMPLETE_EXPRESSION
10191019+ },
10201020+ 'unwatch': {
10211021+ 'action': self.unwatch,
10221022+ 'doc': 'Stop watching a memory region by address.',
10231023+ 'complete': gdb.COMPLETE_EXPRESSION
10241024+ },
10251025+ 'clear': {
10261026+ 'action': self.clear,
10271027+ 'doc': 'Clear all the watched regions.'
10281028+ }
10291029+ }
2487103010311031+class Registers(Dashboard.Module):
10321032+ """Show the CPU registers and their values."""
2488103324892489-# _______________eflags commands______________
24902490-# conditional flags are
24912491-# negative/less than (N), bit 31 of CPSR
24922492-# zero (Z), bit 30
24932493-# Carry/Borrow/Extend (C), bit 29
24942494-# Overflow (V), bit 28
10341034+ def __init__(self):
10351035+ self.table = {}
2495103624962496-# negative/less than (N), bit 31 of CPSR
24972497-define cfn
24982498- if $ARM == 1
24992499- set $tempflag = $cpsr->n
25002500- if ($tempflag & 1)
25012501- set $cpsr->n = $tempflag&~0x1
25022502- else
25032503- set $cpsr->n = $tempflag|0x1
25042504- end
25052505- end
25062506-end
25072507-document cfn
25082508-Syntax: cfn
25092509-| Change Negative/Less Than Flag.
25102510-end
10371037+ def label(self):
10381038+ return 'Registers'
2511103910401040+ def lines(self):
10411041+ # fetch registers status
10421042+ registers = []
10431043+ for reg_info in run('info registers').strip().split('\n'):
10441044+ # fetch register and update the table
10451045+ name = reg_info.split(None, 1)[0]
10461046+ value = gdb.parse_and_eval('${}'.format(name))
10471047+ string_value = self.format_value(value)
10481048+ changed = self.table and (self.table.get(name, '') != string_value)
10491049+ self.table[name] = string_value
10501050+ registers.append((name, string_value, changed))
10511051+ # split registers in rows and columns, each column is composed of name,
10521052+ # space, value and another trailing space which is skipped in the last
10531053+ # column (hence term_width + 1)
10541054+ max_name = max(len(name) for name, _, _ in registers)
10551055+ max_value = max(len(value) for _, value, _ in registers)
10561056+ max_width = max_name + max_value + 2
10571057+ per_line = int((Dashboard.term_width + 1) / max_width) or 1
10581058+ # redistribute extra space among columns
10591059+ extra = int((Dashboard.term_width + 1 -
10601060+ max_width * per_line) / per_line)
10611061+ if per_line == 1:
10621062+ # center when there is only one column
10631063+ max_name += int(extra / 2)
10641064+ max_value += int(extra / 2)
10651065+ else:
10661066+ max_value += extra
10671067+ # format registers info
10681068+ partial = []
10691069+ for name, value, changed in registers:
10701070+ styled_name = ansi(name.rjust(max_name), R.style_low)
10711071+ value_style = R.style_selected_1 if changed else ''
10721072+ styled_value = ansi(value.ljust(max_value), value_style)
10731073+ partial.append(styled_name + ' ' + styled_value)
10741074+ out = []
10751075+ for i in range(0, len(partial), per_line):
10761076+ out.append(' '.join(partial[i:i + per_line]).rstrip())
10771077+ return out
2512107825132513-define cfc
25142514-# Carry/Borrow/Extend (C), bit 29
25152515- if $ARM == 1
25162516- set $tempflag = $cpsr->c
25172517- if ($tempflag & 1)
25182518- set $cpsr->c = $tempflag&~0x1
25192519- else
25202520- set $cpsr->c = $tempflag|0x1
25212521- end
25222522- else
25232523- if ((unsigned int)$eflags & 1)
25242524- set $eflags = (unsigned int)$eflags&~0x1
25252525- else
25262526- set $eflags = (unsigned int)$eflags|0x1
25272527- end
25282528- end
25292529-end
25302530-document cfc
25312531-Syntax: cfc
25322532-| Change Carry Flag.
25332533-end
10791079+ def format_value(self, value):
10801080+ try:
10811081+ if value.type.code in [gdb.TYPE_CODE_INT, gdb.TYPE_CODE_PTR]:
10821082+ int_value = to_unsigned(value, value.type.sizeof)
10831083+ value_format = '0x{{:0{}x}}'.format(2 * value.type.sizeof)
10841084+ return value_format.format(int_value)
10851085+ except (gdb.error, ValueError):
10861086+ # convert to unsigned but preserve code and flags information
10871087+ pass
10881088+ return str(value)
2534108910901090+class Threads(Dashboard.Module):
10911091+ """List the currently available threads."""
2535109225362536-define cfp
25372537- if (((unsigned int)$eflags >> 2) & 1)
25382538- set $eflags = (unsigned int)$eflags&~0x4
25392539- else
25402540- set $eflags = (unsigned int)$eflags|0x4
25412541- end
25422542-end
25432543-document cfp
25442544-Syntax: cfp
25452545-| Change Parity Flag.
25462546-end
10931093+ def label(self):
10941094+ return 'Threads'
2547109510961096+ def lines(self):
10971097+ out = []
10981098+ selected_thread = gdb.selected_thread()
10991099+ selected_frame = gdb.selected_frame()
11001100+ for thread in gdb.Inferior.threads(gdb.selected_inferior()):
11011101+ is_selected = (thread.ptid == selected_thread.ptid)
11021102+ style = R.style_selected_1 if is_selected else R.style_selected_2
11031103+ number = ansi(str(thread.num), style)
11041104+ tid = ansi(str(thread.ptid[1] or thread.ptid[2]), style)
11051105+ info = '[{}] id {}'.format(number, tid)
11061106+ if thread.name:
11071107+ info += ' name {}'.format(ansi(thread.name, style))
11081108+ # switch thread to fetch frame info
11091109+ thread.switch()
11101110+ frame = gdb.newest_frame()
11111111+ info += ' ' + Stack.get_pc_line(frame, style)
11121112+ out.append(info)
11131113+ # restore thread and frame
11141114+ selected_thread.switch()
11151115+ selected_frame.select()
11161116+ return out
2548111725492549-define cfa
25502550- if (((unsigned int)$eflags >> 4) & 1)
25512551- set $eflags = (unsigned int)$eflags&~0x10
25522552- else
25532553- set $eflags = (unsigned int)$eflags|0x10
25542554- end
25552555-end
25562556-document cfa
25572557-Syntax: cfa
25582558-| Change Auxiliary Carry Flag.
25592559-end
11181118+class Expressions(Dashboard.Module):
11191119+ """Watch user expressions."""
2560112011211121+ def __init__(self):
11221122+ self.number = 1
11231123+ self.table = {}
2561112425622562-define cfz
25632563-# zero (Z), bit 30
25642564- if $ARM == 1
25652565- set $tempflag = $cpsr->z
25662566- if ($tempflag & 1)
25672567- set $cpsr->z = $tempflag&~0x1
25682568- else
25692569- set $cpsr->z = $tempflag|0x1
25702570- end
25712571- else
25722572- if (((unsigned int)$eflags >> 6) & 1)
25732573- set $eflags = (unsigned int)$eflags&~0x40
25742574- else
25752575- set $eflags = (unsigned int)$eflags|0x40
25762576- end
25772577- end
25782578-end
25792579-document cfz
25802580-Syntax: cfz
25812581-| Change Zero Flag.
25822582-end
11251125+ def label(self):
11261126+ return 'Expressions'
2583112711281128+ def lines(self):
11291129+ out = []
11301130+ for number, expression in sorted(self.table.items()):
11311131+ try:
11321132+ value = to_string(gdb.parse_and_eval(expression))
11331133+ except gdb.error as e:
11341134+ value = ansi(e, R.style_error)
11351135+ number = ansi(number, R.style_selected_2)
11361136+ expression = ansi(expression, R.style_low)
11371137+ out.append('[{}] {} = {}'.format(number, expression, value))
11381138+ return out
2584113925852585-define cfs
25862586- if (((unsigned int)$eflags >> 7) & 1)
25872587- set $eflags = (unsigned int)$eflags&~0x80
25882588- else
25892589- set $eflags = (unsigned int)$eflags|0x80
25902590- end
25912591-end
25922592-document cfs
25932593-Syntax: cfs
25942594-| Change Sign Flag.
25952595-end
25962596-25972597-25982598-define cft
25992599- if (((unsigned int)$eflags >>8) & 1)
26002600- set $eflags = (unsigned int)$eflags&~0x100
26012601- else
26022602- set $eflags = (unsigned int)$eflags|0x100
26032603- end
26042604-end
26052605-document cft
26062606-Syntax: cft
26072607-| Change Trap Flag.
26082608-end
26092609-26102610-26112611-define cfi
26122612- if (((unsigned int)$eflags >> 9) & 1)
26132613- set $eflags = (unsigned int)$eflags&~0x200
26142614- else
26152615- set $eflags = (unsigned int)$eflags|0x200
26162616- end
26172617-end
26182618-document cfi
26192619-Syntax: cfi
26202620-| Change Interrupt Flag.
26212621-| Only privileged applications (usually the OS kernel) may modify IF.
26222622-| This only applies to protected mode (real mode code may always modify IF).
26232623-end
26242624-26252625-26262626-define cfd
26272627- if (((unsigned int)$eflags >>0xA) & 1)
26282628- set $eflags = (unsigned int)$eflags&~0x400
26292629- else
26302630- set $eflags = (unsigned int)$eflags|0x400
26312631- end
26322632-end
26332633-document cfd
26342634-Syntax: cfd
26352635-| Change Direction Flag.
26362636-end
26372637-26382638-26392639-define cfo
26402640- if (((unsigned int)$eflags >> 0xB) & 1)
26412641- set $eflags = (unsigned int)$eflags&~0x800
26422642- else
26432643- set $eflags = (unsigned int)$eflags|0x800
26442644- end
26452645-end
26462646-document cfo
26472647-Syntax: cfo
26482648-| Change Overflow Flag.
26492649-end
26502650-11401140+ def watch(self, arg):
11411141+ if arg:
11421142+ self.table[self.number] = arg
11431143+ self.number += 1
11441144+ else:
11451145+ raise Exception('Specify an expression')
2651114626522652-# Overflow (V), bit 28
26532653-define cfv
26542654- if $ARM == 1
26552655- set $tempflag = $cpsr->v
26562656- if ($tempflag & 1)
26572657- set $cpsr->v = $tempflag&~0x1
26582658- else
26592659- set $cpsr->v = $tempflag|0x1
26602660- end
26612661- end
26622662-end
26632663-document cfv
26642664-Syntax: cfv
26652665-| Change Overflow Flag.
26662666-end
11471147+ def unwatch(self, arg):
11481148+ if arg:
11491149+ try:
11501150+ del self.table[int(arg)]
11511151+ except:
11521152+ raise Exception('Expression not watched')
11531153+ else:
11541154+ raise Exception('Specify an identifier')
2667115511561156+ def clear(self, arg):
11571157+ self.table.clear()
2668115826692669-# ____________________patch___________________
26702670-# the usual nops are mov r0,r0 for arm (0xe1a00000)
26712671-# and mov r8,r8 in Thumb (0x46c0)
26722672-# armv7 has other nops
26732673-# FIXME: make sure that the interval fits the 32bits address for arm and 16bits for thumb
26742674-# status: works, fixme
26752675-define nop
26762676- if ($argc > 2 || $argc == 0)
26772677- help nop
26782678- end
11591159+ def commands(self):
11601160+ return {
11611161+ 'watch': {
11621162+ 'action': self.watch,
11631163+ 'doc': 'Watch an expression.',
11641164+ 'complete': gdb.COMPLETE_EXPRESSION
11651165+ },
11661166+ 'unwatch': {
11671167+ 'action': self.unwatch,
11681168+ 'doc': 'Stop watching an expression by id.',
11691169+ 'complete': gdb.COMPLETE_EXPRESSION
11701170+ },
11711171+ 'clear': {
11721172+ 'action': self.clear,
11731173+ 'doc': 'Clear all the watched expressions.'
11741174+ }
11751175+ }
2679117626802680- if $ARM == 1
26812681- if ($argc == 1)
26822682- if ($cpsr->t &1)
26832683- # thumb
26842684- set *(short *)$arg0 = 0x46c0
26852685- else
26862686- # arm
26872687- set *(int *)$arg0 = 0xe1a00000
26882688- end
26892689- else
26902690- set $addr = $arg0
26912691- if ($cpsr->t & 1)
26922692- # thumb
26932693- while ($addr < $arg1)
26942694- set *(short *)$addr = 0x46c0
26952695- set $addr = $addr + 2
26962696- end
26972697- else
26982698- # arm
26992699- while ($addr < $arg1)
27002700- set *(int *)$addr = 0xe1a00000
27012701- set $addr = $addr + 4
27022702- end
27032703- end
27042704- end
27052705- else
27062706- if ($argc == 1)
27072707- set *(unsigned char *)$arg0 = 0x90
27082708- else
27092709- set $addr = $arg0
27102710- while ($addr < $arg1)
27112711- set *(unsigned char *)$addr = 0x90
27122712- set $addr = $addr + 1
27132713- end
27142714- end
27152715- end
27162716-end
27172717-document nop
27182718-Syntax: nop ADDR1 [ADDR2]
27192719-| Patch a single byte at address ADDR1, or a series of bytes between ADDR1 and ADDR2 to a NOP (0x90) instruction.
27202720-| ARM or Thumb code will be patched accordingly.
27211177end
2722117811791179+# Better GDB defaults ----------------------------------------------------------
2723118027242724-define null
27252725- if ( $argc >2 || $argc == 0)
27262726- help null
27272727- end
11811181+set history save
11821182+set confirm off
11831183+set verbose off
11841184+set print pretty on
11851185+set print array off
11861186+set print array-indexes on
11871187+set python print-stack full
2728118827292729- if ($argc == 1)
27302730- set *(unsigned char *)$arg0 = 0
27312731- else
27322732- set $addr = $arg0
27332733- while ($addr < $arg1)
27342734- set *(unsigned char *)$addr = 0
27352735- set $addr = $addr +1
27362736- end
27372737- end
27382738-end
27392739-document null
27402740-Syntax: null ADDR1 [ADDR2]
27412741-| Patch a single byte at address ADDR1 to NULL (0x00), or a series of bytes between ADDR1 and ADDR2.
27422742-end
11891189+# Start ------------------------------------------------------------------------
2743119027442744-# FIXME: thumb breakpoint ?
27452745-define int3
27462746- if $argc != 1
27472747- help int3
27482748- else
27492749- if $ARM == 1
27502750- set $ORIGINAL_INT3 = *(unsigned int *)$arg0
27512751- set $ORIGINAL_INT3ADDRESS = $arg0
27522752- set *(unsigned int*)$arg0 = 0xe7ffdefe
27532753- else
27542754- # save original bytes and address
27552755- set $ORIGINAL_INT3 = *(unsigned char *)$arg0
27562756- set $ORIGINAL_INT3ADDRESS = $arg0
27572757- # patch
27582758- set *(unsigned char *)$arg0 = 0xCC
27592759- end
27602760- end
27612761-end
27622762-document int3
27632763-Syntax int3 ADDR
27642764-| Patch byte at address ADDR to an INT3 (0xCC) instruction or the equivalent software breakpoint for ARM.
27652765-end
11911191+python Dashboard.start()
2766119227672767-27682768-define rint3
27692769- if $ARM == 1
27702770- set *(unsigned int *)$ORIGINAL_INT3ADDRESS = $ORIGINAL_INT3
27712771- set $pc = $ORIGINAL_INT3ADDRESS
27722772- else
27732773- set *(unsigned char *)$ORIGINAL_INT3ADDRESS = $ORIGINAL_INT3
27742774- if ($64BITS == 1)
27752775- set $rip = $ORIGINAL_INT3ADDRESS
27762776- else
27772777- set $eip = $ORIGINAL_INT3ADDRESS
27782778- end
27792779- end
27802780-end
27812781-document rint3
27822782-Syntax: rint3
27832783-| Restore the original byte previous to int3 patch issued with "int3" command.
27842784-end
27852785-27862786-define patch
27872787- if $argc != 3
27882788- help patch
27892789- end
27902790- set $patchaddr = $arg0
27912791- set $patchbytes = $arg1
27922792- set $patchsize = $arg2
27932793-27942794- if ($patchsize == 1)
27952795- set *(unsigned char*)$patchaddr = $patchbytes
27962796- end
27972797- if ($patchsize == 2)
27982798- set $lendianbytes = (unsigned short)(($patchbytes << 8) | ($patchbytes >> 8))
27992799- set *(unsigned short*)$patchaddr = $lendianbytes
28002800- end
28012801- if ($patchsize == 4)
28022802- set $lendianbytes = (unsigned int)( (($patchbytes << 8) & 0xFF00FF00 ) | (($patchbytes >> 8) & 0xFF00FF ))
28032803- set $lendianbytes = (unsigned int)($lendianbytes << 0x10 | $lendianbytes >> 0x10)
28042804- set *(unsigned int*)$patchaddr = $lendianbytes
28052805- end
28062806- if ($patchsize == 8)
28072807- set $lendianbytes = (unsigned long long)( (($patchbytes << 8) & 0xFF00FF00FF00FF00ULL ) | (($patchbytes >> 8) & 0x00FF00FF00FF00FFULL ) )
28082808- set $lendianbytes = (unsigned long long)( (($lendianbytes << 0x10) & 0xFFFF0000FFFF0000ULL ) | (($lendianbytes >> 0x10) & 0x0000FFFF0000FFFFULL ) )
28092809- set $lendianbytes = (unsigned long long)( ($lendianbytes << 0x20) | ($lendianbytes >> 0x20) )
28102810- set *(unsigned long long*)$patchaddr = $lendianbytes
28112811- end
28122812-end
28132813-document patch
28142814-Syntax: patch address bytes size
28152815-| Patch a given address, converting the bytes to little-endian.
28162816-| Assumes input bytes are unsigned values and should be in hexadecimal format (0x...).
28172817-| Size must be 1, 2, 4, 8 bytes.
28182818-| Main purpose is to be used with the output from the asm commands.
28192819-end
28202820-28212821-# ____________________cflow___________________
28222822-define print_insn_type
28232823- if $argc != 1
28242824- help print_insn_type
28252825- else
28262826- if ($arg0 < 0 || $arg0 > 5)
28272827- printf "UNDEFINED/WRONG VALUE"
28282828- end
28292829- if ($arg0 == 0)
28302830- printf "UNKNOWN"
28312831- end
28322832- if ($arg0 == 1)
28332833- printf "JMP"
28342834- end
28352835- if ($arg0 == 2)
28362836- printf "JCC"
28372837- end
28382838- if ($arg0 == 3)
28392839- printf "CALL"
28402840- end
28412841- if ($arg0 == 4)
28422842- printf "RET"
28432843- end
28442844- if ($arg0 == 5)
28452845- printf "INT"
28462846- end
28472847- end
28482848-end
28492849-document print_insn_type
28502850-Syntax: print_insn_type INSN_TYPE_NUMBER
28512851-| Print human-readable mnemonic for the instruction type (usually $INSN_TYPE).
28522852-end
28532853-28542854-28552855-define get_insn_type
28562856- if $argc != 1
28572857- help get_insn_type
28582858- else
28592859- set $INSN_TYPE = 0
28602860- set $_byte1 = *(unsigned char *)$arg0
28612861- if ($_byte1 == 0x9A || $_byte1 == 0xE8)
28622862- # "call"
28632863- set $INSN_TYPE = 3
28642864- end
28652865- if ($_byte1 >= 0xE9 && $_byte1 <= 0xEB)
28662866- # "jmp"
28672867- set $INSN_TYPE = 1
28682868- end
28692869- if ($_byte1 >= 0x70 && $_byte1 <= 0x7F)
28702870- # "jcc"
28712871- set $INSN_TYPE = 2
28722872- end
28732873- if ($_byte1 >= 0xE0 && $_byte1 <= 0xE3 )
28742874- # "jcc"
28752875- set $INSN_TYPE = 2
28762876- end
28772877- if ($_byte1 == 0xC2 || $_byte1 == 0xC3 || $_byte1 == 0xCA || \
28782878- $_byte1 == 0xCB || $_byte1 == 0xCF)
28792879- # "ret"
28802880- set $INSN_TYPE = 4
28812881- end
28822882- if ($_byte1 >= 0xCC && $_byte1 <= 0xCE)
28832883- # "int"
28842884- set $INSN_TYPE = 5
28852885- end
28862886- if ($_byte1 == 0x0F )
28872887- # two-byte opcode
28882888- set $_byte2 = *(unsigned char *)($arg0 + 1)
28892889- if ($_byte2 >= 0x80 && $_byte2 <= 0x8F)
28902890- # "jcc"
28912891- set $INSN_TYPE = 2
28922892- end
28932893- end
28942894- if ($_byte1 == 0xFF)
28952895- # opcode extension
28962896- set $_byte2 = *(unsigned char *)($arg0 + 1)
28972897- set $_opext = ($_byte2 & 0x38)
28982898- if ($_opext == 0x10 || $_opext == 0x18)
28992899- # "call"
29002900- set $INSN_TYPE = 3
29012901- end
29022902- if ($_opext == 0x20 || $_opext == 0x28)
29032903- # "jmp"
29042904- set $INSN_TYPE = 1
29052905- end
29062906- end
29072907- end
29082908-end
29092909-document get_insn_type
29102910-Syntax: get_insn_type ADDR
29112911-| Recognize instruction type at address ADDR.
29122912-| Take address ADDR and set the global $INSN_TYPE variable to
29132913-| 0, 1, 2, 3, 4, 5 if the instruction at that address is
29142914-| unknown, a jump, a conditional jump, a call, a return, or an interrupt.
29152915-end
29162916-29172917-29182918-define step_to_call
29192919- set $_saved_ctx = $SHOW_CONTEXT
29202920- set $SHOW_CONTEXT = 0
29212921- set $SHOW_NEST_INSN = 0
29222922-29232923- set logging file /dev/null
29242924- set logging redirect on
29252925- set logging on
29262926-29272927- set $_cont = 1
29282928- while ($_cont > 0)
29292929- stepi
29302930- get_insn_type $pc
29312931- if ($INSN_TYPE == 3)
29322932- set $_cont = 0
29332933- end
29342934- end
29352935-29362936- set logging off
29372937-29382938- if ($_saved_ctx > 0)
29392939- context
29402940- end
29412941-29422942- set $SHOW_CONTEXT = $_saved_ctx
29432943- set $SHOW_NEST_INSN = 0
29442944-29452945- set logging file ~/gdb.txt
29462946- set logging redirect off
29472947- set logging on
29482948-29492949- printf "step_to_call command stopped at:\n "
29502950- x/i $pc
29512951- printf "\n"
29522952- set logging off
29532953-29542954-end
29552955-document step_to_call
29562956-Syntax: step_to_call
29572957-| Single step until a call instruction is found.
29582958-| Stop before the call is taken.
29592959-| Log is written into the file ~/gdb.txt.
29602960-end
29612961-29622962-29632963-define trace_calls
29642964-29652965- printf "Tracing...please wait...\n"
29662966-29672967- set $_saved_ctx = $SHOW_CONTEXT
29682968- set $SHOW_CONTEXT = 0
29692969- set $SHOW_NEST_INSN = 0
29702970- set $_nest = 1
29712971- set listsize 0
29722972-29732973- set logging overwrite on
29742974- set logging file ~/gdb_trace_calls.txt
29752975- set logging on
29762976- set logging off
29772977- set logging overwrite off
29782978-29792979- while ($_nest > 0)
29802980- get_insn_type $pc
29812981- # handle nesting
29822982- if ($INSN_TYPE == 3)
29832983- set $_nest = $_nest + 1
29842984- else
29852985- if ($INSN_TYPE == 4)
29862986- set $_nest = $_nest - 1
29872987- end
29882988- end
29892989- # if a call, print it
29902990- if ($INSN_TYPE == 3)
29912991- set logging file ~/gdb_trace_calls.txt
29922992- set logging redirect off
29932993- set logging on
29942994-29952995- set $x = $_nest - 2
29962996- while ($x > 0)
29972997- printf "\t"
29982998- set $x = $x - 1
29992999- end
30003000- x/i $pc
30013001- end
30023002-30033003- set logging off
30043004- set logging file /dev/null
30053005- set logging redirect on
30063006- set logging on
30073007- stepi
30083008- set logging redirect off
30093009- set logging off
30103010- end
30113011-30123012- set $SHOW_CONTEXT = $_saved_ctx
30133013- set $SHOW_NEST_INSN = 0
30143014-30153015- printf "Done, check ~/gdb_trace_calls.txt\n"
30163016-end
30173017-document trace_calls
30183018-Syntax: trace_calls
30193019-| Create a runtime trace of the calls made by target.
30203020-| Log overwrites(!) the file ~/gdb_trace_calls.txt.
30213021-end
30223022-30233023-30243024-define trace_run
30253025-30263026- printf "Tracing...please wait...\n"
30273027-30283028- set $_saved_ctx = $SHOW_CONTEXT
30293029- set $SHOW_CONTEXT = 0
30303030- set $SHOW_NEST_INSN = 1
30313031- set logging overwrite on
30323032- set logging file ~/gdb_trace_run.txt
30333033- set logging redirect on
30343034- set logging on
30353035- set $_nest = 1
30363036-30373037- while ( $_nest > 0 )
30383038-30393039- get_insn_type $pc
30403040- # jmp, jcc, or cll
30413041- if ($INSN_TYPE == 3)
30423042- set $_nest = $_nest + 1
30433043- else
30443044- # ret
30453045- if ($INSN_TYPE == 4)
30463046- set $_nest = $_nest - 1
30473047- end
30483048- end
30493049- stepi
30503050- end
30513051-30523052- printf "\n"
30533053-30543054- set $SHOW_CONTEXT = $_saved_ctx
30553055- set $SHOW_NEST_INSN = 0
30563056- set logging redirect off
30573057- set logging off
30583058-30593059- # clean up trace file
30603060- shell grep -v ' at ' ~/gdb_trace_run.txt > ~/gdb_trace_run.1
30613061- shell grep -v ' in ' ~/gdb_trace_run.1 > ~/gdb_trace_run.txt
30623062- shell rm -f ~/gdb_trace_run.1
30633063- printf "Done, check ~/gdb_trace_run.txt\n"
30643064-end
30653065-document trace_run
30663066-Syntax: trace_run
30673067-| Create a runtime trace of target.
30683068-| Log overwrites(!) the file ~/gdb_trace_run.txt.
30693069-end
30703070-30713071-define entry_point
30723072-30733073- set logging redirect on
30743074- set logging file /tmp/gdb-entry_point
30753075- set logging on
30763076-30773077- info files
30783078-30793079- set logging off
30803080-30813081- shell entry_point="$(/usr/bin/grep 'Entry point:' /tmp/gdb-entry_point | /usr/bin/awk '{ print $3 }')"; echo "$entry_point"; echo 'set $entry_point_address = '"$entry_point" > /tmp/gdb-entry_point
30823082- source /tmp/gdb-entry_point
30833083- shell /bin/rm -f /tmp/gdb-entry_point
30843084-end
30853085-document entry_point
30863086-Syntax: entry_point
30873087-| Prints the entry point address of the target and stores it in the variable entry_point.
30883088-end
30893089-30903090-define break_entrypoint
30913091- entry_point
30923092- break *$entry_point_address
30933093-end
30943094-document break_entrypoint
30953095-Syntax: break_entrypoint
30963096-| Sets a breakpoint on the entry point of the target.
30973097-end
30983098-30993099-define objc_symbols
31003100-31013101- set logging redirect on
31023102- set logging file /tmp/gdb-objc_symbols
31033103- set logging on
31043104-31053105- info target
31063106-31073107- set logging off
31083108- # XXX: define paths for objc-symbols and SymTabCreator
31093109- shell target="$(/usr/bin/head -1 /tmp/gdb-objc_symbols | /usr/bin/head -1 | /usr/bin/awk -F '"' '{ print $2 }')"; objc-symbols "$target" | SymTabCreator -o /tmp/gdb-symtab
31103110-31113111- set logging on
31123112- add-symbol-file /tmp/gdb-symtab
31133113- set logging off
31143114- shell /bin/rm -f /tmp/gdb-objc_symbols
31153115-end
31163116-document objc_symbols
31173117-Syntax: objc_symbols
31183118-| Loads stripped objc symbols into gdb using objc-symbols and SymTabCreator
31193119-| See http://stackoverflow.com/questions/17554070/import-class-dump-info-into-gdb
31203120-| and https://github.com/0xced/class-dump/tree/objc-symbols (for the required utils)
31213121-end
31223122-31233123-#define ptraceme
31243124-# catch syscall ptrace
31253125-# commands
31263126-# if ($64BITS == 0)
31273127-# if ($ebx == 0)
31283128-# set $eax = 0
31293129-# continue
31303130-# end
31313131-# else
31323132-# if ($rdi == 0)
31333133-# set $rax = 0
31343134-# continue
31353135-# end
31363136-# end
31373137-# end
31383138-# set $ptrace_bpnum = $bpnum
31393139-#end
31403140-#document ptraceme
31413141-#Syntax: ptraceme
31423142-#| Hook ptrace to bypass PTRACE_TRACEME anti debugging technique
31433143-#end
31443144-31453145-define rptraceme
31463146- if ($ptrace_bpnum != 0)
31473147- delete $ptrace_bpnum
31483148- set $ptrace_bpnum = 0
31493149- end
31503150-end
31513151-document rptraceme
31523152-Syntax: rptraceme
31533153-| Remove ptrace hook.
31543154-end
31553155-31563156-31573157-# ____________________misc____________________
31583158-define hook-stop
31593159- if (sizeof(void*) == 8)
31603160- set $64BITS = 1
31613161- else
31623162- set $64BITS = 0
31633163- end
31643164-31653165- if ($KDP64BITS != -1)
31663166- if ($KDP64BITS == 0)
31673167- set $64BITS = 0
31683168- else
31693169- set $64BITS = 1
31703170- end
31713171- end
31723172-31733173- # Display instructions formats
31743174- if $ARM == 1
31753175- if $ARMOPCODES == 1
31763176- set arm show-opcode-bytes 1
31773177- end
31783178- else
31793179- if $X86FLAVOR == 0
31803180- set disassembly-flavor intel
31813181- else
31823182- set disassembly-flavor att
31833183- end
31843184- end
31853185-31863186- # this makes 'context' be called at every BP/step
31873187- if ($SHOW_CONTEXT > 0)
31883188- context
31893189- end
31903190- if ($SHOW_NEST_INSN > 0)
31913191- set $x = $_nest
31923192- while ($x > 0)
31933193- printf "\t"
31943194- set $x = $x - 1
31953195- end
31963196- end
31973197-end
31983198-document hook-stop
31993199-Syntax: hook-stop
32003200-| !!! FOR INTERNAL USE ONLY - DO NOT CALL !!!
32013201-end
32023202-32033203-32043204-# original by Tavis Ormandy (http://my.opera.com/taviso/blog/index.dml/tag/gdb) (great fix!)
32053205-# modified to work with Mac OS X by fG!
32063206-# seems nasm shipping with Mac OS X has problems accepting input from stdin or heredoc
32073207-# input is read into a variable and sent to a temporary file which nasm can read
32083208-define assemble
32093209- # dont enter routine again if user hits enter
32103210- dont-repeat
32113211- if ($argc)
32123212- if (*$arg0 = *$arg0)
32133213- # check if we have a valid address by dereferencing it,
32143214- # if we havnt, this will cause the routine to exit.
32153215- end
32163216- printf "Instructions will be written to %#x.\n", $arg0
32173217- else
32183218- printf "Instructions will be written to stdout.\n"
32193219- end
32203220- printf "Type instructions, one per line."
32213221- color_bold
32223222- printf " Do not forget to use NASM assembler syntax!\n"
32233223- color_reset
32243224- printf "End with a line saying just \"end\".\n"
32253225-32263226- if ($argc)
32273227- if ($64BITS == 1)
32283228- # argument specified, assemble instructions into memory at address specified.
32293229- shell ASMOPCODE="$(while read -ep '>' r && test "$r" != end ; do echo -E "$r"; done)" ; GDBASMFILENAME=$RANDOM; \
32303230- echo -e "BITS 64\n$ASMOPCODE" >/tmp/$GDBASMFILENAME ; /usr/local/bin/nasm -f bin -o /dev/stdout /tmp/$GDBASMFILENAME | /usr/bin/hexdump -ve '1/1 "set *((unsigned char *) $arg0 + %#2_ax) = %#02x\n"' >/tmp/gdbassemble ; /bin/rm -f /tmp/$GDBASMFILENAME
32313231- source /tmp/gdbassemble
32323232- # all done. clean the temporary file
32333233- shell /bin/rm -f /tmp/gdbassemble
32343234- else
32353235- # argument specified, assemble instructions into memory at address specified.
32363236- shell ASMOPCODE="$(while read -ep '>' r && test "$r" != end ; do echo -E "$r"; done)" ; GDBASMFILENAME=$RANDOM; \
32373237- echo -e "BITS 32\n$ASMOPCODE" >/tmp/$GDBASMFILENAME ; /usr/bin/nasm -f bin -o /dev/stdout /tmp/$GDBASMFILENAME | /usr/bin/hexdump -ve '1/1 "set *((unsigned char *) $arg0 + %#2_ax) = %#02x\n"' >/tmp/gdbassemble ; /bin/rm -f /tmp/$GDBASMFILENAME
32383238- source /tmp/gdbassemble
32393239- # all done. clean the temporary file
32403240- shell /bin/rm -f /tmp/gdbassemble
32413241- end
32423242- else
32433243- if ($64BITS == 1)
32443244- # no argument, assemble instructions to stdout
32453245- shell ASMOPCODE="$(while read -ep '>' r && test "$r" != end ; do echo -E "$r"; done)" ; GDBASMFILENAME=$RANDOM; \
32463246- echo -e "BITS 64\n$ASMOPCODE" >/tmp/$GDBASMFILENAME ; /usr/local/bin/nasm -f bin -o /dev/stdout /tmp/$GDBASMFILENAME | /usr/local/bin/ndisasm -i -b64 /dev/stdin ; \
32473247- /bin/rm -f /tmp/$GDBASMFILENAME
32483248- else
32493249- # no argument, assemble instructions to stdout
32503250- shell ASMOPCODE="$(while read -ep '>' r && test "$r" != end ; do echo -E "$r"; done)" ; GDBASMFILENAME=$RANDOM; \
32513251- echo -e "BITS 32\n$ASMOPCODE" >/tmp/$GDBASMFILENAME ; /usr/bin/nasm -f bin -o /dev/stdout /tmp/$GDBASMFILENAME | /usr/bin/ndisasm -i -b32 /dev/stdin ; \
32523252- /bin/rm -f /tmp/$GDBASMFILENAME
32533253- end
32543254- end
32553255-end
32563256-document assemble
32573257-Syntax: assemble <ADDR>
32583258-| Assemble instructions using nasm.
32593259-| Type a line containing "end" to indicate the end.
32603260-| If an address is specified, insert/modify instructions at that address.
32613261-| If no address is specified, assembled instructions are printed to stdout.
32623262-| Use the pseudo instruction "org ADDR" to set the base address.
32633263-end
32643264-32653265-define assemble32
32663266- # dont enter routine again if user hits enter
32673267- dont-repeat
32683268- if ($argc)
32693269- if (*$arg0 = *$arg0)
32703270- # check if we have a valid address by dereferencing it,
32713271- # if we havnt, this will cause the routine to exit.
32723272- end
32733273- printf "Instructions will be written to %#x.\n", $arg0
32743274- else
32753275- printf "Instructions will be written to stdout.\n"
32763276- end
32773277- printf "Type instructions, one per line."
32783278- color_bold
32793279- printf " Do not forget to use NASM assembler syntax!\n"
32803280- color_reset
32813281- printf "End with a line saying just \"end\".\n"
32823282-32833283- if ($argc)
32843284- # argument specified, assemble instructions into memory at address specified.
32853285- shell ASMOPCODE="$(while read -ep '>' r && test "$r" != end ; do echo -E "$r"; done)" ; GDBASMFILENAME=$RANDOM; \
32863286- echo -e "BITS 32\n$ASMOPCODE" >/tmp/$GDBASMFILENAME ; /usr/bin/nasm -f bin -o /dev/stdout /tmp/$GDBASMFILENAME | /usr/bin/hexdump -ve '1/1 "set *((unsigned char *) $arg0 + %#2_ax) = %#02x\n"' >/tmp/gdbassemble ; /bin/rm -f /tmp/$GDBASMFILENAME
32873287- source /tmp/gdbassemble
32883288- # all done. clean the temporary file
32893289- shell /bin/rm -f /tmp/gdbassemble
32903290- else
32913291- # no argument, assemble instructions to stdout
32923292- shell ASMOPCODE="$(while read -ep '>' r && test "$r" != end ; do echo -E "$r"; done)" ; GDBASMFILENAME=$RANDOM; \
32933293- echo -e "BITS 32\n$ASMOPCODE" >/tmp/$GDBASMFILENAME ; /usr/bin/nasm -f bin -o /dev/stdout /tmp/$GDBASMFILENAME | /usr/bin/ndisasm -i -b32 /dev/stdin ; \
32943294- /bin/rm -f /tmp/$GDBASMFILENAME
32953295- end
32963296-end
32973297-document assemble32
32983298-Syntax: assemble32 <ADDR>
32993299-| Assemble 32 bits instructions using nasm.
33003300-| Type a line containing "end" to indicate the end.
33013301-| If an address is specified, insert/modify instructions at that address.
33023302-| If no address is specified, assembled instructions are printed to stdout.
33033303-| Use the pseudo instruction "org ADDR" to set the base address.
33043304-end
33053305-33063306-define assemble64
33073307- # dont enter routine again if user hits enter
33083308- dont-repeat
33093309- if ($argc)
33103310- if (*$arg0 = *$arg0)
33113311- # check if we have a valid address by dereferencing it,
33123312- # if we havnt, this will cause the routine to exit.
33133313- end
33143314- printf "Instructions will be written to %#x.\n", $arg0
33153315- else
33163316- printf "Instructions will be written to stdout.\n"
33173317- end
33183318- printf "Type instructions, one per line."
33193319- color_bold
33203320- printf " Do not forget to use NASM assembler syntax!\n"
33213321- color_reset
33223322- printf "End with a line saying just \"end\".\n"
33233323-33243324- if ($argc)
33253325- # argument specified, assemble instructions into memory at address specified.
33263326- shell ASMOPCODE="$(while read -ep '>' r && test "$r" != end ; do echo -E "$r"; done)" ; GDBASMFILENAME=$RANDOM; \
33273327- echo -e "BITS 64\n$ASMOPCODE" >/tmp/$GDBASMFILENAME ; /usr/local/bin/nasm -f bin -o /dev/stdout /tmp/$GDBASMFILENAME | /usr/bin/hexdump -ve '1/1 "set *((unsigned char *) $arg0 + %#2_ax) = %#02x\n"' >/tmp/gdbassemble ; /bin/rm -f /tmp/$GDBASMFILENAME
33283328- source /tmp/gdbassemble
33293329- # all done. clean the temporary file
33303330- shell /bin/rm -f /tmp/gdbassemble
33313331- else
33323332- # no argument, assemble instructions to stdout
33333333- shell ASMOPCODE="$(while read -ep '>' r && test "$r" != end ; do echo -E "$r"; done)" ; GDBASMFILENAME=$RANDOM; \
33343334- echo -e "BITS 64\n$ASMOPCODE" >/tmp/$GDBASMFILENAME ; /usr/local/bin/nasm -f bin -o /dev/stdout /tmp/$GDBASMFILENAME | /usr/local/bin/ndisasm -i -b64 /dev/stdin ; \
33353335- /bin/rm -f /tmp/$GDBASMFILENAME
33363336- end
33373337-end
33383338-document assemble64
33393339-Syntax: assemble64 <ADDR>
33403340-| Assemble 64 bits instructions using nasm.
33413341-| Type a line containing "end" to indicate the end.
33423342-| If an address is specified, insert/modify instructions at that address.
33433343-| If no address is specified, assembled instructions are printed to stdout.
33443344-| Use the pseudo instruction "org ADDR" to set the base address.
33453345-end
33463346-33473347-define asm
33483348- if $argc == 1
33493349- assemble $arg0
33503350- else
33513351- assemble
33523352- end
33533353-end
33543354-document asm
33553355-Syntax: asm <ADDR>
33563356-| Shortcut to the asssemble command.
33573357-end
33583358-33593359-define asm32
33603360- if $argc == 1
33613361- assemble32 $arg0
33623362- else
33633363- assemble32
33643364- end
33653365-end
33663366-document asm32
33673367-Syntax: asm32 <ADDR>
33683368-| Shortcut to the assemble32 command.
33693369-end
33703370-33713371-define asm64
33723372- if $argc == 1
33733373- assemble64 $arg0
33743374- else
33753375- assemble64
33763376- end
33773377-end
33783378-document asm64
33793379-Syntax: asm64 <ADDR>
33803380-| Shortcut to the assemble64 command.
33813381-end
33823382-33833383-define assemble_gas
33843384- printf "\nType code to assemble and hit Ctrl-D when finished.\n"
33853385- printf "You must use GNU assembler (AT&T) syntax.\n"
33863386-33873387- shell filename=$(mktemp); \
33883388- binfilename=$(mktemp); \
33893389- echo -e "Writing into: ${filename}\n"; \
33903390- cat > $filename; echo ""; \
33913391- as -o $binfilename < $filename; \
33923392- objdump -d -j .text $binfilename; \
33933393- rm -f $binfilename; \
33943394- rm -f $filename; \
33953395- echo -e "temporaly files deleted.\n"
33963396-end
33973397-document assemble_gas
33983398-Syntax: assemble_gas
33993399-| Assemble instructions to binary opcodes. Uses GNU as and objdump.
34003400-end
34013401-34023402-34033403-define dump_hexfile
34043404- dump ihex memory $arg0 $arg1 $arg2
34053405-end
34063406-document dump_hexfile
34073407-Syntax: dump_hexfile FILENAME ADDR1 ADDR2
34083408-| Write a range of memory to a file in Intel ihex (hexdump) format.
34093409-| The range is specified by ADDR1 and ADDR2 addresses.
34103410-end
34113411-34123412-34133413-define dump_binfile
34143414- dump memory $arg0 $arg1 $arg2
34153415-end
34163416-document dump_binfile
34173417-Syntax: dump_binfile FILENAME ADDR1 ADDR2
34183418-| Write a range of memory to a binary file.
34193419-| The range is specified by ADDR1 and ADDR2 addresses.
34203420-end
34213421-34223422-34233423-define dumpmacho
34243424- if $argc != 2
34253425- help dumpmacho
34263426- end
34273427- set $headermagic = *$arg0
34283428- # the || operator isn't working as it should, wtf!!!
34293429- if $headermagic != 0xfeedface
34303430- if $headermagic != 0xfeedfacf
34313431- printf "[Error] Target address doesn't contain a valid Mach-O binary!\n"
34323432- help dumpmacho
34333433- end
34343434- end
34353435- set $headerdumpsize = *($arg0+0x14)
34363436- if $headermagic == 0xfeedface
34373437- dump memory $arg1 $arg0 ($arg0+0x1c+$headerdumpsize)
34383438- end
34393439- if $headermagic == 0xfeedfacf
34403440- dump memory $arg1 $arg0 ($arg0+0x20+$headerdumpsize)
34413441- end
34423442-end
34433443-document dumpmacho
34443444-Syntax: dumpmacho STARTADDRESS FILENAME
34453445-| Dump the Mach-O header to a file.
34463446-| You need to input the start address (use info shared command to find it).
34473447-end
34483448-34493449-34503450-define cls
34513451- shell clear
34523452-end
34533453-document cls
34543454-Syntax: cls
34553455-| Clear screen.
34563456-end
34573457-34583458-34593459-define search
34603460- set $start = (char *) $arg0
34613461- set $end = (char *) $arg1
34623462- set $pattern = (short) $arg2
34633463- set $p = $start
34643464- while $p < $end
34653465- if (*(short *) $p) == $pattern
34663466- printf "pattern 0x%hx found at 0x%x\n", $pattern, $p
34673467- end
34683468- set $p++
34693469- end
34703470-end
34713471-document search
34723472-Syntax: search <START> <END> <PATTERN>
34733473-| Search for the given pattern beetween $start and $end address.
34743474-end
34753475-34763476-34773477-# _________________user tips_________________
34783478-# The 'tips' command is used to provide tutorial-like info to the user
34793479-define tips
34803480- printf "Tip Topic Commands:\n"
34813481- printf "\ttip_display : Automatically display values on each break\n"
34823482- printf "\ttip_patch : Patching binaries\n"
34833483- printf "\ttip_strip : Dealing with stripped binaries\n"
34843484- printf "\ttip_syntax : AT&T vs Intel syntax\n"
34853485-end
34863486-document tips
34873487-Syntax: tips
34883488-| Provide a list of tips from users on various topics.
34893489-end
34903490-34913491-34923492-define tip_patch
34933493- printf "\n"
34943494- printf " PATCHING MEMORY\n"
34953495- printf "Any address can be patched using the 'set' command:\n"
34963496- printf "\t`set ADDR = VALUE` \te.g. `set *0x8049D6E = 0x90`\n"
34973497- printf "\n"
34983498- printf " PATCHING BINARY FILES\n"
34993499- printf "Use `set write` in order to patch the target executable\n"
35003500- printf "directly, instead of just patching memory\n"
35013501- printf "\t`set write on` \t`set write off`\n"
35023502- printf "Note that this means any patches to the code or data segments\n"
35033503- printf "will be written to the executable file\n"
35043504- printf "When either of these commands has been issued,\n"
35053505- printf "the file must be reloaded.\n"
35063506- printf "\n"
35073507-end
35083508-document tip_patch
35093509-Syntax: tip_patch
35103510-| Tips on patching memory and binary files.
35113511-end
35123512-35133513-35143514-define tip_strip
35153515- printf "\n"
35163516- printf " STOPPING BINARIES AT ENTRY POINT\n"
35173517- printf "Stripped binaries have no symbols, and are therefore tough to\n"
35183518- printf "start automatically. To debug a stripped binary, use\n"
35193519- printf "\tinfo file\n"
35203520- printf "to get the entry point of the file\n"
35213521- printf "The first few lines of output will look like this:\n"
35223522- printf "\tSymbols from '/tmp/a.out'\n"
35233523- printf "\tLocal exec file:\n"
35243524- printf "\t `/tmp/a.out', file type elf32-i386.\n"
35253525- printf "\t Entry point: 0x80482e0\n"
35263526- printf "Use this entry point to set an entry point:\n"
35273527- printf "\t`tbreak *0x80482e0`\n"
35283528- printf "The breakpoint will delete itself after the program stops as\n"
35293529- printf "the entry point\n"
35303530- printf "\n"
35313531-end
35323532-document tip_strip
35333533-Syntax: tip_strip
35343534-| Tips on dealing with stripped binaries.
35353535-end
35363536-35373537-35383538-define tip_syntax
35393539- printf "\n"
35403540- printf "\t INTEL SYNTAX AT&T SYNTAX\n"
35413541- printf "\tmnemonic dest, src, imm mnemonic src, dest, imm\n"
35423542- printf "\t[base+index*scale+disp] disp(base, index, scale)\n"
35433543- printf "\tregister: eax register: %%eax\n"
35443544- printf "\timmediate: 0xFF immediate: $0xFF\n"
35453545- printf "\tdereference: [addr] dereference: addr(,1)\n"
35463546- printf "\tabsolute addr: addr absolute addr: *addr\n"
35473547- printf "\tbyte insn: mov byte ptr byte insn: movb\n"
35483548- printf "\tword insn: mov word ptr word insn: movw\n"
35493549- printf "\tdword insn: mov dword ptr dword insn: movd\n"
35503550- printf "\tfar call: call far far call: lcall\n"
35513551- printf "\tfar jump: jmp far far jump: ljmp\n"
35523552- printf "\n"
35533553- printf "Note that order of operands in reversed, and that AT&T syntax\n"
35543554- printf "requires that all instructions referencing memory operands \n"
35553555- printf "use an operand size suffix (b, w, d, q)\n"
35563556- printf "\n"
35573557-end
35583558-document tip_syntax
35593559-Syntax: tip_syntax
35603560-| Summary of Intel and AT&T syntax differences.
35613561-end
35623562-35633563-35643564-define tip_display
35653565- printf "\n"
35663566- printf "Any expression can be set to automatically be displayed every time\n"
35673567- printf "the target stops. The commands for this are:\n"
35683568- printf "\t`display expr' : automatically display expression 'expr'\n"
35693569- printf "\t`display' : show all displayed expressions\n"
35703570- printf "\t`undisplay num' : turn off autodisplay for expression # 'num'\n"
35713571- printf "Examples:\n"
35723572- printf "\t`display/x *(int *)$esp` : print top of stack\n"
35733573- printf "\t`display/x *(int *)($ebp+8)` : print first parameter\n"
35743574- printf "\t`display (char *)$esi` : print source string\n"
35753575- printf "\t`display (char *)$edi` : print destination string\n"
35763576- printf "\n"
35773577-end
35783578-document tip_display
35793579-Syntax: tip_display
35803580-| Tips on automatically displaying values when a program stops.
35813581-end
35823582-35833583-# bunch of semi-useless commands
35843584-35853585-# enable and disable shortcuts for stop-on-solib-events fantastic trick!
35863586-define enablesolib
35873587- set stop-on-solib-events 1
35883588- printf "Stop-on-solib-events is enabled!\n"
35893589-end
35903590-document enablesolib
35913591-Syntax: enablesolib
35923592-| Shortcut to enable stop-on-solib-events trick.
35933593-end
35943594-35953595-35963596-define disablesolib
35973597- set stop-on-solib-events 0
35983598- printf "Stop-on-solib-events is disabled!\n"
35993599-end
36003600-document disablesolib
36013601-Syntax: disablesolib
36023602-| Shortcut to disable stop-on-solib-events trick.
36033603-end
36043604-36053605-36063606-# enable commands for different displays
36073607-define enableobjectivec
36083608- set $SHOWOBJECTIVEC = 1
36093609-end
36103610-document enableobjectivec
36113611-Syntax: enableobjectivec
36123612-| Enable display of objective-c information in the context window.
36133613-end
36143614-36153615-36163616-define enablecpuregisters
36173617- set $SHOWCPUREGISTERS = 1
36183618-end
36193619-document enablecpuregisters
36203620-Syntax: enablecpuregisters
36213621-| Enable display of cpu registers in the context window.
36223622-end
36233623-36243624-36253625-define enablestack
36263626- set $SHOWSTACK = 1
36273627-end
36283628-document enablestack
36293629-Syntax: enablestack
36303630-| Enable display of stack in the context window.
36313631-end
36323632-36333633-36343634-define enabledatawin
36353635- set $SHOWDATAWIN = 1
36363636-end
36373637-document enabledatawin
36383638-Syntax: enabledatawin
36393639-| Enable display of data window in the context window.
36403640-end
36413641-36423642-36433643-# disable commands for different displays
36443644-define disableobjectivec
36453645- set $SHOWOBJECTIVEC = 0
36463646-end
36473647-document disableobjectivec
36483648-Syntax: disableobjectivec
36493649-| Disable display of objective-c information in the context window.
36503650-end
36513651-36523652-36533653-define disablecpuregisters
36543654- set $SHOWCPUREGISTERS = 0
36553655-end
36563656-document disablecpuregisters
36573657-Syntax: disablecpuregisters
36583658-| Disable display of cpu registers in the context window.
36593659-end
36603660-36613661-36623662-define disablestack
36633663- set $SHOWSTACK = 0
36643664-end
36653665-document disablestack
36663666-Syntax: disablestack
36673667-| Disable display of stack information in the context window.
36683668-end
36693669-36703670-36713671-define disabledatawin
36723672- set $SHOWDATAWIN = 0
36733673-end
36743674-document disabledatawin
36753675-Syntax: disabledatawin
36763676-| Disable display of data window in the context window.
36773677-end
36783678-36793679-36803680-define arm
36813681- if $ARMOPCODES == 1
36823682- set arm show-opcode-bytes 1
36833683- end
36843684- set $ARM = 1
36853685-end
36863686-document arm
36873687-Syntax: arm
36883688-| Set gdb to work with ARM binaries.
36893689-end
36903690-36913691-define ioskdp
36923692- set $SHOW_CONTEXT = 0
36933693- set $SHOW_NEST_INSN = 0
36943694-end
36953695-document ioskdp
36963696-Syntax: ioskdp
36973697-| Disable dumping context information for iOS KDP debugging
36983698-end
36993699-37003700-define intelsyntax
37013701- if $ARM == 0
37023702- set disassembly-flavor intel
37033703- set $X86FLAVOR = 0
37043704- end
37053705-end
37063706-document intelsyntax
37073707-Syntax: intelsyntax
37083708-| Change disassembly syntax to intel flavor.
37093709-end
37103710-37113711-37123712-define attsyntax
37133713- if $ARM == 0
37143714- set disassembly-flavor att
37153715- set $X86FLAVOR = 1
37163716- end
37173717-end
37183718-document attsyntax
37193719-Syntax: attsyntax
37203720-| Change disassembly syntax to at&t flavor.
37213721-end
37223722-37233723-define kernel32
37243724- if $argc != 0
37253725- # try to load kgmacros files
37263726- # failure is silent if non-existent...
37273727- source $arg0
37283728- set architecture i386
37293729- if $argc == 2
37303730- target remote localhost:$arg1
37313731- else
37323732- target remote localhost:8832
37333733- end
37343734- else
37353735- help kernel32
37363736- end
37373737-end
37383738-document kernel32
37393739-Syntax: kernel32 PATH_TO_KGMACROS <PORT>
37403740-| Attach to VMware gdb stub for 32 bits kernel.
37413741-| The path to kgmacros must be supplied as first parameter.
37423742-| If you don't want to load kgmacros just put something as the first parameter.
37433743-| Optional parameter is the port to connect to, in case you are not using the default 8832
37443744-| or want to kernel debug more than one active virtual machine.
37453745-| By supplying a bogus kgmacros this command should be compatible with any OS.
37463746-end
37473747-37483748-define kernel64
37493749- if $argc != 0
37503750- # try to load kgmacros files
37513751- # failure is silent if non-existent...
37523752- source $arg0
37533753- set architecture i386:x86-64
37543754- if $argc == 2
37553755- target remote localhost:$arg1
37563756- else
37573757- target remote localhost:8864
37583758- end
37593759- else
37603760- help kernel64
37613761- end
37623762-end
37633763-document kernel64
37643764-Syntax: kernel64 PATH_TO_KGMACROS <PORT>
37653765-| Attach to VMware gdb stub for 64 bits kernel.
37663766-| The path to kgmacros must be supplied as first parameter.
37673767-| If you don't want to load kgmacros just put something as the first parameter.
37683768-| Optional parameter is the port to connect to, in case you are not using the default 8864
37693769-| or want to kernel debug more than one active virtual machine.
37703770-| By supplying a bogus kgmacros this command should be compatible with any OS.
37713771-end
37723772-37733773-define 32bits
37743774- set $KDP64BITS = 0
37753775- set $64BITS = 0
37763776-end
37773777-37783778-define 64bits
37793779- set $KDP64BITS = 1
37803780- set $64BITS = 1
37813781-end
37823782-37833783-define resetkdp
37843784- set $KDP64BITS = -1
37853785-end
37863786-37873787-define header
37883788- if $argc != 1
37893789- help header
37903790- else
37913791- dump memory /tmp/gdbinit_header_dump $arg0 $arg0 + 4096
37923792- shell /usr/bin/otool -h /tmp/gdbinit_header_dump
37933793- shell /bin/rm -f /tmp/gdbinit_header_dump
37943794- end
37953795-end
37963796-document header
37973797-Syntax: header MACHO_HEADER_START_ADDRESS
37983798-| Dump the Mach-O header located at given address
37993799-end
38003800-38013801-define loadcmds
38023802- if $argc != 1
38033803- help loadcmds
38043804- else
38053805- # this size should be good enough for most binaries
38063806- dump memory /tmp/gdbinit_header_dump $arg0 $arg0 + 4096 * 10
38073807- shell /usr/bin/otool -l /tmp/gdbinit_header_dump
38083808- shell /bin/rm -f /tmp/gdbinit_header_dump
38093809- end
38103810-end
38113811-document loadcmds
38123812-Syntax: loadcmds MACHO_HEADER_START_ADDRESS
38133813-| Dump the Mach-O load commands
38143814-end
38153815-38163816-# defining it here doesn't get the space #$#$%"#!
38173817-define disablecolorprompt
38183818- set prompt gdb$
38193819-end
38203820-document disablecolorprompt
38213821-| Remove color from prompt
38223822-end
38233823-38243824-define enablecolorprompt
38253825- set prompt \033[31mgdb$ \033[0m
38263826-end
38273827-document enablecolorprompt
38283828-| Enable color prompt
38293829-end
38303830-38313831-#EOF
38323832-38333833-# Older change logs:
11931193+# ------------------------------------------------------------------------------
11941194+# Copyright (c) 2015 Andrea Cardaci <cyrus.and@gmail.com>
38341195#
38353835-# Version 7.4.4 (02/01/2012)
38363836-# - Added the "skip" command. This will jump to the next instruction after EIP/RIP without executing the current one.
38373837-# Thanks to @bSr43 for the tip to retrieve the current instruction size.
38383838-#
38393839-# Version 7.4.3 (04/11/2011)
38403840-# - Modified "hexdump" command to support a variable number of lines (optional parameter)
38413841-# - Removed restrictions on type of addresses in the "dd" command - Thanks to Plouj for the warning :-)
38423842-# I don't know what was the original thinking behind those :-)
38433843-# - Modified the assemble command to support 64bits - You will need to recompile nasm since the version shipped with OS X doesn't supports 64bits (www.nasm.us).
38443844-# Assumes that the new binary is installed at /usr/local/bin - modify the variable at the top if you need so.
38453845-# It will assemble based on the target arch being debugged. If you want to use gdb for a quick asm just use the 32bits or 64bits commands to set your target.
38463846-# Thanks to snare for the warning and original patch :-)
38473847-# - Added "asm" command - it's a shortcut to the "assemble" command.
38483848-# - Added configuration variable for colorized prompt. Plouj reported some issues with Ubuntu's gdb 7.2 if prompt is colorized.
38493849-#
38503850-# Version 7.4.2 (11/08/2011)
38513851-# Small fix to a weird bug happening on FreeBSD 8.2. It doesn't like a "if(" instruction, needs to be "if (". Weird!
38523852-# Many thanks to Evan for reporting and sending the patch :-)
38533853-# Added the ptraceme/rptraceme commands to bypass PTRACE_TRACME anti-debugging technique.
38543854-# Grabbed this from http://falken.tuxfamily.org/?p=171
38553855-# It's commented out due to a gdb problem in OS X (refer to http://reverse.put.as/2011/08/20/another-patch-for-apples-gdb-the-definecommands-problem/ )
38563856-# Just uncomment it if you want to use in ptrace enabled systems.
38573857-#
38583858-# Version 7.4.1 (21/06/2011) - fG!
38593859-# Added patch sent by sbz, more than 1 year ago, which I forgot to add :-/
38603860-# This will allow to search for a given pattern between start and end address.
38613861-# On sbz words: "It's usefull to find call, ret or everything like that." :-)
38623862-# New command is "search"
38633863-#
38643864-# Version 7.4 (20/06/2011) - fG!
38653865-# When registers change between instructions the color will change to red (like it happens in OllyDBG)
38663866-# This is the default behavior, if you don't like it, modify the variable SHOWREGCHANGES
38673867-# Added patch sent by Philippe Langlois
38683868-# color the first disassembly line - change the setting below on SETCOLOR1STLINE - by default it's disabled
38693869-#
38703870-# Version 7.3.2 (21/02/2011) - fG!
38713871-# Added the command rint3 and modified the int3 command. The new command will restore the byte in previous int3 patch.
38723872-#
38733873-# Version 7.3.1 (29/06/2010) - fG!
38743874-# Added enablelib/disablelib command to quickly set the stop-on-solib-events trick
38753875-# Implemented the stepoh command equivalent to the stepo but using hardware breakpoints
38763876-# More fixes to stepo
38773877-#
38783878-# Version 7.3 (16/04/2010) - fG!
38793879-# Support for 64bits targets. Default is 32bits, you should modify the variable or use the 32bits or 64bits to choose the mode.
38803880-# I couldn't find another way to recognize the type of binary… Testing the register doesn't work that well.
38813881-# TODO: fix objectivec messages and stepo for 64bits
38823882-# Version 7.2.1 (24/11/2009) - fG!
38833883-# Another fix to stepo (0xFF92 missing)
38843884-#
38853885-# Version 7.2 (11/10/2009) - fG!
38863886-# Added the smallregisters function to create 16 and 8 bit versions from the registers EAX, EBX, ECX, EDX
38873887-# Revised and fixed all the dumpjump stuff, following Intel manuals. There were some errors (thx to rev who pointed the jle problem).
38883888-# Small fix to stepo command (missed a few call types)
38893889-#
38903890-# Version 7.1.7 - fG!
38913891-# Added the possibility to modify what's displayed with the context window. You can change default options at the gdb options part. For example, kernel debugging is much slower if the stack display is enabled...
38923892-# New commands enableobjectivec, enablecpuregisters, enablestack, enabledatawin and their disable equivalents (to support realtime change of default options)
38933893-# Fixed problem with the assemble command. I was calling /bin/echo which doesn't support the -e option ! DUH ! Should have used bash internal version.
38943894-# Small fixes to colors...
38953895-# New commands enablesolib and disablesolib . Just shortcuts for the stop-on-solib-events fantastic trick ! Hey... I'm lazy ;)
38963896-# Fixed this: Possible removal of "u" command, info udot is missing in gdb 6.8-debian . Doesn't exist on OS X so bye bye !!!
38973897-# Displays affected flags in jump decisions
38983898-#
38993899-# Version 7.1.6 - fG!
39003900-# Added modified assemble command from Tavis Ormandy (further modified to work with Mac OS X) (shell commands used use full path name, working for Leopard, modify for others if necessary)
39013901-# Renamed thread command to threads because thread is an internal gdb command that allows to move between program threads
11961196+# Permission is hereby granted, free of charge, to any person obtaining a copy
11971197+# of this software and associated documentation files (the "Software"), to deal
11981198+# in the Software without restriction, including without limitation the rights
11991199+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12001200+# copies of the Software, and to permit persons to whom the Software is
12011201+# furnished to do so, subject to the following conditions:
39021202#
39033903-# Version 7.1.5 (04/01/2009) - fG!
39043904-# Fixed crash on Leopard ! There was a If Else condition where the else had no code and that made gdb crash on Leopard (CRAZY!!!!)
39053905-# Better code indention
12031203+# The above copyright notice and this permission notice shall be included in all
12041204+# copies or substantial portions of the Software.
39061205#
39073907-# Version 7.1.4 (02/01/2009) - fG!
39083908-# Bug in show objective c messages with Leopard ???
39093909-# Nop routine support for single address or range (contribution from gln [ghalen at hack.se])
39103910-# Used the same code from nop to null routine
39113911-#
39123912-# Version 7.1.3 (31/12/2008) - fG!
39133913-# Added a new command 'stepo'. This command will step a temporary breakpoint on next instruction after the call, so you can skip over
39143914-# the call. Did this because normal commands not always skip over (mainly with objc_msgSend)
39153915-#
39163916-# Version 7.1.2 (31/12/2008) - fG!
39173917-# Support for the jump decision (will display if a conditional jump will be taken or not)
39183918-#
39193919-# Version 7.1.1 (29/12/2008) - fG!
39203920-# Moved gdb options to the beginning (makes more sense)
39213921-# Added support to dump message being sent to msgSend (easier to understand what's going on)
39223922-#
39233923-# Version 7.1
39243924-# Fixed serious (and old) bug in dd and datawin, causing dereference of
39253925-# obviously invalid address. See below:
39263926-# gdb$ dd 0xffffffff
39273927-# FFFFFFFF : Cannot access memory at address 0xffffffff
39283928-#
39293929-# Version 7.0
39303930-# Added cls command.
39313931-# Improved documentation of many commands.
39323932-# Removed bp_alloc, was neither portable nor usefull.
39333933-# Checking of passed argument(s) in these commands:
39343934-# contextsize-stack, contextsize-data, contextsize-code
39353935-# bp, bpc, bpe, bpd, bpt, bpm, bhb,...
39363936-# Fixed bp and bhb inconsistencies, look at * signs in Version 6.2
39373937-# Bugfix in bhb command, changed "break" to "hb" command body
39383938-# Removed $SHOW_CONTEXT=1 from several commands, this variable
39393939-# should only be controlled globally with context-on and context-off
39403940-# Improved stack, func, var and sig, dis, n, go,...
39413941-# they take optional argument(s) now
39423942-# Fixed wrong $SHOW_CONTEXT assignment in context-off
39433943-# Fixed serious bug in cft command, forgotten ~ sign
39443944-# Fixed these bugs in step_to_call:
39453945-# 1) the correct logging sequence is:
39463946-# set logging file > set logging redirect > set logging on
39473947-# 2) $SHOW_CONTEXT is now correctly restored from $_saved_ctx
39483948-# Fixed these bugs in trace_calls:
39493949-# 1) the correct logging sequence is:
39503950-# set logging file > set logging overwrite >
39513951-# set logging redirect > set logging on
39523952-# 2) removed the "clean up trace file" part, which is not needed now,
39533953-# stepi output is properly redirected to /dev/null
39543954-# 3) $SHOW_CONTEXT is now correctly restored from $_saved_ctx
39553955-# Fixed bug in trace_run:
39563956-# 1) $SHOW_CONTEXT is now correctly restored from $_saved_ctx
39573957-# Fixed print_insn_type -- removed invalid semicolons!, wrong value checking,
39583958-# Added TODO entry regarding the "u" command
39593959-# Changed name from gas_assemble to assemble_gas due to consistency
39603960-# Output from assemble and assemble_gas is now similar, because i made
39613961-# both of them to use objdump, with respect to output format (AT&T|Intel).
39623962-# Whole code was checked and made more consistent, readable/maintainable.
39633963-#
39643964-# Version 6.2
39653965-# Add global variables to allow user to control stack, data and code window sizes
39663966-# Increase readability for registers
39673967-# Some corrections (hexdump, ddump, context, cfp, assemble, gas_asm, tips, prompt)
39683968-#
39693969-# Version 6.1-color-user
39703970-# Took the Gentoo route and ran sed s/user/user/g
39713971-#
39723972-# Version 6.1-color
39733973-# Added color fixes from
39743974-# http://gnurbs.blogsome.com/2006/12/22/colorizing-mamons-gdbinit/
39753975-#
39763976-# Version 6.1
39773977-# Fixed filename in step_to_call so it points to /dev/null
39783978-# Changed location of logfiles from /tmp to ~
39793979-#
39803980-# Version 6
39813981-# Added print_insn_type, get_insn_type, context-on, context-off commands
39823982-# Added trace_calls, trace_run, step_to_call commands
39833983-# Changed hook-stop so it checks $SHOW_CONTEXT variable
39843984-#
39853985-# Version 5
39863986-# Added bpm, dump_bin, dump_hex, bp_alloc commands
39873987-# Added 'assemble' by elaine, 'gas_asm' by mong
39883988-# Added Tip Topics for aspiring users ;)
39893989-#
39903990-# Version 4
39913991-# Added eflags-changing insns by pusillus
39923992-# Added bp, nop, null, and int3 patch commands, also hook-stop
39933993-#
39943994-# Version 3
39953995-# Incorporated elaine's if/else goodness into the hex/ascii dump
39963996-#
39973997-# Version 2
39983998-# Radix bugfix by elaine
12061206+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12071207+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12081208+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
12091209+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
12101210+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
12111211+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
12121212+# SOFTWARE.
12131213+# ------------------------------------------------------------------------------
12141214+# vi:syntax=python
12151215+# Local Variables:
12161216+# mode: python
12171217+# End: