WebAssembly Debugging Cheat Sheet [2026 Reference]
Bottom Line
For day-to-day browser debugging, use DWARF builds in Chrome; for optimized or more portable location mapping, emit source maps. When variables disappear or layouts look wrong, inspect raw linear memory directly instead of guessing.
Key Takeaways
- ›DWARF gives the best Wasm source-level debugging; source maps are broader but mostly location-only.
- ›In Emscripten, debug output is controlled at link time as well as compile time.
- ›Chrome Memory Inspector is available from Chrome 91; Wasm object-memory workflows are best on Chrome 107+.
- ›Use -g2 for cheap readable stacks, -gsource-map for optimized location mapping, and -gseparate-dwarf to keep shipped Wasm lean.
Wasm debugging is finally practical, but the toolchain still punishes fuzzy build settings. On May 11, 2026, the fastest path is simple: use DWARF when you need variable-aware stepping in Chrome, use source maps when you need optimized location mapping, and drop into Memory Inspector when symbols stop telling the truth. This reference keeps the commands, shortcuts, and configuration edges in one place.
Key Takeaways
- DWARF gives the richest browser debugging experience; source maps are broader but mostly map locations.
- With Emscripten, debug behavior is controlled at link time too, not only when compiling objects.
- Chrome 91+ ships Memory Inspector; Chrome 107+ improves Wasm object-memory inspection for C/C++ debugging.
- -g2, -gsource-map, and -gseparate-dwarf solve different problems. Pick deliberately.
Debugging Stack at a Glance
Bottom Line
Use DWARF for real source-level browser debugging, use source maps for optimized line mapping, and use Memory Inspector when byte-level truth matters more than symbol fidelity.
Emscripten officially supports both DWARF and source maps for source-level debugging. The tradeoff is straightforward:
- DWARF offers the best debugging experience in Chrome, including better variable and call-stack inspection.
- Source maps are more widely supported, but they mainly provide source location mapping and are not a substitute for rich variable inspection.
- Memory Inspector complements both by exposing the raw
WebAssembly.Memorybuffer. - Debug preservation is not automatic. In Emscripten, the final output still depends on link-time flags.
Pick the right artifact
- Choose DWARF for browser stepping, locals, scopes, and better inline-aware traces.
- Choose source maps when you want optimized output and source line mapping without shipping full DWARF in the main binary.
- Choose -g2 when you mainly want readable function names and low overhead.
- Choose separate DWARF when production payload size matters but developers still need source-level debugging.
Keyboard Shortcuts
These are the high-value shortcuts to keep your hands off the mouse while debugging Wasm in the Sources panel.
| Action | macOS | Windows / Linux |
|---|---|---|
| Open DevTools | Command+Option+I | F12 or Control+Shift+I |
| Open Command Menu | Command+Shift+P | Control+Shift+P |
| Pause / Resume script execution | F8 or Command+\ | F8 or Control+\ |
| Step over next function call | F10 or Command+' | F10 or Control+' |
| Step into next function call | F11 or Command+; | F11 or Control+; |
| Step out of current function | Shift+F11 or Command+Shift+; | Shift+F11 or Control+Shift+; |
| Continue to a certain line while paused | Hold Command and click the line | Hold Control and click the line |
| Go to line | Control+G | Control+G |
Commands by Purpose
Filter the snippets below by flag, tool, or use case.
Full DWARF for stepping and locals
- Use when you want the best Chrome debugging experience.
- Best fit for local development and breakpoint-heavy sessions.
emcc -g source.cc -o app.htmlSource maps for optimized location mapping
- Generate DWARF in objects first, then emit the Wasm source map at link time.
- Use --source-map-base when maps are hosted outside the app directory.
emcc source.c -c -o source.o -g
emcc source.o -o app.js -gsource-map --source-map-base https://debug.example.com/maps/Inline source maps for self-contained debugging
- Useful for temporary repro builds and demos.
- Expensive in file size because source content is embedded.
emcc source.c -c -o source.o -g
emcc source.o -o app.js -gsource-map=inlineSidecar DWARF for lean shipped Wasm
- Keeps the main Wasm lighter.
- Lets DevTools find debug info through a separate file.
emcc -g source.cc -o app.html \
-gseparate-dwarf=app.debug.wasm \
-sSEPARATE_DWARF_URL=https://debug.example.com/dwarf/app.debug.wasmCheap readable stacks with -g2
- Preserves function names via the Wasm name section.
- Good default when full symbolic debugging is overkill.
emcc source.c -c -o source.o
emcc source.o -o app.js -g2Production symbolication with line tables only
- Use -gline-tables-only when you need line info but not full type and variable detail.
- Strip the shipped binary while retaining a debug copy for postmortems.
emcc source.c -c -o source.o -gline-tables-only
emcc source.o -o program2.js -g
llvm-strip program2.wasm -o program2_stripped.wasmRuntime guards for memory and logic issues
- ASSERTIONS catches common runtime mistakes.
- SAFE_HEAP adds extra memory access checks when you are chasing invalid writes or alignment issues.
emcc -O1 -sASSERTIONS test/hello_world.c
emcc -O1 -sSAFE_HEAP=1 test/hello_world.cConsole-level memory inspection
- Use browser console expressions when you already know the address or pointer range.
- Useful when locals are optimized away or when you want exact byte views.
new Uint8Array(wasmMemory.buffer, ptr, len)
new DataView(wasmMemory.buffer).getUint32(ptr, true)
new DataView(wasmMemory.buffer).getFloat64(ptr, true)Configuration
Default recipes
- Local stepping build: compile and link with -g, then debug in Chrome with the C/C++ DevTools Support (DWARF) extension.
- Optimized repro build: compile with -g, link with -gsource-map, and keep your normal optimization settings.
- Small production binary with debug fallback: use -gseparate-dwarf and host the sidecar through SEPARATEDWARFURL.
- Fast developer stacks: use -g2 when you only need names and readable stack traces.
Path and hosting fixes
- Use --source-map-base to point the generated Wasm at the correct source-map host.
- Use -sSOURCEMAPPREFIXES=/old/path=/new/path to rewrite source paths inside the map.
- If you build on a different machine or inside a container, Chrome's C/C++ DevTools Support (DWARF) extension can remap old and new file paths.
emcc source.c -c -o source.o -g
emcc source.o -o app.js \
-gsource-map \
--source-map-base https://debug.example.com/maps/ \
-sSOURCE_MAP_PREFIXES=/build/src=/srcMemory Inspection
Memory Inspector is available from Chrome 91. For full Wasm object-memory workflows in C/C++, Chrome documents the best experience on Chrome 107+ with the C/C++ DevTools Support (DWARF) extension installed.
How to open it
- From DevTools:
More tools > Memory inspector. - While paused: click
Reveal in Memory Inspectorfrom the variable in Scope. - You can inspect multiple objects at once in separate tabs.
What it is good at
- Jumping to exact addresses in hex.
- Switching between big-endian and little-endian views.
- Reading integer and floating-point interpretations without writing ad hoc parsing code.
- Following
Pointer 32-bitandPointer 64-bitjump targets when the addresses are valid.
// Common console helpers while paused
const bytes = new Uint8Array(wasmMemory.buffer, ptr, len)
const dv = new DataView(wasmMemory.buffer)
const u32 = dv.getUint32(ptr, true)
const f64 = dv.getFloat64(ptr, true)Safe workflow for real incidents
- Pause at the suspect write or read.
- Inspect the source-level variable first through DWARF.
- If the value looks impossible, open Memory Inspector and validate the backing bytes.
- Before sharing copied buffers or dumps externally, scrub secrets with the Data Masking Tool.
Advanced Usage
When DWARF beats source maps
- DWARF carries richer type, variable, and inline information.
- Source maps survive aggressive post-link optimization better and are easier for broad ecosystem tooling.
- If stack accuracy matters more than portability, prefer DWARF.
Profiling caveat
- Chrome documents that when DevTools is open for Wasm debugging, the code it runs is not optimized; it is tiered down for a better debugging experience.
- Do not trust
console.time()orperformance.now()collected under an attached DevTools session as your primary performance signal. - Use the Performance panel, or profile without DevTools open and inspect output afterward.
Minimal decision matrix
- Need variables, scopes, and line stepping: use -g.
- Need optimized line mapping without full symbolic payload: use -gsource-map.
- Need small artifacts plus later debugging: use -gseparate-dwarf.
- Need readable names only: use -g2.
- Need production crash line info with less debug bulk: use -gline-tables-only.
Official references checked
Frequently Asked Questions
Should I use DWARF or source maps for WebAssembly debugging? +
Why are my local variables missing in optimized Wasm builds? +
-g alone is not sufficient.How do I inspect WebAssembly linear memory in Chrome DevTools? +
How do I ship a small Wasm file but keep source-level debugging? +
-gseparate-dwarf so the main Wasm omits embedded debug info while a sidecar debug file is generated. If the sidecar lives elsewhere, point to it with -sSEPARATE_DWARF_URL=... so DevTools can resolve it.Get Engineering Deep-Dives in Your Inbox
Weekly breakdowns of architecture, security, and developer tooling — no fluff.
Related Deep-Dives
WebAssembly Multi-threading Cheat Sheet: WASM & SharedArrayBuffer
The companion reference for threading, workers, and SharedArrayBuffer configuration in modern Wasm apps.
Developer ReferenceWebAssembly SIMD & Threads Flags [Cheat Sheet 2026]
A flag-by-flag reference for SIMD, pthreads, and cross-origin isolation in performance-focused Wasm builds.
System ArchitectureWebAssembly Component Model 2026: Rust + Go with Wasi-Cloud
A broader architecture deep dive on where Wasm components fit once your debugging story is under control.