A zero-dependency WebAssembly VM with a full-featured Web UI debugger implemented in Rust.
一个用 Rust 实现的零依赖 WebAssembly 虚拟机,带有全功能的 Web UI 调试界面。
Features
- Run multi-module WASM applications.
- Disassemble WASM applications.
- Web UI debugging interface, support step-by-step tracing, set breakpoints, and view memory and call stack data.
- Supports WASI interface, can run applications compiled from C/C++ and Rust.
- Support for loading application images, providing Docker-like container features.
- Support for state persistence, 0-time cold startup, providing Serverless and Function-as-a-Service (FaaS) services.
- 运行多模块 WASM 应用程序;
- 反汇编 WASM 应用程序;
- Web UI 调试界面,支持逐步跟踪、设置断点,能直观地查看内存、调用栈的数据;
- 支持 WASI 接口,能运行 C/C++ 和 Rust 编译的程序;
- 支持加载应用程序映像,实现类似 Docker 的容器功能;
- 支持状态持久化,支持 0 时间冷启动,实现 Serverless 和 Function-as-a-Service (FaaS) 功能;
你可以通过下载预编译的可执行文件来获取 XiaoXuan VM 程序,也可以从源代码开始编译而获得。
访问 XiaoXuan VM 项目的 源代码仓库,进入 "Release 页面",选择最新的版本,然后根据你的 CPU 架构和操作系统选择相应的可执行文件压缩包下载。(如果找不到合适的预编译可执行文件,则需要从源代码编译)
下载完毕之后解压压缩包,并复制里面的程序到目录 ~/.local/bin
或者任意一个位于环境变量 $PATH
列表当中的目录即可。
访问 XiaoXuan VM 项目的 源代码仓库,下载源代码的压缩包然后解压到任意目录。
或者使用 Git 克隆项目的源代码:
$ git clone https://github.com/hemashushu/xiaoxuan-vm.git
切换到 XiaoXuan VM 项目的源代码的首层目录,然后运行下面命令:
$ cargo test
如果所有单元测试均通过,则可以进行下一步。
运行下面命令以编译 XiaoXuan VM 程序:
$ cargo build
编译完成之后将会在目录 ./target/debug/
里面得到 anvm
和 anvm-debugger
两个程序。
注意默认编译得到的是调试版的程序,调试版的程序运行速度可能非常慢,如果不需要调试程序,建议编译为发行版:
$ cargo build --release
编译完成之后将会在目录 ./target/release/
里面得到 anvm
和 anvm-debugger
两个程序。
为了方便运行程序,建议将上面步骤得到的两个程序复制到目录 ~/.local/bin
或者任意一个位于环境变量 $PATH
列表当中的目录。也可以使用下面命令将程序复制到目录 ~/.cargo/bin
:
$ cargo install --path ./crates/launcher
$ cargo install --path ./crates/debugger
XiaoXuan VM 可以运行由 C/C++/Rust 编译而得的 WebAssembly 应用程序(以下简称 "WASM 应用程序"),你也可以通过文本格式 *.wat
手动书写 WebAssembly 应用程序,然后使用 XiaoXuan VM 的编译程序(尚未完成)或者 wasm-tools 将 *.wat
编译为 *.wasm
。
注意区分
XiaoXuan VM 程序
和WASM 应用程序
,前者是一个虚拟机,同时也是一个引擎,也就是本项目的程序,是一个可执行的程序,用于加载和运行后者。后者是一个或多个*.wasm
模块文件,通常由 C/C++/Rust 或者其他语言编译而得,无法直接运行。
XiaoXuan VM 支持 WASI 接口,即支持基本的文件 I/O、Socket I/O 等操作(尚未完成)。
XiaoXuan VM 项目自带几个测试用的 WASM 应用程序,位于
./crate/launcher/resources
目录之中,可用于下面的示例。
假设有一个 WASM 应用程序的模块文件名为 fib.wasm
,则可以用如下命令运行这个应用程序:
$ anvm fib.wasm
如果模块文件不在当前目录,则需要指明模块文件的完整路径或者相对路径,比如:
$ anvm ~/projects/xiaoxuan-vm/crates/launcher/resources/fib.wasm
WebAssembly 模块当中有一个 start
段,该段所指向的函数将会作为 WASM 应用程序的入口(即起始函数),如果模块不存在 start
段,则 XiaoXuan VM 会尝试寻找模块当中名称为 _start
的导出函数,如果找到则它将会作为程序的入口;如果找不到,则 XiaoXuan VM 会因为找不到入口而无法运行 WASM 应用程序。
你可以手动指定 WASM 应用程序的起始函数,假设有 WASM 应用程序 lib.wasm
,其中有一个名称为 pow
的导出函数,如果想执行它,则可以运行如下命令:
$ anvm lib.wasm --function lib::pow 2 10
命令参数
--function
可以使用-f
来代替。
上面的 lib::pow
为起始函数的完整名称,其中 lib
为模块的名称(即 *.wasm
的文件名当中排除了扩展名的部分),pow
则为该模块所导出的函数的名称,2 10
为函数的参数,多个参数之间使用空格分隔。
注意 "函数的参数" 跟我们平常通过命令行传递给应用程序的 "命令行参数" 不是同一个概念,"函数的参数" 仅用于手动指定起始函数这种场合,这相当于一种 hack 手段,将数据强行传递给应用程序里的某个片段(即函数)。
WebAssembly 1.0 只支持 4 种基本的数字的数据类型,分别是 i32
、i64
、f32
和 f64
。在我们输入的命令行中的 "函数参数值" 如果其中存在小数点,则视为 f32
,如果没有小数点,则视为 i32
。当然可以通过在数字后面加上后缀 i
、l
、f
和 d
显式指定数据类型,示例:
数据类型 | 示例 |
---|---|
i32 |
123 、123i |
i64 |
3l 、345l |
f32 |
3.142 、3.142f |
f64 |
2d 、2.718d |
XiaoXuan VM 也能执行一个未导出的函数,只需指定函数的索引即可,假设 lib.wasm
模块里有一个函数 pow
,其索引值为 0
,则命令为:
$ anvm lib.wasm --function lib::0 2 10
有时一个 WASM 应用程序由多个模块组成,如果要运行这种应用程序,则需要将所有模块(的文件路径及名称)传入 XiaoXuan VM ,例如:
$ anvm lib.wasm app.wasm
XiaoXuan VM 将会从右侧的模块开始搜索应用程序的入口函数。当然你仍然可以手动指定起始函数,比如:
$ anvm lib.wasm app.wasm -f lib::pow 2 20
XiaoXuam VM 也提供了反汇编的功能,用于将 WASM 应用程序的二进制的格式 *.wasm
反汇编为文本格式 *.wat
,命令如下:
$ anvm --disassembly input.wasm output.wat
但每次只能反汇编一个模块,其中的命令参数 --disassembly
可以使用 -d
来代替,比如:
$ anvm -d input.wasm output.wat
一般的 WASM 应用程序是由 C/C++/Rust 或者其他语言编译而得,当然你也可以手动书写文本格式的 WebAssembly 应用程序,然后编译成二进制格式。
WASM 的文本格式在外观上很像 Lisp 程序,比如下面是一个计算 斐波那契数
(fib
)的函数的源代码:
(module
;; 计算 `斐波那契数`(`fib`)的函数
;;
;; 0、 1、 1、 2、 3、 5、 8、 13、 21、 34、 55、 89、 144、 233、 377、 610
;; ^ ^ ^
;; | \-- 第 1 项 \-- 第 10 项
;; \------ 第 0 项
(func $fib (param $n i32) (result i32)
(if (result i32)
(i32.le_s (local.get $n) (i32.const 1))
(then
(local.get $n)
)
(else
(i32.add
(i32.sub (local.get $n) (i32.const 1))
(call $fib)
(i32.sub (local.get $n) (i32.const 2))
(call $fib)
)
)
)
)
(export "fib" (func $fib))
)
把上面的代码保存到一个文件(比如 my.wat
),然后使用 XiaoXuan VM 的编译功能把它编译为二进制格式(尚未完成):
$ anvm -a my.wat my.wasm
或者使用 wasm-tools 来编译:
$ wasm-tools parse my.wat -o my.wasm
编译完成之后将会得到 WASM 应用程序模块文件 my.wasm
,然后就可以使用 XiaoXuan VM 运行它了:
$ anvm my.wasm -f my::fib 10
todo::
todo::
todo::