Debugging SpiderMonkey with Archer
December 20, 2010 § 4 Comments
If you’re hacking on SpiderMonkey, the JavaScript engine used in Mozilla Firefox, the debugger can be less than helpful when viewing SpiderMonkey’s data structures:
(gdb) print str $1 = (JSString *) 0x7ffff680a440 (gdb) print *str $2 = {mLengthAndFlags = 148, {mChars = 0x7ffff680a450, mLeft = 0x7ffff680a450}, {mInlineStorage = {118, 97, 114, 32}, e = {{mCapacity = 9007688887369846, mParent = 0x20007200610076, mBufferWithInfo = 0x20007200610076}, {mBase = 0x20003d00200078, mRight = 0x20003d00200078}}, externalStringType = 6357110}} (gdb) print/c str->mChars[0]@(str->mLengthAndFlags / 16) $4 = {118 'v', 97 'a', 114 'r', 32 ' ', 120 'x', 32 ' ', 61 '=', 32 ' ', 53 '5'}
If you know enough magic, you can make it work, but there’s a lot of clutter, and it’s a distraction from the task at hand.
The Archer Project is a development branch of GDB that you can customize in Python. In particular, you can have Archer automatically call your own Python functions to format particular types of values. I’ve written a set of pretty-printers for SpiderMonkey’s datatypes, so for me the above interaction would go:
(gdb) print str $1 = 0x7ffff680a440 "var x=5" ATOMIZED (gdb) print *str $2 = {mLengthAndFlags = (7 << 4)|FLAT|ATOMIZED, mChars = 0x7ffff680a450, externalStringType = 6357110}
When printing a pointer to a JSString, Archer shows the string’s contents, and any flags (like ATOMIZED). When printing a JSString struct value, Archer omits dead union branches — in this case, most of the members.
Archer applies the pretty-printers whenever it needs to print a value, so, for example, stack traces are legible, too:
(gdb) where 1 #0 js_SetPropertyHelper (cx=0xa8e550, obj=0x7ffff6803048 [Object global], id=$jsid("x"), defineHow=1, vp=0x7fffffffc7f0, strict=0) at ../jsobj.cpp:5367
Here the JSObject pointer and the jsid have been printed in a more helpful way.
At present, I have pretty-printers for:
- jsval and js::Value
- JSString, JSString *, JSAtom *, and jsid
- JSObject *, JSFunction *, and JSFunction
- js::PropertyCacheEntry and js::PCVal
- JSParseNode *, JSDefinition *, JSParseNode, JSDefinition, and JSFunctionBox *
- js::Shape
You can check out a copy of the current sources using Mercurial:
$ hg clone http://hg.mozilla.org/users/jblandy_mozilla.com/archer-mozilla destination directory: archer-mozilla requesting all changes ... 22 files updated, 0 files merged, 0 files removed, 0 files unresolved $ cd archer-mozilla $ more README
This creates a directory called archer-mozilla; the README file there explains how to make Archer use the pretty-printers.
This is very much a work in progress; there are certainly bugs, and while there are regression tests, they don’t cover all the pretty-printers the package defines. Please let me know if you find a bug, or have suggestions for improvements.
I use Archer on Linux; I don’t know how well it works on Macintosh OS X or Windows. I hear that these pretty-printers can be used with modern stock GDB releases.
You actually shouldn’t need archer to use python for pretty printing. GDB 7.0 should be enough for that.
I wrote some regression tests for the pretty-printers, to help me keep up with rapidly changing SpiderMonkey internals. Those tests show two failures when run against GDB 7.2, and none when run against the archer-tromey-python Archer branch recommended in the README file. Patches would be greatly appreciated.
[…] clutter up the output. I use a modified version of this .gdbinit. I also highly, highly recommend Jim Blandy’s archer-mozilla gdb extensions written in Python. I’d actually like to stop using that .gdbinit, since it’s written […]
[…] Blandy announced his archer-mozilla pretty-printers for Spidermonkey late last year. I’ve used them a few times while working on […]