Skip to content

Commit

Permalink
Move readMemory and writeMemory into Adapter Capabilities
Browse files Browse the repository at this point in the history
Abstract the readMemory and writeMemory into adapter-capbilities so
that different adapter targets can override them as needed.
  • Loading branch information
WyoTwT committed Apr 5, 2024
1 parent fd1d918 commit eb25f0b
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 9 deletions.
7 changes: 7 additions & 0 deletions src/plugin/adapter-registry/adapter-capabilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { DebugProtocol } from '@vscode/debugprotocol';
import * as vscode from 'vscode';
import { Context, isDebugRequest, isDebugResponse } from '../../common/debug-requests';
import { VariableRange } from '../../common/memory-range';
import { ReadMemoryArguments, ReadMemoryResult, WriteMemoryArguments, WriteMemoryResult } from '../../common/messaging';
import { Logger } from '../logger';

/** Represents capabilities that may be achieved with particular debug adapters but are not part of the DAP */
Expand All @@ -32,6 +33,8 @@ export interface AdapterCapabilities {
getSizeOfVariable?(session: vscode.DebugSession, variableName: string): Promise<bigint | undefined>;
initializeAdapterTracker?(session: vscode.DebugSession): vscode.DebugAdapterTracker | undefined;
getChildContexts?(session: vscode.DebugSession): Promise<Context[]>;
readMemory?(session: vscode.DebugSession, params: ReadMemoryArguments, child?: Context): Promise<ReadMemoryResult>;
writeMemory?(session: vscode.DebugSession, params: WriteMemoryArguments, child?: Context): Promise<WriteMemoryResult>;
}

export type WithChildren<Original> = Original & { children?: Array<WithChildren<DebugProtocol.Variable>> };
Expand Down Expand Up @@ -134,6 +137,10 @@ export class AdapterVariableTracker implements vscode.DebugAdapterTracker {
getSizeOfVariable?(variableName: string, session: vscode.DebugSession): Promise<bigint | undefined>;

getChildContexts?(session: vscode.DebugSession): Promise<Context[]>;

readMemory?(session: vscode.DebugSession, params: ReadMemoryArguments, context: Context): Promise<ReadMemoryResult>;

writeMemory?(session: vscode.DebugSession, params: WriteMemoryArguments, context: Context): Promise<WriteMemoryResult>;
}

export class VariableTracker implements AdapterCapabilities {
Expand Down
25 changes: 24 additions & 1 deletion src/plugin/adapter-registry/amalgamator-gdb-tracker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,31 @@

import * as vscode from 'vscode';
import { Context } from '../../common/debug-requests';
import { GetChildContextsResult } from '../../common/messaging';
import { GetChildContextsResult, ReadMemoryArguments, ReadMemoryResult, WriteMemoryArguments, WriteMemoryResult } from '../../common/messaging';
import { AdapterCapabilities, AdapterVariableTracker, VariableTracker } from './adapter-capabilities';

export interface AmalgamatorReadArgs extends ReadMemoryArguments {
child: Context;
}

export class AmalgamatorSessionManager extends VariableTracker implements AdapterCapabilities {
async getChildContexts(session: vscode.DebugSession): Promise<Context[]> {
return this.sessions.get(session.id)?.getChildContexts?.(session) || [];
}

async readMemory(session: vscode.DebugSession, args: ReadMemoryArguments, child: Context): Promise<ReadMemoryResult> {
if (!child) {
vscode.window.showErrorMessage('Invalid child for Amalgamator. Select Child in Dropdown');
return {
address: args.memoryReference
};
}
return this.sessions.get(session.id)?.readMemory?.(session, args, child);
}

async writeMemory(session: vscode.DebugSession, args: WriteMemoryArguments, child: Context): Promise<WriteMemoryResult> {
return this.sessions.get(session.id)?.writeMemory?.(session, args, child);
}
}

export class AmalgamatorGdbVariableTransformer extends AdapterVariableTracker {
Expand All @@ -38,4 +56,9 @@ export class AmalgamatorGdbVariableTransformer extends AdapterVariableTracker {
}
return Promise.resolve(this.childContexts);
}

readMemory(session: vscode.DebugSession, args: ReadMemoryArguments, child: Context): Promise<ReadMemoryResult> {
const amalReadArgs: AmalgamatorReadArgs = {...args, child};
return Promise.resolve(session.customRequest('cdt-amalgamator/readMemory', amalReadArgs));
}
}
25 changes: 17 additions & 8 deletions src/plugin/memory-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,24 +144,33 @@ export class MemoryProvider {
}

public async readMemory(args: [DebugProtocol.ReadMemoryArguments, Context?]): Promise<ReadMemoryResult> {
return sendRequest(this.assertCapability('supportsReadMemoryRequest', 'read memory'), 'readMemory', args[0]);
const session = this.assertCapability('supportsReadMemoryRequest', 'read memory');
const handler = this.adapterRegistry?.getHandlerForSession(session.type);
if (handler?.readMemory) { return handler.readMemory(session, args[0], args[1]); }
return sendRequest(session, 'readMemory', args[0]);
}

public async writeMemory(args: [DebugProtocol.WriteMemoryArguments, Context?]): Promise<WriteMemoryResult> {
const readArgs = args[0];
const writeArgs = args[0];
const session = this.assertCapability('supportsWriteMemoryRequest', 'write memory');
// Schedule a emit in case we don't retrieve a memory event
this.scheduledOnDidMemoryWriteEvents[readArgs.memoryReference] = response => {
this.scheduledOnDidMemoryWriteEvents[writeArgs.memoryReference] = response => {
// We only send out a custom event if we don't expect the client to handle the memory event
// since our client is VS Code we can assume that they will always support this but better to be safe
const offset = response?.offset ? (readArgs.offset ?? 0) + response.offset : readArgs.offset;
const count = response?.bytesWritten ?? stringToBytesMemory(readArgs.data).length;
this._onDidWriteMemory.fire({ memoryReference: readArgs.memoryReference, offset, count });
const offset = response?.offset ? (writeArgs.offset ?? 0) + response.offset : writeArgs.offset;
const count = response?.bytesWritten ?? stringToBytesMemory(writeArgs.data).length;
this._onDidWriteMemory.fire({ memoryReference: writeArgs.memoryReference, offset, count });
};
const handler = this.adapterRegistry?.getHandlerForSession(session.type);
if (handler?.writeMemory) { return handler.writeMemory(session, writeArgs, args[1]).then(response => {
// The memory event is handled before we got here, if the scheduled event still exists, we need to handle it
this.scheduledOnDidMemoryWriteEvents[writeArgs.memoryReference]?.(response);
return response;
}); };

return sendRequest(session, 'writeMemory', readArgs).then(response => {
return sendRequest(session, 'writeMemory', writeArgs).then(response => {
// The memory event is handled before we got here, if the scheduled event still exists, we need to handle it
this.scheduledOnDidMemoryWriteEvents[readArgs.memoryReference]?.(response);
this.scheduledOnDidMemoryWriteEvents[writeArgs.memoryReference]?.(response);
return response;
});
}
Expand Down

0 comments on commit eb25f0b

Please sign in to comment.