Introduction to Wasabi
Wasabi is a dynamic analysis framework for WebAssembly. What does this mean and why is it useful?
Dynamic analysis means observing some properties of a program while it is running.
Dynamic analysis is routinely used to find and fix bugs, identify performance bottlenecks, or to search for security problems.
Since dynamic analysis has access to runtime information (e.g., program inputs and its current state), it can often be more precise than static analysis, that looks at the program without executing it. Obviously, static analysis has benefits as well. In practice, they often complement each other and you need at least a little bit of both. Dynamic analysis can answer many questions in the areas of
- correctness, e.g., “How much of my code is covered by this test suite?” or “Where does this null pointer come from?”,
- performance, e.g., “In which loop is most of the time spent?” or “Do these memory accesses happen in a cache-friendly order?”, and
- security, e.g., “Is privacy sensitive information leaking to unauthorized places?” or “Is there a memory error that corrupts the heap meta data?”
Writing a (static or dynamic) program analysis is hard, partly because the involved algorithms are complex. But at least some part of that complexity is independent of the individual analyses, for example because it stems from the program representation that is analyzed (e.g., native code or byte code) or the execution model (e.g., a virtual machine or actual hardware). Implementing these parts over and over again for specific analyses would be repetitive and error prone. The frameworks above have been a huge success in academia and practical use by providing a reusable platform for many different dynamic analyses. We would like to follow their path with this first dynamic analysis framework for WebAssembly.
WebAssembly is a new programming language (or more precisely: byte code) for browsers.
It is faster, more low-level, and a better compilation target than JavaScript, the only option on the client-side until now.
We expect it to be hugely successful in the near future.
For the first time in 20 years, all major browsers support client-side execution of a different language than JavaScript, without requiring third-party plugins like Flash or Java. The official website is a great resource for more details, but in short WebAssembly offers predictable, near-native performance without garbage collection, a compact binary representation that is quick to send over the network and parse, and nice static properties with a type system and clean module interfaces. It is designed from the start as a compilation target for “systems languages”, such as C and C++. Naturally, compute-intensive applications are WebAssembly’s strong suit, e.g., game engines or machine learning, but even plain front-end work might profit off the possibility to run other languages than JavaScript in the browser.
(Click on the bullets for more information. Simplified for the sake of giving a quick intuition.)
How Does It Work?
Conceptually
The name Wasabi stands for WebAssembly analysis using binary instrumentation, which hints at the two phases Wasabi operates in:
- It statically instruments a WebAssembly binary (e.g.,
program.wasm
). That is, it inserts additional instructions, such as function calls, in between the original instructions of the program. This happens before the execution. Since WebAssembly is a binary format, and to be independent of the source code (which is often not available when analyzing third-party code in websites), we directly modify the byte code. - To perform the dynamic analysis, the program is then executed (by opening the website with the now instrumented
program.wasm
). To make the user-written analysis functions known to the WebAssembly program (and for other technical reasons), awasabi.js
script has to be added to the page alongside theanalysis.js
.
As an Analysis Author / In Practice
The following picture shows the main steps necessary to analyze a WebAssembly program from the view of a user of Wasabi:
- Write an analysis (e.g.,
analysis.js
) against our high-level API in JavaScript (example below). The analysis can do anything JavaScript can do in the browser, e.g., output analysis results to the console, send them via WebSocket, or store them in an IndexedDB. - Run the Wasabi tool on the WebAssembly program that shall be analyzed (e.g.,
program.wasm
).
Wasabi outputs two files in the process: First, the instrumented program (now contains calls to Wasabi’s analysis hooks) and second, a JavaScript filewasabi.js
that contains statically extracted information about the program and some glue code to connect the analysis with the program itself. - Modify the HTML harness (e.g.,
website.html
) of the WebAssembly program.
Since WebAssembly cannot be directly executed in a browser, it is typically embedded in a website and loaded with JavaScript. This website needs to be made aware of Wasabi. For that, addanalysis.js
(written by you) andwasabi.js
(generated by Wasabi) with<script ...>
tags to the HTML file. Also note that the instrumented WebAssembly program replaces the original file. - Finally, open the website to execute the WebAssembly program as usual. Because of Wasabi’s instrumentation and runtime library, during the execution the analysis hooks inside
analysis.js
are called.
Example and Demo
Typically, WebAssembly programs are compiled from C or C++ via emscripten. But for this example, assume we have a small program written manually in the WebAssembly text format, called program.wat
.
We can create a binary from the text format with wat2wasm
from the WebAssembly Binary Toolkit (WABT).
The program below contains two functions, $main
and $loop
, and imports a third function $print
.
The $
signifies indices in WebAssembly.
That is, these “names” are actually encoded as integers and thus lost in the binary format.
If you are interested, you can download the (uninstrumented) binary here.
(module
;; import function for printing integers from host environment
(import "env" "print" (func $print (param i32)))
;; make main function available to the host environment
(export "main" (func $main))
(func $main
;; print 42 via the imported function
i32.const 42
call $print
;; call the function with index $loop
call $loop
)
(func $loop
(local $counter i32)
i32.const 5
local.set $counter
loop
;; print current loop counter
local.get $counter
call $print
;; subtract 1 from loop counter
local.get $counter
i32.const -1
i32.add
local.tee $counter
;; backward branch (== continue) while $loop > 0
i32.const 0
i32.gt_s
br_if 0
end
)
)
For this demo, we have already run Wasabi on the program above, which results in an instrumented binary and a generated wasabi.js
file.
In the editor below, you can enter a Wasabi analysis.
Once you click on “Run Program”, the WebAssembly program is run and outputs some numbers below.
(Note that your browser needs to support WebAssembly, we tested it with Chrome 61+ and Firefox 58+.)
By default, there is no analysis, so the only output is from the program itself. Click on the links below the editor for small example analyses or have a look into the Wasabi repository.
Wasabi Analysis (JavaScript):
Example: All hooks Example: Calls
Program and Analysis Output (via print()
function):
Getting Started
This is a quick overview, for a more extensive version, see the README in the repository (but that version might get outdated at some point).
- Install the requirements: Rust programming language (compiler + package manager
cargo
, if there are errors, please use a recent stable version) and WebAssembly Binary Toolkit. Clone, build, and install Wasabi from source.
$ git clone https://github.com/danleh/wasabi $ cd wasabi $ cargo install --path .
Assemble the WebAssembly example program from above.
$ wat2wasm program.wat $ ls program.wat program.wasm
Instrument with Wasabi and generate
wasabi.js
file.$ wasabi program.wasm $ ls out/ program.wasm program.wasabi.js
Replace original
program.wasm
with instrumented one fromout/
directory and addprogram.wasabi.js
as script to website.Write your analysis and add that
analysis.js
script to website.
More Details
For more details, you can:
- Read our paper. It gives a high-level overview of the approach and explains some of the unique challenges when instrumenting WebAssembly. The paper focuses more on the concepts than the implementation.
- Inspect the source code.
The project is in Rust and some JavaScript.
This is the definitive source of how everything works in practice.
High-level documentation is scarce, but comments exist.
We are happy to take pull requests, the shorter the better! - Follow-up on our tutorial at PLDI 2019. The conference is already over, but since the material is available online under the linked website, you can follow-up on your own.
- Contact Daniel Lehmann via e-mail.