Stream: git-wasmtime

Topic: wasmtime / issue #9657 Debug intrinsics do not work in th...


view this post on Zulip Wasmtime GitHub notifications bot (Nov 22 2024 at 19:04):

SingleAccretion opened issue #9657:

Reproduction:

1) Obtain wasmtime.exe from the released artifacts. You will also need LLDB.
2) Run: lldb wasmtime -Ddebug-info -Oopt-level=0 <any WASM file with debug info>.
3) Place a breakpoint on any WASM frame.
4) Execute p __vmctx->set().

Expected result: it works.
Actual result:

error: Couldn't look up symbols:
  set_vmctx_memory_27_0_0

This is because the symbol is not present anywhere visible to LLDB. On Unix-likes it will be in the symbol table, which Windows doesn't have.

(lldb) image dump symtab wasmtime.exe:

Symtab, file = C:\Program Files\Wasmtime\bin\wasmtime.exe, num_symbols = 2:
               Debug symbol
               |Synthetic symbol
               ||Externally Visible
               |||
Index   UserID DSX Type            File Address/Value Load Address       Size               Flags      Name
------- ------ --- --------------- ------------------ ------------------ ------------------ ---------- ----------------------------------
[    0]      1   X Data            0x0000000141b396c0 0x00007ff7f9b996c0 0x0000000000005fb8 0x00000000 __jit_debug_descriptor
[    1]      2   X Code            0x0000000141158dc0 0x00007ff7f91b8dc0 0x0000000000161ec0 0x00000000 __jit_debug_register_code

view this post on Zulip Wasmtime GitHub notifications bot (Nov 22 2024 at 19:23):

SingleAccretion edited issue #9657:

Reproduction:

1) Obtain wasmtime.exe from the released artifacts. You will also need LLDB.
2) Run: lldb wasmtime -Ddebug-info -Oopt-level=0 <any WASM file with debug info>.
3) Place a breakpoint on any WASM frame.
4) Execute p __vmctx->set().

Expected result: it works.
Actual result:

error: Couldn't look up symbols:
  set_vmctx_memory_27_0_0

This is because the symbol is not present anywhere visible to LLDB. On Unix-likes it will be in the symbol table, which Windows doesn't have.

(lldb) image dump symtab wasmtime.exe:

Symtab, file = C:\Program Files\Wasmtime\bin\wasmtime.exe, num_symbols = 2:
               Debug symbol
               |Synthetic symbol
               ||Externally Visible
               |||
Index   UserID DSX Type            File Address/Value Load Address       Size               Flags      Name
------- ------ --- --------------- ------------------ ------------------ ------------------ ---------- ----------------------------------
[    0]      1   X Data            0x0000000141b396c0 0x00007ff7f9b996c0 0x0000000000005fb8 0x00000000 __jit_debug_descriptor
[    1]      2   X Code            0x0000000141158dc0 0x00007ff7f91b8dc0 0x0000000000161ec0 0x00000000 __jit_debug_register_code

Of note is the fact that if you build wasmtime locally, this works fine because LLDB synthesizes symbols using wasmtime's PDB.

view this post on Zulip Wasmtime GitHub notifications bot (Nov 22 2024 at 20:16):

SingleAccretion edited issue #9657:

Reproduction:

1) Obtain wasmtime.exe from the released artifacts. You will also need LLDB.
2) Run: lldb wasmtime -Ddebug-info -Oopt-level=0 <any WASM file with debug info>.
3) Place a breakpoint on any WASM frame.
4) Execute p __vmctx->set().

Expected result: it works.
Actual result:

error: Couldn't look up symbols:
  set_vmctx_memory_27_0_0

This is because the symbol is not present anywhere visible to LLDB. On Unix-likes it will be in the symbol table, which Windows doesn't have. And #[export_name] doesn't do anything for executables (https://github.com/rust-lang/rust/issues/84161).

(lldb) image dump symtab wasmtime.exe:

Symtab, file = C:\Program Files\Wasmtime\bin\wasmtime.exe, num_symbols = 2:
               Debug symbol
               |Synthetic symbol
               ||Externally Visible
               |||
Index   UserID DSX Type            File Address/Value Load Address       Size               Flags      Name
------- ------ --- --------------- ------------------ ------------------ ------------------ ---------- ----------------------------------
[    0]      1   X Data            0x0000000141b396c0 0x00007ff7f9b996c0 0x0000000000005fb8 0x00000000 __jit_debug_descriptor
[    1]      2   X Code            0x0000000141158dc0 0x00007ff7f91b8dc0 0x0000000000161ec0 0x00000000 __jit_debug_register_code

Of note is the fact that if you build wasmtime locally, this works fine because LLDB synthesizes symbols using wasmtime's PDB.

view this post on Zulip Wasmtime GitHub notifications bot (Nov 22 2024 at 20:18):

SingleAccretion edited issue #9657:

Reproduction:

1) Obtain wasmtime.exe from the released artifacts. You will also need LLDB.
2) Run: lldb wasmtime -Ddebug-info -Oopt-level=0 <any WASM file with debug info>.
3) Place a breakpoint on any WASM frame.
4) Execute p __vmctx->set().

Expected result: it works.
Actual result:

error: Couldn't look up symbols:
  set_vmctx_memory_27_0_0

This is because the symbol is not present anywhere visible to LLDB. On Unix-likes it will be in the symbol table, which Windows doesn't have. And #[export_name] doesn't do anything for executables (https://github.com/rust-lang/rust/issues/84161).

(lldb) image dump symtab wasmtime.exe:

Symtab, file = C:\Program Files\Wasmtime\bin\wasmtime.exe, num_symbols = 2:
               Debug symbol
               |Synthetic symbol
               ||Externally Visible
               |||
Index   UserID DSX Type            File Address/Value Load Address       Size               Flags      Name
------- ------ --- --------------- ------------------ ------------------ ------------------ ---------- ----------------------------------
[    0]      1   X Data            0x0000000141b396c0 0x00007ff7f9b996c0 0x0000000000005fb8 0x00000000 __jit_debug_descriptor
[    1]      2   X Code            0x0000000141158dc0 0x00007ff7f91b8dc0 0x0000000000161ec0 0x00000000 __jit_debug_register_code

Of note is the fact that if you build wasmtime locally, this works fine because LLDB synthesizes symbols using wasmtime's PDB.

I wonder if we could use the same mechanism that libcalls and use a (dynamically) relocatable DWARF DIE for the debug intrinsics with an explicit entry point address, instead of utilizing the platform-specific symbol lookup mechanisms.

view this post on Zulip Wasmtime GitHub notifications bot (Nov 22 2024 at 20:18):

SingleAccretion edited issue #9657:

Reproduction:

1) Obtain wasmtime.exe from the released artifacts. You will also need LLDB.
2) Run: lldb wasmtime -Ddebug-info -Oopt-level=0 <any WASM file with debug info>.
3) Place a breakpoint on any WASM frame.
4) Execute p __vmctx->set().

Expected result: it works.
Actual result:

error: Couldn't look up symbols:
  set_vmctx_memory_27_0_0

This is because the symbol is not present anywhere visible to LLDB. On Unix-likes it will be in the symbol table, which Windows doesn't have. And #[export_name] doesn't do anything for executables (https://github.com/rust-lang/rust/issues/84161).

(lldb) image dump symtab wasmtime.exe:

Symtab, file = C:\Program Files\Wasmtime\bin\wasmtime.exe, num_symbols = 2:
               Debug symbol
               |Synthetic symbol
               ||Externally Visible
               |||
Index   UserID DSX Type            File Address/Value Load Address       Size               Flags      Name
------- ------ --- --------------- ------------------ ------------------ ------------------ ---------- ----------------------------------
[    0]      1   X Data            0x0000000141b396c0 0x00007ff7f9b996c0 0x0000000000005fb8 0x00000000 __jit_debug_descriptor
[    1]      2   X Code            0x0000000141158dc0 0x00007ff7f91b8dc0 0x0000000000161ec0 0x00000000 __jit_debug_register_code

Of note is the fact that if you build wasmtime locally, this works fine because LLDB synthesizes symbols using wasmtime's PDB.

I wonder if we could use the system mechanism that libcalls use via a (dynamically) relocatable DWARF DIE for the debug intrinsics with an explicit entry point address, instead of utilizing the platform-specific symbol lookup mechanisms.

view this post on Zulip Wasmtime GitHub notifications bot (Nov 23 2024 at 22:37):

SingleAccretion edited issue #9657:

Reproduction:

1) Obtain wasmtime.exe from the released artifacts. You will also need LLDB.
2) Run: lldb wasmtime -Ddebug-info -Oopt-level=0 <any WASM file with debug info>.
3) Place a breakpoint on any WASM frame.
4) Execute p __vmctx->set().

Expected result: it works.
Actual result:

error: Couldn't look up symbols:
  set_vmctx_memory_27_0_0

This is because the symbol is not present anywhere visible to LLDB. On Unix-likes it will be in the symbol table, which Windows doesn't have. And #[export_name] doesn't do anything for executables (https://github.com/rust-lang/rust/issues/84161).

(lldb) image dump symtab wasmtime.exe:

Symtab, file = C:\Program Files\Wasmtime\bin\wasmtime.exe, num_symbols = 2:
               Debug symbol
               |Synthetic symbol
               ||Externally Visible
               |||
Index   UserID DSX Type            File Address/Value Load Address       Size               Flags      Name
------- ------ --- --------------- ------------------ ------------------ ------------------ ---------- ----------------------------------
[    0]      1   X Data            0x0000000141b396c0 0x00007ff7f9b996c0 0x0000000000005fb8 0x00000000 __jit_debug_descriptor
[    1]      2   X Code            0x0000000141158dc0 0x00007ff7f91b8dc0 0x0000000000161ec0 0x00000000 __jit_debug_register_code

Of note is the fact that if you build wasmtime locally, this works fine because LLDB synthesizes symbols using wasmtime's PDB.

I wonder if we could use the system mechanism that libcalls use via a (dynamically) relocatable DWARF DIE for the debug intrinsics with an explicit entry point address, instead of utilizing the platform-specific symbol lookup mechanisms.

Edit: working on this...

view this post on Zulip Wasmtime GitHub notifications bot (Nov 23 2024 at 22:39):

SingleAccretion edited issue #9657:

Reproduction:

1) Obtain wasmtime.exe from the released artifacts. You will also need LLDB.
2) Run: lldb wasmtime -Ddebug-info -Oopt-level=0 <any WASM file with debug info>.
3) Place a breakpoint on any WASM frame.
4) Execute p __vmctx->set().

Expected result: it works.
Actual result:

error: Couldn't look up symbols:
  set_vmctx_memory_27_0_0

This is because the symbol is not present anywhere visible to LLDB. On Unix-likes it will be in the symbol table, which Windows doesn't have. And #[export_name] doesn't do anything for executables (https://github.com/rust-lang/rust/issues/84161).

(lldb) image dump symtab wasmtime.exe:

Symtab, file = C:\Program Files\Wasmtime\bin\wasmtime.exe, num_symbols = 2:
               Debug symbol
               |Synthetic symbol
               ||Externally Visible
               |||
Index   UserID DSX Type            File Address/Value Load Address       Size               Flags      Name
------- ------ --- --------------- ------------------ ------------------ ------------------ ---------- ----------------------------------
[    0]      1   X Data            0x0000000141b396c0 0x00007ff7f9b996c0 0x0000000000005fb8 0x00000000 __jit_debug_descriptor
[    1]      2   X Code            0x0000000141158dc0 0x00007ff7f91b8dc0 0x0000000000161ec0 0x00000000 __jit_debug_register_code

Of note is the fact that if you build wasmtime locally, this works fine because LLDB synthesizes symbols using wasmtime's PDB.

I wonder if we could use the mechanism that libcalls use via a (dynamically) relocatable DWARF DIE for the debug intrinsics with an explicit entry point address, instead of utilizing the platform-specific symbol lookup mechanisms.

Edit: working on this...

view this post on Zulip Wasmtime GitHub notifications bot (Nov 25 2024 at 15:38):

alexcrichton commented on issue #9657:

Oh dear, thanks for finding this! I see you're working on this but wanted to leave a comment as well saying I like the idea of using the relocation phase for dwarf for this to avoid needing to deal with symbols :+1:

view this post on Zulip Wasmtime GitHub notifications bot (Nov 27 2024 at 14:00):

SingleAccretion commented on issue #9657:

This has turned out to be a trickier problem than initially anticipated.

The expression evaluator (in LLDB) evaluates expression by compiling them to C++ in a context of an AST rehydrated from DWARF. It means that even if the DWARF spec has many interesting facilities in it that could help solve this issue (e. g. DW_TAG_entry_point, DW_AT_vtable_elem_location), what we can actually use must be representable in C++ source, with just a little bit of wiggle room left with location descriptors.

What I have experimented with then, is describing wasmtime's code in the generated DWARF by adding a small CU that describes the debug intrinsics with low_pc/high_pc ranges. It works, however, I don't think it is an acceptable solution because:
1) We can't describe the ranges faithfully (no way to know the length of Rust functions).
2) The generated CU may conflict with actual CUs generated by rustc on platforms where DWARF is the default DI format.

A way to salvage this approach is to include generated trampolines that would jmp to the debug intrinsics into the overall module, but that would not be very satisfying.

Another angle I explored is using virtual functions to bypass symbol names. However, that also won't work because LLDB hardcodes the assumption that a C++ class will have the vtable as the first field at a zero offset.

view this post on Zulip Wasmtime GitHub notifications bot (Dec 02 2024 at 20:48):

alexcrichton closed issue #9657:

Reproduction:

1) Obtain wasmtime.exe from the released artifacts. You will also need LLDB.
2) Run: lldb wasmtime -Ddebug-info -Oopt-level=0 <any WASM file with debug info>.
3) Place a breakpoint on any WASM frame.
4) Execute p __vmctx->set().

Expected result: it works.
Actual result:

error: Couldn't look up symbols:
  set_vmctx_memory_27_0_0

This is because the symbol is not present anywhere visible to LLDB. On Unix-likes it will be in the symbol table, which Windows doesn't have. And #[export_name] doesn't do anything for executables (https://github.com/rust-lang/rust/issues/84161).

(lldb) image dump symtab wasmtime.exe:

Symtab, file = C:\Program Files\Wasmtime\bin\wasmtime.exe, num_symbols = 2:
               Debug symbol
               |Synthetic symbol
               ||Externally Visible
               |||
Index   UserID DSX Type            File Address/Value Load Address       Size               Flags      Name
------- ------ --- --------------- ------------------ ------------------ ------------------ ---------- ----------------------------------
[    0]      1   X Data            0x0000000141b396c0 0x00007ff7f9b996c0 0x0000000000005fb8 0x00000000 __jit_debug_descriptor
[    1]      2   X Code            0x0000000141158dc0 0x00007ff7f91b8dc0 0x0000000000161ec0 0x00000000 __jit_debug_register_code

Of note is the fact that if you build wasmtime locally, this works fine because LLDB synthesizes symbols using wasmtime's PDB.

I wonder if we could use the mechanism that libcalls use via a (dynamically) relocatable DWARF DIE for the debug intrinsics with an explicit entry point address, instead of utilizing the platform-specific symbol lookup mechanisms.

Edit: working on this...


Last updated: Dec 23 2024 at 13:07 UTC