Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WASM debugging support #1789

Closed
4 tasks done
connor4312 opened this issue Aug 24, 2023 · 3 comments · Fixed by #1811
Closed
4 tasks done

WASM debugging support #1789

connor4312 opened this issue Aug 24, 2023 · 3 comments · Fixed by #1811
Assignees
Labels
feature-request Request for new features or functionality on-testplan VS Code - Issue added to test plan

Comments

@connor4312
Copy link
Member

connor4312 commented Aug 24, 2023

js-debug should be able to debug WebAssembly.

There's two parts of this. The base devtools experience allows users to step into and around WebAssembly, displayed as WAT. Supporting this can be done pretty easily.

The next step is giving source-level support for debugging. The Chromium team recently made their DWARF debugger open source. While this very sadly doesn't work out of the box for Rust yet, it should eventually (we can hope), and it does support any other language that outputs DWARF symbols.

While the extension is built for integration in Chrome devtools, it looks like it's architected in a way that pretty much all the work happens in the DevToolsPluginWorker. I think that we could package this up into an node module that the extension could consume and run in a Node worker_thread.

The downside is the the DWARF SymbolBackend includes(?) chunks from LLVM and even compressed is pretty hefty at 11MB, so we may not want to have it included in vscode by default like js-debug is. My thought is that we can have an extension that exports a known API for js-debug to consume, alongside an npm package that ships only the types in the package (or maybe I just copy the types directly into js-debug). We can try to both
require('vscode').extensions.getExtension('ms-vscode.js-debug-dwarf') as well as require('@vscode/dwarf-debugging') to enable pure DAP consumers to get this too. And of course we can prompt the user to install this extension when they first step into WASM code.

  1. Enable basic debugging with WAT
  2. Create a module bundling the devtools c/++ worker debugger
  3. Integrate the module into js-debug
  4. Externalize the module into an extension with suggestions
@connor4312 connor4312 added the feature-request Request for new features or functionality label Aug 24, 2023
@connor4312 connor4312 self-assigned this Aug 24, 2023
connor4312 added a commit that referenced this issue Aug 25, 2023
Supports viewing, stepping through, and setting breakpoints in
webassembly (decompiled as WAT) in the editor. Includes a
basic tmLanguage for WAT.

![](https://memes.peet.io/img/23-08-b7617299-9f8d-41c9-8fe0-ada8a3c57966.png)

Unfortunately we eagerly have to decompile WASM in order to get line
mappings to show e.g. in breakpoints. Location mapping is currently
mostly synchronous and I didn't want to make everything async
for webassembly. However, we don't keep the WAT source in memory,
instead request it again if it's needed. I opted to do this to reduce
memory usage for user applications that just happen to contain WASM
where they aren't always interested in debugging it.

For #1789
Fixes #1715 on the way
connor4312 added a commit that referenced this issue Aug 27, 2023
* feat: support basic webassembly debugging

Supports viewing, stepping through, and setting breakpoints in
webassembly (decompiled as WAT) in the editor. Includes a
basic tmLanguage for WAT.

![](https://memes.peet.io/img/23-08-b7617299-9f8d-41c9-8fe0-ada8a3c57966.png)

Unfortunately we eagerly have to decompile WASM in order to get line
mappings to show e.g. in breakpoints. Location mapping is currently
mostly synchronous and I didn't want to make everything async
for webassembly. However, we don't keep the WAT source in memory,
instead request it again if it's needed. I opted to do this to reduce
memory usage for user applications that just happen to contain WASM
where they aren't always interested in debugging it.

For #1789
Fixes #1715 on the way

* retain wasm-set breakpoints between reloads
connor4312 added a commit that referenced this issue Sep 15, 2023
Enables stepping around and setting breakpoints in native code.
Variables represenation is still a todo, and this needs some polish.

It refactors the `Source.sourceMap` into a more generic location
provider, which may be backed by the new IWasmSymbols interface. This
then talks to the DWARF debugger. The SourceContainer's `_sourceMaps`
are also now just folded into the `Source.sourceMap`; that information
was duplicate and the only benefit was deduplication if two sources had
the same sourcemap, but this is really rare.

This also made all location mapping asynchronous, so there were a
few refactors around there, too.

It also refactors how I implemented WAT (text format decompilation) last
iteration. That previously "pretended" the source of the WASM was WAT,
but this caused issues because the location transformation we did on the
scripts is done before location mapping. So instead, the WAT is an extra
fake 'file' in the symbols and we resolve any unknown locations into the
WAT file.

One that that _doesn't_ work yet is entrypoint breakpoints for wasm,
which means that breakpoints set before the debug session starts may be
missed. I have a thread out to the Chromium folks to see if there's
a solution to this.

For #1789
connor4312 added a commit that referenced this issue Sep 15, 2023
Enables stepping around and setting breakpoints in native code.
Variables represenation is still a todo, and this needs some polish.

It refactors the `Source.sourceMap` into a more generic location
provider, which may be backed by the new IWasmSymbols interface. This
then talks to the DWARF debugger. The SourceContainer's `_sourceMaps`
are also now just folded into the `Source.sourceMap`; that information
was duplicate and the only benefit was deduplication if two sources had
the same sourcemap, but this is really rare.

This also made all location mapping asynchronous, so there were a
few refactors around there, too.

It also refactors how I implemented WAT (text format decompilation) last
iteration. That previously "pretended" the source of the WASM was WAT,
but this caused issues because the location transformation we did on the
scripts is done before location mapping. So instead, the WAT is an extra
fake 'file' in the symbols and we resolve any unknown locations into the
WAT file.

One that that _doesn't_ work yet is entrypoint breakpoints for wasm,
which means that breakpoints set before the debug session starts may be
missed. I have a thread out to the Chromium folks to see if there's
a solution to this.

For #1789
@connor4312
Copy link
Member Author

connor4312 commented Sep 19, 2023

This is largely done now in PRs #1804 through #1808. Tomorrow I will do some final cleanup and try to get some tests going, and then it will ship in the nightly.

@fleabitten232
Copy link

Does this currently support the "path substitution" feature from the Chrome plugin? I compile in a container, which means that the source file paths are incorrect for the machine I want to debug on.

Appreciate all the work that's been done on this and I'm eager to try it out!

@connor4312
Copy link
Member Author

The path goes through the usual path mapping logic in js-debug, so for your case you'd want to set the localRoot/remoteRoot in your launch.json as described in https://code.visualstudio.com/docs/nodejs/nodejs-debugging#_remote-debugging

@bhavyaus bhavyaus added the on-testplan VS Code - Issue added to test plan label Sep 26, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature-request Request for new features or functionality on-testplan VS Code - Issue added to test plan
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants