orca-app/orca

Debugging story

Opened this issue · 0 comments

One of next big topic we have to tackle is debugging. Here are some thoughts.

There's two way we can approach this (and both can certainly coexist, but it's a matter of choosing where we put our limited resources on):
- Making apps debuggable from external tools (eg lldb). Right now since we simply interpret wasm, lldb doesn't even has any means to know that we're running wasm code. It's just C code working with a blob of data. I'm not clear yet what we should expose to allow a debugger to take control of the interpreter and step through wasm code. This approach would be better for composability with existing tools and not having to rewrite all debugging features. But it seems we'd miss out on a number of important contextual information.
- Building our own internal tool. This way the debugging tools are available out of the box, and can take advantage of contextual knowledge of the runtime. For example our debugger could understand that such and such structs are actually UI widgets, and highlight them on the screen when we step through their functions. Or that a specific handle refers to an image, and show a thumbnail of that image. etc...

I'm leaning towards the internal tooling, because I think its where we can deliver a lot of value for app developers, and we can take some shortcuts by knowing the specifics of our "platform". It is also less dependent on external factors we don't control (eg the various ways external tools want to talk to wasm interpreters).

This mean we should be able to, at the very least:

  • Parse Dwarf, or at least the subset of dwarf that interests us. Basically symbol names, source locations, variable locations? One problem is that wasm doesn't really specify much in terms of debug info, so that might or might not change depending on the toolchain/langage. We can start with what clang outputs for C code at least.
  • Get stack unwinding info. That might actually be easier than for native code since wasm does have a inherent concept of functions.
  • Setting breakpoints and single stepping. Since we control the interpreter, it should be relatively easy to expose that: save the opcode at the breakpoint location, overwrite with a breakpoint opcode, and restore the original opcode before single stepping over the breakpoint.
  • Watching variables (again depends on what we can get from wasm debug info).

Besides line stepping, we can have a number of nice debugging tools accessible from developer overlays:

  • Debug overlay: log, UI styling debugger, resources debugger (show open files, sockets, graphics surfaces, ...), etc.
  • Perf overlay: frame statistics / history, function timings, code heatmap, etc ...