Giter Club home page Giter Club logo

debug-adapter-protocol's Introduction

Debug Adapter Protocol

The Debug Adapter Protocol is now available through its own Web site. The Web site contains information about how the protocol works, a more readable specification, and documents listing protocol implementations.

Contributing

If you are interested in fixing issues like typos you can either file an issue or provide a pull request containing the changes to the specification file.

When proposing an addition to the protocol, then please refer to the How to Contribute to the Debug Adapter Protocol document.

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact [email protected] with any additional questions or comments.

The Debug Adapter Protocol

See the Web site

Running the web site locally

In the project's root directory start a server with this command:

bundle exec jekyll serve

and then open http://127.0.0.1:4000/debug-adapter-protocol/ in a browser.

License

Creative Commons Attribution / MIT

debug-adapter-protocol's People

Contributors

apupier avatar auott avatar connor4312 avatar dantup avatar dependabot[bot] avatar eshelyaron avatar fwcd avatar gama11 avatar iusildra avatar jonahgraham avatar kamasamak avatar mfussenegger avatar microsoftopensource avatar nickbattle avatar qwe-q avatar rillig avatar robertoaloi avatar roblourens avatar rzhao271 avatar sana-ajani avatar sbatten avatar sim642 avatar soarex16 avatar suzmue avatar svenefftinge avatar sztomi avatar tmueller avatar vermiculus avatar wardengnaw avatar weinand avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

debug-adapter-protocol's Issues

Debugging session state management notifications.

Debugger client shell be able to manage debugging session state to support remote debugging:
Use case 1: developer starts debugging session but wishes to start communication with debugger server only when either main thread is started or 1st break
point is reached.
Use case 2: debugging session has lead to undesired results and developer wishes to abort debugging
Use case 3: mutation of application state by developer resulted in undesired results and developer wishes to restore initial application state and re-start debugging session without re-opening UI and going through initialization phase - neither server nor client capabilities changed.
Development tools supporting remote debugging like Java and Chrome debuggers support this functionality.

Debug Protocol: Allow exception conditions to be specified by the protocol

In Visual Studio, users can ignore first chance exceptions when they are raised in specific modules. This is useful when an external component raises a lot of exceptions that the user does not care about. This feature can be supported by the protocol by adding the concept of exception conditions. Although these conditions are currently either "Module == name" or "Module != name" this proposal lets the condition type be specified in case other condition types are added.

/** An ExceptionOptions assigns configuration options to a set of exceptions.*/
export interface ExceptionOptions {

    // ....

    /** A set of conditions used to determine whether the exception should result in a break.
        The debugger will break only if the exception matches all listed conditions.*/
    conditions?: ExceptionCondition[];
}

/** Condition to determine if the exception should be handled by the debugger.*/
export interface ExceptionCondition {
    /** Type of the condition.*/
    type: 'module';
    /** Operation to apply to the condition value.*/
    operator?: 'equals' | 'notEquals';
    /** Value of the condition.*/
    value: string;
}

/** Information about the capabilities of a debug adapter.*/
export interface Capabilities {

    // ....

    /** The debug adapter supports using exception conditions in exception options.*/
    supportsExceptionConditions?: boolean;
}

@weinand @andrewcrawley @gregg-miskelly

Introduce a mechanism to protect against stale requests

Some DAP requests return reference IDs that are used in subsequent requests to retrieve more data.
Since some of these reference IDs are only valid between two stop events, it is possible that a request arrives at the DA after a new stop event has already happened and the reference ID is no longer valid.

Since the DAP only requires that those reference IDs are unique for one stop event, a DA is free to reuse the IDs for every new stop. This makes it impossible for the DA to verify that an IDs is not from an old stop.

One idea to address this problem is to introduce a unique stop ID that the client receives with the stop event and can pass for any subsequent request that uses reference IDs of that stop event.

With this the DA can easily verify that a request refers to the same stop event that the DA sees. If the DAs has already seen a new stop event, stale requests can be detected and aborted.

See bug microsoft/vscode#27694 for details.

Debug adapters can notify VSCode about out-of-band line breakpoints but not command breakpoints

I work on the PowerShell debug adapter and that adapter provides a REPL while debugging. In the PowerShell Integrated Console during debugging, a user can use a PowerShell command Set-PSBreakpoint to set both line and function breakpoints. On the line breakpoints we can use the BreakpointEvent to communicate this back to VSCode;

https://github.com/Microsoft/vscode-debugadapter-node/blob/b61cf04501cfe7356b695f99bc60961684f89a4f/protocol/src/debugProtocol.ts#L179-L189

However I'm not finding an equivalent event for function breakpoints. What am I missing? Or is this missing from the debug protocol?

Add Remote and Snapshot debugging operations

Add notifications used in remote debuggers and Cloud applications debuggers
They are used for debugging of application deployed to production cloud infrastructure

  • Attach : all remote debuggers
  • Set snap point : Microsoft Snapshot debugger for remote .Net debugging
  • Set conditional Snap point
  • Inspect snapshot : Microsoft Snapshot debugger for remote .Net debugging, Google Stackdriver debugger
  • Take-a-snapshort Microsoft Snapshot debugger for remote .Net debugging, Google Stackdriver
  • View snapshot - Microsoft Snapshot debugger for remote .Net debugging, Google Stackdriver debugger
  • Clear snapshotMicrosoft Snapshot debugger for remote .Net debugging, Google Stackdriver debugger

Parsing logMessage templates

As of 4102c79 the specification for logMessage is lacking in detail on how to parse the attribute

If this attribute exists and is non-empty, the backend must not 'break' (stop) but log the message instead. Expressions within {} are interpolated.

For some languages it is quite normal for expressions to include the { and } delimiters, in Perl for instance you might want to log

Value of key field in hash is {$hash{key}} # ?

I would expect either \-escaping or actually configurable delimiters. For Perl it might be better to use backticks instead of curly braces, for instance, in which case the specification should allow implementations to vary on that point.

ExitedEvent versus TerminatedEvent

When should a debugger use the ExitedEvent vs the TerminatedEvent? The PowerShell debugger is launched (it doesn't support attach yet) but we are sending a TerminatedEvent at the end which apparently causes the client to send us a disconnectRequest which is a bit odd. We don't respond to this message because we are in the middle of shutting the debug host down. This results (sometimes) in a Error Canceled popup. It seems to happen when we pause/resume the debugger.

If I switch that to use the ExitedEvent we don't get the disconnectRequest message but the client pops a new error Error Debug adapter process has terminated unexpectedly. And if the program was paused and resumed it also pops up Error Canceled.

launch request type for listening/await modes

The vscode-debug-perl extension supports a launch.json configuration where it just starts a TCP server and awaits an incoming connection from a debugger (possibly on a remote machine). It neither launches the debugger nor the debuggee, so it's not really request: launch; it also does not attach to anything, so it's not request: attach either.

It also supports launching debugger+debuggee on the local machine. That matches request: launch, but it seems strange to use request: launch for both scenarios. Perhaps another type could be allowed, like request: listen (or await) to cover the first scenario?

Debug Adapter Protocol: Is there any way to send an event to vscode to initiate a variable request

I'm writing a debug adapter for a Z80 emulator. I would like to change some variables (e.g. memory or register values) at the emulator and then display the result in vscode. Currently I have put the registers in the VARIABLES area and on every step-over (next) vscode sends a variable request to get the variables updated. That works fine.

But how should it work if e.g. the debugger is paused and then a register value is changed manually at the emulator.

I would like to inform vscode about the new value but there doesn't seem to be any API for this.

Every update request is initated from vscode as it seems. Or am I missing something?

  • VSCode Version: 1.22.2
  • OS Version: OSX 10.13.4

Variables, evaluation, and escaping

It seems to me, after guessing and experiments with some debug adapters, that Variable.value is supposed to hold a string that can be evaluated (in some unspecified context) to some approximately equivalent value. So, when the value is the 4-letter string null, it is supposed to be something like "null".

The specification completely fails to discuss that, and existing debug adapters implement this improperly, including Microsoft's own debug adapters. For instance, when debugging typescript, and my variable holds a string that contains quote marks, they are not escaped. Consequently, when I right click the variable, select »Set Value«, and want to append a single character, I may have to go through the whole string to manually escape quote marks and possibly other characters, to make up an expression that can be evaluated.

Likewise, the specification never says for setVariable that the value is actually not a value but an expression that ought to be evaluated in the context of the variablesReference first, before modifying the variable.

The specification should call this out explicitly, including the need to escape values properly, and probably ought to link Variables requests semantically to SetVariable requests (values from a response to the former should be valid input to the latter, with the general expectation that setting a variable to the value reported by the Variables request, does not change the value or its properties like its type).

Document DAP features that are not yet implemented in all IDEs

The debug adapter protocol is independent from VS Code and contains quite a few features that are not implemented in VS Code but exist in VS or VS for Mac.
In the VS Code release notes you always try to clearly state whether a new DAP feature is implemented in VS Code or not.
But it is difficult to review all release notes to find if a feature of the DAP is implemented or not.

For now the only way I see is to test the feature and see if it does something. But when it doesn't I'm not sure if the feature is not implemented or if I misuse the DAP.

Maybe some labels like "VSCode-only" or "VS-only" in the DAP documentation could help developers what is available for the IDE they target ?

Add shellProcessId to RunInTerminalResponse

Enhancement request raised as a result of microsoft/vscode#61640

Apparently it is not possible for the response from RunInTerminalRequest to return in the (optional) processId value the PID in which the requested command was executed. I would like a new return value shellProcessId that gives us the PID of the shell. In some circumstances we may be able derive the command PID from that.

GotoTarget lifetime

The specification does not define the lifetime of a GotoTarget as obtained from a given GotoTargetsRequest, so it is unclear if it's legal for an IDE to cache them and reuse them later (possibly across goto, across continue, or in different frames that just happen to use the same source), or whether the adapter can clean up associated resources more aggressively - e.g. on invalidate them on every goto.

It's also unclear whether the adapter can return different IDs for the same file/line on a subsequent request, even if it ensures that old IDs are still valid to use in goto - and if it can do so, then how should the IDE interpret this.

Debug protocol: support side effect flags on expressions

In order to use the debug protocol in VS and Xamerin, we need the ability to differentiate between expressions that contain side effects and those that don't. In VS, for instance, the expression evaluator being used by the debugger can mark an expression as side effect free, therefore, safe for implicit evaluation, and non-side effect free evaluations. As mentioned above, this is primarily used to determine if an expression is safe to re-evaluate at each break mode, or if it should only evaluate once. Examples of expressions with side effects:
I=3;
Foo();
Examples of expressions without side effects:
squild.length where length is a property getter (still requiring func-eval but safe).

An optional flag on the evaluation result and the the variables result would be sufficient.

Debug session recovery in the case of brief disconnection

Actual:
It looks like DAP inherits single node architecture where application and debugger are located on same computer or local network, both are state-full and restart of both partners can be manually synchronized. in the real world cloud scenario the debugger client are stateful but everything between is stateless

Breakpoint hit count

Some clients display the breakpoint hit count, as a number next to the breakpoint decoration. Especially useful with hitCondition. We could use BreakpointEvent for this.

cc
@mostafaeweda
@ebluestein

Allow DAP to set granularity for steps

For a lot of languages it makes sense to set granularity for steps. For instance, in any bytecode language it makes sense for step normally step over lines, but sometimes it should step over bytecode instead.

Debug protocol: Please add Variable::settable

From @vadimcn on August 5, 2016 19:11

  • VSCode Version: 1.4
  • OS Version: All

When a debug adapter reports that is supports setVariable, all leaf variables become editable, but compound objects do not. While a reasonable heuristic, this is not optimal because:

  • primitive values may be not editable if they are "synthetic" i.e. generated by a visualizer.
  • compound objects may be editable, e.g. std::string (which may still want to show individual characters as children, and possibly provide a "raw" view of the implementation as a synthetic child).

I'd suggest adding an explicit "settable" flag into Variable.

Copied from original issue: microsoft/vscode#10217

Proposal: Support for reading registers

We propose that adapters can present a set of CPU registers to the frontend by returning an additional scope in response to the scopes request. The name of this scope would be provided in the adapter's Capabilities to support frontends such as VS that show registers in a separate window. This allows adapters to localize the scope's name for display in VSCode while still allowing VS to find it:

export interface Capabilities {
    // ....

    /** Name of the scope that contains register variables. */
    registersScopeName?: string;
}

In the simplest form, the scope would contain one variable for each register, e.g.:

  • [Scope] Registers
    • [Variable] EAX = ...
    • [Variable] EBX = ...
    • [Variable] XMM0 = ...
    • [Variable] XMM1 = ...
    • ...

Additionally, VS supports categorization of registers, and allows individual categories to be shown / hidden. This could be supported via nesting, where the intermediate level variable provides the category name and contains the actual register values as children, e.g.:

  • [Scope] Registers
    • [Variable] CPU
      • [Variable] EAX = ...
      • [Variable] EBX = ...
      • ...
    • [Variable] SSE
      • [Variable] XMM0 = ...
      • [Variable] XMM1 = ...
      • ...

CC: @gregg-miskelly

Type information proposal

Some debuggers (WinDbg is a good example) support a command to display information for a particular type. dt ntdll!_PEB. It would be nice if DAP supported a similar request, as this is a not-uncommon "power feature" in debuggers.

The main complicating factor here is that types can be pretty complicated, so there is the question of whether it is worth designing a serialization format for them and what granularity of information you wish to report (for example, would it only be sufficient for dumping a high-level representation of the type, or would it be sufficient for reconstructing an accurate AST?).

Support for attaching a command interpreter to a pty slave

I work on lldb and would like to provide functionality for lldb to be handed a pty slave and then attach it's standard command interpreter. Note that we'd like this functionality in addition to the Debug Console prompt as that is only used for expression evaluation.

Within lldb-vscode, we just offer the user to prefix their Debug Console input with a literal backtick to pass the command to the CommandInterpreter class. This is a clumsy work around. It lacks completion, history, and the rest of the editline/readline repertoire that command line users are used to.

A temporary workaround I've done is to just launch lldb-vscode in the terminal and attach the CommandInterpreter to the standard stdin/out/err pty slave and then listen to the DAP communication over a socket connection. But this is just another clumsy workaround.

We envision the server responding to initialize with supportsAttachingCommandInterpreter: true or a similar packet to which the client would respond by doing the ptyopen dance and handing the slave to the server via commandInterpreterPty: "/dev/pty0123" and then opening a new terminal emulator attached to the master. The server could then open("/dev/pty0123", "rw"); and dup to stdout and stderr to have a full fidelity command line debugging experience on top of the lovely integrated GUI experience.

Data breakpoints proposal

Data breakpoints are only available if the supportsDataBreakpoints capability is true:

/** Information about the capabilities of a debug adapter. */
export interface Capabilities {

	// ...

	/** The debug adapter supports data breakpoints. */
	supportsDataBreakpoints?: boolean;
}

The dataBreakpointInfo request must be used to determine whether a data breakpoint is available for a specific variable or expression and returns a "data id" for it.

/** DataBreakpointInfo request; value of command field is 'dataBreakpointInfo'.
	Obtains information on a possible data breakpoint that could be set on an expression or variable.
*/
export interface DataBreakpointInfoRequest extends Request {
	// command: 'dataBreakpointInfo';
	arguments: DataBreakpointInfoArguments;
}

/** Arguments for 'dataBreakpointInfo' request. */
export interface DataBreakpointInfoArguments {
	/** Reference to the Variable container if the data breakpoint is requested for a child of the container. */
	variablesReference?: number;
	/** The name of the Variable's child to obtain data breakpoint information for. If variableReference isn’t provided, this can be an expression. */
	name: string;
}

/** Response to 'dataBreakpointInfo' request. */
export interface DataBreakpointInfoResponse extends Response {
	body: {
		/** 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. */
		dataId: string | null;
		/** UI string that describes on what data the breakpoint is set on or why a data breakpoint is not available. */
		description: string;
		/** Optional attribute listing the available access types for a potential data breakpoint. A UI frontend could surface this information. */
		accessTypes?: DataBreakpointAccessType[];
		/** Optional attribute indicating that a potential data breakpoint could be persisted across sessions. */
		canPersist?: boolean;
	};
}

The "data id" (and additional breakpoint options) can be used to create a DataBreakpoint:

/** Properties of a data breakpoint passed to the setDataBreakpoints request. */
export interface DataBreakpoint {
	/** An id representing the data. This id is returned from the dataBreakpointInfo request. */
	dataId: string;
	/** The access type of the data. */
	accessType?: DataBreakpointAccessType;
	/** An optional expression for conditional breakpoints. */
	condition?: string;
	/** An optional expression that controls how many hits of the breakpoint are ignored. The backend is expected to interpret the expression as needed. */
	hitCondition?: string;
}

/** This enumeration defines all possible access types for data breakpoints. */
export type DataBreakpointAccessType = 'read' | 'write' | 'readWrite';

Multiple data breakpoints are registered and deregistered for a debug session with the setDataBreakpoints request:

/** SetDataBreakpoints request; value of command field is 'setDataBreakpoints'.
	Replaces all existing data breakpoints with new data breakpoints.
	To clear all data breakpoints, specify an empty array.
	When a data breakpoint is hit, a 'stopped' event (with reason 'data breakpoint') is generated.
*/
export interface SetDataBreakpointsRequest extends Request {
	// command: 'setDataBreakpoints';
	arguments: SetDataBreakpointsArguments;
}

/** Arguments for 'setDataBreakpoints' request. */
export interface SetDataBreakpointsArguments {
	/** The contents of this array replaces all existing data breakpoints. An empty array clears all data breakpoints. */
	breakpoints: DataBreakpoint[];
}

/** Response to 'setDataBreakpoints' request.
	Returned is information about each breakpoint created by this request.
*/
export interface SetDataBreakpointsResponse extends Response {
	body: {
		/** Information about the data breakpoints. The array elements correspond to the elements of the input argument 'breakpoints' array. */
		breakpoints: Breakpoint[];
	};
}

And a new value dataBreakpoint for the VariablePresentationHint can be used to hint to the UI frontend that a data breakpoint is installed on a variable.

/** Optional properties of a variable that can be used to determine how to render the variable in the UI. */
export interface VariablePresentationHint {
	/** The kind of variable. Before introducing additional values, try to use the listed values.
		Values: 
                 // ...
		'dataBreakpoint': Indicates that a data breakpoint is registered for the object.
		etc.
	*/
	kind?: string;

	// ...
}

DataBreakpointEvent?

I might be missing something here, but the Breakpoint type is for »Information about a Breakpoint created in setBreakpoints or setFunctionBreakpoints« while DataBreakpoint is for »Properties of a data breakpoint passed to the setDataBreakpoints request« and the BreakpointEvent is only for Breakpoint breakpoints. So it does not make sense to use BreakpointEvent for a change in a DataBreakpoint.

There is no DataBreakpointEvent. Is that an accidental omission?

I might want to create a data breakpoint based on a launch.json configuration option and inform vscode about it, so users can disable the breakpoint if they so choose (or for that matter, users might configure data breakpoints through the debug console instead of the vscode ui, and then I might also want to surface such breakpoints through vscode anyways).

Update Debug Adapter Protocol to support notifying of function breakpoints

Raised as a result of the suggestion from @weinand on microsoft/vscode#59746

The debug protocol provided by vscode allows the IDE to inform the debug server of function breakpoints that should be set by sending a SetFunctionBreakpoints request. This request contains an array of objects of type FunctionBreakpoint.

The debug protocol also allows the debug server to inform the IDE that breakpoints have been set by sending a BreakpointEvent. This event contains information on whether the breakpoint was added, removed or changed and contains an object of type Breakpoint representing the event.

Unfortunately this Breakpoint type is for source breakpoints and doesn't contain the ability to specify information about function breakpoints. I tried a few different things by not setting line numbers, source file etc. but they all resulted in issues with the breakpoints view in vscode.

I had a look through debugSession.ts in the vscode source (see line 365) and there is some logic for function breakpoints, but it doesn't apply if the reason on the event is 'new'

breakpoints not available on startup

Hi,
I was trying to read the vscode.debug.breakpoints array from the launchRequest method.
But unfortunately the array is defined but empty even if breakpoints are set in the sources.

Additional info: If I access the same array from the restartRequest the array is filled with all breakpoints.

"readOnlyTarget" capability

Nuclide has a "readOnlyTarget" capability flag which disables some unsupported features of the debugger, for debugging static dumps. This should exist in the debug protocol too.

Instead of a master flag like "readOnlyTarget", we would prefer more specific flags for individual features. But capabilities usually enable features, not disable them, and it seems weird to have a flag like supportsStepping which must be set 99% of the time.

@mostafaeweda
@ebluestein

Which features are disabled by this flag? Do you think there would be different features supported in different situations (so they'd need to be disabled on a more granular level)?

VS docs: https://msdn.microsoft.com/en-us/library/d5zhxt22.aspx

Debug Adapter protocol definition clarification

I propose to clarify Debug Adapter protocol definition and add words "High level language" It will prevent protocol features inflation by features like "Arm processor register reading" or "Display content of nVidea GPU memory".
Any high level language is abstraction and debugger UI has its own abstraction: it has stack pane, global and local variables pane, breakpoints pane, variable watch pane, hosted editor pane to display and navigate through source code, Server can order source coding modification via passing editor commands. Command pane and message pane are displayed bellow. Callouts and Popup windows can appear to display requests results. Hoover over source code tokens produces events which trigger requests to server. Module source opening, code changes, save, etc are reported to the server as didOpened, didModified, didSaved notifications. Server notifies. UI in the cases when intermediate processing results should be reflected by UI immediately.
Expected UI behavior should be explained in implementation notes if it is self explainable like it is done in LSP protocol definition. These notes are used for future Debugger UI implementors. Nothing is assumed!

Debug adapter protocol: Allow for breakpoints to resolve to multiple locations

Currently, the protocol allows the debug adapter to respond to a SetBreakpoints request with a response that contains a Breakpoint (https://github.com/Microsoft/vscode-debugadapter-node/blob/master/protocol/src/debugProtocol.ts#L1462)

Breakpoint, if representing a Verified breakpoint, has a single notion of the breakpoint's resolved location. But for many debug adapters, a single breakpoint might actually resolve to n locations. This is especially true for native debuggers where a function in a header file might be inlined all over the program.

The debug adapter can maintain this mapping internally and not share it with the UX, but then the user can't accurately see the location(s) a breakpoint resolved to.

Would it be possible to add something like an optional array of resolved locations to Breakpoint? Maybe something like:

export interface BreakpointLocation {
    /** The source where the breakpoint is located. */
    source?: Source;
    /** The start line of the actual range covered by the breakpoint. */
    line?: number;
    /** An optional start column of the actual range covered by the breakpoint. */
    column?: number;
    /** An optional end line of the actual range covered by the breakpoint. */
    endLine?: number;
    /** An optional end column of the actual range covered by the breakpoint. If no end line is given, then the end column is assumed to be in the start line. */
    endColumn?: number;
}

Debug protocol: Support browser launching

Currently the debug protocol has no way for a debug adapter to request that the IDE open up a web browser. Some debug adapters, such as the C# debug adapter, can start a web browser as part of launching a web server project. The debug adapter needs some control to be able to signal when the web server is ready.

This could either be designed as an event (ex: WebServerReady) or as a callback request like starting processes in the terminal.

Dependent issue: dotnet/vscode-csharp#2657
Related issue: microsoft/vscode-debugadapter-node#153

GotoTargetsArguments should have thread id

Currently GotoTargetsArguments provides only source, line, and column. This is not enough to identify if a given line is valid for the user to move there. It should have threadId as an argument. This will allow the debugger to validate.

# test.py
def foo():
    print('A')  # suppose thread 2 is stopped here

def bar():
    print('B')  # suppose thread 1 is stopped here
    print('C')

It is valid for thread 1 to move within the same block to print('C'). It is not valid for thread 2 to move to print('C'). There is no way to tell which thread the user wants to move from the arguments of gotoTargets request. The goto request will fail for thread 2, but this can be avoided.

For the screenshot below, I forced a blank targets response. This allows IDE to show changes to cursor indicating the move invalid
image

Issue with how responses are defined

In your json, you have responses simply as extending generic response + description, which is incorrect because response has to have same command value as request. So it should be marked in same was as responses are, ie with constant enum for command. What I would propose is to fix those to this:

"LaunchResponse": {
		"allOf": [ { "$ref": "#/definitions/Response" }, {
			"type": "object",
			"description": "Response to 'launch' request. This is just an acknowledgement, so no body field is required.",
			"properties": {
				"command": {
					"type": "string",
					"enum": [ "launch" ]
				}
			},
			"required": [ "command"  ]
		}]
	}

Proposal: Support for memory access and disassembly

This proposal covers both disassembly and memory access, since they both depend on the same underlying primitive - a "memory reference".

Memory references

A memory reference is an opaque identifier that can be used (along with an optional byte offset) to identify a single location in memory. An adapter has the option of providing a memory reference on several protocol objects that represent things a frontend might want to display in a memory view or use as a starting point for disassembly:

export interface EvaluateResponse {
    // ...

    /**  Memory reference to an adapter-determined location appropriate for this result.  For pointer types, this is generally a reference to the memory address contained in the pointer. */
    memoryReference?: string;
}

export interface Variable {
    // ...

    /** Memory reference for the variable if the variable represents executable code, such as a function pointer. */
    memoryReference?: string;
}

export interface StackFrame {
    // ...

    /** Memory reference for the current instruction pointer in this frame. */
    instructionPointerReference?: string;
}

export interface GotoTarget {
    // ...

    /** Memory reference for the instruction pointer value represented by this target. */
    instructionPointerReference?: string;
}

Memory references are expressed as strings rather than numbers because the most common implementation will likely be to use the address directly, and a 64-bit memory address will not fit in a JSON number.

Reading memory

Reading memory from a location represented by a memory reference and offset is accomplished via a new readMemory request:

export interface Capabilities {
    // ...

    /** The debug adapter supports the 'readMemory' request. */
    supportsReadMemoryRequest?: boolean;
}

/** Reads bytes from memory at the provided location. */
export interface ReadMemoryRequest extends Request {
    // command: 'readMemory'
    arguments: ReadMemoryArguments;
}

/** Arguments for 'readMemory' request. */
export interface ReadMemoryArguments {
    /** Memory reference to the base location from which data should be read. */
    memoryReference: string;

    /** Optional offset (in bytes) to be applied to the reference location before reading data.  Can be negative. */
    offset?: number;

    /** Number of bytes to read at the specified location and offset. */
    count: number;
}

/** Response to 'readMemory' request. */
export interface ReadMemoryResponse extends Response {
    body: {
        /** The address of the first byte of data returned.  Treated as a hex value if prefixed with '0x', or as a decimal value otherwise. */
        address: string;

        /** The number of unreadable bytes encountered after the last successfully read byte.  This can be used to determine the number of bytes that must be skipped before a subsequent 'readMemory' request will succeed. */
        unreadableBytes?: number;

        /** The bytes read from memory, encoded using base64. **/
        data: string;
    }
}

Note that the read memory request should be considered to have succeeded even if none of the requested bytes are available. For instance, a read might extend into a page that is not mapped - in this case, the adapter would be expected to return the bytes it could read (if any), along with a value for unreadableBytes that can be used to skip the unmapped page.

Additionally, it is intended that a zero-byte read (that is, a readMemory request with a count of zero) could be used to determine the actual address identified by the memory reference and offset.

Disassembly

Disassembling code at a location represented by a memory reference is accomplished via a new disassemble request:

export interface Capabilities {
    // ...

    /** The debug adapters supports the 'disassemble' request. */
    supportsDisassembleRequest?: boolean;
}

/** Disassembles code stored at the provided location. */
export interface DisassembleRequest extends Request {
    // command: 'disassemble'
    arguments: DisassembleArguments;
}

/** Arguments for 'disassemble' request. */
export interface DisassembleArguments {
    /** Memory reference to the base location containing the instructions to disassemble. */
    memoryReference: string;

    /** Optional offset (in bytes) to be applied to the reference location before disassembling.  Can be negative. */
    offset?: number;

    /** Optional offset (in instructions) to be applied after the byte offset (if any) before disassembling.  Can be negative. */
    instructionOffset?: number;

    /** Number of instructions to disassemble starting at the specified location and offset.  An adapter must return exactly this number of instructions - any unavailable instructions should be replaced with an implementation-defined 'invalid instruction' value. */
    instructionCount: number;

    /** If true, the adapter should attempt to resolve memory addresses and other values to symbolic names. */
    resolveSymbols?: boolean;
}

/** Response to 'disassemble' request */
export interface DisassembleResponse extends Response {
    body: {
        /** The list of disassembled instructions. */
        instructions: DisassembledInstruction[];
    }
}

/** Represents a single disassembled instruction. */
export interface DisassembledInstruction {
    /** The address of the instruction.  Treated as a hex value if prefixed with '0x', or as a decimal value otherwise. */
    address: string;

    /** Raw bytes representing the instruction and its operands, in an implementation-defined format. */
    instructionBytes?: string;

    /** Text representing the instruction and its operands, in an implementation-defined format. */
    instruction: string;

    /** Name of the symbol that correponds with the location of this instruction, if any. */
    symbol?: string;

    /** Source location that coresponds to this instruction, if any.  Should always be set (if available) on the first instruction returned, but can be omitted afterwards if this instruction maps to the same source file as the previous instruction. */
    location?: Source;

    /** The line within the source location that corresponds to this instruction, if any. */
    line?: number;

    /** The column within the line that corresponds to this instruction, if any. */
    column?: number;

    /** The end line of the range that corresponds to this instruction, if any. */
    endLine?: number;

    /** The end column of the range that corresponds to this instruction, if any. */
    endColumn?: number;
}

The location, line, column, endLine and endColumn members on DisassembledInstruction are intended to provide a mapping between a disassembled instruction and the source code it was generated from, if this information is available to the adapter.

Formatting

A debugger UI that implements this proposal will likely want to display addresses differently for 32-bit vs 64-bit processes. This information would be conveyed via an additional property on the process event:

export interface ProcessEvent extends Event {
    // ...

    /** The size of a pointer or address for this process, in bits. */
    pointerLength?: number;
}

CC: @gregg-miskelly

Continue request shouldn't fall back on continuing all threads, when a single thread can't be continued

"Continue" currently says that if it can't continue just one thread, it should continue all threads.

The protocol shouldn't specify a fallback on different behavior - instead the continue request should fail, while a continue request without a threadID should mean "continue all threads".

@weinand:

I agree that the fallback semantics is a bad idea. Please file DAP protocol bug for this.

But please note that it might be impossible to fix this in the current version of the DAP in a non-breaking way.

cc
@mostafaeweda
@ebluestein

Debug protocol: `setVariable` identifies variables by display name

From @vadimcn on August 5, 2016 19:43

  • VSCode Version: 1.4
  • OS Version: All

The new setVariable request identifies variables by display name.
This is fragile because the name may have been generated by the adapter (e.g. [N] for array indices).
There may also be more than one variable with the same name in the stack frame in languages that allow variable shadowing. For example, in C++ one can write

int a = 10; 
{ 
    int a = 20;
    ... // There are now two `a`'s here! 

The debugger can see both, even though in C++ there's no way to access the outer one.

To make this work robustly, I would suggest adding an optional "handle" field into Variable, which gets round-tripped back to the adapter in setVariable.

Copied from original issue: microsoft/vscode#10219

Valid values for IDs are underspecified

The spec just says that all IDs are numbers - which is to say, 64-bit floats. It does not say much about how they should be compared, including weird cases like NaN or positive/negative zero, which are seemingly legal.

In practice it seems that protocol clients have much more stringent limitations - for example, VS uses 32-bit integers internally for many IDs, and is unable to cope with any number that doesn't fit. It would be nice to reflect it in the spec itself, limiting the values to some sane subset that all current implementations support in practice (e.g. int32 > 0?).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.