Debugging complex applications can be a daunting task, especially when dealing with web browsers like WebKit. Armed with the right environment and tools, you can navigate through the labyrinth of code to identify and fix issues.
However, something curious happens to me. I’ve gone through these same steps many times before and I always face the same situation when I need to debug some issue: How was it? What was it that I needed to setup the debug environment? What was the order? The name of that variable? … Always the same, always the same promise when I finally find the answers (“I will write it down somewhere for the next time”) and never fulfilled … until today.
In this post, we’ll walk you through a real-world example of live debugging WebKit using GDB (GNU Debugger).
Introduction to the Setup
In this scenario, we’ll delve into a command-line snippet that initiates a debugging session for WebKit using GDB. The code snippet looks like this:
WEB_PROCESS_CMD_PREFIX='/usr/bin/gdbserver --no-startup-with-shell localhost:9090' \
WAYLAND_DISPLAY=wayland-1 \
XDG_RUNTIME_DIR=/run/user/1000 \
WEBKIT_INJECTED_BUNDLE_PATH=/home/psaavedra/local/git/webkit-gtk/WebKit/WebKitBuild/Debug/lib \
WEBKIT_EXEC_PATH=/home/psaavedra/local/git/webkit-gtk/WebKit/WebKitBuild/Debug/bin \
LD_LIBRARY_PATH=/home/psaavedra/local/git/webkit-gtk/WebKit/WebKitBuild/Debug/lib \
COG_MODULEDIR=./WebKitBuild/Debug/Tools/cog-prefix/src/cog-build/platform \
gdb --args ./WebKitBuild/Debug/Tools/cog-prefix/src/cog-build/launcher/cog -P wl https://www.igalia.com
Launching the Debugger
- Setting Up GDB Environment: The first part of the snippet configures the environment for GDB. It sets several environment variables that guide GDB’s behavior during debugging. For instance, it tells GDB to start a gdbserver on localhost:9090, defines the display server (Wayland), and specifies various paths for required libraries and executable files.
- Starting GDB: Next, the snippet runs the GDB command itself. It launches GDB in the terminal. The
-args
flag indicates that the subsequent command and arguments should be executed within the GDB session.
Getting Started with GDB Commands
Once the GDB session starts, you’re presented with a GDB command prompt. Now, let’s walk through the commands used in the debugging session:
- Setting Up GDB Environment in GDB: While inside GDB, you can fine-tune the environment further. For example, you can set the system root directory and library search paths using the
set sysroot
andset solib-search-path
commands.
$ gdb
set sysroot /
set solib-search-path /lib/:/usr/lib:/usr/lib32:/usr/lib64:/home/psaavedra/local/git/webkit-gtk/WebKit/WebKitBuild/Debug/lib
- Specifying Source Code Directory: The
directory
command is used to inform GDB about the location of source code files. This helps GDB locate and display source code lines during debugging.
directory /home/psaavedra/local/git/webkit-gtk/WebKit/Source
- Loading Shared Libraries: .
info sharedlibrary
add-symbol-file /home/psaavedra/local/git/webkit-gtk/WebKit/WebKitBuild/Debug/lib/libWPEWebKit-2.0.so.0
add-symbol-file /home/psaavedra/local/git/webkit-gtk/WebKit/WebKitBuild/Debug/bin/WPEWebProcess
add-symbol-file /home/psaavedra/install/lib/x86_64-linux-gnu/libWPEBackend-fdo-1.0.so
The info sharedlibrary
command lists loaded shared libraries. In this case, additional libraries are loaded using the add-symbol-file
command. These libraries’ paths are explicitly provided to help GDB locate symbols for debugging
- Connecting to GDB Server:
target remote localhost:9090
The target remote
command connects GDB to the gdbserver started earlier. This establishes a remote debugging session, allowing you to debug code running on another machine.
Setting Breakpoints and Running the Debugger
- Setting Breakpoints: Debugging is most effective when you can pause execution at specific points. The
b
command is used to set breakpoints. You can specify functions or exact source code locations where you want execution to halt:
b LayerTreeHost::willRenderFrame
b /home/psaavedra/local/git/webkit-(gdb) gtk/WebKit/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp:407
b /home/psaavedra/local/git/webkit-gtk/WebKit/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp:412
b /home/psaavedra/local/git/webkit-gtk/WebKit/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp:380
b /home/psaavedra/local/git/webkit-gtk/WebKit/Source/WebKit/WebProcess/WebPage/libwpe/AcceleratedSurfaceLibWPE.cpp:105
b /home/psaavedra/local/git/webkit-gtk/WebKit/Source/WebKit/Shared/CoordinatedGraphics/threadedcompositor/ThreadedDisplayRefreshMonitor.cpp:89
Alternatively, you can set breakpoints based on symbol names:
b wl_buffer_send_release
b wpe_view_backend_exportable_fdo_egl_dispatch_release_exported_image
info breakpoints
The info breakpoints
command provides a list of all set breakpoints. This gives you an overview of the breakpoints you’ve configured.
- Running the Debugger: Once breakpoints are in place, use the
run
command to start execution. The application will run until a breakpoint is hit, at which point it will pause, allowing you to inspect the program state and variables.
(gdb) run
Long story short
Debugging WebKit is not far away in complex than any other application but demands setting up the right environment variables, loading necessary libraries, and configuring breakpoints to halt execution at crucial points. GDB still enables you to dive deep into the application’s codebase and identify issues.
Armed with these insights, you can run your first step for fixing bugs, enhance performance, and contribute to the improvement of large-scale software project as WebKit it is. So, the next time you ( me) encounter a perplexing issue, remember this guide to effectively navigate the debugging process. Happy debugging!