//===-- lldb-dap.cpp -----------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "DAP.h" #include "Watchpoint.h" #include "lldb/API/SBDeclaration.h" #include "lldb/API/SBMemoryRegionInfo.h" #include "llvm/Support/Base64.h" #include <cassert> #include <climits> #include <cstdarg> #include <cstdio> #include <cstdlib> #include <cstring> #include <optional> #include <sys/stat.h> #include <sys/types.h> #if defined(_WIN32) // We need to #define NOMINMAX in order to skip `min()` and `max()` macro // definitions that conflict with other system headers. // We also need to #undef GetObject (which is defined to GetObjectW) because // the JSON code we use also has methods named `GetObject()` and we conflict // against these. #define NOMINMAX #include <windows.h> #undef GetObject #include <io.h> #else #include <netinet/in.h> #include <sys/socket.h> #include <unistd.h> #endif #if defined(__linux__) #include <sys/prctl.h> #endif #include <algorithm> #include <array> #include <chrono> #include <fstream> #include <map> #include <memory> #include <mutex> #include <set> #include <sstream> #include <thread> #include <vector> #include "lldb/API/SBStream.h" #include "lldb/Host/Config.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" #include "llvm/Option/OptTable.h" #include "llvm/Option/Option.h" #include "llvm/Support/Errno.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/InitLLVM.h" #include "llvm/Support/Path.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/raw_ostream.h" #include "JSONUtils.h" #include "LLDBUtils.h" #include "OutputRedirector.h" #if defined(_WIN32) #ifndef PATH_MAX #define PATH_MAX … #endif typedef int socklen_t; #endif usingnamespacelldb_dap; namespace { usingnamespacellvm::opt; enum ID { … }; #define PREFIX … #include "Options.inc" #undef PREFIX static constexpr llvm::opt::OptTable::Info InfoTable[] = …; class LLDBDAPOptTable : public llvm::opt::GenericOptTable { … }; RequestCallback; enum LaunchMethod { … }; /// Page size used for reporting addtional frames in the 'stackTrace' request. constexpr int StackPageSize = …; /// Prints a welcome message on the editor if the preprocessor variable /// LLDB_DAP_WELCOME_MESSAGE is defined. static void PrintWelcomeMessage() { … } lldb::SBValueList *GetTopLevelScope(int64_t variablesReference) { … } SOCKET AcceptConnection(int portno) { … } std::vector<const char *> MakeArgv(const llvm::ArrayRef<std::string> &strs) { … } // Send a "exited" event to indicate the process has exited. void SendProcessExitedEvent(lldb::SBProcess &process) { … } void SendThreadExitedEvent(lldb::tid_t tid) { … } // Send a "continued" event to indicate the process is in the running state. void SendContinuedEvent() { … } // Send a "terminated" event to indicate the process is done being // debugged. void SendTerminatedEvent() { … } // Send a thread stopped event for all threads as long as the process // is stopped. void SendThreadStoppedEvent() { … } // "ProcessEvent": { // "allOf": [ // { "$ref": "#/definitions/Event" }, // { // "type": "object", // "description": "Event message for 'process' event type. The event // indicates that the debugger has begun debugging a // new process. Either one that it has launched, or one // that it has attached to.", // "properties": { // "event": { // "type": "string", // "enum": [ "process" ] // }, // "body": { // "type": "object", // "properties": { // "name": { // "type": "string", // "description": "The logical name of the process. This is // usually the full path to process's executable // file. Example: /home/myproj/program.js." // }, // "systemProcessId": { // "type": "integer", // "description": "The system process id of the debugged process. // This property will be missing for non-system // processes." // }, // "isLocalProcess": { // "type": "boolean", // "description": "If true, the process is running on the same // computer as the debug adapter." // }, // "startMethod": { // "type": "string", // "enum": [ "launch", "attach", "attachForSuspendedLaunch" ], // "description": "Describes how the debug engine started // debugging this process.", // "enumDescriptions": [ // "Process was launched under the debugger.", // "Debugger attached to an existing process.", // "A project launcher component has launched a new process in // a suspended state and then asked the debugger to attach." // ] // } // }, // "required": [ "name" ] // } // }, // "required": [ "event", "body" ] // } // ] // } void SendProcessEvent(LaunchMethod launch_method) { … } // Grab any STDOUT and STDERR from the process and send it up to VS Code // via an "output" event to the "stdout" and "stderr" categories. void SendStdOutStdErr(lldb::SBProcess &process) { … } void ProgressEventThreadFunction() { … } // All events from the debugger, target, process, thread and frames are // received in this function that runs in its own thread. We are using a // "FILE *" to output packets back to VS Code and they have mutexes in them // them prevent multiple threads from writing simultaneously so no locking // is required. void EventThreadFunction() { … } lldb::SBValue FindVariable(uint64_t variablesReference, llvm::StringRef name) { … } // Both attach and launch take a either a sourcePath or sourceMap // argument (or neither), from which we need to set the target.source-map. void SetSourceMapFromArguments(const llvm::json::Object &arguments) { … } // Fill in the stack frames of the thread. // // Threads stacks may contain runtime specific extended backtraces, when // constructing a stack trace first report the full thread stack trace then // perform a breadth first traversal of any extended backtrace frames. // // For example: // // Thread (id=th0) stack=[s0, s1, s2, s3] // \ Extended backtrace "libdispatch" Thread (id=th1) stack=[s0, s1] // \ Extended backtrace "libdispatch" Thread (id=th2) stack=[s0, s1] // \ Extended backtrace "Application Specific Backtrace" Thread (id=th3) // stack=[s0, s1, s2] // // Which will flatten into: // // 0. th0->s0 // 1. th0->s1 // 2. th0->s2 // 3. th0->s3 // 4. label - Enqueued from th1, sf=-1, i=-4 // 5. th1->s0 // 6. th1->s1 // 7. label - Enqueued from th2 // 8. th2->s0 // 9. th2->s1 // 10. label - Application Specific Backtrace // 11. th3->s0 // 12. th3->s1 // 13. th3->s2 // // s=3,l=3 = [th0->s3, label1, th1->s0] bool FillStackFrames(lldb::SBThread &thread, llvm::json::Array &stack_frames, int64_t &offset, const int64_t start_frame, const int64_t levels) { … } // "AttachRequest": { // "allOf": [ { "$ref": "#/definitions/Request" }, { // "type": "object", // "description": "Attach request; value of command field is 'attach'.", // "properties": { // "command": { // "type": "string", // "enum": [ "attach" ] // }, // "arguments": { // "$ref": "#/definitions/AttachRequestArguments" // } // }, // "required": [ "command", "arguments" ] // }] // }, // "AttachRequestArguments": { // "type": "object", // "description": "Arguments for 'attach' request.\nThe attach request has no // standardized attributes." // }, // "AttachResponse": { // "allOf": [ { "$ref": "#/definitions/Response" }, { // "type": "object", // "description": "Response to 'attach' request. This is just an // acknowledgement, so no body field is required." // }] // } void request_attach(const llvm::json::Object &request) { … } // "ContinueRequest": { // "allOf": [ { "$ref": "#/definitions/Request" }, { // "type": "object", // "description": "Continue request; value of command field is 'continue'. // The request starts the debuggee to run again.", // "properties": { // "command": { // "type": "string", // "enum": [ "continue" ] // }, // "arguments": { // "$ref": "#/definitions/ContinueArguments" // } // }, // "required": [ "command", "arguments" ] // }] // }, // "ContinueArguments": { // "type": "object", // "description": "Arguments for 'continue' request.", // "properties": { // "threadId": { // "type": "integer", // "description": "Continue execution for the specified thread (if // possible). If the backend cannot continue on a single // thread but will continue on all threads, it should // set the allThreadsContinued attribute in the response // to true." // } // }, // "required": [ "threadId" ] // }, // "ContinueResponse": { // "allOf": [ { "$ref": "#/definitions/Response" }, { // "type": "object", // "description": "Response to 'continue' request.", // "properties": { // "body": { // "type": "object", // "properties": { // "allThreadsContinued": { // "type": "boolean", // "description": "If true, the continue request has ignored the // specified thread and continued all threads // instead. If this attribute is missing a value // of 'true' is assumed for backward // compatibility." // } // } // } // }, // "required": [ "body" ] // }] // } void request_continue(const llvm::json::Object &request) { … } // "ConfigurationDoneRequest": { // "allOf": [ { "$ref": "#/definitions/Request" }, { // "type": "object", // "description": "ConfigurationDone request; value of command field // is 'configurationDone'.\nThe client of the debug protocol must // send this request at the end of the sequence of configuration // requests (which was started by the InitializedEvent).", // "properties": { // "command": { // "type": "string", // "enum": [ "configurationDone" ] // }, // "arguments": { // "$ref": "#/definitions/ConfigurationDoneArguments" // } // }, // "required": [ "command" ] // }] // }, // "ConfigurationDoneArguments": { // "type": "object", // "description": "Arguments for 'configurationDone' request.\nThe // configurationDone request has no standardized attributes." // }, // "ConfigurationDoneResponse": { // "allOf": [ { "$ref": "#/definitions/Response" }, { // "type": "object", // "description": "Response to 'configurationDone' request. This is // just an acknowledgement, so no body field is required." // }] // }, void request_configurationDone(const llvm::json::Object &request) { … } // "DisconnectRequest": { // "allOf": [ { "$ref": "#/definitions/Request" }, { // "type": "object", // "description": "Disconnect request; value of command field is // 'disconnect'.", // "properties": { // "command": { // "type": "string", // "enum": [ "disconnect" ] // }, // "arguments": { // "$ref": "#/definitions/DisconnectArguments" // } // }, // "required": [ "command" ] // }] // }, // "DisconnectArguments": { // "type": "object", // "description": "Arguments for 'disconnect' request.", // "properties": { // "terminateDebuggee": { // "type": "boolean", // "description": "Indicates whether the debuggee should be terminated // when the debugger is disconnected. If unspecified, // the debug adapter is free to do whatever it thinks // is best. A client can only rely on this attribute // being properly honored if a debug adapter returns // true for the 'supportTerminateDebuggee' capability." // }, // "restart": { // "type": "boolean", // "description": "Indicates whether the debuggee should be restart // the process." // } // } // }, // "DisconnectResponse": { // "allOf": [ { "$ref": "#/definitions/Response" }, { // "type": "object", // "description": "Response to 'disconnect' request. This is just an // acknowledgement, so no body field is required." // }] // } void request_disconnect(const llvm::json::Object &request) { … } // "ExceptionInfoRequest": { // "allOf": [ { "$ref": "#/definitions/Request" }, { // "type": "object", // "description": "Retrieves the details of the exception that // caused this event to be raised. Clients should only call this request if // the corresponding capability `supportsExceptionInfoRequest` is true.", // "properties": { // "command": { // "type": "string", // "enum": [ "exceptionInfo" ] // }, // "arguments": { // "$ref": "#/definitions/ExceptionInfoArguments" // } // }, // "required": [ "command", "arguments" ] // }] // }, // "ExceptionInfoArguments": { // "type": "object", // "description": "Arguments for `exceptionInfo` request.", // "properties": { // "threadId": { // "type": "integer", // "description": "Thread for which exception information should be // retrieved." // } // }, // "required": [ "threadId" ] // }, // "ExceptionInfoResponse": { // "allOf": [ { "$ref": "#/definitions/Response" }, { // "type": "object", // "description": "Response to `exceptionInfo` request.", // "properties": { // "body": { // "type": "object", // "properties": { // "exceptionId": { // "type": "string", // "description": "ID of the exception that was thrown." // }, // "description": { // "type": "string", // "description": "Descriptive text for the exception." // }, // "breakMode": { // "$ref": "#/definitions/ExceptionBreakMode", // "description": "Mode that caused the exception notification to // be raised." // }, // "details": { // "$ref": "#/definitions/ExceptionDetails", // "description": "Detailed information about the exception." // } // }, // "required": [ "exceptionId", "breakMode" ] // } // }, // "required": [ "body" ] // }] // } // "ExceptionDetails": { // "type": "object", // "description": "Detailed information about an exception that has // occurred.", "properties": { // "message": { // "type": "string", // "description": "Message contained in the exception." // }, // "typeName": { // "type": "string", // "description": "Short type name of the exception object." // }, // "fullTypeName": { // "type": "string", // "description": "Fully-qualified type name of the exception object." // }, // "evaluateName": { // "type": "string", // "description": "An expression that can be evaluated in the current // scope to obtain the exception object." // }, // "stackTrace": { // "type": "string", // "description": "Stack trace at the time the exception was thrown." // }, // "innerException": { // "type": "array", // "items": { // "$ref": "#/definitions/ExceptionDetails" // }, // "description": "Details of the exception contained by this exception, // if any." // } // } // }, void request_exceptionInfo(const llvm::json::Object &request) { … } // "CompletionsRequest": { // "allOf": [ { "$ref": "#/definitions/Request" }, { // "type": "object", // "description": "Returns a list of possible completions for a given caret // position and text.\nThe CompletionsRequest may only be called if the // 'supportsCompletionsRequest' capability exists and is true.", // "properties": { // "command": { // "type": "string", // "enum": [ "completions" ] // }, // "arguments": { // "$ref": "#/definitions/CompletionsArguments" // } // }, // "required": [ "command", "arguments" ] // }] // }, // "CompletionsArguments": { // "type": "object", // "description": "Arguments for 'completions' request.", // "properties": { // "frameId": { // "type": "integer", // "description": "Returns completions in the scope of this stack frame. // If not specified, the completions are returned for the global scope." // }, // "text": { // "type": "string", // "description": "One or more source lines. Typically this is the text a // user has typed into the debug console before he asked for completion." // }, // "column": { // "type": "integer", // "description": "The character position for which to determine the // completion proposals." // }, // "line": { // "type": "integer", // "description": "An optional line for which to determine the completion // proposals. If missing the first line of the text is assumed." // } // }, // "required": [ "text", "column" ] // }, // "CompletionsResponse": { // "allOf": [ { "$ref": "#/definitions/Response" }, { // "type": "object", // "description": "Response to 'completions' request.", // "properties": { // "body": { // "type": "object", // "properties": { // "targets": { // "type": "array", // "items": { // "$ref": "#/definitions/CompletionItem" // }, // "description": "The possible completions for ." // } // }, // "required": [ "targets" ] // } // }, // "required": [ "body" ] // }] // }, // "CompletionItem": { // "type": "object", // "description": "CompletionItems are the suggestions returned from the // CompletionsRequest.", "properties": { // "label": { // "type": "string", // "description": "The label of this completion item. By default this is // also the text that is inserted when selecting this completion." // }, // "text": { // "type": "string", // "description": "If text is not falsy then it is inserted instead of the // label." // }, // "sortText": { // "type": "string", // "description": "A string that should be used when comparing this item // with other items. When `falsy` the label is used." // }, // "type": { // "$ref": "#/definitions/CompletionItemType", // "description": "The item's type. Typically the client uses this // information to render the item in the UI with an icon." // }, // "start": { // "type": "integer", // "description": "This value determines the location (in the // CompletionsRequest's 'text' attribute) where the completion text is // added.\nIf missing the text is added at the location specified by the // CompletionsRequest's 'column' attribute." // }, // "length": { // "type": "integer", // "description": "This value determines how many characters are // overwritten by the completion text.\nIf missing the value 0 is assumed // which results in the completion text being inserted." // } // }, // "required": [ "label" ] // }, // "CompletionItemType": { // "type": "string", // "description": "Some predefined types for the CompletionItem. Please note // that not all clients have specific icons for all of them.", "enum": [ // "method", "function", "constructor", "field", "variable", "class", // "interface", "module", "property", "unit", "value", "enum", "keyword", // "snippet", "text", "color", "file", "reference", "customcolor" ] // } void request_completions(const llvm::json::Object &request) { … } // "EvaluateRequest": { // "allOf": [ { "$ref": "#/definitions/Request" }, { // "type": "object", // "description": "Evaluate request; value of command field is 'evaluate'. // Evaluates the given expression in the context of the // top most stack frame. The expression has access to any // variables and arguments that are in scope.", // "properties": { // "command": { // "type": "string", // "enum": [ "evaluate" ] // }, // "arguments": { // "$ref": "#/definitions/EvaluateArguments" // } // }, // "required": [ "command", "arguments" ] // }] // }, // "EvaluateArguments": { // "type": "object", // "description": "Arguments for 'evaluate' request.", // "properties": { // "expression": { // "type": "string", // "description": "The expression to evaluate." // }, // "frameId": { // "type": "integer", // "description": "Evaluate the expression in the scope of this stack // frame. If not specified, the expression is evaluated // in the global scope." // }, // "context": { // "type": "string", // "_enum": [ "watch", "repl", "hover" ], // "enumDescriptions": [ // "evaluate is run in a watch.", // "evaluate is run from REPL console.", // "evaluate is run from a data hover." // ], // "description": "The context in which the evaluate request is run." // }, // "format": { // "$ref": "#/definitions/ValueFormat", // "description": "Specifies details on how to format the Evaluate // result." // } // }, // "required": [ "expression" ] // }, // "EvaluateResponse": { // "allOf": [ { "$ref": "#/definitions/Response" }, { // "type": "object", // "description": "Response to 'evaluate' request.", // "properties": { // "body": { // "type": "object", // "properties": { // "result": { // "type": "string", // "description": "The result of the evaluate request." // }, // "type": { // "type": "string", // "description": "The optional type of the evaluate result." // }, // "presentationHint": { // "$ref": "#/definitions/VariablePresentationHint", // "description": "Properties of a evaluate result that can be // used to determine how to render the result in // the UI." // }, // "variablesReference": { // "type": "number", // "description": "If variablesReference is > 0, the evaluate // result is structured and its children can be // retrieved by passing variablesReference to the // VariablesRequest." // }, // "namedVariables": { // "type": "number", // "description": "The number of named child variables. The // client can use this optional information to // present the variables in a paged UI and fetch // them in chunks." // }, // "indexedVariables": { // "type": "number", // "description": "The number of indexed child variables. The // client can use this optional information to // present the variables in a paged UI and fetch // them in chunks." // } // "memoryReference": { // "type": "string", // "description": "A memory reference to a location appropriate // for this result. For pointer type eval // results, this is generally a reference to the // memory address contained in the pointer. This // attribute may be returned by a debug adapter // if corresponding capability // `supportsMemoryReferences` is true." // }, // }, // "required": [ "result", "variablesReference" ] // } // }, // "required": [ "body" ] // }] // } void request_evaluate(const llvm::json::Object &request) { … } // "compileUnitsRequest": { // "allOf": [ { "$ref": "#/definitions/Request" }, { // "type": "object", // "description": "Compile Unit request; value of command field is // 'compileUnits'.", // "properties": { // "command": { // "type": "string", // "enum": [ "compileUnits" ] // }, // "arguments": { // "$ref": "#/definitions/compileUnitRequestArguments" // } // }, // "required": [ "command", "arguments" ] // }] // }, // "compileUnitsRequestArguments": { // "type": "object", // "description": "Arguments for 'compileUnits' request.", // "properties": { // "moduleId": { // "type": "string", // "description": "The ID of the module." // } // }, // "required": [ "moduleId" ] // }, // "compileUnitsResponse": { // "allOf": [ { "$ref": "#/definitions/Response" }, { // "type": "object", // "description": "Response to 'compileUnits' request.", // "properties": { // "body": { // "description": "Response to 'compileUnits' request. Array of // paths of compile units." // } // } // }] // } void request_compileUnits(const llvm::json::Object &request) { … } // "modulesRequest": { // "allOf": [ { "$ref": "#/definitions/Request" }, { // "type": "object", // "description": "Modules request; value of command field is // 'modules'.", // "properties": { // "command": { // "type": "string", // "enum": [ "modules" ] // }, // }, // "required": [ "command" ] // }] // }, // "modulesResponse": { // "allOf": [ { "$ref": "#/definitions/Response" }, { // "type": "object", // "description": "Response to 'modules' request.", // "properties": { // "body": { // "description": "Response to 'modules' request. Array of // module objects." // } // } // }] // } void request_modules(const llvm::json::Object &request) { … } // "InitializeRequest": { // "allOf": [ { "$ref": "#/definitions/Request" }, { // "type": "object", // "description": "Initialize request; value of command field is // 'initialize'.", // "properties": { // "command": { // "type": "string", // "enum": [ "initialize" ] // }, // "arguments": { // "$ref": "#/definitions/InitializeRequestArguments" // } // }, // "required": [ "command", "arguments" ] // }] // }, // "InitializeRequestArguments": { // "type": "object", // "description": "Arguments for 'initialize' request.", // "properties": { // "clientID": { // "type": "string", // "description": "The ID of the (frontend) client using this adapter." // }, // "adapterID": { // "type": "string", // "description": "The ID of the debug adapter." // }, // "locale": { // "type": "string", // "description": "The ISO-639 locale of the (frontend) client using // this adapter, e.g. en-US or de-CH." // }, // "linesStartAt1": { // "type": "boolean", // "description": "If true all line numbers are 1-based (default)." // }, // "columnsStartAt1": { // "type": "boolean", // "description": "If true all column numbers are 1-based (default)." // }, // "pathFormat": { // "type": "string", // "_enum": [ "path", "uri" ], // "description": "Determines in what format paths are specified. The // default is 'path', which is the native format." // }, // "supportsVariableType": { // "type": "boolean", // "description": "Client supports the optional type attribute for // variables." // }, // "supportsVariablePaging": { // "type": "boolean", // "description": "Client supports the paging of variables." // }, // "supportsRunInTerminalRequest": { // "type": "boolean", // "description": "Client supports the runInTerminal request." // } // }, // "required": [ "adapterID" ] // }, // "InitializeResponse": { // "allOf": [ { "$ref": "#/definitions/Response" }, { // "type": "object", // "description": "Response to 'initialize' request.", // "properties": { // "body": { // "$ref": "#/definitions/Capabilities", // "description": "The capabilities of this debug adapter." // } // } // }] // } void request_initialize(const llvm::json::Object &request) { … } llvm::Error request_runInTerminal(const llvm::json::Object &launch_request, const uint64_t timeout_seconds) { … } // Takes a LaunchRequest object and launches the process, also handling // runInTerminal if applicable. It doesn't do any of the additional // initialization and bookkeeping stuff that is needed for `request_launch`. // This way we can reuse the process launching logic for RestartRequest too. lldb::SBError LaunchProcess(const llvm::json::Object &request) { … } // "LaunchRequest": { // "allOf": [ { "$ref": "#/definitions/Request" }, { // "type": "object", // "description": "Launch request; value of command field is 'launch'.", // "properties": { // "command": { // "type": "string", // "enum": [ "launch" ] // }, // "arguments": { // "$ref": "#/definitions/LaunchRequestArguments" // } // }, // "required": [ "command", "arguments" ] // }] // }, // "LaunchRequestArguments": { // "type": "object", // "description": "Arguments for 'launch' request.", // "properties": { // "noDebug": { // "type": "boolean", // "description": "If noDebug is true the launch request should launch // the program without enabling debugging." // } // } // }, // "LaunchResponse": { // "allOf": [ { "$ref": "#/definitions/Response" }, { // "type": "object", // "description": "Response to 'launch' request. This is just an // acknowledgement, so no body field is required." // }] // } void request_launch(const llvm::json::Object &request) { … } // Check if the step-granularity is `instruction` static bool hasInstructionGranularity(const llvm::json::Object &requestArgs) { … } // "NextRequest": { // "allOf": [ { "$ref": "#/definitions/Request" }, { // "type": "object", // "description": "Next request; value of command field is 'next'. The // request starts the debuggee to run again for one step. // The debug adapter first sends the NextResponse and then // a StoppedEvent (event type 'step') after the step has // completed.", // "properties": { // "command": { // "type": "string", // "enum": [ "next" ] // }, // "arguments": { // "$ref": "#/definitions/NextArguments" // } // }, // "required": [ "command", "arguments" ] // }] // }, // "NextArguments": { // "type": "object", // "description": "Arguments for 'next' request.", // "properties": { // "threadId": { // "type": "integer", // "description": "Execute 'next' for this thread." // }, // "granularity": { // "$ref": "#/definitions/SteppingGranularity", // "description": "Stepping granularity. If no granularity is specified, a // granularity of `statement` is assumed." // } // }, // "required": [ "threadId" ] // }, // "NextResponse": { // "allOf": [ { "$ref": "#/definitions/Response" }, { // "type": "object", // "description": "Response to 'next' request. This is just an // acknowledgement, so no body field is required." // }] // } void request_next(const llvm::json::Object &request) { … } // "PauseRequest": { // "allOf": [ { "$ref": "#/definitions/Request" }, { // "type": "object", // "description": "Pause request; value of command field is 'pause'. The // request suspenses the debuggee. The debug adapter first sends the // PauseResponse and then a StoppedEvent (event type 'pause') after the // thread has been paused successfully.", "properties": { // "command": { // "type": "string", // "enum": [ "pause" ] // }, // "arguments": { // "$ref": "#/definitions/PauseArguments" // } // }, // "required": [ "command", "arguments" ] // }] // }, // "PauseArguments": { // "type": "object", // "description": "Arguments for 'pause' request.", // "properties": { // "threadId": { // "type": "integer", // "description": "Pause execution for this thread." // } // }, // "required": [ "threadId" ] // }, // "PauseResponse": { // "allOf": [ { "$ref": "#/definitions/Response" }, { // "type": "object", // "description": "Response to 'pause' request. This is just an // acknowledgement, so no body field is required." // }] // } void request_pause(const llvm::json::Object &request) { … } // "RestartRequest": { // "allOf": [ { "$ref": "#/definitions/Request" }, { // "type": "object", // "description": "Restarts a debug session. Clients should only call this // request if the corresponding capability `supportsRestartRequest` is // true.\nIf the capability is missing or has the value false, a typical // client emulates `restart` by terminating the debug adapter first and then // launching it anew.", // "properties": { // "command": { // "type": "string", // "enum": [ "restart" ] // }, // "arguments": { // "$ref": "#/definitions/RestartArguments" // } // }, // "required": [ "command" ] // }] // }, // "RestartArguments": { // "type": "object", // "description": "Arguments for `restart` request.", // "properties": { // "arguments": { // "oneOf": [ // { "$ref": "#/definitions/LaunchRequestArguments" }, // { "$ref": "#/definitions/AttachRequestArguments" } // ], // "description": "The latest version of the `launch` or `attach` // configuration." // } // } // }, // "RestartResponse": { // "allOf": [ { "$ref": "#/definitions/Response" }, { // "type": "object", // "description": "Response to `restart` request. This is just an // acknowledgement, so no body field is required." // }] // }, void request_restart(const llvm::json::Object &request) { … } // "ScopesRequest": { // "allOf": [ { "$ref": "#/definitions/Request" }, { // "type": "object", // "description": "Scopes request; value of command field is 'scopes'. The // request returns the variable scopes for a given stackframe ID.", // "properties": { // "command": { // "type": "string", // "enum": [ "scopes" ] // }, // "arguments": { // "$ref": "#/definitions/ScopesArguments" // } // }, // "required": [ "command", "arguments" ] // }] // }, // "ScopesArguments": { // "type": "object", // "description": "Arguments for 'scopes' request.", // "properties": { // "frameId": { // "type": "integer", // "description": "Retrieve the scopes for this stackframe." // } // }, // "required": [ "frameId" ] // }, // "ScopesResponse": { // "allOf": [ { "$ref": "#/definitions/Response" }, { // "type": "object", // "description": "Response to 'scopes' request.", // "properties": { // "body": { // "type": "object", // "properties": { // "scopes": { // "type": "array", // "items": { // "$ref": "#/definitions/Scope" // }, // "description": "The scopes of the stackframe. If the array has // length zero, there are no scopes available." // } // }, // "required": [ "scopes" ] // } // }, // "required": [ "body" ] // }] // } void request_scopes(const llvm::json::Object &request) { … } // "SetBreakpointsRequest": { // "allOf": [ { "$ref": "#/definitions/Request" }, { // "type": "object", // "description": "SetBreakpoints request; value of command field is // 'setBreakpoints'. Sets multiple breakpoints for a single source and // clears all previous breakpoints in that source. To clear all breakpoint // for a source, specify an empty array. When a breakpoint is hit, a // StoppedEvent (event type 'breakpoint') is generated.", "properties": { // "command": { // "type": "string", // "enum": [ "setBreakpoints" ] // }, // "arguments": { // "$ref": "#/definitions/SetBreakpointsArguments" // } // }, // "required": [ "command", "arguments" ] // }] // }, // "SetBreakpointsArguments": { // "type": "object", // "description": "Arguments for 'setBreakpoints' request.", // "properties": { // "source": { // "$ref": "#/definitions/Source", // "description": "The source location of the breakpoints; either // source.path or source.reference must be specified." // }, // "breakpoints": { // "type": "array", // "items": { // "$ref": "#/definitions/SourceBreakpoint" // }, // "description": "The code locations of the breakpoints." // }, // "lines": { // "type": "array", // "items": { // "type": "integer" // }, // "description": "Deprecated: The code locations of the breakpoints." // }, // "sourceModified": { // "type": "boolean", // "description": "A value of true indicates that the underlying source // has been modified which results in new breakpoint locations." // } // }, // "required": [ "source" ] // }, // "SetBreakpointsResponse": { // "allOf": [ { "$ref": "#/definitions/Response" }, { // "type": "object", // "description": "Response to 'setBreakpoints' request. Returned is // information about each breakpoint created by this request. This includes // the actual code location and whether the breakpoint could be verified. // The breakpoints returned are in the same order as the elements of the // 'breakpoints' (or the deprecated 'lines') in the // SetBreakpointsArguments.", "properties": { // "body": { // "type": "object", // "properties": { // "breakpoints": { // "type": "array", // "items": { // "$ref": "#/definitions/Breakpoint" // }, // "description": "Information about the breakpoints. The array // elements are in the same order as the elements of the // 'breakpoints' (or the deprecated 'lines') in the // SetBreakpointsArguments." // } // }, // "required": [ "breakpoints" ] // } // }, // "required": [ "body" ] // }] // }, // "SourceBreakpoint": { // "type": "object", // "description": "Properties of a breakpoint or logpoint passed to the // setBreakpoints request.", "properties": { // "line": { // "type": "integer", // "description": "The source line of the breakpoint or logpoint." // }, // "column": { // "type": "integer", // "description": "An optional source column of the breakpoint." // }, // "condition": { // "type": "string", // "description": "An optional expression for conditional breakpoints." // }, // "hitCondition": { // "type": "string", // "description": "An optional expression that controls how many hits of // the breakpoint are ignored. The backend is expected to interpret the // expression as needed." // }, // "logMessage": { // "type": "string", // "description": "If this attribute exists and is non-empty, the backend // must not 'break' (stop) but log the message instead. Expressions within // {} are interpolated." // } // }, // "required": [ "line" ] // } void request_setBreakpoints(const llvm::json::Object &request) { … } // "SetExceptionBreakpointsRequest": { // "allOf": [ { "$ref": "#/definitions/Request" }, { // "type": "object", // "description": "SetExceptionBreakpoints request; value of command field // is 'setExceptionBreakpoints'. The request configures the debuggers // response to thrown exceptions. If an exception is configured to break, a // StoppedEvent is fired (event type 'exception').", "properties": { // "command": { // "type": "string", // "enum": [ "setExceptionBreakpoints" ] // }, // "arguments": { // "$ref": "#/definitions/SetExceptionBreakpointsArguments" // } // }, // "required": [ "command", "arguments" ] // }] // }, // "SetExceptionBreakpointsArguments": { // "type": "object", // "description": "Arguments for 'setExceptionBreakpoints' request.", // "properties": { // "filters": { // "type": "array", // "items": { // "type": "string" // }, // "description": "IDs of checked exception options. The set of IDs is // returned via the 'exceptionBreakpointFilters' capability." // }, // "exceptionOptions": { // "type": "array", // "items": { // "$ref": "#/definitions/ExceptionOptions" // }, // "description": "Configuration options for selected exceptions." // } // }, // "required": [ "filters" ] // }, // "SetExceptionBreakpointsResponse": { // "allOf": [ { "$ref": "#/definitions/Response" }, { // "type": "object", // "description": "Response to 'setExceptionBreakpoints' request. This is // just an acknowledgement, so no body field is required." // }] // } void request_setExceptionBreakpoints(const llvm::json::Object &request) { … } // "SetFunctionBreakpointsRequest": { // "allOf": [ { "$ref": "#/definitions/Request" }, { // "type": "object", // "description": "SetFunctionBreakpoints request; value of command field is // 'setFunctionBreakpoints'. Sets multiple function breakpoints and clears // all previous function breakpoints. To clear all function breakpoint, // specify an empty array. When a function breakpoint is hit, a StoppedEvent // (event type 'function breakpoint') is generated.", "properties": { // "command": { // "type": "string", // "enum": [ "setFunctionBreakpoints" ] // }, // "arguments": { // "$ref": "#/definitions/SetFunctionBreakpointsArguments" // } // }, // "required": [ "command", "arguments" ] // }] // }, // "SetFunctionBreakpointsArguments": { // "type": "object", // "description": "Arguments for 'setFunctionBreakpoints' request.", // "properties": { // "breakpoints": { // "type": "array", // "items": { // "$ref": "#/definitions/FunctionBreakpoint" // }, // "description": "The function names of the breakpoints." // } // }, // "required": [ "breakpoints" ] // }, // "FunctionBreakpoint": { // "type": "object", // "description": "Properties of a breakpoint passed to the // setFunctionBreakpoints request.", "properties": { // "name": { // "type": "string", // "description": "The name of the function." // }, // "condition": { // "type": "string", // "description": "An optional expression for conditional breakpoints." // }, // "hitCondition": { // "type": "string", // "description": "An optional expression that controls how many hits of // the breakpoint are ignored. The backend is expected to interpret the // expression as needed." // } // }, // "required": [ "name" ] // }, // "SetFunctionBreakpointsResponse": { // "allOf": [ { "$ref": "#/definitions/Response" }, { // "type": "object", // "description": "Response to 'setFunctionBreakpoints' request. Returned is // information about each breakpoint created by this request.", // "properties": { // "body": { // "type": "object", // "properties": { // "breakpoints": { // "type": "array", // "items": { // "$ref": "#/definitions/Breakpoint" // }, // "description": "Information about the breakpoints. The array // elements correspond to the elements of the 'breakpoints' array." // } // }, // "required": [ "breakpoints" ] // } // }, // "required": [ "body" ] // }] // } void request_setFunctionBreakpoints(const llvm::json::Object &request) { … } // "DataBreakpointInfoRequest": { // "allOf": [ { "$ref": "#/definitions/Request" }, { // "type": "object", // "description": "Obtains information on a possible data breakpoint that // could be set on an expression or variable.\nClients should only call this // request if the corresponding capability `supportsDataBreakpoints` is // true.", "properties": { // "command": { // "type": "string", // "enum": [ "dataBreakpointInfo" ] // }, // "arguments": { // "$ref": "#/definitions/DataBreakpointInfoArguments" // } // }, // "required": [ "command", "arguments" ] // }] // }, // "DataBreakpointInfoArguments": { // "type": "object", // "description": "Arguments for `dataBreakpointInfo` request.", // "properties": { // "variablesReference": { // "type": "integer", // "description": "Reference to the variable container if the data // breakpoint is requested for a child of the container. The // `variablesReference` must have been obtained in the current suspended // state. See 'Lifetime of Object References' in the Overview section for // details." // }, // "name": { // "type": "string", // "description": "The name of the variable's child to obtain data // breakpoint information for.\nIf `variablesReference` isn't specified, // this can be an expression." // }, // "frameId": { // "type": "integer", // "description": "When `name` is an expression, evaluate it in the scope // of this stack frame. If not specified, the expression is evaluated in // the global scope. When `variablesReference` is specified, this property // has no effect." // } // }, // "required": [ "name" ] // }, // "DataBreakpointInfoResponse": { // "allOf": [ { "$ref": "#/definitions/Response" }, { // "type": "object", // "description": "Response to `dataBreakpointInfo` request.", // "properties": { // "body": { // "type": "object", // "properties": { // "dataId": { // "type": [ "string", "null" ], // "description": "An identifier for the data on which a data // breakpoint can be registered with the `setDataBreakpoints` // request or null if no data breakpoint is available. If a // `variablesReference` or `frameId` is passed, the `dataId` is // valid in the current suspended state, otherwise it's valid // indefinitely. See 'Lifetime of Object References' in the Overview // section for details. Breakpoints set using the `dataId` in the // `setDataBreakpoints` request may outlive the lifetime of the // associated `dataId`." // }, // "description": { // "type": "string", // "description": "UI string that describes on what data the // breakpoint is set on or why a data breakpoint is not available." // }, // "accessTypes": { // "type": "array", // "items": { // "$ref": "#/definitions/DataBreakpointAccessType" // }, // "description": "Attribute lists the available access types for a // potential data breakpoint. A UI client could surface this // information." // }, // "canPersist": { // "type": "boolean", // "description": "Attribute indicates that a potential data // breakpoint could be persisted across sessions." // } // }, // "required": [ "dataId", "description" ] // } // }, // "required": [ "body" ] // }] // } void request_dataBreakpointInfo(const llvm::json::Object &request) { … } // "SetDataBreakpointsRequest": { // "allOf": [ { "$ref": "#/definitions/Request" }, { // "type": "object", // "description": "Replaces all existing data breakpoints with new data // breakpoints.\nTo clear all data breakpoints, specify an empty // array.\nWhen a data breakpoint is hit, a `stopped` event (with reason // `data breakpoint`) is generated.\nClients should only call this request // if the corresponding capability `supportsDataBreakpoints` is true.", // "properties": { // "command": { // "type": "string", // "enum": [ "setDataBreakpoints" ] // }, // "arguments": { // "$ref": "#/definitions/SetDataBreakpointsArguments" // } // }, // "required": [ "command", "arguments" ] // }] // }, // "SetDataBreakpointsArguments": { // "type": "object", // "description": "Arguments for `setDataBreakpoints` request.", // "properties": { // "breakpoints": { // "type": "array", // "items": { // "$ref": "#/definitions/DataBreakpoint" // }, // "description": "The contents of this array replaces all existing data // breakpoints. An empty array clears all data breakpoints." // } // }, // "required": [ "breakpoints" ] // }, // "SetDataBreakpointsResponse": { // "allOf": [ { "$ref": "#/definitions/Response" }, { // "type": "object", // "description": "Response to `setDataBreakpoints` request.\nReturned is // information about each breakpoint created by this request.", // "properties": { // "body": { // "type": "object", // "properties": { // "breakpoints": { // "type": "array", // "items": { // "$ref": "#/definitions/Breakpoint" // }, // "description": "Information about the data breakpoints. The array // elements correspond to the elements of the input argument // `breakpoints` array." // } // }, // "required": [ "breakpoints" ] // } // }, // "required": [ "body" ] // }] // } void request_setDataBreakpoints(const llvm::json::Object &request) { … } // "SourceRequest": { // "allOf": [ { "$ref": "#/definitions/Request" }, { // "type": "object", // "description": "Source request; value of command field is 'source'. The // request retrieves the source code for a given source reference.", // "properties": { // "command": { // "type": "string", // "enum": [ "source" ] // }, // "arguments": { // "$ref": "#/definitions/SourceArguments" // } // }, // "required": [ "command", "arguments" ] // }] // }, // "SourceArguments": { // "type": "object", // "description": "Arguments for 'source' request.", // "properties": { // "source": { // "$ref": "#/definitions/Source", // "description": "Specifies the source content to load. Either // source.path or source.sourceReference must be specified." // }, // "sourceReference": { // "type": "integer", // "description": "The reference to the source. This is the same as // source.sourceReference. This is provided for backward compatibility // since old backends do not understand the 'source' attribute." // } // }, // "required": [ "sourceReference" ] // }, // "SourceResponse": { // "allOf": [ { "$ref": "#/definitions/Response" }, { // "type": "object", // "description": "Response to 'source' request.", // "properties": { // "body": { // "type": "object", // "properties": { // "content": { // "type": "string", // "description": "Content of the source reference." // }, // "mimeType": { // "type": "string", // "description": "Optional content type (mime type) of the source." // } // }, // "required": [ "content" ] // } // }, // "required": [ "body" ] // }] // } void request_source(const llvm::json::Object &request) { … } // "StackTraceRequest": { // "allOf": [ { "$ref": "#/definitions/Request" }, { // "type": "object", // "description": "StackTrace request; value of command field is // 'stackTrace'. The request returns a stacktrace from the current execution // state.", "properties": { // "command": { // "type": "string", // "enum": [ "stackTrace" ] // }, // "arguments": { // "$ref": "#/definitions/StackTraceArguments" // } // }, // "required": [ "command", "arguments" ] // }] // }, // "StackTraceArguments": { // "type": "object", // "description": "Arguments for 'stackTrace' request.", // "properties": { // "threadId": { // "type": "integer", // "description": "Retrieve the stacktrace for this thread." // }, // "startFrame": { // "type": "integer", // "description": "The index of the first frame to return; if omitted // frames start at 0." // }, // "levels": { // "type": "integer", // "description": "The maximum number of frames to return. If levels is // not specified or 0, all frames are returned." // }, // "format": { // "$ref": "#/definitions/StackFrameFormat", // "description": "Specifies details on how to format the stack frames. // The attribute is only honored by a debug adapter if the corresponding // capability `supportsValueFormattingOptions` is true." // } // }, // "required": [ "threadId" ] // }, // "StackTraceResponse": { // "allOf": [ { "$ref": "#/definitions/Response" }, { // "type": "object", // "description": "Response to `stackTrace` request.", // "properties": { // "body": { // "type": "object", // "properties": { // "stackFrames": { // "type": "array", // "items": { // "$ref": "#/definitions/StackFrame" // }, // "description": "The frames of the stackframe. If the array has // length zero, there are no stackframes available. This means that // there is no location information available." // }, // "totalFrames": { // "type": "integer", // "description": "The total number of frames available in the // stack. If omitted or if `totalFrames` is larger than the // available frames, a client is expected to request frames until // a request returns less frames than requested (which indicates // the end of the stack). Returning monotonically increasing // `totalFrames` values for subsequent requests can be used to // enforce paging in the client." // } // }, // "required": [ "stackFrames" ] // } // }, // "required": [ "body" ] // }] // } void request_stackTrace(const llvm::json::Object &request) { … } // "StepInRequest": { // "allOf": [ { "$ref": "#/definitions/Request" }, { // "type": "object", // "description": "StepIn request; value of command field is 'stepIn'. The // request starts the debuggee to step into a function/method if possible. // If it cannot step into a target, 'stepIn' behaves like 'next'. The debug // adapter first sends the StepInResponse and then a StoppedEvent (event // type 'step') after the step has completed. If there are multiple // function/method calls (or other targets) on the source line, the optional // argument 'targetId' can be used to control into which target the 'stepIn' // should occur. The list of possible targets for a given source line can be // retrieved via the 'stepInTargets' request.", "properties": { // "command": { // "type": "string", // "enum": [ "stepIn" ] // }, // "arguments": { // "$ref": "#/definitions/StepInArguments" // } // }, // "required": [ "command", "arguments" ] // }] // }, // "StepInArguments": { // "type": "object", // "description": "Arguments for 'stepIn' request.", // "properties": { // "threadId": { // "type": "integer", // "description": "Execute 'stepIn' for this thread." // }, // "targetId": { // "type": "integer", // "description": "Optional id of the target to step into." // }, // "granularity": { // "$ref": "#/definitions/SteppingGranularity", // "description": "Stepping granularity. If no granularity is specified, a // granularity of `statement` is assumed." // } // }, // "required": [ "threadId" ] // }, // "StepInResponse": { // "allOf": [ { "$ref": "#/definitions/Response" }, { // "type": "object", // "description": "Response to 'stepIn' request. This is just an // acknowledgement, so no body field is required." // }] // } void request_stepIn(const llvm::json::Object &request) { … } // "StepInTargetsRequest": { // "allOf": [ { "$ref": "#/definitions/Request" }, { // "type": "object", // "description": "This request retrieves the possible step-in targets for // the specified stack frame.\nThese targets can be used in the `stepIn` // request.\nClients should only call this request if the corresponding // capability `supportsStepInTargetsRequest` is true.", "properties": { // "command": { // "type": "string", // "enum": [ "stepInTargets" ] // }, // "arguments": { // "$ref": "#/definitions/StepInTargetsArguments" // } // }, // "required": [ "command", "arguments" ] // }] // }, // "StepInTargetsArguments": { // "type": "object", // "description": "Arguments for `stepInTargets` request.", // "properties": { // "frameId": { // "type": "integer", // "description": "The stack frame for which to retrieve the possible // step-in targets." // } // }, // "required": [ "frameId" ] // }, // "StepInTargetsResponse": { // "allOf": [ { "$ref": "#/definitions/Response" }, { // "type": "object", // "description": "Response to `stepInTargets` request.", // "properties": { // "body": { // "type": "object", // "properties": { // "targets": { // "type": "array", // "items": { // "$ref": "#/definitions/StepInTarget" // }, // "description": "The possible step-in targets of the specified // source location." // } // }, // "required": [ "targets" ] // } // }, // "required": [ "body" ] // }] // } void request_stepInTargets(const llvm::json::Object &request) { … } // "StepOutRequest": { // "allOf": [ { "$ref": "#/definitions/Request" }, { // "type": "object", // "description": "StepOut request; value of command field is 'stepOut'. The // request starts the debuggee to run again for one step. The debug adapter // first sends the StepOutResponse and then a StoppedEvent (event type // 'step') after the step has completed.", "properties": { // "command": { // "type": "string", // "enum": [ "stepOut" ] // }, // "arguments": { // "$ref": "#/definitions/StepOutArguments" // } // }, // "required": [ "command", "arguments" ] // }] // }, // "StepOutArguments": { // "type": "object", // "description": "Arguments for 'stepOut' request.", // "properties": { // "threadId": { // "type": "integer", // "description": "Execute 'stepOut' for this thread." // } // }, // "required": [ "threadId" ] // }, // "StepOutResponse": { // "allOf": [ { "$ref": "#/definitions/Response" }, { // "type": "object", // "description": "Response to 'stepOut' request. This is just an // acknowledgement, so no body field is required." // }] // } void request_stepOut(const llvm::json::Object &request) { … } // "ThreadsRequest": { // "allOf": [ { "$ref": "#/definitions/Request" }, { // "type": "object", // "description": "Thread request; value of command field is 'threads'. The // request retrieves a list of all threads.", "properties": { // "command": { // "type": "string", // "enum": [ "threads" ] // } // }, // "required": [ "command" ] // }] // }, // "ThreadsResponse": { // "allOf": [ { "$ref": "#/definitions/Response" }, { // "type": "object", // "description": "Response to 'threads' request.", // "properties": { // "body": { // "type": "object", // "properties": { // "threads": { // "type": "array", // "items": { // "$ref": "#/definitions/Thread" // }, // "description": "All threads." // } // }, // "required": [ "threads" ] // } // }, // "required": [ "body" ] // }] // } void request_threads(const llvm::json::Object &request) { … } // "SetVariableRequest": { // "allOf": [ { "$ref": "#/definitions/Request" }, { // "type": "object", // "description": "setVariable request; value of command field is // 'setVariable'. Set the variable with the given name in the variable // container to a new value.", "properties": { // "command": { // "type": "string", // "enum": [ "setVariable" ] // }, // "arguments": { // "$ref": "#/definitions/SetVariableArguments" // } // }, // "required": [ "command", "arguments" ] // }] // }, // "SetVariableArguments": { // "type": "object", // "description": "Arguments for 'setVariable' request.", // "properties": { // "variablesReference": { // "type": "integer", // "description": "The reference of the variable container." // }, // "name": { // "type": "string", // "description": "The name of the variable." // }, // "value": { // "type": "string", // "description": "The value of the variable." // }, // "format": { // "$ref": "#/definitions/ValueFormat", // "description": "Specifies details on how to format the response value." // } // }, // "required": [ "variablesReference", "name", "value" ] // }, // "SetVariableResponse": { // "allOf": [ { "$ref": "#/definitions/Response" }, { // "type": "object", // "description": "Response to 'setVariable' request.", // "properties": { // "body": { // "type": "object", // "properties": { // "value": { // "type": "string", // "description": "The new value of the variable." // }, // "type": { // "type": "string", // "description": "The type of the new value. Typically shown in the // UI when hovering over the value." // }, // "variablesReference": { // "type": "number", // "description": "If variablesReference is > 0, the new value is // structured and its children can be retrieved by passing // variablesReference to the VariablesRequest." // }, // "namedVariables": { // "type": "number", // "description": "The number of named child variables. The client // can use this optional information to present the variables in a // paged UI and fetch them in chunks." // }, // "indexedVariables": { // "type": "number", // "description": "The number of indexed child variables. The client // can use this optional information to present the variables in a // paged UI and fetch them in chunks." // } // }, // "required": [ "value" ] // } // }, // "required": [ "body" ] // }] // } void request_setVariable(const llvm::json::Object &request) { … } // "VariablesRequest": { // "allOf": [ { "$ref": "#/definitions/Request" }, { // "type": "object", // "description": "Variables request; value of command field is 'variables'. // Retrieves all child variables for the given variable reference. An // optional filter can be used to limit the fetched children to either named // or indexed children.", "properties": { // "command": { // "type": "string", // "enum": [ "variables" ] // }, // "arguments": { // "$ref": "#/definitions/VariablesArguments" // } // }, // "required": [ "command", "arguments" ] // }] // }, // "VariablesArguments": { // "type": "object", // "description": "Arguments for 'variables' request.", // "properties": { // "variablesReference": { // "type": "integer", // "description": "The Variable reference." // }, // "filter": { // "type": "string", // "enum": [ "indexed", "named" ], // "description": "Optional filter to limit the child variables to either // named or indexed. If ommited, both types are fetched." // }, // "start": { // "type": "integer", // "description": "The index of the first variable to return; if omitted // children start at 0." // }, // "count": { // "type": "integer", // "description": "The number of variables to return. If count is missing // or 0, all variables are returned." // }, // "format": { // "$ref": "#/definitions/ValueFormat", // "description": "Specifies details on how to format the Variable // values." // } // }, // "required": [ "variablesReference" ] // }, // "VariablesResponse": { // "allOf": [ { "$ref": "#/definitions/Response" }, { // "type": "object", // "description": "Response to 'variables' request.", // "properties": { // "body": { // "type": "object", // "properties": { // "variables": { // "type": "array", // "items": { // "$ref": "#/definitions/Variable" // }, // "description": "All (or a range) of variables for the given // variable reference." // } // }, // "required": [ "variables" ] // } // }, // "required": [ "body" ] // }] // } void request_variables(const llvm::json::Object &request) { … } // "LocationsRequest": { // "allOf": [ { "$ref": "#/definitions/Request" }, { // "type": "object", // "description": "Looks up information about a location reference // previously returned by the debug adapter.", // "properties": { // "command": { // "type": "string", // "enum": [ "locations" ] // }, // "arguments": { // "$ref": "#/definitions/LocationsArguments" // } // }, // "required": [ "command", "arguments" ] // }] // }, // "LocationsArguments": { // "type": "object", // "description": "Arguments for `locations` request.", // "properties": { // "locationReference": { // "type": "integer", // "description": "Location reference to resolve." // } // }, // "required": [ "locationReference" ] // }, // "LocationsResponse": { // "allOf": [ { "$ref": "#/definitions/Response" }, { // "type": "object", // "description": "Response to `locations` request.", // "properties": { // "body": { // "type": "object", // "properties": { // "source": { // "$ref": "#/definitions/Source", // "description": "The source containing the location; either // `source.path` or `source.sourceReference` must be // specified." // }, // "line": { // "type": "integer", // "description": "The line number of the location. The client // capability `linesStartAt1` determines whether it // is 0- or 1-based." // }, // "column": { // "type": "integer", // "description": "Position of the location within the `line`. It is // measured in UTF-16 code units and the client // capability `columnsStartAt1` determines whether // it is 0- or 1-based. If no column is given, the // first position in the start line is assumed." // }, // "endLine": { // "type": "integer", // "description": "End line of the location, present if the location // refers to a range. The client capability // `linesStartAt1` determines whether it is 0- or // 1-based." // }, // "endColumn": { // "type": "integer", // "description": "End position of the location within `endLine`, // present if the location refers to a range. It is // measured in UTF-16 code units and the client // capability `columnsStartAt1` determines whether // it is 0- or 1-based." // } // }, // "required": [ "source", "line" ] // } // } // }] // }, void request_locations(const llvm::json::Object &request) { … } // "DisassembleRequest": { // "allOf": [ { "$ref": "#/definitions/Request" }, { // "type": "object", // "description": "Disassembles code stored at the provided // location.\nClients should only call this request if the corresponding // capability `supportsDisassembleRequest` is true.", "properties": { // "command": { // "type": "string", // "enum": [ "disassemble" ] // }, // "arguments": { // "$ref": "#/definitions/DisassembleArguments" // } // }, // "required": [ "command", "arguments" ] // }] // }, // "DisassembleArguments": { // "type": "object", // "description": "Arguments for `disassemble` request.", // "properties": { // "memoryReference": { // "type": "string", // "description": "Memory reference to the base location containing the // instructions to disassemble." // }, // "offset": { // "type": "integer", // "description": "Offset (in bytes) to be applied to the reference // location before disassembling. Can be negative." // }, // "instructionOffset": { // "type": "integer", // "description": "Offset (in instructions) to be applied after the byte // offset (if any) before disassembling. Can be negative." // }, // "instructionCount": { // "type": "integer", // "description": "Number of instructions to disassemble starting at the // specified location and offset.\nAn adapter must return exactly this // number of instructions - any unavailable instructions should be // replaced with an implementation-defined 'invalid instruction' value." // }, // "resolveSymbols": { // "type": "boolean", // "description": "If true, the adapter should attempt to resolve memory // addresses and other values to symbolic names." // } // }, // "required": [ "memoryReference", "instructionCount" ] // }, // "DisassembleResponse": { // "allOf": [ { "$ref": "#/definitions/Response" }, { // "type": "object", // "description": "Response to `disassemble` request.", // "properties": { // "body": { // "type": "object", // "properties": { // "instructions": { // "type": "array", // "items": { // "$ref": "#/definitions/DisassembledInstruction" // }, // "description": "The list of disassembled instructions." // } // }, // "required": [ "instructions" ] // } // } // }] // } void request_disassemble(const llvm::json::Object &request) { … } // "ReadMemoryRequest": { // "allOf": [ { "$ref": "#/definitions/Request" }, { // "type": "object", // "description": "Reads bytes from memory at the provided location. Clients // should only call this request if the corresponding // capability `supportsReadMemoryRequest` is true.", // "properties": { // "command": { // "type": "string", // "enum": [ "readMemory" ] // }, // "arguments": { // "$ref": "#/definitions/ReadMemoryArguments" // } // }, // "required": [ "command", "arguments" ] // }] // }, // "ReadMemoryArguments": { // "type": "object", // "description": "Arguments for `readMemory` request.", // "properties": { // "memoryReference": { // "type": "string", // "description": "Memory reference to the base location from which data // should be read." // }, // "offset": { // "type": "integer", // "description": "Offset (in bytes) to be applied to the reference // location before reading data. Can be negative." // }, // "count": { // "type": "integer", // "description": "Number of bytes to read at the specified location and // offset." // } // }, // "required": [ "memoryReference", "count" ] // }, // "ReadMemoryResponse": { // "allOf": [ { "$ref": "#/definitions/Response" }, { // "type": "object", // "description": "Response to `readMemory` request.", // "properties": { // "body": { // "type": "object", // "properties": { // "address": { // "type": "string", // "description": "The address of the first byte of data returned. // Treated as a hex value if prefixed with `0x`, or // as a decimal value otherwise." // }, // "unreadableBytes": { // "type": "integer", // "description": "The number of unreadable bytes encountered after // the last successfully read byte.\nThis can be // used to determine the number of bytes that should // be skipped before a subsequent // `readMemory` request succeeds." // }, // "data": { // "type": "string", // "description": "The bytes read from memory, encoded using base64. // If the decoded length of `data` is less than the // requested `count` in the original `readMemory` // request, and `unreadableBytes` is zero or // omitted, then the client should assume it's // reached the end of readable memory." // } // }, // "required": [ "address" ] // } // } // }] // }, void request_readMemory(const llvm::json::Object &request) { … } // A request used in testing to get the details on all breakpoints that are // currently set in the target. This helps us to test "setBreakpoints" and // "setFunctionBreakpoints" requests to verify we have the correct set of // breakpoints currently set in LLDB. void request__testGetTargetBreakpoints(const llvm::json::Object &request) { … } // "SetInstructionBreakpointsRequest" : { // "allOf" : [ // {"$ref" : "#/definitions/Request"}, { // "type" : "object", // "description" : // "Replaces all existing instruction breakpoints. Typically, " // "instruction breakpoints would be set from a disassembly window. " // "\nTo clear all instruction breakpoints, specify an empty " // "array.\nWhen an instruction breakpoint is hit, a `stopped` event " // "(with reason `instruction breakpoint`) is generated.\nClients " // "should only call this request if the corresponding capability " // "`supportsInstructionBreakpoints` is true.", // "properties" : { // "command" : {"type" : "string", "enum" : // ["setInstructionBreakpoints"]}, "arguments" : // {"$ref" : "#/definitions/SetInstructionBreakpointsArguments"} // }, // "required" : [ "command", "arguments" ] // } // ] // }, // "SetInstructionBreakpointsArguments" // : { // "type" : "object", // "description" : "Arguments for `setInstructionBreakpoints` request", // "properties" : { // "breakpoints" : { // "type" : "array", // "items" : {"$ref" : "#/definitions/InstructionBreakpoint"}, // "description" : "The instruction references of the breakpoints" // } // }, // "required" : ["breakpoints"] // }, // "SetInstructionBreakpointsResponse" // : { // "allOf" : [ // {"$ref" : "#/definitions/Response"}, { // "type" : "object", // "description" : "Response to `setInstructionBreakpoints` request", // "properties" : { // "body" : { // "type" : "object", // "properties" : { // "breakpoints" : { // "type" : "array", // "items" : {"$ref" : "#/definitions/Breakpoint"}, // "description" : // "Information about the breakpoints. The array elements // " "correspond to the elements of the `breakpoints` // array." // } // }, // "required" : ["breakpoints"] // } // }, // "required" : ["body"] // } // ] // }, // "InstructionBreakpoint" : { // "type" : "object", // "description" : "Properties of a breakpoint passed to the " // "`setInstructionBreakpoints` request", // "properties" : { // "instructionReference" : { // "type" : "string", // "description" : // "The instruction reference of the breakpoint.\nThis should be a " // "memory or instruction pointer reference from an // `EvaluateResponse`, " // "`Variable`, `StackFrame`, `GotoTarget`, or `Breakpoint`." // }, // "offset" : { // "type" : "integer", // "description" : "The offset from the instruction reference in " // "bytes.\nThis can be negative." // }, // "condition" : { // "type" : "string", // "description" : "An expression for conditional breakpoints.\nIt is only // " // "honored by a debug adapter if the corresponding " // "capability `supportsConditionalBreakpoints` is true." // }, // "hitCondition" : { // "type" : "string", // "description" : "An expression that controls how many hits of the " // "breakpoint are ignored.\nThe debug adapter is expected // " "to interpret the expression as needed.\nThe // attribute " "is only honored by a debug adapter if the // corresponding " "capability // `supportsHitConditionalBreakpoints` is true." // }, // "mode" : { // "type" : "string", // "description" : "The mode of this breakpoint. If defined, this must be // " // "one of the `breakpointModes` the debug adapter " // "advertised in its `Capabilities`." // } // }, // "required" : ["instructionReference"] // }, // "Breakpoint" // : { // "type" : "object", // "description" : // "Information about a breakpoint created in `setBreakpoints`, " // "`setFunctionBreakpoints`, `setInstructionBreakpoints`, or " // "`setDataBreakpoints` requests.", // "properties" : { // "id" : { // "type" : "integer", // "description" : // "The identifier for the breakpoint. It is needed if breakpoint // " "events are used to update or remove breakpoints." // }, // "verified" : { // "type" : "boolean", // "description" : "If true, the breakpoint could be set (but not " // "necessarily at the desired location)." // }, // "message" : { // "type" : "string", // "description" : "A message about the state of the breakpoint.\nThis // " // "is shown to the user and can be used to explain // why " "a breakpoint could not be verified." // }, // "source" : { // "$ref" : "#/definitions/Source", // "description" : "The source where the breakpoint is located." // }, // "line" : { // "type" : "integer", // "description" : // "The start line of the actual range covered by the breakpoint." // }, // "column" : { // "type" : "integer", // "description" : // "Start position of the source range covered by the breakpoint. // " "It is measured in UTF-16 code units and the client // capability " // "`columnsStartAt1` determines whether it is 0- or 1-based." // }, // "endLine" : { // "type" : "integer", // "description" : // "The end line of the actual range covered by the breakpoint." // }, // "endColumn" : { // "type" : "integer", // "description" : // "End position of the source range covered by the breakpoint. It // " "is measured in UTF-16 code units and the client capability " // "`columnsStartAt1` determines whether it is 0- or 1-based.\nIf // " "no end line is given, then the end column is assumed to be // in " "the start line." // }, // "instructionReference" : { // "type" : "string", // "description" : "A memory reference to where the breakpoint is // set." // }, // "offset" : { // "type" : "integer", // "description" : "The offset from the instruction reference.\nThis " // "can be negative." // }, // "reason" : { // "type" : "string", // "description" : // "A machine-readable explanation of why a breakpoint may not be // " "verified. If a breakpoint is verified or a specific reason // is " "not known, the adapter should omit this property. // Possible " "values include:\n\n- `pending`: Indicates a // breakpoint might be " "verified in the future, but the adapter // cannot verify it in the " "current state.\n - `failed`: // Indicates a breakpoint was not " "able to be verified, and the // adapter does not believe it can be " "verified without // intervention.", // "enum" : [ "pending", "failed" ] // } // }, // "required" : ["verified"] // }, void request_setInstructionBreakpoints(const llvm::json::Object &request) { … } void RegisterRequestCallbacks() { … } } // anonymous namespace static void printHelp(LLDBDAPOptTable &table, llvm::StringRef tool_name) { … } // If --launch-target is provided, this instance of lldb-dap becomes a // runInTerminal launcher. It will ultimately launch the program specified in // the --launch-target argument, which is the original program the user wanted // to debug. This is done in such a way that the actual debug adaptor can // place breakpoints at the beginning of the program. // // The launcher will communicate with the debug adaptor using a fifo file in the // directory specified in the --comm-file argument. // // Regarding the actual flow, this launcher will first notify the debug adaptor // of its pid. Then, the launcher will be in a pending state waiting to be // attached by the adaptor. // // Once attached and resumed, the launcher will exec and become the program // specified by --launch-target, which is the original target the // user wanted to run. // // In case of errors launching the target, a suitable error message will be // emitted to the debug adaptor. void LaunchRunInTerminalTarget(llvm::opt::Arg &target_arg, llvm::StringRef comm_file, lldb::pid_t debugger_pid, char *argv[]) { … } /// used only by TestVSCode_redirection_to_console.py void redirection_test() { … } /// Redirect stdout and stderr fo the IDE's console output. /// /// Errors in this operation will be printed to the log file and the IDE's /// console output as well. /// /// \return /// A fd pointing to the original stdout. int SetupStdoutStderrRedirection() { … } int main(int argc, char *argv[]) { … }