-
Notifications
You must be signed in to change notification settings - Fork 132
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add new Memory Event to refresh an address range #194
Comments
The I think we would also implicitly invalidate memory if the source of the memory being read (e.g. |
Hi, EDIT: I was using GDB "Memory Changed" event as a reference: A memory changed for a given range should trigger a refresh. It should be perfect if we can |
@yannickowow thanks for the proposal Introducing a new event with specific properties for Memory ranges makes sense and corresponds to the other DAP events for Modules, Threads, LoadedSource, and Process. I do not recommend to use the @gregg-miskelly @yannickowow @connor4312 |
Another possibility is to send an event with |
I am assuming the primary scenario here something like: the client has a memory window, and the something decides make an operation that writes to memory (for example, the user modifies a local variable) and we want to let the memory window know that it should refresh the given address range if it was being shown. Is that correct? Assuming so: I think I would agree with @yannick-mamudo that we probably want to remove If a DA knows that some memory changed, but doesn't know what memory that was (ex: an assignment where the underlying debugger doesn't easily expose what addresses were modified), should we use an |
I don’t think clients have any way to ‘interpret’ memoryReferences. They are opaque to clients so even if server returned an address and count, client would not have any way to map that to something it knows about. Agree that Invalidated seems wrong for this, but in either case it requires the DA to remember (somehow?) that client has a memory window open for a given range. Unless I’m missing something, without this wouldn’t this event be really noisy… like every write to memory triggering an event? if the intention is to only raise these events when the client cares, then there needs to be some synchronisation for client to request and then cancel these updates? Am I missing something obvious? |
Yes you're right. But this event should return an
If a client does not have a That's why I suppose that we need to remove |
I still think there's a pathological case here. if the server is to produce an event on any change to any memory that ever had a readMemeoryRequest made for it, then on a long debug session, can't that combine to a lot of redundant chatter. Example:
I agree that removing data reduces the chatter somewhat, but it's still potentially significant work for both client and adapter.
I didn't realise that was the intention of the |
I might explained it incorrectly or you missed the point. A Debug Adapter will not be aware of any Memory Window opened nor previous requests done. These sort of events are already supported by GDB, using "memory-changed" MI Event. Your current adapter will only need to translate between GDB and DAP response. |
I’m still utterly confused. What I would suggest is that if/when this is included in the specification that a clear set of use cases and expected client and server behaviours are included. I don’t think that just referencing some gdb behaviour is sufficient for that. Maybe a message flow diagram etc. Certainly I would only implement this in my client if the there are clear bounds on the frequency of this event and that servers are well directed in how to implement it. Happy to discuss further ofc. |
I think this would solve your issue, @puremourning. That removes the notion of "windows" and provides a lightweight way to indicate when the underlying memory changes, which could span across opened "windows". The lifecycle of that memory would be tied to the Variable it's associated with, and notifications would be sent using the same behavior as "invalidated". Memory references can also be returned from evaluation and disassembly--I'm not sure whether a DA would ever want to indicate mutation on those. |
I think we've achieved agreement about the event's properties: the /**
* This event indicates that some memory has been updated.
* Clients typically react to the event by issuing a `readMemory` request if they show the memory range
* in the UI, otherwise they ignore the event.
* Debug adapters can use this event to indicate that the contents of a memory range has changed
* due to some other DAP request like `setVariable` or `setExpression`.
* Debug adapters are not expected to use this event to indicate each and every memory change of a
* running program, because that information is typically not available from debuggers and it would flood
* clients with too many events.
*/
interface MemoryEvent extends Event {
event: 'memory';
body: {
/* Start address where memory has been updated.
* Treated as a hex value if prefixed with '0x', or as a decimal value otherwise.
**/
address: string;
/* Number of bytes updated.
*/
count: number;
};
} Opinions? |
Sounds great to me. |
@annickowow oops, copy-paste error... thanks for spotting this. I've fixed this in my comment above. |
Looking better, thanks! I wonder if we can slightly modify the wording to be clear about how the client uses this event to issue a 'readMemory' request. It says:
A readMemory request contains a
Therefore, perhaps this wording (or similar), changes in bold:
|
Something interesting about the previous Read/WriteMemory requests is that they don't imply that all memory is in single contiguous range, and therefore don't require that However, since refresh memory only has an address, now this implies or requires that addresses for read memory are unique. For JavaScript (and I'm guessing several other interpreted languages) this means that I effectively have to write an "allocator" to slot binary data I read from the runtime into arbitrary places in I think using the |
@connor4312 good point about the "parameter consistency". @puremourning I've tried to fold your proposed wording into the comment. /**
* This event indicates that some memory range has been updated.
* Clients typically react to the event by re-issuing a readMemory request if they show the memory
* identified by the memoryReference and if the updated memory range overlaps the displayed range.
* Clients should not make assumptions how individual memoryReferences relate to each other,
* so they should not assume that they are part of a single continuous address range and might overlap.
* Debug adapters can use this event to indicate that the contents of a memory range has changed
* due to some other DAP request like `setVariable` or `setExpression`.
* Debug adapters are not expected to use this event to indicate each and every memory change of a
* running program, because that information is typically not available from debuggers and it would flood
* clients with too many events.
*/
interface MemoryEvent extends Event {
event: 'memory';
body: {
/**
* Memory reference of a memory range that has been updated.
*/
memoryReference: string;
/**
* Starting offset in bytes where memory has been updated. Can be negative.
*/
offset: number;
/**
* Number of bytes updated.
*/
count: number;
};
} |
Looks great! |
Here is the final generated spec in TypeScript: /** Arguments for 'initialize' request. */
export interface InitializeRequestArguments {
// ...
/** Client supports the memory event. */
supportsMemoryEvent?: boolean;
}
/** Event message for 'memory' event type.
This event indicates that some memory range has been updated. It should only be sent if the debug adapter
has received a value true for the `supportsMemoryEvent` capability of the `initialize` request.
Clients typically react to the event by re-issuing a `readMemory` request if they show the memory
identified by the `memoryReference` and if the updated memory range overlaps the displayed range.
Clients should not make assumptions how individual memory references relate to each other, so they
should not assume that they are part of a single continuous address range and might overlap.
Debug adapters can use this event to indicate that the contents of a memory range has changed due
to some other DAP request like `setVariable` or `setExpression`. Debug adapters are not expected
to emit this event for each and every memory change of a running program, because that information
is typically not available from debuggers and it would flood clients with too many events.
*/
export interface MemoryEvent extends Event {
// event: 'memory';
body: {
/** Memory reference of a memory range that has been updated. */
memoryReference: string;
/** Starting offset in bytes where memory has been updated. Can be negative. */
offset: number;
/** Number of bytes updated. */
count: number;
};
} |
Hi,
I open this request to have the ability to throw an event if a range of address has been updated.
Here is my first idea:
count
can be used.Thanks
The text was updated successfully, but these errors were encountered: