type "mbt", see this.
gdb has had integrated python support for some time and it is truly awesome. The innards have changed here and there, so my previous efforts to show colorized/fancy backtraces, show colorized source listings, and provide unified JS/C++ mozilla backtraces (with colors still) have experienced some bit-rot over time.
type "cbt", see this
I have de-bitrotted the changes, hard. Hard in this case means that the changes depend on gdb 7.3 which only exists in the future or in the archer repo you can find on this wiki page, or maybe in gdb upstream but I already had the archer repo checked out…
type "sl", see this.
In any event, if you like gdb and work with mozilla, you will not only want these things, but also Jim Blandy’s mozilla-archer repo which has magic SpiderMonkey JS helpers (one of which mozbt depends on; those JSStrings are crazy, yo!). Coincidentally, he also depends on the future, and his README tells you how to check out the archer branch in greater detail.
You can get your own copy of these very exciting gdb python things from my github pythongdb-gaudy repo.
The important notes for the unified backtrace are:
- It does’t work with the tracing JIT; the trace JIT doesn’t produce the required frames during its normal operation.
- It might work with the method JIT if gdb could unwind method JIT frames, but it doesn’t seem to do that yet. (Or I didn’t build with the right flag to tell it to use a frame pointer/etc., or I am using the wrong gdb branch/etc.) Once the Method JIT starts telling gdb about its generated code with debug symbols and the performance issues in gdb’s JIT interface are dealt with, you can just use the colorizing backtrace because no special logic is required to interleave frames at that point and Jim Blandy’s magic JS pretty printers should ‘just work’.
- Don’t forget that if you just want a pure JS backtrace (and with all kinds of fanciness) and have a debug build, you can just do “call DumpJSStack()” in gdb and it will call back into XPConnect and invoke the C++ code that authoritatively knows how to walk this stuff.
- If you’re cool and using generators, then you’re stuck with the interpreter, so it will totally work.
As far as I know (and ignoring my previous efforts on chroniquery along these lines), up until now you had your C/C++ Mozilla backtraces via gdb (chocolate) and your JS backtraces via “call DumpJSStack()” or the debugger keyword from within JS (peanut butter), but these two great flavors had never come together to make a lot of money for dentists.
The screenshots (which is actually just one screenshot split in two) show invocation of a custom python gdb command building on my previous exciting pretty gdb commands. The command has filtered out boring JS interpreter / XPConnect code and interleaved exciting interesting JS stack frames.
The implementation is reasonably simple and intended to be able to be implemented using VProbes to support my recent performance work along those lines. We walk stack frames the usual way. Ahead of time, we have marked out the PC ranges of interesting JS interpreter functions (js_Interpret and js_Execute). If the stack frame’s instruction pointer is in one of those functions we grab the JSContext argument. We pop frames until we reach the native frame those functions allocate from their own stack space (whose boundaries we know from the stack walking).
There is one trick we have to do involving dormantFrameChain. While js_Execute has a consistent and straightforward usage of JS_SaveFrameChain, XPConnect and its quickstub friends are more complex. Right now we use a dumb heuristic that just looks if our frame pointer is 0 and there is a dormantFrameChain, and in that case we restore it. (Thankfully the garbage collector needs to know about the shelved frames, otherwise we might have to chase frames down.) I haven’t put much effort into thinking about it, but the heurstic seems a bit reckless. We could likely just concurrently walk the XPConnect context stack to figure out when to restore dormant frame chains. The existing VProbe JS stack (only) code already goes to the horrible effort to get at the thread-local stack, so it wouldn’t be too much more work. Things probably also fall down during garbage collection right now.
Hg repository is here. Under no circumstances try to use this with jblandy’s excellent archer-mozilla JS magic right now. The current code is very distrustful of gdb.Value in a dumb way and does exceedingly dangerous things wherein pointers are bounced to strings and back to integers because direct integer coercion is forbidden. With pretty printers installed this is likely to break. Also, this is all only tested on 1.9.1.
Gaudily syntax-highlighted code listing in gdb joins the gaudy gdb plugin family! (Other members include gaudily colorized backtraces, which you can also see in the bottom of the screenshot.) This, of course, requires gdb with python crammed inside. It might require one crammed a few months ago too; I haven’t updated my archer-gdb repo for at least that long.
The “sl” plugin uses Pygments for the syntax highlighting. Although pygments has a 256 color terminal formatter (woo!), I ended up using my pyflam module because it did not support my need to color the background of the current line without doing something convoluted. (I would have had to create a filter that did its own line-counting and created background-color-styled token variant of every token on the desired line.) Also, it didn’t do line numbers.
The color theme is based off the “fruity” color theme. Much of the gaudy comes from a filter I added that tries to do various Mozilla C++-aware code styling things by recognizing naming patterns of Name tokens. Before you complain about the colors hurting your brain, remember that this is the alternative:
That’s right. It’s like looking at static. You can barely make anything out. And imagine if it was more than just the 10 lines “list” gives you.
Anywho, the repo is here: http://hg.mozilla.org/users/bugmail_asutherland.org/pythongdb-gaudy/
The README tells you what to do. For complete-ness, and because I went to all the effort to write documentation for the command, here is what it does!
Prints a syntax-highlighted source listing. Currently limited to only
work based on the current debug frame and position.
By default, the 11 lines before the current position and 8 lines after are
displayed. A line context is saved between command invocations if the current
source line does not change.
Arguments when used in a new context:
(none) Shows the 11 lines before the current position and 8 lines after.
N Shows the N/2 lines befores the current position and N/2 lines after.
-N Shows the N lines before the current position and 8 lines after.
+N Shows the 11 lines before the current position and N lines after.
M N Shows the M lines before the current position and N lines after.
Arguments in an existing context:
(none) Shows the 20 lines after the last-shown lines.
- Shows the 20 lines preceding the last-shown lines.
N Shows the N lines after the last-shown lines.
-N Shows the N lines preceding the last-shown lines.
M N Shows the M last lines of the last-shown lines and N lines after the
Arguments regardless of context
@A,B Shows lines A through B.
Like many people who have overdosed on syntax highlighting and other forms of colorization, my brain is no longer able to process monochrome text displays. Which is why I have been so excited about gdb with python crammed inside. (The good sense of “crammed”, wherein one is cramming cookies in one’s mouth.) I have perverted its spirit and used it to colorize gdb backtraces! Woo!
While I was in there, I have done two useful things:
- There is magic of limited potency that normalizes the path automatically.
- It looks at all the values in the arguments (and locals too, I guess) and if they are used more than once, it considers making them “interesting”. Interesting values get named based on where we first saw them, and assigned a color. Then, whenever they appear in the backtrace, they get their special name and color to help us see the flow of values through the backtrace. For example, in the screenshot above you can see “this5” in a nice* blue color. Each time its value appears, the “this5” label appears (the 5 is for frame 5). I find this easier than manually scanning using my brain.
My hg repo is here: http://hg.mozilla.org/users/bugmail_asutherland.org/pythongdb-gaudy/
If you like this, or if you don’t like this but do like useful things, you are even more likely to like Jim Blandy’s archer-mozilla repo which is full of magic debugging help for spidermonkey in gdb. (nb: The python-gdb trunk right now has changed how pretty printers register, and I don’t think that repo has yet caught up.) Also, see Tom Tromey’s blog posts about the whole python-gdb thing.
* When I use “nice” in terms of colors, this is from my perspective as someone who demands many colors, has the time to add crazy colors to everything, but inexplicably does not have the time to actually pick colors that humans find appealing (or even non-nauseating). I am going to pass the buck to the people who originally conceived of 256-color xterms and thought I could be trusted with a color cube, no matter how limited.
Python code driving gdb via the mi2 interface (using pexpect and pyparsing) begets a trace file. Python code processing the trace file begets an html document (with syntax highlighting thanks to pygments.) The above is just a screenshot of the output, which you can actually browse here.
The “visualization” is pretty simple. Lines of code with a light green background were executed in the trace. 15 lines of context are shown around executed lines of code. The bars to the left show when the line of code was executed during the trace. If the code was a function call, its bar is extended until the function call completed based on conclusions drawn from knowing the stack depth at each step. There is currently no way to visually distinguish from the graphic between a line executed many times in rapid succession and a call that lasted a long time. You would need to either look at the code or cheat and use firebug.
The visualization is of a call to commit() using pysqlite2 on sqlite3 which fails because of an outstanding select that has not yet had all its rows retrieved. My conclusion is that clever generator tricks (not mine!) can bite you when any piece of your stack has concurrency issues… and pysqlite2 should report the most specific error string possible. (Going to provide a patch; still think the trunk would provide the rather generic error that bit me.) For those using trac’s version control abstraction, be warned that changeset traversal is most definitely a (logic) generator wrapping a row-results-fetching generator.
The tracing mechanism is pretty straight-forward. The tracing class is told an interesting breakpoint and an ignore count. Once the count has been reached, “step” tracing begins. The idea was to do a first pass that just counts how many times the interesting breakpoint occurs before the program tanks, then we can skip to the last few before doing the (slow) step-wise tracing in the second pass. The goal would be to approximate a light-weight tracing mechanism where we can see what the program did before whatever bad state occurred. Gah! I was just going to say that there aren’t any open source tools readily available to accomplish that goal (dyninst/dpcl still require a bit of legwork), but it turns out that Chronicle (formerly Amber) has recently been released. (For whatever reason, Robert O’Callahan’s post didn’t show up in his feed via planet mozilla for me.) OTOH, this method is still potentially useful for remote gdb target debugging on actual hardware (albeit extremely slowly), or perhaps for a case where the program must do a lot of execution before the interesting part of the trace happens, lending itself to a non-valgrind solution. I presume you would pay the simulation price for valgrind the whole way through, unless valgrind can ‘absorb’ a running process into its simulation.
I also have a visualization done using visophyte’s model abstraction (if you are going to go and invent yet another multi-backend canvas abstraction layer, you might as well use it), but without some way to view the corresponding code and explore, it is useless. The generated HTML here is more useful, but still lacking in interactivity or true context. That would be the next step. The step after that would be throwing back in a concise and interactive visualization. The same effort required for that should allow me to produce interactive visualizations from thunderbird.