An easy way to debug WebKit’s WebProcess with GDB

WebKit is an engine that uses multiple processes and multiple threads at runtime. There are some very useful generic instructions on how to debug one of its processes on Linux (with focus on the GTK port) in this wiki page. They work pretty well when WebKit is built using the Flatpak SDK and the scripts and gdbserver is installed in the system, but I faced some problems when I wanted to built WebKit with CMake having custom build and installation directories. So in this post, I’m going to describe the easiest way I’ve found so far to debug it when SDK is not being used and a gdbserver is not present in the system. I’ve found this simple solution after having tried a combination of tricks from the WebKit wiki instructions, GDB documentation and a discussion with my colleages at Igalia.

Building WebKit with CMake

As I’ve mentioned in my previous post on building WebKit, the easiest method to build WebKit is using the Flatpak SDK. But when I build it for development, I prefer to keep it simple and just use CMake and the same installation dir where I manually install all the dependencies I want to debug as well (for example WPE and WPEBackendFDO). And so, I follow the steps I’ve described in my previous post on building WPE, and when I build the GTK port I simply set the PORT (-DPORT CMake option) to be GTK instead of WPE.

Configuring GDB

Supposing you debug WebKit with MiniBrowser, there are different ways to use GDB. You can either start the program with GDB attached ( gdb --args ./build/bin/MiniBrowser bar.html) or start MiniBrowser and then attach the WebProcess to GDB. Not all my settings are required for both cases but having them set while debugging a single process doesn’t harm.

Settings:

I opened my global $HOME/.gdbinit and included the WebKit .gdbinit path as a safe path:
add-auto-load-safe-path /home/eleni/igalia/code/WebKit/.gdbinit

Then, I added the following lines in the WebKit/.gdbinit:

What they are for:

set follow-fork-mode child:
The new process is debugged after a fork. The parent process runs unimpeded.

set detach-on-fork off:
In this mode GDB will be attached to both parent and child processes after a call to fork() or vfork(). One can use the info inferiors command to show details and the inferior command to switch between them.

Running WebKit with GDB and setting a breakpoint in WebGL code.

I opened a terminal (where I’ve set all the required environment variables to build and run WebKit, see my previous post on building WebKit) and ran Minibrowser from the build directory, for me this directory is WebKit/build/ (if you use the flatpak SDK it will be the standard build directory WebKitBuild and you can modify the paths accordingly):

where bar.html was a customized WebGL test I wanted to debug (most standard WebGL tests can be found under LayoutTests/fast/canvas/webgl or LayoutTests/webgl/)

I switched to a different terminal where the environment was identical to the first terminal’s environment (important!):

As I wanted to debug WebGL, I’ve first found the process that contains the WebGL calls. If you check the pstree output, you will notice that WebKit forks 2 processes: the WebKitWebProces and the WebKitNetworkPr that are the Web and the Network processes respectively.

WebGL is part of the WebProcess (you can tell that from the code). So, in order to debug graphics code I had to attach the WebProcess to GDB.

This is how to do it:

1. Enter the directory where you would run MiniBrowser! This is important otherwise some symbols might not be found!!! I run MiniBrowser from my checkout root directory, so the command was:

2. Find the pid of the WebProcess:

a pid will be returned for example 29086

3. Attach GDB to this process:

Note that you must run gdb and use the path to MiniBrowser that is running, the same way you’d set it to start MiniBrowser inside GDB and simply add the pid at the end. No other parameters should be needed as MiniBrowser is supposed to run at this moment.

4. Set a breakpoint the “usual” way, eg:

5. Press continue (c in GDB) and reload the webpage in MiniBrowser. You will see that the program stopped when it reached the breakpoint:

Note that symbols are loaded from my custom installation directory ~/igalia/install where I install every WebKit dependency I need to debug myself as well as WebKit itself! This is why it is important to be in the correct directory when you attach the WebProcess to GDB! You might not have to worry about this when you’ve built WebKit using the flatpak SDK and simply follow the instructions from the wiki page I’ve mentioned before, but if you do everything manually, this is important! Simply running gdb -p on a new terminal without the path to MiniBrowser and the same environment setup might attach the process, but GDB won’t be able to detect all the available debugging symbols!!

What about WEB_PROCESS_CMD_PREFIX?

If you build WebKit the recommended way (using the flatpak SDK) you might also want to try setting the prefix WEB_PROCESS_CMD_PREFIX from instructions. Building WebKit inside “non-standard” build directories with CMake and the option -DDEVELOPER_MODE=ON is tricky as some python scripts involved in the process might crash or complain. In case you build with CMake and don’t use the “standard” paths you might prefer to follow the steps above (and you won’t need to setup gdbserver!).

Another thing I tried and worked for me was to attach the parent process to gdb ( gdb --args ./build/bin/MiniBrowser bar.html) and switch processes using inferior <num_process>. But there were other issues when switching between processes and threads: a process or a thread could crash from a bug while I was debugging another, and then I wasn’t always able to switch to it. Also, always following the child process would by default follow the network process and I’d have to switch to the web later. So, I gave up and chose the simple method I described above.

And at least for debugging WebGL tests, attaching the WebProcess to gdb without using the gdbserver or having to set the prefix works well (so far! :D).

Links

[1]: WebKitGTK Debugging https://trac.webkit.org/wiki/WebKitGTK/Debugging
[2]: Environment Variables that can be used for debugging: https://trac.webkit.org/wiki/EnvironmentVariables (not used in this post, but handy in general!)
[3]: How to build WebKit with CMake (change the port to GTK instead of WPE for GTK builds): Build WebKit/WPE on Linux/X11


See you next time!

1 thought on “An easy way to debug WebKit’s WebProcess with GDB”

  1. Thank you for this tutorial, i was missing this somewhat basic gdb skill.
    However i learnt the great power of https://sourceware.org/elfutils/Debuginfod.html
    bash
    export DEBUGINFOD_URLS="https://debuginfod.debian.net"

    and then just use gdb as usual, it will download symbols automatically (and cache them). Checkout the upstream doc to know what url works with your favorite distribution.

Leave a Reply

Your email address will not be published. Required fields are marked *