How to Debug WebAssembly Pipelines in Your Web Browser
Tags: webdev, webassembly, tutorial
Published: 2023-03-08 21:45:52

###### 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](https://en.wikipedia.org/wiki/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](https://www.kitware.com/how-to-debug-wasi-pipelines-with-itk-wasm/).

In this tutorial, we will learn how to debug [itk-wasm](https://wasm.itk.org) C++ data processing pipelines built to [WebAssembly (wasm)](https://webassembly.org) 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](https://www.kitware.com/how-to-debug-wasi-pipelines-with-itk-wasm/).

As with the previous tutorial, we will be debugging the following C++ code:

```cpp
#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](https://github.com/InsightSoftwareConsortium/itk-wasm/tree/main/examples/debugging) 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:

![Emscripten build Release](https://i.imgur.com/8DKAnqQ.png)

the JavaScript support code is minified, and difficult to debug:

![Run Node Release](https://i.imgur.com/QwMl2SK.png)

However, when built with the `Debug` build type:

![Emscripten build Debug](https://i.imgur.com/63tC2wC.png)

you can obtain a useful backtrace:

![Run Node Debug](https://i.imgur.com/8tUmqRd.png)

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](https://goo.gle/wasm-debugging-extension).

Next, enable it in DevTools:

1.   In DevTools, click the *gear (⚙)* icon in the top-right corner.
2.   Go to the *Experiments* panel.
3.   Select *WebAssembly Debugging: Enable DWARF support*.

![Enable Wasm Debugging](https://i.imgur.com/L5zyBlJ.png)

Exit Settings, then reload DevTools as prompted.

Next, open the options for the Chrome WebAssembly Debugging extension:

![Wasm Debugging Options](https://i.imgur.com/Gbe53Fz.png)

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:

![Path substitution](https://i.imgur.com/YuUp7rP.png)

Build the project with itk-wasm and the `Debug` `CMAKE_BUILD_TYPE` to include DWARF debugging information:

![Emscripten build Debug](https://i.imgur.com/d36DmGJ.png)

Here we load and run the WebAssembly with a simple HTML file and server:

```html
<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>
```

![HTTP Server](https://i.imgur.com/bZsm9lG.png)

And we can debug the C++ code in Chrome's DevTools debugger alongside the executing JavaScript!

![Debug C++ DevTools](https://i.imgur.com/iO8QhDz.png)

## 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!**