Skip to content
instrumenting wasm binaries to trace function execution
Rust Makefile
Branch: master
Clone or download
Sarah Lim
Latest commit 796219b May 22, 2019
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
examples Update to reflect dependencies May 22, 2019
src Parse names section Jun 7, 2018
tests Split JS into modules Jun 7, 2018
.gitignore Separate Node examples from tests May 31, 2018
Cargo.toml Use Tracer interface in examples Jun 4, 2018
README.md Update to reflect dependencies May 22, 2019

README.md

wasm-trace

a tool that would take a wasm module and modify its code to inject tracing calls, so that you could get an trace of the wasm's execution in the console

Based on an idea by Nick Fitzgerald from Mozilla.

Usage

Given the following Rust program:

#[macro_use]
extern crate wasm_trace;

use wasm_trace::tracer::Tracer;

tracer_dependencies!();
tracer_bootstrap!();

#[no_mangle]
pub extern "C" fn do_stuff(x: i32) -> i32 {
    println!("{}", double(x) + double(x));
    println!("{}", factorial(x as u32));
    let result = double(x) + negate(5) + 1;
    void();
    return result;
}

#[no_mangle]
pub fn double(x: i32) -> i32 {
    return x * 2;
}

#[no_mangle]
pub fn negate(x: i32) -> i32 {
    return -1 * x;
}

#[no_mangle]
pub fn void() {
    println!("No return value here!");
}

#[no_mangle]
pub fn factorial(n: u32) -> u32 {
    if n == 1 || n == 0 {
        1
    } else {
        n * factorial(n - 1)
    }
}

We can compile this program to a .wasm binary and pass that binary to our program:

> cargo build --example function-calls --target=wasm32-unknown-unknown
> cp target/wasm32-unknown-unknown/debug/examples/function-calls.wasm .
> cargo run function-calls.wasm  # `cargo run` our `wasm-trace` binary

This will output an instrumented binary called output.wasm. We can evaluate this module in Node.js and invoke do_stuff(4):

> node examples/js/runWasm.js function-calls.wasm do_stuff 4
Invoking exported function do_stuff with arguments [ 4 ] ...
Result of function call: 4
 call function do_stuff
  |  call function double
  |  return 8 from double
  |  call function double
  |  return 8 from double
  |  call function factorial
  |   |  call function factorial
  |   |   |  call function factorial
  |   |   |   |  call function factorial
  |   |   |   |  return 1 from factorial
  |   |   |  return 2 from factorial
  |   |  return 6 from factorial
  |  return 24 from factorial
  |  call function double
  |  return 8 from double
  |  call function negate
  |  return -5 from negate
  |  call function void
  |  return from void
 return 4 from do_stuff

You can preview the changes to the disassembly.

Requirements

Install the WebAssembly toolchain:

rustup update
rustup target add wasm32-unknown-unknown --toolchain nightly

In addition, the following binaries must be installed to run the tests in tests/:

  • wasm-gc, which removes unneeded exports, imports, and functions.
  • Binaryen, a compiler toolchain for WebAssembly. In particular, we're using the wasm-dis tool to disassemble a .wasm binary into the readable .wat S-expression format.
  • Node.js with WebAssembly support.

Team

Meg Grasse and Sarah Lim, with support from Jim Blandy and Nick Fitzgerald.

You can’t perform that action at this time.