Skip to content

Commit f171d9f

Browse files
committed
Utilize GDB/MI Variable Objects for local variables
Replace own value parser with GDB's variable objects interface. See https://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Variable-Objects.html
1 parent 18f1a10 commit f171d9f

File tree

2 files changed

+61
-42
lines changed

2 files changed

+61
-42
lines changed

src/backend/mi2/mi2.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,9 @@ export class MI2 extends EventEmitter implements IBackend {
196196
];
197197
if (!attach)
198198
cmds.push(this.sendCommand("file-exec-and-symbols \"" + escape(target) + "\""));
199+
200+
// TODO: add extension parameter for enabling/disabling pretty printers
201+
cmds.push(this.sendCommand("enable-pretty-printing"));
199202
return cmds;
200203
}
201204

@@ -658,6 +661,19 @@ export class MI2 extends EventEmitter implements IBackend {
658661
});
659662
}
660663

664+
async varCreate(expression: string): Promise<MINode> {
665+
if (trace)
666+
this.log("stderr", "varCreate");
667+
return this.sendCommand(`var-create - * "${expression}"`);
668+
}
669+
670+
async varListChildren(name: string): Promise<MINode> {
671+
if (trace)
672+
this.log("stderr", "varListChildren");
673+
//TODO: add `from` and `to` arguments
674+
return this.sendCommand(`var-list-children --simple-values ${name}`);
675+
}
676+
661677
logNoNewLine(type: string, msg: string) {
662678
this.emit("msg", type, msg);
663679
}

src/mibase.ts

Lines changed: 45 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -272,32 +272,49 @@ export class MI2DebugSession extends DebugSession {
272272
return this.variableHandles.create(arg);
273273
};
274274

275+
let miVarObjToVariable = (varObj: any): DebugProtocol.Variable => {
276+
const evaluateName = MINode.valueOf(varObj, "name");
277+
const value = MINode.valueOf(varObj, "value");
278+
const numChild = parseInt(MINode.valueOf(varObj, "numchild"));
279+
const dynamic = MINode.valueOf(varObj, "dynamic") || 0;
280+
let displayHint, hasMore;
281+
if (dynamic) {
282+
displayHint = MINode.valueOf(varObj, "displayhint");
283+
hasMore = parseInt(MINode.valueOf(varObj, "has_more"));
284+
}
285+
const isCompound = numChild > 0 ||
286+
value === "{...}" ||
287+
(dynamic > 0 && (displayHint === "array" || displayHint === "map"));
288+
289+
let res = {
290+
name: MINode.valueOf(varObj, "exp"),
291+
evaluateName,
292+
type: MINode.valueOf(varObj, "type"),
293+
value: value || "<value>",
294+
variablesReference: isCompound ? createVariable(evaluateName) : 0
295+
} as DebugProtocol.Variable;
296+
return res;
297+
};
298+
275299
if (typeof id == "string") {
276300
if (id.startsWith("@frame:")) {
277301
let stack: Variable[];
278302
try {
279303
stack = await this.miDebugger.getStackVariables(this.threadID, parseInt(id.substr("@frame:".length)));
280304
for (const variable of stack) {
281-
if (variable.valueStr !== undefined) {
282-
let expanded = expandValue(createVariable, `{${variable.name}=${variable.valueStr})`, "", variable.raw);
283-
if (expanded) {
284-
if (typeof expanded[0] == "string")
285-
expanded = [
286-
{
287-
name: "<value>",
288-
value: prettyStringArray(expanded),
289-
variablesReference: 0
290-
}
291-
];
292-
variables.push(expanded[0]);
293-
}
294-
} else
305+
try {
306+
const varObj = await this.miDebugger.varCreate(variable.name);
307+
let v = miVarObjToVariable(varObj.resultRecords.results);
308+
v.name = variable.name;
309+
variables.push(v);
310+
}
311+
catch (err) {
295312
variables.push({
296313
name: variable.name,
297-
type: variable.type,
298-
value: "<unknown>",
299-
variablesReference: createVariable(variable.name)
314+
value: err,
315+
variablesReference: 0
300316
});
317+
}
301318
}
302319
response.body = {
303320
variables: variables
@@ -310,32 +327,18 @@ export class MI2DebugSession extends DebugSession {
310327
}
311328
else {
312329
// Variable members
313-
let variable;
330+
let listChildren;
314331
try {
315-
variable = await this.miDebugger.evalExpression(JSON.stringify(id));
316-
try {
317-
let expanded = expandValue(createVariable, variable.result("value"), id, variable);
318-
if (!expanded) {
319-
this.sendErrorResponse(response, 2, `Could not expand variable`);
320-
}
321-
else {
322-
if (typeof expanded[0] == "string")
323-
expanded = [
324-
{
325-
name: "<value>",
326-
value: prettyStringArray(expanded),
327-
variablesReference: 0
328-
}
329-
];
330-
response.body = {
331-
variables: expanded
332-
};
333-
this.sendResponse(response);
334-
}
335-
}
336-
catch (e) {
337-
this.sendErrorResponse(response, 2, `Could not expand variable: ${e}`);
332+
listChildren = await this.miDebugger.varListChildren(id);
333+
const children: any[] = listChildren.result("children");
334+
// TODO: use hasMore when it's > 0
335+
// const hasMore = parseInt(listChildren.result("has_more"));
336+
const vars = children.map(child => miVarObjToVariable(child[1]));
337+
338+
response.body = {
339+
variables: vars
338340
}
341+
this.sendResponse(response);
339342
}
340343
catch (err) {
341344
this.sendErrorResponse(response, 1, `Could not expand variable: ${err}`);
@@ -514,4 +517,4 @@ function prettyStringArray(strings) {
514517
return JSON.stringify(strings);
515518
}
516519
else return strings;
517-
}
520+
}

0 commit comments

Comments
 (0)