Skip to content

Instantly share code, notes, and snippets.

@scottt
Last active August 29, 2015 14:24
Show Gist options
  • Save scottt/411b59e84e64de0607c4 to your computer and use it in GitHub Desktop.
Save scottt/411b59e84e64de0607c4 to your computer and use it in GitHub Desktop.
until-breakpoint: A GDB command that waits for a specific breakpoint to hit
volatile int n;
int main()
{
n = 29;
while (n != 1)
if (n % 2 == 1)
n = 3*n + 1;
else
n = n/2;
return 0;
}
set python print-stack full
source until-breakpoint.py
file ./3n1
break 3n1.c:5
until-breakpoint $bpnum
step
set var n=3
printf "n: %d\n", n
while 1
if n % 2 == 1
break 3n1.c:8
else
break 3n1.c:10
end
until-breakpoint $bpnum
step
printf "n: %d\n", n
if n == 2
loop_break
end
#info breakpoints
delete $bpnum
end
quit
$ cc -Og -Wall -g3 -I. 3n1.c -o 3n1
$ gdb -x 3n1.gdb
Breakpoint 1 at 0x4004f6: file 3n1.c, line 5.
Breakpoint 1, main () at 3n1.c:5
5 n = 29;
6 while (n != 1)
n: 3
Breakpoint 2 at 0x400519: file 3n1.c, line 8.
Breakpoint 2, main () at 3n1.c:8
8 n = 3*n + 1;
6 while (n != 1)
n: 10
Breakpoint 3 at 0x40052b: file 3n1.c, line 10.
Breakpoint 3, main () at 3n1.c:10
10 n = n/2;
6 while (n != 1)
n: 5
Breakpoint 4 at 0x400519: file 3n1.c, line 8.
Breakpoint 4, main () at 3n1.c:8
8 n = 3*n + 1;
6 while (n != 1)
n: 16
Breakpoint 5 at 0x40052b: file 3n1.c, line 10.
Breakpoint 5, main () at 3n1.c:10
10 n = n/2;
6 while (n != 1)
n: 8
Breakpoint 6 at 0x40052b: file 3n1.c, line 10.
Breakpoint 6, main () at 3n1.c:10
10 n = n/2;
6 while (n != 1)
n: 4
Breakpoint 7 at 0x40052b: file 3n1.c, line 10.
Breakpoint 7, main () at 3n1.c:10
10 n = n/2;
6 while (n != 1)
n: 2
import gdb
class UntilBreakpointContext:
(STATE_NOT_WAITING, # initial state
STATE_WAIT_INITED, # post wait_init
STATE_STOPPED_SHOULD_CONTINUE, # stopped, but not by a breakpoints we want
STATE_INFERIOR_EXITED, # the process being debugged ('inferior') exited
STATE_STOPPED_BP_HIT # stopped by a breakpoint we're waiting for
) = range(5)
def __init__(self):
self.bpnums = []
self.state = self.STATE_NOT_WAITING
self.stopped_by_bpnum = None
def stop_handler(self, e):
if not isinstance(e, gdb.BreakpointEvent):
self.state = self.STATE_STOPPED_SHOULD_CONTINUE
return
for i in e.breakpoints:
if i.number in self.bpnums:
(self.state, self.stopped_by_bpnum) = (self.STATE_STOPPED_BP_HIT, i.number)
return
else:
self.state = self.STATE_STOPPED_SHOULD_CONTINUE
def exited_handler(self, e):
self.state = self.STATE_INFERIOR_EXITED
return
def wait_init(self):
if self.state != self.STATE_NOT_WAITING:
return
gdb.events.stop.connect(self.stop_handler)
gdb.events.exited.connect(self.exited_handler)
self.state = self.STATE_WAIT_INITED
def wait_end(self):
if self.state == self.STATE_NOT_WAITING:
return
gdb.events.stop.disconnect(self.stop_handler)
gdb.events.exited.disconnect(self.exited_handler)
self.state = self.STATE_NOT_WAITING
def wait(self, bpnums):
assert(self.state == self.STATE_NOT_WAITING)
self.bpnums = bpnums
self.wait_init()
while 1:
if gdb.selected_inferior().pid == 0:
gdb.execute('run')
else:
gdb.execute('continue')
# 'run' or 'continue' returned, state changed
if self.state == self.STATE_STOPPED_SHOULD_CONTINUE:
gdb.execute('continue')
elif self.state == self.STATE_INFERIOR_EXITED:
self.wait_end()
raise gdb.GdbError('until-breakpoint: '
'inferior exited while waiting for breakpoints %r' % (self.bpnums,))
elif self.state == self.STATE_STOPPED_BP_HIT:
self.wait_end()
return
else:
assert(0)
until_breakpoint_cxt = UntilBreakpointContext()
class UntilBreakpoint(gdb.Command):
'''until-breakpoint BPNUM. Run until BPNUM is hit'''
def __init__(self):
super(UntilBreakpoint, self).__init__('until-breakpoint',
gdb.COMMAND_RUNNING, gdb.COMPLETE_EXPRESSION)
def invoke(self, args, from_tty):
global until_breakpoint_cxt
bpnum = int(gdb.parse_and_eval(args))
until_breakpoint_cxt.wait([bpnum])
UntilBreakpoint()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment