Repository navigation
Add a bytes range to the DataBreakpointInfo Request #455
Description
Activity
- addedfeature-requestRequest for new features or functionalityRequest for new features or functionality
on Jan 19, 2024 gregg-miskelly commented
on Jan 20, 2024 MemberMore actionsdataBreakpointInfois really about asking a debug adapter to provide a description of how to set a data breakpoint on a variable. In this scenario, it doesn't seem like there is a variable involved -- it seems like the user is really inputting an address, size, and access settings.Questions:
- Can we come up with a standard set of properties for 'access settings'? Or do we really need a custom request (like launch arguments)?
- Instead of extending
dataBreakpointInfo, should we just extendDataBreakpointso that when a new capability is present,dataIdcan have some special value (empty string?) and then there is a new field that carries additional properties about the address range?
I agree with Gregg Miskelly (@gregg-miskelly) about
DataBreakpointInfousage. Two fields from this interface,variableReferenceandframeId, are not useful for data breakpoints.
What about to introduceDataRangeBreakpointorMemoryRangeBreakpoinginterfaces, inspired byDataBreakpointbut tailored to the specific case? With a correspondingset*()method?I agree with Kostiantyn Kirenko (@kkistm) that making the interface more precise makes the purpose easier to understand and its usage cleaner.
Thanks for the feedback. How about we introduce an alternative request, like
DataAddressBreakpointInfo, with argumentsinterface DataAddressBreakpointInfoArguments { /** * The address of the data for which to obtain breakpoint information. * Treated as a hex value if prefixed with `0x`, or as a decimal value * otherwise. */ address: string; /** * If passed, requests breakpoint information for an exclusive byte range * rather than a single address. The range extends the given number of `bytes` * from the start `address`. * * Treated as a hex value if prefixed with `0x`, or as a decimal value * otherwise. */ bytes?: string }
The response is identical to the
DataBreakpointInforesponse, allowing the resultingdataIdto interop with the existingSetDataBreakpointsrequest.This covers the 'access settings' menu with the exception of the "mask" field, though that could be added as a property.
Of course this comes with a capability.
interface Capability { // ... in addition to existing properties: /** * The debug adapter supports the `dataAdressBreakpointInfo` request. */ supportsDataAddressInfo?: boolean;
Reacted by Gregg MiskellyConnor Peet (@connor4312), the proposition about
DataAddressBreakpointInfosounds good for me, keeping in mind that additional properties could be added as needed.Reacted by Connor Peethttps://microsoft.github.io/debug-adapter-protocol/specification#Requests_DataBreakpointInfo says "If
variablesReferenceisn't specified, this can be an expression." inDataBreakpointInfoArguments'snamefield. If this request is added, does this mean the name could not be an expression anymore? If no, we still need the number of bytes to watch from expression.connor4312 commented
on Feb 14, 2024 MemberAuthorMore actionsThis was finished in #461
Zequan Wu (@ZequanWu) see that PR for what we ended up doing, let us know if you have any feedback. Thanks!
Oh, I saw the new request
DataAddressBreakpointInfohas two fields:addressandbytes. Then my question might be another issue: FornameinDataBreakpointInfoArguments, it could be an expression ifvariablesReferenceis not specified, like${variable} + ${offset}. How would the debugger know how many bytes to watch from the starting address evaluated from the expression in this case?I prefer the original change by adding
bytestoDataBreakpointInfoArgumentsas this will solve both problem.connor4312 commented
on Feb 14, 2024 MemberAuthorMore actionsWe don't specify that an adapter should treat a numeric return value from an expression in
nameas a pointer to that address. A common implementation may be expecting some pointer-type result from the name and breaking either on that specific address or size of the data that was pointed to. An adapter or debugger could implement this in any number of ways. In a JavaScript runtime, there may be no notion of memory addresses at all and only object identity.While a little roundabout it's possible to get the address of a variable via its
memoryReference, which one could use to use the new range request to set a custom range of bytes for a variableA common implementation may be expecting some pointer-type result from the name and breaking either on that specific address or size of the data that was pointed to.
I think it's common the pointer-type result from the name is a
void*type which doesn't tell the underlying pointee's type information and size information in C/C++. In this case, the best we can do is to set the size to watch to the pointer size which might not always be the case.connor4312 commented
on Feb 16, 2024 MemberAuthorMore actionsReopening for discussion.
If we were to do it that way, we'd need some additional flagging for the debugger to treat the
nameas a numeric value. It's a bit of an overload, but we cannot make it optional as that would be backwards-incompatible.interface DataBreakpointInfoArguments { /** * 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. */ variablesReference?: number; /** * The name of the variable's child to obtain data breakpoint information for. * If `variablesReference` isn't specified, this can be an expression. * If `asAddress` is specified, this is a memory address: interpreted as a * hex value if prefixed with `0x`, or a decimal value otherwise. */ name: string; /** * Clients may set this variable only if the `supportsDataBreakpointBytes` * capability is true. * * Clients may pass this to request a reference to a range of memory rather * than a single address. Data breakpoints set using the resulting data ID * request that the debugger pauses within the range of memory extending * `bytes` from the address or variable specified by `name`. * * Treated as a hex value if prefixed with `0x`, or as a decimal value * otherwise. */ bytes?: number; /** * If `true`, the `name` is a memory address and the debugger should interpret. * * Clients may set this variable only if the `supportsDataBreakpointBytes` * capability is true. */ asAddress?: boolean; /** * 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. */ frameId?: number; }
Technically
asAddressandbytescould be two different capabilities, but both require an adapter able to address memory regions, so they go hand-in-hand.The downside of this is that there is less support for "address-only" properties, but otherwise it's also a nice solution and solves the issue you mention -- and practically I don't expect adapters have special behavior applicable only for a data breakpoint on a variable versus a range of addresses or vise versa.
Do we need the extra field
asAddress?Given "If
variablesReferenceisn't specified, this can be an expression." forname, an expression could be a numeric value (decimal or hex) representing the address, right?connor4312 commented
on Feb 22, 2024 MemberAuthorMore actionsI think
asAddressis preferable so that DA's don't have to try to pattern match what they're being given. In common lisp for example,0x123is also a valid variable name, so it would be impossible to differentiate when taking input from a client.connor4312 commented
on Feb 22, 2024 MemberAuthorMore actionsAfter playing around with this a bit, I prefer the new proposal in #455 (comment). I'm going to back my previous changes out of the upcoming DAP release and put a PR in with that proposal for next month's release to allow time for additional discussion.
- added a commit that references this issue
on Feb 27, 2024 - added 3 commits that reference this issue
on Feb 28, 2024
One feature from the authors of the request include the ability to set breakpoints for a range of memory:
The "event points" map pretty well onto DAP data breakpoints, except data breakpoints can only be set for singular variables in the protocol.
To allow a range to be set, we need a corresponding capability
Then there may be an additional field in the info request, which specifies the number of bytes following the address in which the debugger should stop: