The main source tree for Firefox, Mozilla Central, now includes some code that should make debugging SpiderMonkey with GDB on Linux much more pleasant and productive.
GDB understands C++ types and values, but naturally it has no idea what the debuggee intends them to represent. As a result, GDB’s attempts to display those values can sometimes be worse than printing nothing at all. For example, here’s how a stock GDB displays a stack frame for a call to js::baseops::SetPropertyHelper
:
(gdb) frame
#0 js::baseops::SetPropertyHelper (cx=0xc648b0, obj={<js::HandleBase> = {}, ptr = 0x7fffffffc960}, receiver={<js::HandleBase> = {}, ptr = 0x7fffffffc960}, id={<js::HandleBase> = {}, ptr = 0x7fffffffc1e0}, defineHow=4, vp={<js::MutableHandleBase> = {<js::MutableValueOperations<JS::MutableHandle >> = {<js::ValueOperations<JS::MutableHandle >> = {}, }, }, ptr = 0x7fffffffc1f0}, strict=0) at /home/jimb/moz/dbg/js/src/jsobj.cpp:3593
There exist people who can pick through that, but for me it’s just a pile of hexadecimal noise. And yet, if you persevere, what those arguments represent is quite simple: in this case, obj
and receiver
are both the JavaScript global object; id
is the identifier "x"
; and vp
refers to the JavaScript string value "foo"
. This SetPropertyHelper
call is simply storing "foo"
as the value of the global variable x
. But it sure is hard to tell—and that’s an annoyance for SpiderMonkey developers.
As of early December, Mozilla Central includes Python scripts for GDB that define custom printers for SpiderMonkey types, so that when GDB comes across a SpiderMonkey type like MutableValueHandle
, it can print it in a meaningful way. With these changes, GDB displays the stack frame shown above like this:
(gdb) frame
#0 js::baseops::SetPropertyHelper (cx=0xc648b0, obj=(JSObject * const) 0x7ffff151f060 [object global] delegate, receiver=(JSObject * const) 0x7ffff151f060 [object global] delegate, id=$jsid("x"), defineHow=4, vp=$jsval("foo"), strict=0) at /home/jimb/moz/dbg/js/src/jsobj.cpp:3593
Here it’s much easier to see what’s going on. Objects print with their class, like “global” or “Object”; strings print as strings; jsval
values print as appropriate for their tags; and so on. (The line breaks could still be improved, but that’s GDB for you.)
Naturally, the pretty-printers work with any command in GDB that displays values: print
, backtrace
, display
, and so on. Each type requires custom Python code to decode it; at present we have pretty-printers for JSObject, JSString, jsval, the various Rooted
and Handle
types, and things derived from those. The list will grow.
GDB picks up the SpiderMonkey support scripts automatically when you’re debugging the JavaScript shell, as directed by the js-gdb.py
file that the build system places in the same directory as the js
executable. We haven’t yet made the support scripts load automatically when debugging Firefox, as that’s a much larger audience of developers, and we’d like a chance to shake out bugs before foisting it on everyone.
Some versions of GDB are patched to trust only auto-load files found in directories you’ve whitelisted; if this is the case for you, GDB will complain, and you’ll need to add a command like the following to your ~/.gdbinit
file:
# Tell GDB to trust auto-load files found under ~/moz.
add-auto-load-safe-path ~/moz
If you need to see a value in its plain C++ form, with no pretty-printing applied, you can add the /r
format modifier to the print
command:
(gdb) print vp
$1 = $jsval("foo")
(gdb) print/r vp
$2 = {
<js::MutableHandleBase> = {
<js::MutableValueOperations<JS::MutableHandle >> = {
<js::ValueOperations<JS::MutableHandle >> = {}, }, },
members of JS::MutableHandle:
ptr = 0x7fffffffc1f0
}
If you run into troubles with a pretty-printer, please file a bug in Bugzilla, under the “Core” product, for the “JavaScript Engine” component. (The pretty-printers have their own unit and regression tests; we do want them to be reliable.) In the mean time, you can disable the pretty-printers with the disable pretty-printer
command:
(gdb) disable pretty-printer .* SpiderMonkey
12 printers disabled
128 of 140 printers enabled
For more details, see the GDB support directory’s README file.
Question wrote on :