From 5fc87656783a9ab0ce728f685b9f224c05fda6aa Mon Sep 17 00:00:00 2001 From: WebFreak001 Date: Sat, 13 Aug 2016 13:34:34 +0200 Subject: [PATCH] Fixed C/C++ argument list & char*[] Fix #69 (hihi Kappa) --- src/backend/backend.ts | 1 + src/backend/gdb_expansion.ts | 25 +++++-- src/backend/mi2/mi2.ts | 3 +- src/mibase.ts | 135 ++++++++++++++++++++++++++++------- test/gdb_expansion.test.ts | 13 ++++ 5 files changed, 144 insertions(+), 33 deletions(-) diff --git a/src/backend/backend.ts b/src/backend/backend.ts index eec6745..675f135 100644 --- a/src/backend/backend.ts +++ b/src/backend/backend.ts @@ -18,6 +18,7 @@ export interface Variable { name: string; valueStr: string; type: string; + raw?: any; } export interface SSHArguments { diff --git a/src/backend/gdb_expansion.ts b/src/backend/gdb_expansion.ts index 2ced453..efb5949 100644 --- a/src/backend/gdb_expansion.ts +++ b/src/backend/gdb_expansion.ts @@ -1,4 +1,6 @@ -const resultRegex = /^([a-zA-Z_\-][a-zA-Z0-9_\-]*)\s*=\s*/; +import { MINode } from "./mi_parse" + +const resultRegex = /^([a-zA-Z_\-][a-zA-Z0-9_\-]*|\[\d+\])\s*=\s*/; const variableRegex = /^[a-zA-Z_\-][a-zA-Z0-9_\-]*/; const errorRegex = /^\<.+?\>/; const referenceStringRegex = /^(0x[0-9a-fA-F]+\s*)"/; @@ -18,6 +20,7 @@ export function isExpandable(value: string): number { else if (value.startsWith("true")) return 0; else if (value.startsWith("false")) return 0; else if (match = nullpointerRegex.exec(value)) return 0; + else if (match = referenceStringRegex.exec(value)) return 0; else if (match = referenceRegex.exec(value)) return 2; // reference else if (match = charRegex.exec(value)) return 0; else if (match = numberRegex.exec(value)) return 0; @@ -26,7 +29,7 @@ export function isExpandable(value: string): number { else return 0; } -export function expandValue(variableCreate: Function, value: string, root: string = ""): any { +export function expandValue(variableCreate: Function, value: string, root: string = "", extra: any = undefined): any { let parseCString = () => { value = value.trim(); if (value[0] != '"' && value[0] != '\'') @@ -155,10 +158,10 @@ export function expandValue(variableCreate: Function, value: string, root: strin } else if (match = nullpointerRegex.exec(value)) { primitive = ""; - value = value.substr(3).trim(); + value = value.substr(match[0].length).trim(); } else if (match = referenceStringRegex.exec(value)) { - value = value.substr(match[1].length); + value = value.substr(match[1].length).trim(); primitive = parseCString(); } else if (match = referenceRegex.exec(value)) { @@ -183,7 +186,7 @@ export function expandValue(variableCreate: Function, value: string, root: strin value = value.substr(match[0].length).trim(); } else { - primitive = ""; + primitive = value; } return primitive; }; @@ -220,8 +223,16 @@ export function expandValue(variableCreate: Function, value: string, root: strin val = "Object"; } if (typeof val == "string" && val.startsWith("*0x")) { - ref = variableCreate(getNamespace("*" + name)); - val = "Object@" + val; + if (extra && MINode.valueOf(extra, "arg") == "1") + { + ref = variableCreate(getNamespace("*(" + name), { arg: true }); + val = ""; + } + else + { + ref = variableCreate(getNamespace("*" + name)); + val = "Object@" + val; + } } if (typeof val == "string" && val.startsWith("<...>")) { ref = variableCreate(getNamespace(name)); diff --git a/src/backend/mi2/mi2.ts b/src/backend/mi2/mi2.ts index 0b6f9dc..71a4a00 100644 --- a/src/backend/mi2/mi2.ts +++ b/src/backend/mi2/mi2.ts @@ -549,7 +549,8 @@ export class MI2 extends EventEmitter implements IBackend { ret.push({ name: key, valueStr: value, - type: type + type: type, + raw: element }); }); resolve(ret); diff --git a/src/mibase.ts b/src/mibase.ts index 5ac6932..c4fbc93 100644 --- a/src/mibase.ts +++ b/src/mibase.ts @@ -13,6 +13,11 @@ import * as fs from "fs"; let resolve = posix.resolve; let relative = posix.relative; +class ExtendedVariable { + constructor(public name, public options) { + } +} + export class MI2DebugSession extends DebugSession { protected variableHandles = new Handles(); protected quit: boolean; @@ -242,8 +247,11 @@ export class MI2DebugSession extends DebugSession { const variables: DebugProtocol.Variable[] = []; const id = this.variableHandles.get(args.variablesReference); - let createVariable = (arg) => { - return this.variableHandles.create(arg); + let createVariable = (arg, options?) => { + if (options) + return this.variableHandles.create(new ExtendedVariable(arg, options)); + else + return this.variableHandles.create(arg); }; if (typeof id == "string") { @@ -251,7 +259,7 @@ export class MI2DebugSession extends DebugSession { this.miDebugger.getStackVariables(this.threadID, parseInt(id.substr("@frame:".length))).then(stack => { stack.forEach(variable => { if (variable.valueStr !== undefined) { - let expanded = expandValue(createVariable, "{" + variable.name + "=" + variable.valueStr + ")"); + let expanded = expandValue(createVariable, "{" + variable.name + "=" + variable.valueStr + ")", "", variable.raw); if (expanded) { if (typeof expanded[0] == "string") expanded = [ @@ -282,23 +290,28 @@ export class MI2DebugSession extends DebugSession { else { // Variable members this.miDebugger.evalExpression(JSON.stringify(id)).then(variable => { - let expanded = expandValue(createVariable, variable.result("value"), id); - if (!expanded) { - this.sendErrorResponse(response, 2, `Could not expand variable`); + try { + let expanded = expandValue(createVariable, variable.result("value"), id, variable); + if (!expanded) { + this.sendErrorResponse(response, 2, `Could not expand variable`); + } + else { + if (typeof expanded[0] == "string") + expanded = [ + { + name: "", + value: prettyStringArray(expanded), + variablesReference: 0 + } + ]; + response.body = { + variables: expanded + }; + this.sendResponse(response); + } } - else { - if (typeof expanded[0] == "string") - expanded = [ - { - name: "", - value: prettyStringArray(expanded), - variablesReference: 0 - } - ]; - response.body = { - variables: expanded - }; - this.sendResponse(response); + catch (e) { + this.sendErrorResponse(response, 2, `Could not expand variable: ` + e); } }, err => { this.sendErrorResponse(response, 1, `Could not expand variable`); @@ -306,10 +319,76 @@ export class MI2DebugSession extends DebugSession { } } else if (typeof id == "object") { - response.body = { - variables: id - }; - this.sendResponse(response); + if (id instanceof ExtendedVariable) { + let varReq = id; + if (varReq.options.arg) { + let strArr = []; + let argsPart = true; + let arrIndex = 0; + let submit = () => { + response.body = { + variables: strArr + }; + this.sendResponse(response); + }; + let addOne = () => { + this.miDebugger.evalExpression(JSON.stringify(varReq.name + "+" + arrIndex + ")")).then(variable => { + try { + let expanded = expandValue(createVariable, variable.result("value"), id, variable); + if (!expanded) { + this.sendErrorResponse(response, 15, `Could not expand variable`); + } + else { + if (typeof expanded == "string") { + if (expanded == "") + { + if (argsPart) + argsPart = false; + else + return submit(); + } + else if (expanded[0] != '"') + { + strArr.push({ + name: "[err]", + value: expanded, + variablesReference: 0 + }); + return submit(); + } + strArr.push({ + name: "[" + (arrIndex++) + "]", + value: expanded, + variablesReference: 0 + }); + addOne(); + } + else { + strArr.push({ + name: "[err]", + value: expanded, + variablesReference: 0 + }); + submit(); + } + } + } + catch (e) { + this.sendErrorResponse(response, 14, `Could not expand variable: ` + e); + } + }); + }; + addOne(); + } + else + this.sendErrorResponse(response, 13, `Unimplemented variable request options: ` + JSON.stringify(varReq.options)); + } + else { + response.body = { + variables: id + }; + this.sendResponse(response); + } } else { response.body = { @@ -398,6 +477,12 @@ export class MI2DebugSession extends DebugSession { } } -function prettyStringArray(strings: string[]) { - return strings.join(", "); +function prettyStringArray(strings) { + if (typeof strings == "object") { + if (strings.length !== undefined) + return strings.join(", "); + else + return JSON.stringify(strings); + } + else return strings; } \ No newline at end of file diff --git a/test/gdb_expansion.test.ts b/test/gdb_expansion.test.ts index 5e790de..60acddf 100644 --- a/test/gdb_expansion.test.ts +++ b/test/gdb_expansion.test.ts @@ -10,6 +10,8 @@ suite("GDB Value Expansion", () => { assert.equal(expandValue(variableCreate, `5`), "5"); assert.strictEqual(isExpandable(`"hello world!"`), 0); assert.equal(expandValue(variableCreate, `"hello world!"`), `"hello world!"`); + assert.strictEqual(isExpandable(`0x7fffffffe956 "foobar"`), 0); + assert.equal(expandValue(variableCreate, `0x7fffffffe956 "foobar"`), `"foobar"`); assert.strictEqual(isExpandable(`0x0`), 0); assert.equal(expandValue(variableCreate, `0x0`), ""); assert.strictEqual(isExpandable(`0x000000`), 0); @@ -29,6 +31,17 @@ suite("GDB Value Expansion", () => { value: "d", variablesReference: 0 }]); + assert.strictEqual(isExpandable(`{[0] = 0x400730 "foo", [1] = 0x400735 "bar"}`), 1); + assert.deepEqual(expandValue(variableCreate, `{[0] = 0x400730 "foo", [1] = 0x400735 "bar"}`), [ + { + name: "[0]", + value: "\"foo\"", + variablesReference: 0 + }, { + name: "[1]", + value: "\"bar\"", + variablesReference: 0 + }]); assert.strictEqual(isExpandable(`{{a = b}}`), 1); assert.deepEqual(expandValue(variableCreate, `{{a = b}}`), [ {