-
Notifications
You must be signed in to change notification settings - Fork 691
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
First version of DebuggingFramework.md. #708
base: main
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
#WebAssembly Debugging | ||
|
||
This is a design proposal for enabling source-level debugging of WebAssembly | ||
modules. | ||
|
||
## Introduction | ||
|
||
There are several entities involved in debugging a source program compiled into | ||
WebAssembly: | ||
|
||
- the compiled code being executed, called the _debuggee_ | ||
- the browser engine executing the debuggee | ||
- the browser devtools | ||
- the source-program listing, usually split into multiple source files | ||
- the description of how the debuggee code maps to the source program and vice | ||
versa (e.g., WebAssembly code locations to source code locations, source | ||
variables to WebAssembly memory, WebAssembly call stack to source functions, | ||
etc.), called the _debug info_ | ||
|
||
These entities carry information and interact in particular ways to enable a | ||
user to perform debugging actions at the source-code level. For example, the | ||
browser devtools offer a UI allowing the user to step through the source code, | ||
requiring partial execution of the debuggee chunk corresponding to each step, | ||
and displaying the source file containing the stepped-through program. | ||
|
||
Specifying the debugging framework means describing how these entities interact, | ||
what they need from each other, and how they access it; all in order to execute | ||
the user's commands. | ||
|
||
## Debugger as a Procedural Interface | ||
|
||
A crucial element of this design proposal is to omit specifying a particular | ||
format for the debug info. Instead, we introduce a separate entity we call the | ||
debugger; its job is to act as a procedural intermediary between the devtools | ||
and the debug info. Devtools execute user actions by leveraging debugger | ||
methods we will specify here. | ||
|
||
Thus any debug-info format is acceptable, as long as the debugger can correctly | ||
interpret it. The format is, in effect, a convention between the front-end | ||
parsing the source and the debugger. | ||
|
||
What the design _does_ specify is two interaction protocols: | ||
|
||
1. between the devtools and the debugger, and | ||
2. between the debugger and the wasm execution engine | ||
|
||
## Action Flow | ||
|
||
For reference, the entities are charted in the figure below: | ||
|
||
![Entities making up the debug framework](wasm-debug-chart.png) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice chart! I'd put the "Debugger" box inside the browser box since it's executing JS or wasm code. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I felt that the wasm module and the debugger should be shown outside, because they don't come with the browser but are downloaded. Then I try to explain in the text how they are used by the browser when obtained. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IIUC 4. and 5. are what you're specifying here, right? It sounds like @lukewagner wants to drop 3. from the diagram, but you'd rather keep it because it can be separate (not being specified in this doc)? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, this aims to specify 3 and 5, while leaving 4 unspecified (other than saying how the debugger can find the debug info and source files). The way the debugger interprets the debug info will be hidden from other actors in this picture, freeing the debugger implementers to choose whatever suits them. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see your point and just noticed that "wasm module" is also, symmetrically, outside the box. |
||
|
||
(The figure uses the conventional phrase "wasm module" to refer to a debuggee. | ||
For now, we overlook the complexities of multiple wasm modules or mixing JS and | ||
wasm on the same call stack.) | ||
|
||
Black arrows in the figure indicate the action flow and timeline: | ||
|
||
1. When the page is first rendered, the debuggee is loaded into the browser and | ||
sent to the wasm execution engine. | ||
2. The user interacts with the browser's devtools UI (eg, requesting a source | ||
listing for a function to set a breakpoint). | ||
3. Devtools call on the debugger to execute operation(s) necessary to fulfilling | ||
the user's request. After going through steps 4 and/or 5, the debugger | ||
returns a result for the devtools to display. | ||
4. The debugger consults the debug info and/or source files to obtain the proper | ||
mapping between the source code and the wasm. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: the chart lacks an arrow from the source files to the debugger. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I felt the extra arrow would clutter the picture without adding much information value. I glommed the debug info and source files rectangles together to suggest that they act in unison. |
||
5. Optionally, the debugger requests information from the browser, such as | ||
examining the wasm memory or call stack in the execution engine. | ||
|
||
Note that 3 and 5 are bidirectional arrows: sometimes the flow of action goes | ||
from the browser through the debugger to devtools. For instance, this will | ||
happen when a breakpoint is hit and the wasm execution is paused. The browser | ||
will then notify the debugger, who will in turn notify devtools after | ||
translating the wasm program counter to the corresponding source line. | ||
|
||
## About the Debugger | ||
|
||
We propose that the debugger be a JavaScript library providing the interface | ||
described in the next section. This allows for easy access to the browser, as | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd s/JavaScript library/JavaScript API/ and then note that in the future (perhaps linking to GC.md), wasm would be able to access the API directly so that the debugger could be compiled wasm. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It'd also be good to point out the option of having this same API debug JS (maybe not in the initial version of the API, but after some iteration). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
well as ease of implementation because JavaScript is widely known and supported. | ||
|
||
This also makes it possible for the debuggee to contain a URL for the debugger | ||
to be used on it. This URL can point to any server, allowing debugger reuse | ||
among many debuggees. | ||
|
||
## UI -> Debugger Protocol Operations | ||
|
||
First, we list the basic debugger operations that the UI can invoke: | ||
|
||
- get a source location given a mangled function name | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To understand what are the right set of primitives/operations here, it'd be nice to outline some end-to-end flows from user action to UI response to the action. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm working on a Chrome prototype that does just that. Armed with that experience, I'll summarize here some of the end-to-end flows. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
- get a function signature given a mangled function name | ||
- get the source given a location | ||
- set a breakpoint at a given location | ||
- interrupt the ongoing debuggee execution | ||
- get the source location for the current debuggee execution point | ||
- step into the next source line, descending into function calls | ||
- step over the next source line | ||
- get the current value of a given identifier (descending into struct members) | ||
- set the current value of a given identifier (descending into struct members) | ||
- get the type of a given identifier (descending into struct members) | ||
- get the current call stack as a list of source locations | ||
- return a given value from the current function | ||
|
||
(TODO: specify parameters and results for the above operations; also describe | ||
custom types like "source location") | ||
|
||
## Debugger -> UI Notifications | ||
|
||
- a step into/over has completed | ||
- a breakpoint was hit | ||
- an uncaught exception was thrown | ||
- `abort()` was called | ||
- `exit()` was called | ||
|
||
(TODO: specify parameters and results) | ||
|
||
## About Debug Info and Source Files | ||
|
||
The debugger will need to access the debug info and source files for the current | ||
debuggee. The debuggee can specify URLs for these items. Their format is not | ||
specified -- it can be anything that the debugger knows how to interpret. | ||
|
||
## Debugger -> Debuggee Protocol Operations | ||
|
||
- interrupt execution | ||
- set a breakpoint at a given byte offset | ||
- get the current call stack | ||
- execute the current wasm instruction and move on to the next one | ||
- get the value of a wasm memory location | ||
- set the value of a wasm memory location | ||
|
||
(TODO: specify parameters and results) | ||
|
||
## Debuggee -> Debugger Notifications | ||
|
||
- an uncaught exception was thrown | ||
|
||
(TODO: specify parameters and results) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a bit redundant, given that we're in the design repo ;-)