DEV Community

Cover image for How to Debug WebAssembly Pipelines in Your Web Browser
Matt McCormick
Matt McCormick

Posted on • Originally published at kitware.com

1

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;
}
Enter fullscreen mode Exit fullscreen mode

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:

Emscripten build Release

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

Run Node Release

However, when built with the Debug build type:

Emscripten build Debug

you can obtain a useful backtrace:

Run Node Debug

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:

  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

Exit Settings, then reload DevTools as prompted.

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

Wasm Debugging Options

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

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

Emscripten build Debug

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>
Enter fullscreen mode Exit fullscreen mode

HTTP Server

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

Debug C++ DevTools

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!

Speedy emails, satisfied customers

Postmark Image

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up

Top comments (0)

The best way to debug slow web pages cover image

The best way to debug slow web pages

Tools like Page Speed Insights and Google Lighthouse are great for providing advice for front end performance issues. But what these tools can’t do, is evaluate performance across your entire stack of distributed services and applications.

Watch video

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay