Delve exposes a DAP API interface.
This interface is served over a streaming TCP socket using dlv
server in one of the two headless modes:
dlv dap
- starts a single-use DAP-only server that waits for a client to specify launch/attach configuration for starting the debug session.dlv --headless <command> <debugee>
- starts a general server, enters a debug session for the specified debuggee and waits for a JSON-RPC or a DAP client to begin interactive debugging. Can be used in multi-client mode with the following options:--accept-multiclient
- use to support connections from multiple clients--continue
- use to resume debuggee execution as soon as server session starts
The primary user of this mode is VS Code Go. Please see its detailed debugging documentation for additional information.
DAP is a general debugging protocol supported by many tools and programming languages. We tailored it to Go specifics, such as mapping threads request to communicate goroutines and exceptionInfo request to support panics and fatal errors.
See dap.Server.handleRequest and capabilities set in dap.Server.onInitializeRequest for an up-to-date list of supported requests and options.
In addition to the general DAP spec, the server supports the following implementation-specific configuration options for starting the debug session:
Not all of the configurations are supported by each of the two available DAP servers:
request | "mode": | `dlv dap` | `dlv --headless` |
---|---|---|---|
launch | "debug" "test" "exec" ... | supported | NOT supported |
attach | "local" | supported | NOT supported |
attach | "remote" | NOT supported | supported |
When used with dlv dap
or dlv --headless --accept-multiclient=false
(default), the DAP server will shut itself down at the end of the debug session, when the client sends a disconnect request. If the debuggee was launched, it will be taken down as well. If the debugee was attached to, terminateDebuggee
option will be respected.
When the program terminates, we send a terminated event, which is expected to trigger a disconnect request from the client for a session and a server shutdown. The restart request is not yet supported.
The server also shuts down in case of a client connection error or SIGTERM signal, taking down a launched process, but letting an attached process continue.
Pressing Ctrl-C on the terminal where a headless server is running sends SIGINT to the debuggee, foregrounded in headless mode to support debugging interactive programs.
When used with dlv --headless --accept-multiclient=true
, the DAP server will honor the multi-client mode when a client disconnects) or client connection fails. The server will remain running and ready for a new client connection, and the debuggee will remain in whatever state it was at the time of disconnect - running or halted. Once suspendDebuggee
option is supported by frontends like VS Code (vscode/issues/134412), we will update the server to offer this as a way to specify debuggee state on disconnect.
The client may request full shutdown of the server and the debuggee with terminateDebuggee
option.
The server shuts down in response to a SIGTERM signal, taking down a launched process, but letting an attached process continue.
Pressing Ctrl-C on the terminal where a headless server is running sends SIGINT to the debuggee, foregrounded in headless mode to support debugging interactive programs.
The debugger always logs one of the following on start-up to stdout:
dlv dap
:DAP server listening at: <host>:<port>
dlv --headless
:API server listening at: <host>:<port>
This can be used to confirm that server start-up succeeded.
The server uses output events to communicate errors and select status messages to the client. For example:
Step interrupted by a breakpoint. Use 'Continue' to resume the original step command.
invalid command: Unable to step while the previous step is interrupted by a breakpoint.
Use 'Continue' to resume the original step command.
Detaching and terminating target process
More detailed logging can be enabled with --log --log-output=dap
as part of the dlv
command.
It will record the server-side DAP message traffic. For example,
2022-01-04T00:27:57-08:00 debug layer=dap [<- from client]{"seq":1,"type":"request","command":"initialize","arguments":{"clientID":"vscode","clientName":"Visual Studio Code","adapterID":"go","locale":"en-us","linesStartAt1":true,"columnsStartAt1":true,"pathFormat":"path","supportsVariableType":true,"supportsVariablePaging":true,"supportsRunInTerminalRequest":true,"supportsMemoryReferences":true,"supportsProgressReporting":true,"supportsInvalidatedEvent":true}}
2022-01-04T00:27:57-08:00 debug layer=dap [-> to client]{"seq":0,"type":"response","request_seq":1,"success":true,"command":"initialize","body":{"supportsConfigurationDoneRequest":true,"supportsFunctionBreakpoints":true,"supportsConditionalBreakpoints":true,"supportsEvaluateForHovers":true,"supportsSetVariable":true,"supportsExceptionInfoRequest":true,"supportTerminateDebuggee":true,"supportsDelayedStackTraceLoading":true,"supportsLogPoints":true,"supportsDisassembleRequest":true,"supportsClipboardContext":true,"supportsSteppingGranularity":true,"supportsInstructionBreakpoints":true}}
2022-01-04T00:27:57-08:00 debug layer=dap [<- from client]{"seq":2,"type":"request","command":"launch","arguments":{"name":"Launch file","type":"go","request":"launch","mode":"debug","program":"./temp.go","hideSystemGoroutines":true,"__buildDir":"/Users/polina/go/src","__sessionId":"2ad0f0c1-a1fd-4fff-9fff-b8bc9a933fe5"}}
2022-01-04T00:27:57-08:00 debug layer=dap parsed launch config: {
"mode": "debug",
"program": "./temp.go",
"backend": "default",
"stackTraceDepth": 50,
"hideSystemGoroutines": true
}
...
This logging is written to stderr and is not forwarded via output events.
Debuggee's stdout and stderr are written to stdout and stderr respectfully and are not forwarded via output events.
The initial DAP support was released in v1.6.1 with many additional improvements in subsequent versions. The remote attach support was added in v1.7.3.
The DAP API changes are backward-compatible as all new features are opt-in only. To update to a new DAP version and import a new DAP feature into delve, one must first update the go-dap dependency.