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.
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?