Repository navigation
Emit line number information for native AOT/WASM - #135740
Conversation
wasmtime with `WASMTIME_BACKTRACE_DETAILS=1` can now print the backtrace including line numbers:
```
d:\git\runtime2>wasmtime artifacts\bin\repro\x64\Debug\reproZero.wasm
Hi
Hi
Error: failed to run main module `artifacts\bin\repro\x64\Debug\reproZero.wasm`
Caused by:
0: failed to invoke command default
1: error while executing at wasm backtrace:
0: 0x86d - abort
at wasisdk://v34.0/build/sysroot/wasi-libc-wasm32-wasip1-build-prefix/src/wasi-libc-wasm32-wasip1-build-build/wasisdk://v34.0/src/wasi-libc/libc-bottom-half/sources/abort.c:5:3
1: 0x43b - reproZero_Program__DoAbort
at D:\git\runtime2\src\coreclr\tools\aot\ILCompiler\reproZero\zerosharp.cs:164:0
2: 0x3d5 - reproZero_Program__Main
at D:\git\runtime2\src\coreclr\tools\aot\ILCompiler\reproZero\zerosharp.cs:156:0
3: 0x349 - reproZero_Program__NativeMain
at D:\git\runtime2\src\coreclr\tools\aot\ILCompiler\reproZero\zerosharp.cs:141:0
4: 0x773 - reproZero.wasm!__main_void
5: 0x2d7 - _start
at wasisdk://v34.0/build/sysroot/wasi-libc-wasm32-wasip1-lto-build-prefix/src/wasi-libc-wasm32-wasip1-lto-build-build/wasisdk://v34.0/src/wasi-libc/libc-bottom-half/crt/crt1-command.c:55:11
2: wasm trap: wasm `unreachable` instruction executed
```
|
Tagging subscribers to 'arch-wasm': @lewing, @pavelsavara |
|
Azure Pipelines: Successfully started running 3 pipeline(s). 13 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
|
Tagging subscribers to this area: @agocke, @dotnet/ilc-contrib |
There was a problem hiding this comment.
🟡 Changes recommended
The Wasm writer silently ignores the requested --gdwarf-5 option.
1 open finding
What changed in this PR
Adds DWARF line information to NativeAOT WebAssembly output for source-level Wasmtime backtraces.
Changes:
- Emits DWARF custom sections and Wasm relocations.
- Maps methods and funclets to source locations.
- Adds Wasm-specific DWARF handling.
| File | Description |
|---|---|
WasmRelocatableObjectWriter.cs |
Emits and relocates DWARF sections. |
WasmObjectWriter.cs |
Creates debug custom sections. |
WasmSection.cs |
Exposes section prefix sizes. |
MethodCodeNode.cs |
Restarts mappings for funclets. |
DwarfLineSequenceWriter.cs |
Completes line sequences correctly. |
DwarfInfo.cs |
Omits unsupported Wasm frame expressions. |
DwarfBuilder.cs |
Adds Wasm architecture support. |
🧠 Review effort: Balanced
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
|
@MichalStrehovsky are the line numbers here correct? We had been concerned that IL -> Native offset mappings in the JIT were incorrect on Wasm. |
They looked good for the stack I pasted in top-post. |
Re-enables RyuJIT variable debug info for ReadyToRun WebAssembly code, which was disabled before wasm locals could be encoded, and defines the encoding that readers consume. - **Register fields** hold `localIndex + WASM_LOCAL_REGNUM_BASE` (3); values 0–2 keep their meanings (`REGNUM_PC`, `REGNUM_COUNT`, `REGNUM_AMBIENT_SP`). - **Stack records** use base 2 (`REG_FPBASE` = `REG_SPBASE` = `REGNUM_AMBIENT_SP` on wasm), so they are slots relative to the logical frame, which readers reconstruct from the stack walk. - **Scopes** open in the first emitted block: wasm is AOT-only, so `getVars` always reports method-wide scopes, and wasm block order doesn't follow IL order. - The hidden portable-entrypoint argument is excluded from source variables, and R2RDump decodes wasm registers. Both constants are fixed for DebugInfo contract `c1` and documented in `DebugInfo.md`. Changing either needs a new contract version and, because R2R images persist the encoding, a ReadyToRun format version change. Browser and WASI publishes strip debug info by default (#134690), so these records reach an image only with `PublishReadyToRunStripDebugInfo=false`; generated code is unchanged. The cDAC consumer is #133890. <details><summary>Test coverage and follow-ups</summary> `WasmWebcilModule` checks invariants rather than exact codegen: register records name declared locals with the expected wasm types, stack records use base 2 without overlapping ranges, recorded frame slots are actually accessed (including from a finally funclet), and GC locals' ranges cover the safepoint. Removing the `+3` bias makes it fail. Follow-ups: NativeAOT DWARF (#135740) can describe locals with `DW_OP_WASM_location` (local index = register − 3); frame-slot variables additionally need the engine local holding the frame pointer, which this format doesn't record. #134808 plans R2R DWARF on top of these records. </details> > [!NOTE] > This pull request description was updated with the assistance of GitHub Copilot. --------- Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Co-authored-by: Jakob Botsch Nielsen <Jakob.botsch.nielsen@gmail.com> Copilot-Session: 51b56d7e-45e5-464d-8c2b-78c744680ff8

wasmtime with
WASMTIME_BACKTRACE_DETAILS=1can now print the backtrace including line numbers. Locals/parameters are not emitted because RyuJIT seems to be lacking that info.