Remember the day when you were asked to remember the days when all the tools at hand looked like a Basic interpreter with 30 commands, the most usable being PEEK, POKE and PRINT?
That’s been almost half a year now, and the tale is ready to get a new chapter.
The latest and greatest in the World of the GNU Project debugger (also known as gdb) is Python scripting, — and it is really awesome. I certainly don’t tend to exaggerate on the positive side, but this is close to sliced bread with chocolate and beer. Erm… well, you get the idea
The feature has been in the works for a while (the initial commit to the gdb CVS repository was in August 2008) and was officially released with gdb 7.0 in October 2009. So in theory it is now in a usable state and accessible on a broad range of platforms.
Unfortunately, outside the Ivory Tower usability is a bit hampered by the fact that gdb 7.0 likes to divide by zero every now and then, and the “broad range of platforms” excludes Mac (Apple’s gdb for Mac is based on FSF gdb 6.3, and FSF gdb does not work there), Symbian (best bet so far is based on FSF gdb 6.4), and, of course, MSVC compiled binaries on Windows (no gdb at all).
But a few Gaul villages are still standing: It does work on Linux, and after tickling the gdb sources a bit it even works well, so well in fact that the next release of Qt Creator will use gdb’s Python scripting to build up the “Locals and Watchers” view.
This also lets us nicely address one of the most prominent feature requests: To “provide hooks so that users could write their own display classes for custom data types to totally do away with the need for printf-style debugging”, or “an easy to use plugin interface for the display of custom object”, or “a nice custom data type display interface would be for the user to implement” (see comments of Ben, Abdel, and spinynorman), or a few similar ones on qt-creator@trolltech.com
Here is how:
- Get a Python enabled gdb by either
- downloading a pre-build binary from here
- building one yourself:
- get build prerequisites including Python development packages (on Ubuntu e.g.
python2.6-dev) - get gdb sources from the archer-tromey-python branch:
git clone git://sourceware.org/git/archer.git cd archer git checkout -b archer-tromey-python origin/archer-tromey-python
- patch sources to work around that division by zero:
--- a/gdb/value.c +++ b/gdb/value.c @@ -1920,7 +1920,8 @@ value_primitive_field (struct value *arg1, int offset, v = allocate_value_lazy (type); v->bitsize = TYPE_FIELD_BITSIZE (arg_type, fieldno); - if ((bitpos % container_bitsize) + v->bitsize < = container_bitsize + if (container_bitsize + && (bitpos % container_bitsize) + v->bitsize < = container_bitsize && TYPE_LENGTH (type) <= (int) sizeof (LONGEST)) v->bitpos = bitpos % container_bitsize; else - configure and build it:
./configure --with-python --disable-werror make
Your new gdb will emerge as gdb/gdb. It will identify itself as gdb-6.8.50.something-cvs. That is fine.
- get build prerequisites including Python development packages (on Ubuntu e.g.
–or–
- Get a recent checkout of Qt Creator master branch and build it:
git clone git://gitorious.org/qt-creator/qt-creator.git cd qt-creator qmake -r make
- Point Qt Creator’s gdb path (Options -> Debugger -> Gdb -> Gdb Location) to your archer gdb or set the QTC_DEBUGGER_PATH environment variable before starting Qt Creator.
- Start debugging as usual.
That gives you the kind of display of QStringList, std::map etc use are used to from the old C++ based debugging helpers. You might notice that it’s even a bit quicker. Nothing to be scared about, though.
But now, time for your own debugging helpers. Assuming you have the following class template in your code:
template <typename T> class Vector
{
public:
explicit Vector(int size) : m_size(size), m_data(new T[size]) {}
~Vector() { delete [] m_data; }
//...
private:
int m_size;
T *m_data;
};
all you need is to
- write the following into some file, say
vector.py:def qdump__Vector(d, item): data = item.value["m_data"] # extract the 'm_data' member from the object size = item.value["m_size"] # extract the 'm_size' member from the object d.putItemCount(size) # set the 'value' field to '< %n items>' d.putNumChild(size) # announce 'size' children if d.isExpanded(item): # check whether the children should be shown, too # start writing 'size', but no more than 10000 children. d.beginChildren([size, 10000], item.value.type.template_argument(0)) for i in d.childRange(): # iterate over the specified range # create a new item from a value obtained from dereferencing the # data pointer, with an internal name composed of the parent's # internal name and the current child number d.putItem(Item(data.dereference(), item.iname, i)) data += 1 # advance the data pointer by one d.endChildren() # end writing the list of children - make it accessible to gdb:
echo "python execfile('/path/to/your/vector.py')" >> ~/.gdbinit - start debugging as usual
Qt Creator’s default helpers are defined in share/qtcreator/gdbmacros/gdbmacros.py. For a description of the two parameters ‘d’ and ‘item’ (of type ‘Dumper’ and ‘Item’ respectively), refer to tomorrow’s Qt Creator documentation (just git pull again after 22:00 GMT). Don’t forget to run make qch_docs and to point your Options -> Help -> Documentation to share/doc/qtcreator/qtcreator.qch if it’s not showing up immediately.
Have fun!
André
Possibly related posts:
9 comments
no motivating screenshot?
Would have been pretty much the same as the old ones at http://labs.trolltech.com/blogs/2009/06/22/peek-and-poke. I thought I could spend the rest of the day with something less challenging than fighting WordPress ;-}
Gdb 7.0 not only has introduced python scripting, but also pretty printing using python scripts:
http://sourceware.org/gdb/current/onlinedocs/gdb/Pretty-Printing.html
Advantage over your home grown solution:
* pretty printers work in cli gdb and any other gdb frontend
* libraries can ship their on pretty printers which gdb will automatically load
I even wrote such scripts for Qt ( http://nikosams.blogspot.com/2009/10/gdb-qt-pretty-printers.html )
So why do have you your own implementation?
Thanks, now I see (I wasn’t aware of the previous post with screenshots).
awesome
@Niko: I am aware of gdb’s own pretty printer. It was a very conscious decision not to use them.
Users will not use the gdb/CLI for data display inside an IDE, and so far there are no libraries shipping usable pretty printers. So the advantages you cite are minor from a Qt Creator perspective, if they exist at all.
On the other hand, using them has some major drawbacks for me. They do not produce the output that I need, but on the other hand they produce also output that I don’t need. Worse, they force me to use MI variable objects, leading to extra roundtrips and bookkeeping for nested structures. While all those might be bearable on desktop machine, they are show stoppers on low bandwidth/high latency connections.
The nail in the coffin is another issue: The world is bigger than FSF gdb 7.0. First, there are a few people on Windows using MSVC. For good reasons even. They, unfortunately, cannot use gdb at all. Also, there are people on Mac and Symbian that cannot use gdb 7.0, and even on *nix it’s not uncommon to be stuck with old software. Even if You-Know-What IDE does not need to care for them, Qt Creator has to. So I have to maintain the Creator’s old C++ based pretty printing in parallel to the python based one, and keeping python and C++ code at least structurally the same helps with that a lot.
I am really, really happy that the python scripting allows me to use the architecture I find useful and produce the data I find interesting.
@André:
Performance shouldn’t be a problem – with varobjs gdb tells you what data changed, you don’t have to re-request everything. That should be a major advantage.
I understand the technical reason for your decision, but from the point of view from an user that want’s to write pretty printer for his own classes it’s not optimal. However it should be not to hard to port QtCreator pretty printers them to gdb pretty printers I guess.
> Unfortunately, outside the Ivory Tower usability is a bit hampered …, and
> the “broad range of platforms” excludes [Microsoft] MSVC compiled binaries
> on Windows (no gdb at all).
There’s no need for gdb on Windows – we have WinDbg and cdb, which are awesome tools. Perhaps the spare cycles (saved by not porting to Windows) can go to help Apple’s shitty assembler, or at least an upgrade to from at&t syntax to intel.
JW
@Jeffrey Walton: There are quite a few features of gdb that are not available or not usable in cdb. Not having a “real” scripting language is one of them, and the whole “pretty printing” stuff mentioned in the blog is only possible because of having that available.
I am aware of what VS can do using autoexp.dat. But this is (a) not available in cdb as far as I know, and (b) not sufficient anyway. Also, writing Extension DLLs is neither trivial nor appealing in cross-platform development (“cross-platform” is not “runs on both XP _and_ Vista”)
cdb is also really, really slow when calling into user code, and it is way less capable in passing function parameters and evaluating expressions compared to gdb.
In addition, cdb cannot be fixed or extended to compensate for the missing features.
So, no, sorry, cdb is not a full replacement for gdb, but unfortunately the best we can get right now for debugging MSVC compiled binaries.
Re ‘AT&T’ vs ‘Intel’ syntax. I pretty much prefer Intel, too. That’s why I put ‘set disassembly-flavor intel’ into my .gdbinit.
Comments on this entry are closed.