How to Debug WebAssembly Pipelines in Your Web Browser
By: Matt McCormick , Mary Elise Dedicke , Jean-Christophe Fillion-Robin , Will Schroeder
Did you know that your web browser comes bundled with extremely powerful development tools?
Modern web browsers are the foundation of the The Web Platform, a full-featured computing environment. However, full-featured platforms are not useful in and of themselves. A large community of software developers is required to program the applications on a platform that people love. And, effective debugging results in effective programming.
In this tutorial, we will learn how to debug itk-wasm C++ data processing pipelines built to WebAssembly (wasm) with the full-featured graphical debugger built into Chromium-based browsers.
In the following sections, we will first explain how to obtain a useful JavaScript backtrace in Node.js, then debug C++ code built to WebAssembly in a Chromium-based web browser. Let’s get started! 🚀
0. Preliminaries
Before starting this tutorial, check out our WASI WebAssembly command line debugging tutorial.
As with the previous tutorial, we will be debugging the following C++ code:
#include <iostream>
int main() {
std::cout << "Hello debugger world!" << std::endl;
const char * wasmDetails = "are no longer hidden";
const int a = 1;
const int b = 2;
const auto c = a + b;
// Simulate a crash.
abort();
return 0;
}
The tutorial code provides npm scripts as a convenient way to execute debugging commands, which you may also invoke directly in a command line shell.
1. Node.js Backtrace
When debugging WebAssembly built with the itk-wasm Emscripten toolchain, set the CMAKE_BUILD_TYPE
to Debug
just like with native binary debug builds.
As with native builds, this build configuration adds debugging symbols, the human-readable names of functions, variables, etc., into the binary. This also adds support for C++ exceptions and retrieving the string name associated with exceptions. Without this itk-wasm instrumentation, a C++ exception will throw an error with an opaque integer value. And, Emscripten JavaScript WebAssembly bindings will not be minified, which facilitates debugging.
When built with the default Release
build type:
the JavaScript support code is minified, and difficult to debug:
However, when built with the Debug
build type:
you can obtain a useful backtrace:
This is helpful for debugging issues that occur in the Emscripten JavaScript interface. The next section describes how to debug issues inside the Emscripten-generated WebAssembly.
2. Debugging in Chromium-based Browsers
Recent Chromium-based browsers have support for debugging C++ -based WebAssembly in the browser. With a few extra steps described in this section, it is possible to interactively step through and inspect WebAssembly that is compiled with C++ running in the browser.
WebAssembly debugging in DevTools requires a few extra setup steps compared to a default browser installation.
First, install the Chrome WebAssembly Debugging extension.
Next, enable it in DevTools:
- In DevTools, click the gear (âš™) icon in the top-right corner.
- Go to the Experiments panel.
- Select WebAssembly Debugging: Enable DWARF support.
Exit Settings, then reload DevTools as prompted.
Next, open the options for the Chrome WebAssembly Debugging extension:
Since itk-wasm builds in a clean Docker environment, the debugging source paths in the Docker environment are different from the paths on the host system. The debugging extension has a path substitution system that can account for these differences. In the Docker image, the directory where itk-wasm
is invoked is mounted as /work
. Substitute /work
with the directory where the itk-wasm
CLI is invoked. For example, if itk-wasm
was invoked at /home/matt/src/itk-wasm/examples/Debugging
, then set the path substitution as shown below:
Build the project with itk-wasm and the Debug
CMAKE_BUILD_TYPE
to include DWARF debugging information:
Here we load and run the WebAssembly with a simple HTML file and server:
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/itk-wasm@1.0.0-a.11/dist/umd/itk-wasm.js"></script>
</head>
<body>
<p>This is an example to demonstrate browser-based debugging of
C++-generated WebAssembly. For more information, please see the
<a target="_blank" href="https://wasm.itk.org/examples/debugging.html">associated
documentation</a>.</p>
<script>
window.addEventListener('load', (event) => {
const pipeline = new URL('emscripten-build-debug/DebugMe', document.location)
itk.runPipeline(null, pipeline)
});
</script>
</body>
</html>
And we can debug the C++ code in Chrome’s DevTools debugger alongside the executing JavaScript!
What’s Next
In our next post, we will provide a tutorial on how to generate JavaScript and TypeScript bindings for Node.js and the browser.
Enjoy ITK!