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