最近在研究 WebAssembly,也写了几篇全面介绍的文章:
本文是学习 WebAssembly 系列的第三篇文章,也是想探究一下 Chrome 开发者工具对 WebAssembly 的调试支持度如何,通过这个探究的过程,我们会了解到 Chrome 调试工具各种方面的使用方法以及作用,发掘你可能不知道的一些知识点。
所以本文既可以当做学习使用 Chrome Devtools 调试工具的一篇比较全面的文章,也可以当做是介绍现阶段我们如何在浏览器中对 WebAssembly 相关的代码进行调试,帮助你成为一个合格的调试工程师 :)。
WebAssembly 的原始调试方式
Chrome 开发者工具目前已经支持 WebAssembly 的调试,虽然存在一些限制,但是针对 WebAssembly 的文本格式的文件能进行单个指令的分析以及查看原始的堆栈追踪,具体见如下图:
上述的方法对于一些无其他依赖函数的 WebAssembly 模块来说可以很好的运行,因为这些模块只涉及到很小的调试范围。但是对于复杂的应用来说,如 C/C++ 编写的复杂应用,一个模块依赖其他很多模块,且源代码与编译后的 WebAssembly 的文本格式的映射有较大的区别时,上述的调试方式就不太直观了,只能靠猜的方式才能理解其中的代码运行方式,且大多数人很难以看懂复杂的汇编代码。
更加直观的调试方式
现代的 JavaScript 项目在开发时通常也会存在编译的过程,使用 ES6 进行开发,编译到 ES5 及以下的版本进行运行,这个时候如果需要调试代码,就涉及到 Source Map 的概念,source map 用于映射编译后的对应代码在源代码中的位置,source map 使得客户端的代码更具可读性、更方便调试,但是又不会对性能造成很大的影响。
而 C/C++ 到 WebAssembly 代码的编译器 Emscripten 则支持在编译时,为代码注入相关的调试信息,生成对应的 source map,然后安装 Chrome 团队编写的 C/C++ Devtools Support 浏览器扩展,就可以使用 Chrome 开发者工具调试 C/C++ 代码了。
这里的原理其实就是,Emscripten 在编译时,会生成一种 DWARF 格式的调试文件,这是一种被大多数编译器使用的通用调试文件格式,而 C/C++ Devtools Support 则会解析 DWARF 文件,为 Chrome Devtools 在调试时提供 source map 相关的信息,使得开发者可以在 89+ 版本以上的 Chrome Devtools 上调试 C/C++ 代码。
调试简单的 C 应用
因为 DWARF 格式的调试文件可以提供处理变量名、格式化类型打印消化、在源代码中执行表达式等等,现在就让我们实际来编写一个简单的 C 程序,然后编译到 WebAssembly 并在浏览器中运行,查看实际的调试效果吧。
首先让我们进入到之前创建的 WebAssembly 目录下,激活 emcc 相关的命令,然后查看激活效果:
cd emsdk && source emsdk_env.sh
emcc --version # emcc (Emscripten gcc/clang-like replacement) 1.39.18 (a3beeb0d6c9825bd1757d03677e817d819949a77)
接着在 WebAssembly 创建一个 temp
文件夹,然后创建 temp.c
文件,填充如下内容并保存:
#include <stdlib.h>
void assert_less(int x, int y) {
if (x >= y) {
abort();
}
}
int main() {
assert_less(10, 20);
assert_less(30, 20);
}
上述代码在执行 asset_less
时,如果遇到 x >= y
的情况会抛出异常,终止程序执行。
在终端切换目录到 temp
目录下执行 emcc
命令进行编译:
emcc -g temp.c -o temp.html
上述命令在普通的编译形式上,加入了 -g
参数,告诉 Emscripten 在编译时为代码注入 DWARF 调试信息。
现在可以开启一个 HTTP 服务器,可以使用 npx serve .
,然后访问 localhost:5000/temp.html
查看运行效果。
需要确保已经安装了 Chrome 扩展:https://chrome.google.com/webstore/detail/cc+±devtools-support-dwa/pdcpmagijalfljmkmjngeonclgbbannb,以及 Chrome Devtools 升级到 89+ 版本。
为了查看调试效果,需要设置一些内容。
- 打开 Chrome Devtools 里面的 WebAssembly 调试选项
设置完之后,在工具栏顶部会出现一个 Reload 的蓝色按钮,需要重新加载配置,点击一下