<section>
<h2> GDB is extensible</h2>
<ul>
- <li class="fragment"> You can automate things </li>
- <li class="fragment"> You can adapt it to your code base </li>
- <li class="fragment"> You can try crazy new ideas :D </li>
+ <li> You can automate things </li>
+ <li> You can adapt it to your code base </li>
+ <li> You can try crazy new ideas :D </li>
+ </ul>
+ </section>
+
+ <section>
+ <h2>Extension points</h2>
+ <ul>
+ <li class="fragment">Pretty printers</li>
+ <li class="fragment">Custom commands</li>
+ <li class="fragment">Code auto-loading</li>
+ <li class="fragment">Event handlers (<code>stop, cont, exited, new_objfile</code>)</li>
+ <li class="fragment">"Convenience functions"</li>
+ <li class="fragment">Custom parameters (like "<code>set parameter value</code>", then retrieve values from commands, etc)</li>
</ul>
</section>
<section>
<h2>Pretty printing</h2>
- <ul>
- <li>
- Friendly representation of your data structures
- </li>
- <li>
- Up-to-date libc versions have pretty printers for STL containers. You don't need to do
- anything to benefit from this RIGHT NOW. <br>
- <img class="fragment" src="its-free.jpg">
+ <p>Friendly representation of your data structures</p>
+<pre class="fragment"><code>(gdb) p m
+$3 = {
+ _M_t = {
+ _M_impl = {
+ <std::allocator<std::_Rb_tree_node<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int> > >> = {
+ <__gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int> > >> = {<No data fields>}, <No data fields>},
+ members of std::_Rb_tree<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int>, std::_Select1st<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int> >, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int> > >::_Rb_tree_impl<std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, true>:
+ _M_key_compare = {
+ <std::binary_function<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool>> = {<No data fields>}, <No data fields>},
+ _M_header = {
+ _M_color = std::_S_red,
+ _M_parent = 0x604120,
+ _M_left = 0x6040b0,
+ _M_right = 0x604190
+ },
+ _M_node_count = 4
+ }
+ }
+}
+</code></pre>
+ </section>
+ <section>
+ <h2>Pretty printing</h2>
+ <p>Friendly representation of your data structures</p>
+<pre><code>(gdb) p m
+$2 = std::map with 4 elements = {
+ ["blah"] = 2,
+ ["lolailo"] = 3,
+ ["trololo"] = 1,
+ ["xyz"] = 4
+}
+</code></pre>
+ </section>
+ <section>
+ <h2>Pretty printing</h2>
+ <p>
+ Up-to-date libc versions have pretty printers for STL containers. You don't need to do
+ anything to benefit from this RIGHT NOW.
+ </p>
- </li>
- </ul>
+ <img class="fragment" src="its-free.jpg">
+ </section>
+
+ <section>
+ <section>
+ <h2>Pretty printing</h2>
+ <p>
+ Of course, you can do it for your own data structures too:
+ <a href="http://sourceware.org/gdb/onlinedocs/gdb/Writing-a-Pretty_002dPrinter.html#Writing-a-Pretty_002dPrinter">Writing a pretty printer</a>
+ </p>
+ </section>
+
+ <section>
+ <h2>Pretty printer implementation</h2>
+ <p>You need to define a class...</p>
+<pre><code>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'
+</code></pre>
+ </section>
+
+ <section>
+ <h2>Pretty printer implementation</h2>
+ <p>... and a lookup function</p>
+<pre><code>def str_lookup_function(val):
+ lookup_tag = val.type.tag
+ if lookup_tag == None:
+ return None
+ regex = re.compile("^std::basic_string<char,.*>$")
+ if regex.match(lookup_tag):
+ return StdStringPrinter(val)
+ return None
+</code></pre>
+ <p class="fragment">And then do some boring stuff to register it into gdb</p>
+ </section>
</section>
<section>
<h2>Custom commands (python version)</h2>
-<pre><code>
+<pre><code> # create a class for your new command
class DoNothingCommand(gdb.Command):
- """This command does nothing.""" # docstring
+ """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)
-
+ super(DoNothingCommand, self).__init__("do_nothing",
+ gdb.COMMAND_USER,
+ gdb.COMPLETE_NONE)
def invoke(self, arg, from_tty):
pass
-DoNothingCommand()
+DoNothingCommand() # and instance it
</code></pre>
</section>
<section>
<h2>Wish list</h2>
- <p>Other debuggers also have cool features</p>
- <ul style="text-align:left;">
- <li> <h3>Symbol server support</h3> records (some finite amount of) program history and allows backwards stepping/running. </li>
+ <ul>
+ <li>
+ <b>Symbol and source server support</b><br>
+ Central store for symbols of every build, so you can always retrieve the correct version automatically
+ without distributing debug info to users. Also, integration with SCM to retrieve the matching source code.
+ See <a href="http://randomascii.wordpress.com/2011/11/11/source-indexing-is-underused-awesomeness/">Bruce Dawson's great post</a>
+ </li>
</ul>
</section>
<section>
<h2>Resources</h2>
- <p> <a href="http://sourceware.org/gdb/wiki/PythonGdbTutorial">http://sourceware.org/gdb/wiki/PythonGdbTutorial</a> </p>
+ <ul>
+ <li> <a href="http://sourceware.org/gdb/wiki/PythonGdbTutorial">http://sourceware.org/gdb/wiki/PythonGdbTutorial</a></li>
+ <li> <a href="http://en.wikibooks.org/wiki/Linux_Applications_Debugging_Techniques">http://en.wikibooks.org/wiki/Linux_Applications_Debugging_Techniques</a></li>
+ </section>
+
+ <section>
+ <h1>Thanks!</h1>
+ <h2>Questions?</h2>
</section>
<!-- End slides. -->