Skip to content

Binaryen - WebAssembly Compiler & Optimizer Toolchain Cheatsheet

Binaryen - WebAssembly Compiler & Optimizer Toolchain Cheatsheet

Binaryen is a compiler and toolchain infrastructure library for WebAssembly, written in C++. Its headline tool, wasm-opt, loads a wasm module into an intermediate representation and runs optimization and transformation passes over it — the same machinery that toolchains like Emscripten use to shrink and speed up wasm. For reverse engineers, Binaryen’s disassembler (wasm-dis) and its analysis/transform passes (including deobfuscation-adjacent simplifications) make it a useful complement to WABT.

Installation

PlatformCommand
macOS (Homebrew)brew install binaryen
Debian/Ubuntusudo apt install binaryen
Arch Linuxsudo pacman -S binaryen
npmnpm install -g binaryen (JS bindings)
From sourcebuild with CMake from the WebAssembly/binaryen repo
Verifywasm-opt --version

Core Tools

ToolDoes
wasm-optLoad, optimize/transform, and re-emit a module
wasm-disDisassemble .wasm → text
wasm-asAssemble text → .wasm
wasm-metadceDead-code-eliminate across module + JS
wasm-ctor-evalEvaluate constructors at build time
wasm-reduceShrink a module while preserving a behavior (bug repro)
wasm-shellRun the spec test shell

Optimizing a Module

# Optimize for size and speed
wasm-opt -O3 module.wasm -o module.opt.wasm

# Optimize aggressively for size
wasm-opt -Oz module.wasm -o module.small.wasm
FlagEffect
-O / -O1..-O4Increasing optimization for speed
-OsOptimize for size
-OzOptimize aggressively for size
--enable-FEATUREEnable a wasm proposal (simd, threads, …)
-o FILEOutput file

Running Individual Passes

wasm-opt exposes many named passes you can run selectively — useful for RE (simplifying obfuscated code) as well as builds.

# List all available passes
wasm-opt --help | grep -A2 "passes:"

# Run specific passes (e.g. simplify + remove unused)
wasm-opt module.wasm --precompute --simplify-locals \
  --remove-unused-names --vacuum -o clean.wasm
Pass (examples)Purpose
--precomputeFold constant expressions
--simplify-localsReduce redundant local usage
--vacuumRemove obviously dead code
--remove-unused-module-elementsStrip unused funcs/globals
--flatten / --rereloopRestructure control flow

Disassemble / Assemble

# Disassemble to Binaryen's text form
wasm-dis module.wasm -o module.wat

# Assemble back
wasm-as module.wat -o module.wasm

RE Use: Simplify Then Read

A practical reversing trick is to run Binaryen’s simplification passes to clean up compiler/obfuscator noise, then read the result.

# Simplify a gnarly module, then decompile with WABT
wasm-opt target.wasm --precompute --simplify-locals --vacuum -o simpler.wasm
wasm-decompile simpler.wasm -o simpler.dcmp

Minimizing a Repro (wasm-reduce)

# Shrink a module while a script still reports the behavior of interest
wasm-reduce big.wasm --command "node check.js" -o small.wasm

Great for isolating the minimal wasm that triggers a bug or a specific behavior.

ToolFocus
BinaryenOptimize/transform/analyze wasm (compiler-grade)
WABTConvert/inspect/validate/decompile
diswasmPseudocode decompiler
wasm-toolsRust low-level manipulation

For RE: use Binaryen to simplify, WABT/diswasm to read, and wasm-tools to validate/mutate.

Resources