Skip to content

Commit

Permalink
feat: support readMemory/writeMemory DAP Event
Browse files Browse the repository at this point in the history
  • Loading branch information
Ricbet committed May 16, 2022
1 parent ddd2e82 commit 0e6ccc9
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 8 deletions.
106 changes: 102 additions & 4 deletions packages/debug/src/browser/debug-memory.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { clamp } from 'lodash';

import { Injectable, Autowired } from '@opensumi/di';
import {
Event,
Expand All @@ -9,9 +11,19 @@ import {
Uri,
BinaryBuffer,
Emitter,
Disposable,
ILogger,
} from '@opensumi/ide-core-common';

import { DEBUG_MEMORY_SCHEME, IDebugSessionManager } from '../common';
import {
DEBUG_MEMORY_SCHEME,
IDebugSession,
IDebugSessionManager,
IMemoryInvalidationEvent,
IMemoryRegion,
MemoryRange,
MemoryRangeType,
} from '../common';

import { DebugSessionManager } from '.';

Expand All @@ -20,7 +32,12 @@ export class DebugMemoryFileSystemProvider implements FileSystemProvider {
@Autowired(IDebugSessionManager)
protected readonly debugSessionManager: DebugSessionManager;

@Autowired(ILogger)
protected readonly logger: ILogger;

private memoryFdCounter = 0;
private readonly changeEmitter = new Emitter<FileChangeEvent>();
private readonly fdMemory = new Map<number, { session: IDebugSession; region: IMemoryRegion }>();

public readonly capabilities: FileSystemProviderCapabilities =
0 | FileSystemProviderCapabilities.PathCaseSensitive | FileSystemProviderCapabilities.FileOpenReadWriteClose;
Expand All @@ -41,13 +58,58 @@ export class DebugMemoryFileSystemProvider implements FileSystemProvider {
});
}

public readFile(uri: Uri): void | Uint8Array | Promise<void | Uint8Array> {
public async readFile(uri: Uri): Promise<void | Uint8Array> {
const parse = this.parseUri(uri);
if (parse && !parse.offset) {
if (!parse) {return this.toBuffer('');}

if (!parse.offset) {return this.toBuffer('');}

const { session, memoryReference, offset } = parse;

const data = new Uint8Array(offset.toOffset - offset.fromOffset);

const fd = this.memoryFdCounter++;
let region = session.getMemory(memoryReference);
if (offset) {
region = new MemoryRegionView(region, offset);
}

this.fdMemory.set(fd, { session, region });
await this.read(fd, offset.fromOffset, data, 0, data.length);
return data;
}

public async read(fd: number, pos: number, data: Uint8Array, offset: number, length: number): Promise<number | void> {
const memory = this.fdMemory.get(fd);
if (!memory) {
return;
}

return this.toBuffer('');
const ranges = await memory.region.read(pos, length);
let readSoFar = 0;
for (const range of ranges) {
switch (range.type) {
case MemoryRangeType.Unreadable:
return readSoFar;
case MemoryRangeType.Error:
if (readSoFar > 0) {
return readSoFar;
} else {
return this.logger.error(range.error);
}
case MemoryRangeType.Valid: {
const start = Math.max(0, pos - range.offset);
const toWrite = range.data.slice(start, Math.min(range.data.byteLength, start + (length - readSoFar)));
data.set(toWrite.buffer, offset + readSoFar);
readSoFar += toWrite.byteLength;
break;
}
default:
this.logger.log(range);
}
}

return readSoFar;
}

private toBuffer(s: string): Uint8Array {
Expand Down Expand Up @@ -112,3 +174,39 @@ export class DebugMemoryFileSystemProvider implements FileSystemProvider {
throw new Error('Method not implemented.');
}
}

class MemoryRegionView extends Disposable implements IMemoryRegion {
private readonly invalidateEmitter = new Emitter<IMemoryInvalidationEvent>();

public readonly onDidInvalidate = this.invalidateEmitter.event;
public readonly writable: boolean;
private readonly width = this.range.toOffset - this.range.fromOffset;

constructor(private readonly parent: IMemoryRegion, public readonly range: { fromOffset: number; toOffset: number }) {
super();
this.writable = parent.writable;

this.registerDispose(parent);
this.registerDispose(
parent.onDidInvalidate((e) => {
const fromOffset = clamp(e.fromOffset - range.fromOffset, 0, this.width);
const toOffset = clamp(e.toOffset - range.fromOffset, 0, this.width);
if (toOffset > fromOffset) {
this.invalidateEmitter.fire({ fromOffset, toOffset });
}
}),
);
}

public read(fromOffset: number, toOffset: number): Promise<MemoryRange[]> {
if (fromOffset < 0) {
throw new RangeError(`Invalid fromOffset: ${fromOffset}`);
}

return this.parent.read(this.range.fromOffset + fromOffset, this.range.fromOffset + Math.min(toOffset, this.width));
}

public write(offset: number, data: BinaryBuffer): Promise<number> {
return this.parent.write(this.range.fromOffset + offset, data);
}
}
16 changes: 12 additions & 4 deletions packages/debug/src/browser/tree/debug-tree-node.define.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ export class ExpressionNode extends TreeNode {
public variablesReference: number;
public namedVariables: number | undefined;
public indexedVariables: number | undefined;
public memoryReference: string | undefined;

constructor(options: ExpressionNode.Options, parent?: ExpressionContainer) {
super(new ExpressionTreeService(options.session, options.source, options.line) as ITree, parent, undefined, {
Expand All @@ -145,6 +146,7 @@ export class ExpressionNode extends TreeNode {
this.variablesReference = options.variablesReference || 0;
this.namedVariables = options.namedVariables;
this.indexedVariables = options.indexedVariables;
this.memoryReference = options.memoryReference;
this.source = options.source;
this.line = options.line;
}
Expand All @@ -165,6 +167,7 @@ export namespace ExpressionNode {
namedVariables?: number;
indexedVariables?: number;
startOfVariables?: number;
memoryReference?: string;
source?: DebugProtocol.Source;
line?: number | string;
}
Expand All @@ -178,6 +181,7 @@ export class ExpressionContainer extends CompositeTreeNode {
public namedVariables: number | undefined;
public indexedVariables: number | undefined;
public startOfVariables: number;
public memoryReference: string | undefined;

public source: DebugProtocol.Source | undefined;
public line: number | string | undefined;
Expand All @@ -196,6 +200,7 @@ export class ExpressionContainer extends CompositeTreeNode {
this.namedVariables = options.namedVariables;
this.indexedVariables = options.indexedVariables;
this.startOfVariables = options.startOfVariables || 0;
this.memoryReference = options.memoryReference;
this.source = options.source;
this.line = options.line;
}
Expand Down Expand Up @@ -225,6 +230,7 @@ export namespace ExpressionContainer {
namedVariables?: number;
indexedVariables?: number;
startOfVariables?: number;
memoryReference?: string;
source?: DebugProtocol.Source;
line?: number | string;
}
Expand Down Expand Up @@ -263,6 +269,7 @@ export class DebugVariable extends ExpressionNode {
variablesReference: variable.variablesReference,
namedVariables: variable.namedVariables,
indexedVariables: variable.indexedVariables,
memoryReference: variable.memoryReference,
},
parent,
);
Expand All @@ -278,6 +285,7 @@ export class DebugVariable extends ExpressionNode {
variablesReference: this.variable.variablesReference || 0,
value: this.value,
evaluateName: this.evaluateName,
memoryReference: this.memoryReference,
};
}

Expand Down Expand Up @@ -364,6 +372,7 @@ export class DebugVariableContainer extends ExpressionContainer {
variablesReference: variable.variablesReference,
namedVariables: variable.namedVariables,
indexedVariables: variable.indexedVariables,
memoryReference: variable.memoryReference,
source,
line,
},
Expand Down Expand Up @@ -413,10 +422,6 @@ export class DebugVariableContainer extends ExpressionContainer {
return this.variable?.evaluateName || '';
}

get memoryReference(): string {
return this.variable.memoryReference || '';
}

get description(): string {
return this._value || this.variable.value;
}
Expand Down Expand Up @@ -550,6 +555,7 @@ export class DebugWatchNode extends ExpressionContainer {
this.variablesReference = body.variablesReference;
this.namedVariables = body.namedVariables;
this.indexedVariables = body.indexedVariables;
this.memoryReference = body.memoryReference;
this.raw = body;
}
} catch (err) {
Expand Down Expand Up @@ -648,6 +654,7 @@ export class DebugConsoleNode extends ExpressionContainer {
this.variablesReference = body.variablesReference;
this.namedVariables = body.namedVariables;
this.indexedVariables = body.indexedVariables;
this.memoryReference = body.memoryReference;
this._available = true;
}
}
Expand Down Expand Up @@ -742,6 +749,7 @@ export class DebugHoverVariableRoot extends ExpressionContainer {
this.variablesReference = body.variablesReference;
this.namedVariables = body.namedVariables;
this.indexedVariables = body.indexedVariables;
this.memoryReference = body.memoryReference;
}
} catch (err) {
this._value = err.message;
Expand Down

0 comments on commit 0e6ccc9

Please sign in to comment.