From eb25f0b1c04918728653d07d7278d2f81d8c1712 Mon Sep 17 00:00:00 2001 From: WyoTwT Date: Fri, 5 Apr 2024 23:25:10 +0200 Subject: [PATCH] Move readMemory and writeMemory into Adapter Capabilities Abstract the readMemory and writeMemory into adapter-capbilities so that different adapter targets can override them as needed. --- .../adapter-registry/adapter-capabilities.ts | 7 ++++++ .../amalgamator-gdb-tracker.ts | 25 ++++++++++++++++++- src/plugin/memory-provider.ts | 25 +++++++++++++------ 3 files changed, 48 insertions(+), 9 deletions(-) diff --git a/src/plugin/adapter-registry/adapter-capabilities.ts b/src/plugin/adapter-registry/adapter-capabilities.ts index 5482ed5..077075e 100644 --- a/src/plugin/adapter-registry/adapter-capabilities.ts +++ b/src/plugin/adapter-registry/adapter-capabilities.ts @@ -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 */ @@ -32,6 +33,8 @@ export interface AdapterCapabilities { getSizeOfVariable?(session: vscode.DebugSession, variableName: string): Promise; initializeAdapterTracker?(session: vscode.DebugSession): vscode.DebugAdapterTracker | undefined; getChildContexts?(session: vscode.DebugSession): Promise; + readMemory?(session: vscode.DebugSession, params: ReadMemoryArguments, child?: Context): Promise; + writeMemory?(session: vscode.DebugSession, params: WriteMemoryArguments, child?: Context): Promise; } export type WithChildren = Original & { children?: Array> }; @@ -134,6 +137,10 @@ export class AdapterVariableTracker implements vscode.DebugAdapterTracker { getSizeOfVariable?(variableName: string, session: vscode.DebugSession): Promise; getChildContexts?(session: vscode.DebugSession): Promise; + + readMemory?(session: vscode.DebugSession, params: ReadMemoryArguments, context: Context): Promise; + + writeMemory?(session: vscode.DebugSession, params: WriteMemoryArguments, context: Context): Promise; } export class VariableTracker implements AdapterCapabilities { diff --git a/src/plugin/adapter-registry/amalgamator-gdb-tracker.ts b/src/plugin/adapter-registry/amalgamator-gdb-tracker.ts index afe0f47..8c1233b 100644 --- a/src/plugin/adapter-registry/amalgamator-gdb-tracker.ts +++ b/src/plugin/adapter-registry/amalgamator-gdb-tracker.ts @@ -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 { return this.sessions.get(session.id)?.getChildContexts?.(session) || []; } + + async readMemory(session: vscode.DebugSession, args: ReadMemoryArguments, child: Context): Promise { + 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 { + return this.sessions.get(session.id)?.writeMemory?.(session, args, child); + } } export class AmalgamatorGdbVariableTransformer extends AdapterVariableTracker { @@ -38,4 +56,9 @@ export class AmalgamatorGdbVariableTransformer extends AdapterVariableTracker { } return Promise.resolve(this.childContexts); } + + readMemory(session: vscode.DebugSession, args: ReadMemoryArguments, child: Context): Promise { + const amalReadArgs: AmalgamatorReadArgs = {...args, child}; + return Promise.resolve(session.customRequest('cdt-amalgamator/readMemory', amalReadArgs)); + } } diff --git a/src/plugin/memory-provider.ts b/src/plugin/memory-provider.ts index 4fbff58..320bfb2 100644 --- a/src/plugin/memory-provider.ts +++ b/src/plugin/memory-provider.ts @@ -144,24 +144,33 @@ export class MemoryProvider { } public async readMemory(args: [DebugProtocol.ReadMemoryArguments, Context?]): Promise { - 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 { - 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; }); }