Skip to content

Commit

Permalink
Add support to retrieve register values.
Browse files Browse the repository at this point in the history
  • Loading branch information
nomtats committed Feb 7, 2024
1 parent 7ee97b6 commit 65234c5
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 55 deletions.
5 changes: 5 additions & 0 deletions src/backend/backend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ export interface Variable {
raw?: any;
}

export interface RegisterValue {
index: number;
value: string;
}

export interface SSHArguments {
forwardX11: boolean;
host: string;
Expand Down
53 changes: 52 additions & 1 deletion src/backend/mi2/mi2.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Breakpoint, IBackend, Thread, Stack, SSHArguments, Variable, VariableObject, MIError } from "../backend";
import { Breakpoint, IBackend, Thread, Stack, SSHArguments, Variable, RegisterValue, VariableObject, MIError } from "../backend";
import * as ChildProcess from "child_process";
import { EventEmitter } from "events";
import { parseMI, MINode } from '../mi_parse';
Expand Down Expand Up @@ -758,6 +758,57 @@ export class MI2 extends EventEmitter implements IBackend {
return ret;
}

async getRegisters(): Promise<Variable[]> {
if (trace)
this.log("stderr", "getRegisters");

// Getting register names and values are separate GDB commands.
// We first retrieve the register names and then the values.
// The register names should never change, so we could cache and reuse them,
// but for now we just retrieve them every time to keep it simple.
const names = await this.getRegisterNames();
const values = await this.getRegisterValues();
const ret: Variable[] = [];
for (const val of values) {
const key = names[val.index];
const value = val.value;
const type = "string";
ret.push({
name: key,
valueStr: value,
type: type
});
}
return ret;
}

async getRegisterNames(): Promise<string[]> {
if (trace)
this.log("stderr", "getRegisterNames");
const result = await this.sendCommand("data-list-register-names");
const names = result.result('register-names');
if (!Array.isArray(names)) {
throw new Error('Failed to retrieve register names.');
}
return names.map(name => name.toString());
}

async getRegisterValues(): Promise<RegisterValue[]> {
if (trace)
this.log("stderr", "getRegisterValues");
const result = await this.sendCommand("data-list-register-values N");
const nodes = result.result('register-values');
if (!Array.isArray(nodes)) {
throw new Error('Failed to retrieve register values.');
}
const ret: RegisterValue[] = nodes.map(node => {
const index = parseInt(MINode.valueOf(node, "number"));
const value = MINode.valueOf(node, "value");
return {index: index, value: value};
});
return ret;
}

examineMemory(from: number, length: number): Thenable<any> {
if (trace)
this.log("stderr", "examineMemory");
Expand Down
119 changes: 65 additions & 54 deletions src/mibase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,8 @@ export class MI2DebugSession extends DebugSession {
return new Scope(scopeName, handle, expensive);
};

scopes.push(createScope("Local", false));
scopes.push(createScope("Registers", false));
scopes.push(createScope("Locals", false));

response.body = {
scopes: scopes
Expand Down Expand Up @@ -436,64 +437,74 @@ export class MI2DebugSession extends DebugSession {
};

if (id instanceof VariableScope) {
let stack: Variable[];
try {
stack = await this.miDebugger.getStackVariables(id.threadId, id.level);
for (const variable of stack) {
if (this.useVarObjects) {
try {
const varObjName = VariableScope.variableName(args.variablesReference, variable.name);
let varObj: VariableObject;
if (id.name == "Registers") {
const registers = await this.miDebugger.getRegisters();
for (const reg of registers) {
variables.push({
name: reg.name,
value: reg.valueStr,
variablesReference: 0
});
}
} else {
const stack: Variable[] = await this.miDebugger.getStackVariables(id.threadId, id.level);
for (const variable of stack) {
if (this.useVarObjects) {
try {
const changes = await this.miDebugger.varUpdate(varObjName);
const changelist = changes.result("changelist");
changelist.forEach((change) => {
const name = MINode.valueOf(change, "name");
const vId = this.variableHandlesReverse[name];
const v = this.variableHandles.get(vId) as any;
v.applyChanges(change);
});
const varId = this.variableHandlesReverse[varObjName];
varObj = this.variableHandles.get(varId) as any;
} catch (err) {
if (err instanceof MIError && err.message == "Variable object not found") {
varObj = await this.miDebugger.varCreate(variable.name, varObjName);
const varId = findOrCreateVariable(varObj);
varObj.exp = variable.name;
varObj.id = varId;
} else {
throw err;
const varObjName = VariableScope.variableName(args.variablesReference, variable.name);
let varObj: VariableObject;
try {
const changes = await this.miDebugger.varUpdate(varObjName);
const changelist = changes.result("changelist");
changelist.forEach((change) => {
const name = MINode.valueOf(change, "name");
const vId = this.variableHandlesReverse[name];
const v = this.variableHandles.get(vId) as any;
v.applyChanges(change);
});
const varId = this.variableHandlesReverse[varObjName];
varObj = this.variableHandles.get(varId) as any;
} catch (err) {
if (err instanceof MIError && err.message == "Variable object not found") {
varObj = await this.miDebugger.varCreate(variable.name, varObjName);
const varId = findOrCreateVariable(varObj);
varObj.exp = variable.name;
varObj.id = varId;
} else {
throw err;
}
}
variables.push(varObj.toProtocolVariable());
} catch (err) {
variables.push({
name: variable.name,
value: `<${err}>`,
variablesReference: 0
});
}
variables.push(varObj.toProtocolVariable());
} catch (err) {
variables.push({
name: variable.name,
value: `<${err}>`,
variablesReference: 0
});
} else {
if (variable.valueStr !== undefined) {
let expanded = expandValue(createVariable, `{${variable.name}=${variable.valueStr})`, "", variable.raw);
if (expanded) {
if (typeof expanded[0] == "string")
expanded = [
{
name: "<value>",
value: prettyStringArray(expanded),
variablesReference: 0
}
];
variables.push(expanded[0]);
}
} else
variables.push({
name: variable.name,
type: variable.type,
value: "<unknown>",
variablesReference: createVariable(variable.name)
});
}
} else {
if (variable.valueStr !== undefined) {
let expanded = expandValue(createVariable, `{${variable.name}=${variable.valueStr})`, "", variable.raw);
if (expanded) {
if (typeof expanded[0] == "string")
expanded = [
{
name: "<value>",
value: prettyStringArray(expanded),
variablesReference: 0
}
];
variables.push(expanded[0]);
}
} else
variables.push({
name: variable.name,
type: variable.type,
value: "<unknown>",
variablesReference: createVariable(variable.name)
});
}
}
response.body = {
Expand Down

0 comments on commit 65234c5

Please sign in to comment.