It's 2012. Why the fuck are you talking about gdb?
You love Richard Stallman (isn't he lovely? :D)
You think IDEs are complex amalgamations of state, hard to understand, and prone to fail in unexpected ways
Nothing impressive here
break myfile.cpp:99 Breakpoint 1 at 0x401193: file myfile.c, line 99. (gdb) commands Type commands for breakpoint(s) 1, one per line. End with a line saying just "end". >silent >print a >cont >end
That cont
screws single-stepping (solvable with Python, see this blog post)
define plist
set $ptr = $arg0
while $ptr != 0
print *$ptr
set $ptr = $ptr->next
end
end
A more complex example, from PpluX's SLB repo
define luastack
set $top = lua_gettop($arg0)
set $i = 1
while $i <= $top
if lua_type($arg0,$i) == -1
printf "stack - %i : No Value \n", $i
else
call lua_pushvalue($arg0,$i)
set $str = lua_tolstring($arg0,-1,0x0)
set $type = lua_typename($arg0,lua_type($arg0,$i))
if $str
printf "stack - %i : %s -> '%s'\n", $i, $type , $str
else
printf "stack - %i : %s\n", $i, $type
end
call lua_settop($arg0,-2)
end
set $i = $i + 1
end
You can also create hooks which run just before or after any gdb command:
define hook-command
to run things before command
define hookpost-command
to run things after command
set parameter value
mechanism
stop, cont, exited, new_objfile
$caller_is(string)
and then break file:line if $caller_is("main")
,
see this article with a implementation of $caller_is()
Hello World
(gdb) python print "Hello, World!"
Hello, World!
Ok, now what?
Friendly representation of your data structures
(gdb) p m
$3 = {
_M_t = {
_M_impl = {
, std::allocator > const, int> > >> = {
<__gnu_cxx::new_allocator, std::allocator > const, int> > >> = {}, },
members of std::_Rb_tree, std::allocator >, std::pair, std::allocator > const, int>, std::_Select1st, std::allocator > const, int> >, std::less, std::allocator > >, std::allocator, std::allocator > const, int> > >::_Rb_tree_impl, std::allocator > >, true>:
_M_key_compare = {
, std::allocator >, std::basic_string, std::allocator >, bool>> = {}, },
_M_header = {
_M_color = std::_S_red,
_M_parent = 0x604120,
_M_left = 0x6040b0,
_M_right = 0x604190
},
_M_node_count = 4
}
}
}
Friendly representation of your data structures
(gdb) p m
$2 = std::map with 4 elements = {
["blah"] = 2,
["lolailo"] = 3,
["trololo"] = 1,
["xyz"] = 4
}
Up-to-date libc versions have pretty printers for STL containers. You don't need to do anything to benefit from this RIGHT NOW.
Of course, you can do it for your own data structures too: Writing a pretty printer
You need to define a class...
class StdStringPrinter(object):
"Print a std::string"
def __init__(self, val):
self.val = val
def to_string(self):
return self.val['_M_dataplus']['_M_p']
def display_hint(self):
return 'string'
... and a lookup function
def str_lookup_function(val):
lookup_tag = val.type.tag
if lookup_tag == None:
return None
regex = re.compile("^std::basic_string$")
if regex.match(lookup_tag):
return StdStringPrinter(val)
return None
And then do some boring stuff to register it into gdb
# create a class for your new command
class DoNothingCommand(gdb.Command):
"""This command does nothing.""" # docstring (shown by gdb help command)
def __init__(self):
super(DoNothingCommand, self).__init__("do_nothing",
gdb.COMMAND_USER,
gdb.COMPLETE_NONE)
def invoke(self, arg, from_tty):
pass
DoNothingCommand() # and instance it
Pretty much every gdb "user" concept is exposed to Python scripts via the API.
Visualize an array from your program as a line graph:
import gdb
import matplotlib.pyplot as plt
class PlotterCommand(gdb.Command):
def __init__(self):
super(PlotterCommand, self).__init__("plot",
gdb.COMMAND_DATA,
gdb.COMPLETE_SYMBOL)
def invoke(self, arg, from_tty):
args = gdb.string_to_argv(arg)
v = gdb.parse_and_eval(args[0])
t = v.type.strip_typedefs()
n = t.sizeof / t.target().sizeof
l = [float(v[i]) for i in range(n)]
plt.plot(l)
plt.show()
PlotterCommand()
(simplified version)
Full source for this demo (try this at home!)A (proof of concept) gtk data structure viewer:
Source for this demo (try this at home!)DDD did these things ages ago.
BROTIP: Andreas Zeller, original author of DDD, has a nice online course on debugging techniques at Udacity
GDB has many other semi-unknown cool features (which I won't talk about today)