Skip to content

Inspecting WebAssembly Binaries

Every .wasm file is a sequence of numbered sections. Understanding which section contributes what makes it possible to target your optimisation efforts precisely. This lesson shows the tools that surface that information.

A WebAssembly binary is divided into up to thirteen standard sections, each with a unique ID. The diagram below shows the most common ones and how they relate to each other.

flowchart TD
  A[".wasm binary"] --> B["Type section\nfunction signatures"]
  A --> C["Import section\nJS / host imports"]
  A --> D["Function section\ntype index per function"]
  A --> E["Export section\npublic API names"]
  A --> F["Code section\nactual instructions"]
  A --> G["Data section\nmemory initialisers"]
  A --> H["Custom sections\nname debug DWARF producers"]
.wasm section layout

The quickest way to read any binary is wasm2wat. It reconstructs the WAT text representation, including function names if a name section is present.

Terminal window
# Dump the full WAT to stdout
wasm2wat add.wasm
# Save to a file for editing or diffing
wasm2wat add.wasm -o add.wat
# Generate synthetic names when none are present
wasm2wat add.wasm --generate-names

wasm-objdump — section-by-section inspection

Section titled “wasm-objdump — section-by-section inspection”

wasm-objdump -x prints a structured summary of every section: type signatures, imports, exports, and function indices. It is faster than a full disassembly when you only need the module’s public API.

Terminal window
# Full section summary
wasm-objdump -x my.wasm
# Disassemble code section only (shows raw instructions)
wasm-objdump -d my.wasm
# Show a single section
wasm-objdump -j export my.wasm
wasm-objdump -j import my.wasm

twiggy is a code-size profiler that attributes every byte in a .wasm binary to a function or section. It is the fastest way to answer “which function is making my binary large?”

Terminal window
# Install
cargo install twiggy
# Print the top contributors to binary size
twiggy top my.wasm
# Show the retaining paths for a specific function
twiggy paths my.wasm --function "some_large_function"
# Output as JSON for further processing
twiggy top my.wasm --output-format json

A twiggy top report looks roughly like:

Terminal window
Shallow Bytes | Shallow % | Item
----------------+-----------+------------------------------
14512 | 42.38% | "function names" subsection
8032 | 23.46% | code[42]: some_large_function
3200 | 9.35% | code[17]: decode_utf8

Modern browsers ship WebAssembly debugging support directly in DevTools. In Chrome and Firefox you can open Sources → wasm to see a disassembly of every instantiated module, set breakpoints on individual instructions, and inspect local variables and the value stack at each breakpoint.

To get readable function names in DevTools you need either:

  • A name section in the binary (produced by wat2wasm --debug-names or wasm-opt --debuginfo), or
  • A DWARF section emitted by Emscripten or clang with -g.
OptionBenefitCost
wasm-opt -Oz (most aggressive optimization)Best size and speed after optimizingLonger build times, and what you see in wasm2wat/wasm-objdump drifts far from the original source, harder to read
Keeping the name section (--debug-names)DevTools and wasm2wat show readable function namesIncreases the size of the binary you actually ship
  • Skipping the inspection step and guessing what’s making a binary large, instead of using twiggy top to find the real culprit
  • Turning on aggressive wasm-opt before actually knowing which section or function is large or slow
  • Stripping the name section from the start, so wasm-objdump, wasm2wat, and DevTools can’t show any readable stack trace at all

💡 Real-world example

Emscripten automatically invokes Binaryen’s wasm-opt when you build with -O2/-O3 (Emscripten optimization docs); the tools in this lesson (wasm-objdump, twiggy, wasm2wat) are what you reach for afterward when you need to know exactly what that optimized binary contains.

Which tool attributes each byte of a .wasm file to a specific function?
What does wasm-objdump -x print?
Which section holds the actual instructions of each function?
What do you need in the binary to see readable function names in DevTools?