WebAssembly 运行时错误调试

345 阅读3分钟

1. 摘要

WebAssembly(WASM)是一种高效的低级字节码格式,可以在现代浏览器中运行近乎原生速度的代码。然而,由于其编译产物是二进制字节码,调试 WebAssembly 模块常常变得复杂和困难。C++ 与 Emscripten 是常见的组合,用于将 C++ 代码编译为 WebAssembly 模块。

本文将介绍如何使用 Emscripten 编译 C++ 代码生成 WebAssembly 模块,并生成和利用 DWARF 调试信息,在浏览器中实现高效的调试过程。

2. 准备工作

安装 C/C++ DevTools Support (DWARF) 插件(chromewebstore.google.com/detail/cc++…

DWARF 是什么?

它的全称是 "Debugging With Attributed Record Formats"。DWARF 格式允许编译器在生成的二进制文件中嵌入或分离详细的调试信息,这些信息可以被调试器读取和使用,以便开发者在调试代码时能够查看源代码、变量值、调用栈等。

插件安装成功并开启后会有这个图标:

3.编译携带调试信息的产物

3.1 编译过程

以下是一段会抛出异常的代码 temp.cc:

#include <stdlib.h>

void assert_less(int x, int y) {
  if (x >= y) {
    abort();
  }
}

int main() {
  assert_less(10, 20);
  assert_less(30, 20);
  return 0;
}

使用 emscripten 编译携带调试信息的产物:

emcc -g temp.cc -o temp.js

编译产物:

加载编译产物:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script>
    Module = {};
    Module.onRuntimeInitialized = function () {
      console.log('onRuntimeInitialized');
    }
  </script>
  <script src="./temp.js"></script>
</head>
<body>
</body>
</html>

3.2 调试演示

关闭插件时的错误信息:

启用插件时的错误信息:

3.3 反查出错误的 C++ 代码

应用上线后我们的拿到的错误信息是这样的 temp.wasm.0x260:

可以在加载了插件的环境下,在 temp.wasm.0x260 这个位置打断点,这时候断点会自动映射到 C++ 代码:

4. 优化编译,分离调试信息

3 章节所示,我们成功的实现了错误调试,但是使用 -g 编译携带调试信息的产物会导致包体变大很多,执行效率可能也会下降很多,下面介绍如何优化编译并把调试信息分离出去。

4.1 编译过程

编译命令:

-fno-inline禁用内敛
-O3编译时优化
-gseparate-dwarf把调试信息拆分为单独的 WebAssembly 文件
-s SEPARATE_DWARF_URL指定一下调试信息的地址 C/C++ DevTools Support (DWARF) 插件会自动去相应地址拉取
emcc -g temp.cc -o temp.js \
     -O3 -fno-inline \
     -gseparate-dwarf=temp.debug.wasm \
     -s SEPARATE_DWARF_URL=http://127.0.0.1:5500/temp.debug.wasm

编译产物:

4.2 使用单独拆出去的 WebAssembly 调试文件

如编译命令所示,让 http://127.0.0.1:5500/temp.debug.wasm 这个连接对应到 temp.debug.wasm 这个文件,之后就和 3 章节是一样的了。

5. 总结

通过这些步骤,我们不仅可以在浏览器中高效地调试 WebAssembly 模块,还能在保持调试能力的同时,优化编译产物的大小和性能。这为开发者提供了一种有效的方法来处理 WebAssembly 调试的复杂性,使其更易于维护和优化,不过也要考虑一下增加 DWARF 的风险点,测试性能是否有损耗。

  1. 参考

developer.chrome.com/blog/wasm-d…