Open ggreif opened 4 years ago
Gabor and I just managed to step through the Rust equivalent of the fak.c
program inside VSCode, through lldb
, via wasmtime
. If we can manage to emit debug information like Rust this should give us a promising way forward.
Regarding "Stand-alone linking", what's the use case exactly?
Implementing a "mock" system API in C or Rust and generating stand-alone wasm binaries would be very helpful for debugging the compiler and RTS issues, but I don't see how that would be useful for users. Could you elaborate more on this? Do we want to allow users to debug their canisters without interacting with the IC or drun?
@osa When I say user I mean developers in charge of maintaining canisters. I don't think end-users of the IC (as in "I just watched a few CanCan videos, here are the links, awww") should get debug privileges (like downloading message histories and syscall traces). The use-case I envision is:
lldb
, debug, debug...It basically boils down to rapid turnaround cycles. That said, I expect that developers can use plain -wasi-system-api
to initially debug their algorithms. So this feature will come to play only when advanced debugging is needed. It is also predicated on the execution team's support for downloads.
This is in-progress. Can read, but there are still infelicities. A savvy
nix
user (from within DFINITY) will be able to debug Motoko using the information bits herein. (On Linux the experience will be more smooth, becausewasmtime
is more reliable there than on macOS.)Getting
wasmtime
on track with DWARF-5See https://github.com/bytecodealliance/wasmtime/issues/932.
We (language team or execution team) could contribute patches.
lldb-9
and DWARF-5 (compiled fromclang-11
(pre-release))lldb-10
testsExprloc
compilation of0xED
locations (this was a documentation bug).DW_OP_bra
work)v0.21.0
)Location expressions (PR merged, part of
v0.20.0
)There is an entire sublanguage in DWARF dealing with encoding the location of information such that a debugger can find it.
wasmtime
translates these expressions from the DWARF5 side to the target architecture's conventions,but currently lacks support for many operations (. https://github.com/bytecodealliance/wasmtime/pull/2143DW_OP_*
), most notably for branchingproposes to fixfixes this.Debugging adapter for Motoko
This turned out to be easier than expected. The VS-Code debugger works nicely with
wasmtime
debug info JIT under LLDB. One has to setwasmtime
as the program and["-g", "<wasm-file>"]
as the arguments. Then the breakpoints can be set and various features are present when running the program.A small example to be tested in VSCode's debug environment (DAP)
Author as `$ cat fak.c`: ``` c++ #includeStand-alone linking
This is about implementing enough of the system interface to be able to ingest (predefined) Candid IDL messages into a stand-alone Wasm binary.
moc -wasi-system-api
is a first step, and will allow to test a lot of the architecture, but we want a bit more in the middle term.What we need is a shim library that implements the IC system interface (either on top of WASI or
node
) and thus enable running canisters outside of their natural habitat under a DWARF-assisted debugger (lldb
or maybeChrome
) with a certain level of fidelity.Download of message histories
Conversely we'll need a mode of the IC that allows to pull out messages of actual transactions for debugging purposes. This is a very sensitive issue, and needs careful consideration, but is essential for a realistic (and useful) debugging experience.
When multi-party message histories are not needed, a watered-down alternative could be to just record the client (JS-side) message dialog with the IC. This should be easy, considering that all messages already pass through the Candid library.
Compiling/linking in the message history
moc -local-system-api
would create a standalone Wasm binary with the message history (andstrace
-like external trace) compiled in. A user would just run this aslldb -- wasmtime -g <app>
to debug.Add DWARF-5 features to Motoko
First step is #1163. PRs split out from this to facilitate review:
With https://github.com/bytecodealliance/wasmtime/pull/1410 we can load (carefully crafted) DWARF-5 into
wasmtime
. Other issues (e.g. in gimli) are linked from there.Packaging the beast
llvm
wasmtime
at some pointmoc -g
directly or viadfx
?Finally I have something working, both on Mac and Linux we can have an IDE inside of
nix-shell
thatVSCodium
(orVSCode
)vscode-motoko
andCodeLLDB
pluginswasmtime
For completeness, here is my current configuration:
`settings.json`
`.vscode/launch.json`
`.vscode/tasks.json`
Packaging up more components
The way forward could be integrating these components into a polished Motoko IDE:
vscode-motoko
plugin (incl.dfx
)CodeLLDB
pluginLocal replica debugging
Another interesting alternative is to attach to the running local replica (
dfx
-like environment), now that it useswasmtime
. Several prerequisites are required to make this work:wasmtime
with the-g
flag (or a procedural equivalent)I assume that the replica utilises
wasmtime
as a library (as opposed to as a process), solldb
must be pointed to the running replica. Also, the replica must still provide the DWARF JIT functionality.Emerging alternatives
There is a lot going on in the WebAssembly debugging space that is promising to offer a less convoluted way of debugging canisters. Below listed are two projects that I am aware of.
wasminspect
There is a new debugging variant on the horizon, in the form of https://github.com/kateinoigakukun/wasminspect. This is a bytecode interpreter-based debugger with a similar command structure to
lldb
, thus potentially usable in an IDE plugin environment. However initial evaluation has shown that the project is still very immature and needs a lot of love to even enter in consideration. Issues and PRs are filed, the maintainer appears to be semi-responsive.wasmrun
Ömer's Wasm project is also progressing.
Speculative outlook
With a canister-forking technology it could become feasible to add live debugging to the IC. A forked canister (system under test) needs to be wrapped into a debugging context, and making the CLI debug commands accessible via Candid. When debugging is concluded the wrapped fork could be deleted like any other canister.
This debug method could be essential as a last-resort solution for problems unique to live IC canisters, where local debugging fails to reproduce. (It could be run in a local testate too.)