2021-08-26 12:42:58 +00:00
|
|
|
package dap
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Launch debug sessions support the following modes:
|
2022-06-17 17:08:11 +00:00
|
|
|
//
|
|
|
|
// -- [DEFAULT] "debug" - builds and launches debugger for specified program (similar to 'dlv debug')
|
|
|
|
//
|
|
|
|
// Required args: program
|
|
|
|
// Optional args with default: output, cwd, noDebug
|
|
|
|
// Optional args: buildFlags, args
|
|
|
|
//
|
|
|
|
// -- "test" - builds and launches debugger for specified test (similar to 'dlv test')
|
|
|
|
//
|
|
|
|
// same args as above
|
|
|
|
//
|
|
|
|
// -- "exec" - launches debugger for precompiled binary (similar to 'dlv exec')
|
|
|
|
//
|
|
|
|
// Required args: program
|
|
|
|
// Optional args with default: cwd, noDebug
|
|
|
|
// Optional args: args
|
|
|
|
//
|
|
|
|
// -- "replay" - replays a trace generated by mozilla rr. Mozilla rr must be installed.
|
|
|
|
//
|
|
|
|
// Required args: traceDirPath
|
|
|
|
// Optional args: args
|
|
|
|
//
|
|
|
|
// -- "core" - examines a core dump (only supports linux and windows core dumps).
|
|
|
|
//
|
|
|
|
// Required args: program, coreFilePath
|
|
|
|
// Optional args: args
|
2021-08-26 12:42:58 +00:00
|
|
|
//
|
|
|
|
// TODO(hyangah): change this to 'validateLaunchMode' that checks
|
|
|
|
// all the required/optional fields mentioned above.
|
|
|
|
func isValidLaunchMode(mode string) bool {
|
|
|
|
switch mode {
|
|
|
|
case "exec", "debug", "test", "replay", "core":
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
// Default values for Launch/Attach configs.
|
|
|
|
// Used to initialize configuration variables before decoding
|
|
|
|
// arguments in launch/attach requests.
|
|
|
|
var (
|
|
|
|
defaultLaunchAttachCommonConfig = LaunchAttachCommonConfig{
|
|
|
|
Backend: "default",
|
|
|
|
StackTraceDepth: 50,
|
|
|
|
}
|
|
|
|
defaultLaunchConfig = LaunchConfig{
|
|
|
|
Mode: "debug",
|
|
|
|
LaunchAttachCommonConfig: defaultLaunchAttachCommonConfig,
|
|
|
|
}
|
|
|
|
defaultAttachConfig = AttachConfig{
|
|
|
|
Mode: "local",
|
|
|
|
LaunchAttachCommonConfig: defaultLaunchAttachCommonConfig,
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2021-10-07 09:28:15 +00:00
|
|
|
// LaunchConfig is the collection of launch request attributes recognized by DAP implementation.
|
2021-08-26 12:42:58 +00:00
|
|
|
type LaunchConfig struct {
|
|
|
|
// Acceptable values are:
|
|
|
|
// "debug": compiles your program with optimizations disabled, starts and attaches to it.
|
|
|
|
// "test": compiles your unit test program with optimizations disabled, starts and attaches to it.
|
|
|
|
// "exec": executes a precompiled binary and begins a debug session.
|
|
|
|
// "replay": replays an rr trace.
|
|
|
|
// "core": examines a core dump.
|
|
|
|
//
|
|
|
|
// Default is "debug".
|
|
|
|
Mode string `json:"mode,omitempty"`
|
|
|
|
|
|
|
|
// Path to the program folder (or any go file within that folder)
|
|
|
|
// when in `debug` or `test` mode, and to the pre-built binary file
|
|
|
|
// to debug in `exec` mode.
|
|
|
|
// If it is not an absolute path, it will be interpreted as a path
|
2021-10-05 11:40:17 +00:00
|
|
|
// relative to Delve's working directory.
|
|
|
|
// Required when mode is `debug`, `test`, `exec`, and `core`.
|
2021-08-26 12:42:58 +00:00
|
|
|
Program string `json:"program,omitempty"`
|
|
|
|
|
|
|
|
// Command line arguments passed to the debugged program.
|
2021-10-05 11:40:17 +00:00
|
|
|
// Relative paths used in Args will be interpreted as paths relative
|
|
|
|
// to `cwd`.
|
2021-08-26 12:42:58 +00:00
|
|
|
Args []string `json:"args,omitempty"`
|
|
|
|
|
2021-10-05 11:40:17 +00:00
|
|
|
// Working directory of the program being debugged.
|
|
|
|
// If a relative path is provided, it will be interpreted as
|
2021-10-07 09:28:15 +00:00
|
|
|
// a relative path to Delve's working directory. This is
|
|
|
|
// similar to `dlv --wd` flag.
|
2021-08-26 12:42:58 +00:00
|
|
|
//
|
2021-10-07 09:28:15 +00:00
|
|
|
// If not specified or empty, Delve's working directory is
|
|
|
|
// used by default. But for `test` mode, Delve tries to find
|
2021-10-05 11:40:17 +00:00
|
|
|
// the test's package source directory and run tests from there.
|
|
|
|
// This matches the behavior of `dlv test` and `go test`.
|
2021-08-26 12:42:58 +00:00
|
|
|
Cwd string `json:"cwd,omitempty"`
|
|
|
|
|
|
|
|
// Build flags, to be passed to the Go compiler.
|
2021-10-05 11:40:17 +00:00
|
|
|
// Relative paths used in BuildFlags will be interpreted as paths
|
|
|
|
// relative to Delve's current working directory.
|
|
|
|
//
|
2023-09-19 16:32:15 +00:00
|
|
|
// It should be a string like `dlv --build-flags`, or
|
|
|
|
// an array of strings that is augmented when invoking the go build or
|
|
|
|
// test command through os/exec.Command API.
|
2023-11-06 13:55:44 +00:00
|
|
|
// For example, both forms are acceptable.
|
2023-09-19 16:32:15 +00:00
|
|
|
// "buildFlags": "-tags=integration -ldflags='-X main.Hello=World'"
|
|
|
|
// or
|
|
|
|
// "buildFlags": ["-tags=integration", "-ldflags=-X main.Hello=World"]
|
|
|
|
// Using other types is an error.
|
|
|
|
BuildFlags BuildFlags `json:"buildFlags,omitempty"`
|
2021-08-26 12:42:58 +00:00
|
|
|
|
2023-04-27 20:39:33 +00:00
|
|
|
// Output path for the binary of the debuggee.
|
2021-08-26 12:42:58 +00:00
|
|
|
// Relative path is interpreted as the path relative to
|
2021-10-07 09:28:15 +00:00
|
|
|
// the Delve's current working directory.
|
2021-08-26 12:42:58 +00:00
|
|
|
// This is deleted after the debug session ends.
|
|
|
|
Output string `json:"output,omitempty"`
|
|
|
|
|
|
|
|
// NoDebug is used to run the program without debugging.
|
|
|
|
NoDebug bool `json:"noDebug,omitempty"`
|
|
|
|
|
|
|
|
// TraceDirPath is the trace directory path for replay mode.
|
2021-10-05 11:40:17 +00:00
|
|
|
// Relative path is interpreted as a path relative to Delve's
|
|
|
|
// current working directory.
|
2021-08-26 12:42:58 +00:00
|
|
|
// This is required for "replay" mode but unused in other modes.
|
|
|
|
TraceDirPath string `json:"traceDirPath,omitempty"`
|
|
|
|
|
|
|
|
// CoreFilePath is the core file path for core mode.
|
2021-10-05 11:40:17 +00:00
|
|
|
//
|
2021-08-26 12:42:58 +00:00
|
|
|
// This is required for "core" mode but unused in other modes.
|
|
|
|
CoreFilePath string `json:"coreFilePath,omitempty"`
|
|
|
|
|
2021-10-07 09:28:15 +00:00
|
|
|
// DlvCwd is the new working directory for Delve server.
|
|
|
|
// If specified, the server will change its working
|
2021-10-05 11:40:17 +00:00
|
|
|
// directory to the specified directory using os.Chdir.
|
2021-10-07 09:28:15 +00:00
|
|
|
// Any other launch attributes with relative paths interpreted
|
|
|
|
// using Delve's working directory will use this new directory.
|
|
|
|
// When Delve needs to build the program (in debug/test modes),
|
|
|
|
// it will run the go command from this directory as well.
|
2021-10-05 11:40:17 +00:00
|
|
|
//
|
2021-10-07 09:28:15 +00:00
|
|
|
// If a relative path is provided as DlvCwd, it will be
|
2021-10-05 11:40:17 +00:00
|
|
|
// interpreted as a path relative to Delve's current working
|
|
|
|
// directory.
|
2021-10-07 09:28:15 +00:00
|
|
|
DlvCwd string `json:"dlvCwd,omitempty"`
|
2021-10-05 11:40:17 +00:00
|
|
|
|
2022-01-06 17:01:09 +00:00
|
|
|
// Env specifies optional environment variables for Delve server
|
|
|
|
// in addition to the environment variables Delve initially
|
|
|
|
// started with.
|
|
|
|
// Variables with 'nil' values can be used to unset the named
|
|
|
|
// environment variables.
|
|
|
|
// Values are interpreted verbatim. Variable substitution or
|
|
|
|
// reference to other environment variables is not supported.
|
|
|
|
Env map[string]*string `json:"env,omitempty"`
|
|
|
|
|
2023-07-05 15:39:01 +00:00
|
|
|
// The output mode specifies how to handle the program's output.
|
|
|
|
OutputMode string `json:"outputMode,omitempty"`
|
|
|
|
|
2021-08-26 12:42:58 +00:00
|
|
|
LaunchAttachCommonConfig
|
|
|
|
}
|
|
|
|
|
|
|
|
// LaunchAttachCommonConfig is the attributes common in both launch/attach requests.
|
|
|
|
type LaunchAttachCommonConfig struct {
|
|
|
|
// Automatically stop program after launch or attach.
|
|
|
|
StopOnEntry bool `json:"stopOnEntry,omitempty"`
|
|
|
|
|
2021-10-07 09:28:15 +00:00
|
|
|
// Backend used for debugging. See `dlv backend` for allowed values.
|
2021-08-26 12:42:58 +00:00
|
|
|
// Default is "default".
|
|
|
|
Backend string `json:"backend,omitempty"`
|
|
|
|
|
2021-10-07 09:28:15 +00:00
|
|
|
// Maximum depth of stack trace to return.
|
2021-08-26 12:42:58 +00:00
|
|
|
// Default is 50.
|
|
|
|
StackTraceDepth int `json:"stackTraceDepth,omitempty"`
|
|
|
|
|
|
|
|
// Boolean value to indicate whether global package variables
|
|
|
|
// should be shown in the variables pane or not.
|
|
|
|
ShowGlobalVariables bool `json:"showGlobalVariables,omitempty"`
|
|
|
|
|
2021-10-15 11:57:50 +00:00
|
|
|
// Boolean value to indicate whether registers should be shown
|
|
|
|
// in the variables pane or not.
|
|
|
|
ShowRegisters bool `json:"showRegisters,omitempty"`
|
|
|
|
|
2021-10-18 20:13:12 +00:00
|
|
|
// Boolean value to indicate whether system goroutines
|
2021-12-07 17:23:55 +00:00
|
|
|
// should be hidden from the call stack view.
|
2021-10-18 20:13:12 +00:00
|
|
|
HideSystemGoroutines bool `json:"hideSystemGoroutines,omitempty"`
|
|
|
|
|
2021-12-07 17:23:55 +00:00
|
|
|
// String value to indicate which system goroutines should be
|
|
|
|
// shown in the call stack view. See filtering documentation:
|
|
|
|
// https://github.com/go-delve/delve/blob/master/Documentation/cli/README.md#goroutines
|
|
|
|
GoroutineFilters string `json:"goroutineFilters,omitempty"`
|
|
|
|
|
2023-12-04 14:44:10 +00:00
|
|
|
// Array of string values indicating the keys of pprof labels to show as a
|
|
|
|
// goroutine name in the threads view. If the array has one element, only
|
|
|
|
// that label's value will be shown; otherwise, each of the labels will be
|
|
|
|
// shown as "key:value". To show all labels, specify the single element "*".
|
|
|
|
ShowPprofLabels []string `json:"showPprofLabels,omitempty"`
|
|
|
|
|
2021-08-26 12:42:58 +00:00
|
|
|
// An array of mappings from a local path (client) to the remote path (debugger).
|
|
|
|
// This setting is useful when working in a file system with symbolic links,
|
|
|
|
// running remote debugging, or debugging an executable compiled externally.
|
|
|
|
// The debug adapter will replace the local path with the remote path in all of the calls.
|
*: misc improvements to config command and substitute-path rules (#3335)
A series of interconnected changes to both the terminal command
'config', DAP command 'dlv config', quality of life improvements to how
substitute-path works, and better documentation.
- Let 'config substitute-path' show the current substitute path rules
- Add a -clear command to 'config substitute-path'
- Support 'config-debug-info-directories'
- rewrite SubstitutePath to be platform independent (see below)
- document path substitution more
Regarding the rewrite of SubstitutePath: the previous version used
runtime.GOOS and filepath.IsAbs to determine which filepath separator to use
and if matching should be case insensitive. This is wrong in all situations
where the client and server run on different OSes, when examining core files
and when cross-compilation is involved.
The new version of SubstitutePath checks the rules and the input path to
determine if Windows is involved in the process, if it looks like it is it
switches to case-insensitive matching. It uses a lax version of
filepath.IsAbs to determine if a path is absolute and tries to avoid having
to select a path separator as much as possible
Fixes #2891, #2890, #2889, #3179, #3332, #3343
2023-05-02 19:23:59 +00:00
|
|
|
// See also Documentation/cli/substitutepath.md.
|
2021-08-26 12:42:58 +00:00
|
|
|
SubstitutePath []SubstitutePath `json:"substitutePath,omitempty"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// SubstitutePath defines a mapping from a local path to the remote path.
|
2022-08-14 14:01:39 +00:00
|
|
|
// Both 'from' and 'to' must be specified and non-null.
|
|
|
|
// Empty values can be used to add or remove absolute path prefixes when mapping.
|
2023-04-27 20:39:33 +00:00
|
|
|
// For example, mapping with empty 'to' can be used to work with binaries with trimmed paths.
|
2021-08-26 12:42:58 +00:00
|
|
|
type SubstitutePath struct {
|
|
|
|
// The local path to be replaced when passing paths to the debugger.
|
|
|
|
From string `json:"from,omitempty"`
|
|
|
|
// The remote path to be replaced when passing paths back to the client.
|
|
|
|
To string `json:"to,omitempty"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *SubstitutePath) UnmarshalJSON(data []byte) error {
|
|
|
|
// use custom unmarshal to check if both from/to are set.
|
2022-08-14 14:01:39 +00:00
|
|
|
type tmpType struct {
|
|
|
|
From *string
|
|
|
|
To *string
|
|
|
|
}
|
2021-08-26 12:42:58 +00:00
|
|
|
var tmp tmpType
|
|
|
|
|
|
|
|
if err := json.Unmarshal(data, &tmp); err != nil {
|
|
|
|
if _, ok := err.(*json.UnmarshalTypeError); ok {
|
|
|
|
return fmt.Errorf(`cannot use %s as 'substitutePath' of type {"from":string, "to":string}`, data)
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
2022-08-14 14:01:39 +00:00
|
|
|
if tmp.From == nil || tmp.To == nil {
|
2021-08-26 12:42:58 +00:00
|
|
|
return errors.New("'substitutePath' requires both 'from' and 'to' entries")
|
|
|
|
}
|
2022-08-14 14:01:39 +00:00
|
|
|
*m = SubstitutePath{*tmp.From, *tmp.To}
|
2021-08-26 12:42:58 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-10-07 09:28:15 +00:00
|
|
|
// AttachConfig is the collection of attach request attributes recognized by DAP implementation.
|
2021-08-26 12:42:58 +00:00
|
|
|
type AttachConfig struct {
|
|
|
|
// Acceptable values are:
|
|
|
|
// "local": attaches to the local process with the given ProcessID.
|
2021-12-07 17:23:26 +00:00
|
|
|
// "remote": expects the debugger to already be running to "attach" to an in-progress debug session.
|
2021-08-26 12:42:58 +00:00
|
|
|
//
|
|
|
|
// Default is "local".
|
|
|
|
Mode string `json:"mode"`
|
|
|
|
|
|
|
|
// The numeric ID of the process to be debugged. Required and must not be 0.
|
|
|
|
ProcessID int `json:"processId,omitempty"`
|
|
|
|
|
|
|
|
LaunchAttachCommonConfig
|
|
|
|
}
|
|
|
|
|
2023-07-11 14:10:41 +00:00
|
|
|
// unmarshalLaunchAttachArgs wraps unmarshaling of launch/attach request's
|
2021-08-26 12:42:58 +00:00
|
|
|
// arguments attribute. Upon unmarshal failure, it returns an error massaged
|
|
|
|
// to be suitable for end-users.
|
|
|
|
func unmarshalLaunchAttachArgs(input json.RawMessage, config interface{}) error {
|
|
|
|
if err := json.Unmarshal(input, config); err != nil {
|
|
|
|
if uerr, ok := err.(*json.UnmarshalTypeError); ok {
|
|
|
|
// Format json.UnmarshalTypeError error string in our own way. E.g.,
|
|
|
|
// "json: cannot unmarshal number into Go struct field LaunchArgs.substitutePath of type dap.SubstitutePath"
|
|
|
|
// => "cannot unmarshal number into 'substitutePath' of type {from:string, to:string}"
|
|
|
|
// "json: cannot unmarshal number into Go struct field LaunchArgs.program of type string" (go1.16)
|
|
|
|
// => "cannot unmarshal number into 'program' of type string"
|
|
|
|
typ := uerr.Type.String()
|
|
|
|
if uerr.Field == "substitutePath" {
|
|
|
|
typ = `{"from":string, "to":string}`
|
|
|
|
}
|
|
|
|
return fmt.Errorf("cannot unmarshal %v into %q of type %v", uerr.Value, uerr.Field, typ)
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
2021-10-13 19:05:47 +00:00
|
|
|
|
|
|
|
func prettyPrint(config interface{}) string {
|
|
|
|
pretty, err := json.MarshalIndent(config, "", "\t")
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Sprintf("%#v", config)
|
|
|
|
}
|
|
|
|
return string(pretty)
|
|
|
|
}
|
2023-09-19 16:32:15 +00:00
|
|
|
|
|
|
|
// BuildFlags is either string or []string.
|
|
|
|
type BuildFlags struct {
|
|
|
|
value interface{}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *BuildFlags) UnmarshalJSON(b []byte) error {
|
|
|
|
if v := string(b); v == "" || v == "null" {
|
|
|
|
s.value = nil
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
var strs []string
|
|
|
|
if err := json.Unmarshal(b, &strs); err == nil {
|
|
|
|
s.value = strs
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
var str string
|
|
|
|
if err := json.Unmarshal(b, &str); err != nil {
|
|
|
|
s.value = nil
|
|
|
|
if uerr, ok := err.(*json.UnmarshalTypeError); ok {
|
|
|
|
return fmt.Errorf(`cannot unmarshal %v into "buildFlags" of type []string or string`, uerr.Value)
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
s.value = str
|
|
|
|
return nil
|
|
|
|
}
|