Skip to content

Debugging

Matt Brubeck edited this page Sep 22, 2017 · 22 revisions

Debugging with gdb

Just run servo with 'debug' option:

./mach run --dev --debug

Now you can set breakpoints etc. To run browser specify URL, e.g.:

r http://en.wikipedia.org

Debugging with rr

There are also mach commands for running Servo under rr:

./mach rr-record
./mach rr-replay

Debugging with Firefox developer tools

See Devtools for instructions to use Firefox's DOM/CSS inspector and JavaScript console/debugger to debug web content running inside Servo.

Debugging task failure

Task failure (e.g. fail!) results in a call to the C function rust_fail. I wrote a small script to automate the process of putting a breakpoint on this function to get a backtrace. Use it like

rust-backtrace ./servo foo.html

Debugging X Windows errors

You can break on _XDefaultError.

To make X requests synchronous, set _Xdebug = 1. In GDB:

(gdb) print _Xdebug = 1

The program needs to be running for the symbol to be loaded, so break on main or something and do it there.

Finding memory errors with Valgrind

You can run Valgrind like so:

valgrind --soname-synonyms=somalloc=NONE --smc-check=all-non-file --num-callers=50 --log-file=valgrind.out --suppressions=../../notes/valgrind.suppression ./servo ../src/test/html/about-mozilla.html

The --soname-synonyms flag fixes an incompatibility with jemalloc and requires a fairly recent version of Valgrind. See this article.

The --smc-check flag is necessary to instrument the code dynamically produced by SpiderMonkey. Otherwise SpiderMonkey can crash or hit assertion failures. See #980.

The suppressions file is here; it just excludes things from i965_dri.so, and not very well.

Even with the suppressions file I get some irrelevant errors from graphics drivers etc, so I also postprocess the output of Valgrind with this script:

#!/usr/bin/env python
import sys
import re

blocks = [[]]

for ln in sys.stdin:
    ln = ln.rstrip()
    m = re.match(r'^==\d+==', ln)
    assert m
    ln = ln[m.end():]
    if not ln:
        blocks.append([])
    blocks[-1].append(ln)

exclude = ['libdrm.so.2.4.0', 'i965_dri.so', '_dl_start']

for b in blocks:
    if not any(any(e in ln for e in exclude) for ln in b):
        for ln in b:
            print ln
Clone this wiki locally