github.com/cnboonhan/delve@v0.0.0-20230908061759-363f2388c2fb/service/dap/types.go (about) 1 package dap 2 3 import ( 4 "encoding/json" 5 "errors" 6 "fmt" 7 ) 8 9 // Launch debug sessions support the following modes: 10 // 11 // -- [DEFAULT] "debug" - builds and launches debugger for specified program (similar to 'dlv debug') 12 // 13 // Required args: program 14 // Optional args with default: output, cwd, noDebug 15 // Optional args: buildFlags, args 16 // 17 // -- "test" - builds and launches debugger for specified test (similar to 'dlv test') 18 // 19 // same args as above 20 // 21 // -- "exec" - launches debugger for precompiled binary (similar to 'dlv exec') 22 // 23 // Required args: program 24 // Optional args with default: cwd, noDebug 25 // Optional args: args 26 // 27 // -- "replay" - replays a trace generated by mozilla rr. Mozilla rr must be installed. 28 // 29 // Required args: traceDirPath 30 // Optional args: args 31 // 32 // -- "core" - examines a core dump (only supports linux and windows core dumps). 33 // 34 // Required args: program, coreFilePath 35 // Optional args: args 36 // 37 // TODO(hyangah): change this to 'validateLaunchMode' that checks 38 // all the required/optional fields mentioned above. 39 func isValidLaunchMode(mode string) bool { 40 switch mode { 41 case "exec", "debug", "test", "replay", "core": 42 return true 43 } 44 return false 45 } 46 47 // Default values for Launch/Attach configs. 48 // Used to initialize configuration variables before decoding 49 // arguments in launch/attach requests. 50 var ( 51 defaultLaunchAttachCommonConfig = LaunchAttachCommonConfig{ 52 Backend: "default", 53 StackTraceDepth: 50, 54 } 55 defaultLaunchConfig = LaunchConfig{ 56 Mode: "debug", 57 LaunchAttachCommonConfig: defaultLaunchAttachCommonConfig, 58 } 59 defaultAttachConfig = AttachConfig{ 60 Mode: "local", 61 LaunchAttachCommonConfig: defaultLaunchAttachCommonConfig, 62 } 63 ) 64 65 // LaunchConfig is the collection of launch request attributes recognized by DAP implementation. 66 type LaunchConfig struct { 67 // Acceptable values are: 68 // "debug": compiles your program with optimizations disabled, starts and attaches to it. 69 // "test": compiles your unit test program with optimizations disabled, starts and attaches to it. 70 // "exec": executes a precompiled binary and begins a debug session. 71 // "replay": replays an rr trace. 72 // "core": examines a core dump. 73 // 74 // Default is "debug". 75 Mode string `json:"mode,omitempty"` 76 77 // Path to the program folder (or any go file within that folder) 78 // when in `debug` or `test` mode, and to the pre-built binary file 79 // to debug in `exec` mode. 80 // If it is not an absolute path, it will be interpreted as a path 81 // relative to Delve's working directory. 82 // Required when mode is `debug`, `test`, `exec`, and `core`. 83 Program string `json:"program,omitempty"` 84 85 // Command line arguments passed to the debugged program. 86 // Relative paths used in Args will be interpreted as paths relative 87 // to `cwd`. 88 Args []string `json:"args,omitempty"` 89 90 // Working directory of the program being debugged. 91 // If a relative path is provided, it will be interpreted as 92 // a relative path to Delve's working directory. This is 93 // similar to `dlv --wd` flag. 94 // 95 // If not specified or empty, Delve's working directory is 96 // used by default. But for `test` mode, Delve tries to find 97 // the test's package source directory and run tests from there. 98 // This matches the behavior of `dlv test` and `go test`. 99 Cwd string `json:"cwd,omitempty"` 100 101 // Build flags, to be passed to the Go compiler. 102 // Relative paths used in BuildFlags will be interpreted as paths 103 // relative to Delve's current working directory. 104 // 105 // It is like `dlv --build-flags`. For example, 106 // "buildFlags": "-tags=integration -mod=vendor -cover -v" 107 BuildFlags string `json:"buildFlags,omitempty"` 108 109 // Output path for the binary of the debuggee. 110 // Relative path is interpreted as the path relative to 111 // the Delve's current working directory. 112 // This is deleted after the debug session ends. 113 Output string `json:"output,omitempty"` 114 115 // NoDebug is used to run the program without debugging. 116 NoDebug bool `json:"noDebug,omitempty"` 117 118 // TraceDirPath is the trace directory path for replay mode. 119 // Relative path is interpreted as a path relative to Delve's 120 // current working directory. 121 // This is required for "replay" mode but unused in other modes. 122 TraceDirPath string `json:"traceDirPath,omitempty"` 123 124 // CoreFilePath is the core file path for core mode. 125 // 126 // This is required for "core" mode but unused in other modes. 127 CoreFilePath string `json:"coreFilePath,omitempty"` 128 129 // DlvCwd is the new working directory for Delve server. 130 // If specified, the server will change its working 131 // directory to the specified directory using os.Chdir. 132 // Any other launch attributes with relative paths interpreted 133 // using Delve's working directory will use this new directory. 134 // When Delve needs to build the program (in debug/test modes), 135 // it will run the go command from this directory as well. 136 // 137 // If a relative path is provided as DlvCwd, it will be 138 // interpreted as a path relative to Delve's current working 139 // directory. 140 DlvCwd string `json:"dlvCwd,omitempty"` 141 142 // Env specifies optional environment variables for Delve server 143 // in addition to the environment variables Delve initially 144 // started with. 145 // Variables with 'nil' values can be used to unset the named 146 // environment variables. 147 // Values are interpreted verbatim. Variable substitution or 148 // reference to other environment variables is not supported. 149 Env map[string]*string `json:"env,omitempty"` 150 151 // The output mode specifies how to handle the program's output. 152 OutputMode string `json:"outputMode,omitempty"` 153 154 LaunchAttachCommonConfig 155 } 156 157 // LaunchAttachCommonConfig is the attributes common in both launch/attach requests. 158 type LaunchAttachCommonConfig struct { 159 // Automatically stop program after launch or attach. 160 StopOnEntry bool `json:"stopOnEntry,omitempty"` 161 162 // Backend used for debugging. See `dlv backend` for allowed values. 163 // Default is "default". 164 Backend string `json:"backend,omitempty"` 165 166 // Maximum depth of stack trace to return. 167 // Default is 50. 168 StackTraceDepth int `json:"stackTraceDepth,omitempty"` 169 170 // Boolean value to indicate whether global package variables 171 // should be shown in the variables pane or not. 172 ShowGlobalVariables bool `json:"showGlobalVariables,omitempty"` 173 174 // Boolean value to indicate whether registers should be shown 175 // in the variables pane or not. 176 ShowRegisters bool `json:"showRegisters,omitempty"` 177 178 // Boolean value to indicate whether system goroutines 179 // should be hidden from the call stack view. 180 HideSystemGoroutines bool `json:"hideSystemGoroutines,omitempty"` 181 182 // String value to indicate which system goroutines should be 183 // shown in the call stack view. See filtering documentation: 184 // https://github.com/go-delve/delve/blob/master/Documentation/cli/README.md#goroutines 185 GoroutineFilters string `json:"goroutineFilters,omitempty"` 186 187 // An array of mappings from a local path (client) to the remote path (debugger). 188 // This setting is useful when working in a file system with symbolic links, 189 // running remote debugging, or debugging an executable compiled externally. 190 // The debug adapter will replace the local path with the remote path in all of the calls. 191 // See also Documentation/cli/substitutepath.md. 192 SubstitutePath []SubstitutePath `json:"substitutePath,omitempty"` 193 } 194 195 // SubstitutePath defines a mapping from a local path to the remote path. 196 // Both 'from' and 'to' must be specified and non-null. 197 // Empty values can be used to add or remove absolute path prefixes when mapping. 198 // For example, mapping with empty 'to' can be used to work with binaries with trimmed paths. 199 type SubstitutePath struct { 200 // The local path to be replaced when passing paths to the debugger. 201 From string `json:"from,omitempty"` 202 // The remote path to be replaced when passing paths back to the client. 203 To string `json:"to,omitempty"` 204 } 205 206 func (m *SubstitutePath) UnmarshalJSON(data []byte) error { 207 // use custom unmarshal to check if both from/to are set. 208 type tmpType struct { 209 From *string 210 To *string 211 } 212 var tmp tmpType 213 214 if err := json.Unmarshal(data, &tmp); err != nil { 215 if _, ok := err.(*json.UnmarshalTypeError); ok { 216 return fmt.Errorf(`cannot use %s as 'substitutePath' of type {"from":string, "to":string}`, data) 217 } 218 return err 219 } 220 if tmp.From == nil || tmp.To == nil { 221 return errors.New("'substitutePath' requires both 'from' and 'to' entries") 222 } 223 *m = SubstitutePath{*tmp.From, *tmp.To} 224 return nil 225 } 226 227 // AttachConfig is the collection of attach request attributes recognized by DAP implementation. 228 type AttachConfig struct { 229 // Acceptable values are: 230 // "local": attaches to the local process with the given ProcessID. 231 // "remote": expects the debugger to already be running to "attach" to an in-progress debug session. 232 // 233 // Default is "local". 234 Mode string `json:"mode"` 235 236 // The numeric ID of the process to be debugged. Required and must not be 0. 237 ProcessID int `json:"processId,omitempty"` 238 239 LaunchAttachCommonConfig 240 } 241 242 // unmarshalLaunchAttachArgs wraps unmarshaling of launch/attach request's 243 // arguments attribute. Upon unmarshal failure, it returns an error massaged 244 // to be suitable for end-users. 245 func unmarshalLaunchAttachArgs(input json.RawMessage, config interface{}) error { 246 if err := json.Unmarshal(input, config); err != nil { 247 if uerr, ok := err.(*json.UnmarshalTypeError); ok { 248 // Format json.UnmarshalTypeError error string in our own way. E.g., 249 // "json: cannot unmarshal number into Go struct field LaunchArgs.substitutePath of type dap.SubstitutePath" 250 // => "cannot unmarshal number into 'substitutePath' of type {from:string, to:string}" 251 // "json: cannot unmarshal number into Go struct field LaunchArgs.program of type string" (go1.16) 252 // => "cannot unmarshal number into 'program' of type string" 253 typ := uerr.Type.String() 254 if uerr.Field == "substitutePath" { 255 typ = `{"from":string, "to":string}` 256 } 257 return fmt.Errorf("cannot unmarshal %v into %q of type %v", uerr.Value, uerr.Field, typ) 258 } 259 return err 260 } 261 return nil 262 } 263 264 func prettyPrint(config interface{}) string { 265 pretty, err := json.MarshalIndent(config, "", "\t") 266 if err != nil { 267 return fmt.Sprintf("%#v", config) 268 } 269 return string(pretty) 270 }