From 65a2acc2c7adc5add4aa7050da57c32d2a63ee12 Mon Sep 17 00:00:00 2001 From: Haoyang Chen Date: Fri, 14 Oct 2022 14:25:29 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=97=A0=E6=B3=95?= =?UTF-8?q?=E6=9F=A5=E7=9C=8B=E6=8C=87=E9=92=88=E5=8F=98=E9=87=8F=E7=9A=84?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复无法查看/设置寄存器的问题; 修复无法设置变量值的问题. Signed-off-by: Haoyang Chen --- .gitignore | 3 +- package-lock.json | 72 +++++++++++++++++++++++++++++++++++- src/backend/backend.ts | 4 +- src/backend/gdb_expansion.ts | 23 +++++++++--- src/backend/mi2/mi2.ts | 6 +-- src/mibase.ts | 55 ++++++++++++++++++++++----- 6 files changed, 141 insertions(+), 22 deletions(-) diff --git a/.gitignore b/.gitignore index 1262404..b3eb14f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ out node_modules *.vsix -.vscode-test \ No newline at end of file +.vscode-test +package-lock.json diff --git a/package-lock.json b/package-lock.json index 416ec04..bf39802 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,18 @@ { "name": "debug", - "version": "0.26.0", + "version": "0.26.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "debug", - "version": "0.26.0", + "version": "0.26.1", "license": "public domain", "dependencies": { + "json-stream-stringify": "^2.0.4", + "node-interval-tree": "^1.3.3", "ssh2": "^1.6.0", + "stream-json": "^1.7.3", "vscode-debugadapter": "^1.45.0", "vscode-debugprotocol": "^1.45.0" }, @@ -719,6 +722,11 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/json-stream-stringify": { + "version": "2.0.4", + "resolved": "https://registry.npmmirror.com/json-stream-stringify/-/json-stream-stringify-2.0.4.tgz", + "integrity": "sha512-gIPoa6K5w6j/RnQ3fOtmvICKNJGViI83A7dnTIL+0QJ/1GKuNvCPFvbFWxt0agruF4iGgDFJvge4Gua4ZoiggQ==" + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -977,6 +985,17 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/node-interval-tree": { + "version": "1.3.3", + "resolved": "https://registry.npmmirror.com/node-interval-tree/-/node-interval-tree-1.3.3.tgz", + "integrity": "sha512-K9vk96HdTK5fEipJwxSvIIqwTqr4e3HRJeJrNxBSeVMNSC/JWARRaX7etOLOuTmrRMeOI/K5TCJu3aWIwZiNTw==", + "dependencies": { + "shallowequal": "^1.0.2" + }, + "engines": { + "node": ">= 7.6.0" + } + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -1159,6 +1178,11 @@ "randombytes": "^2.1.0" } }, + "node_modules/shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -1182,6 +1206,19 @@ "nan": "^2.15.0" } }, + "node_modules/stream-chain": { + "version": "2.2.5", + "resolved": "https://registry.npmmirror.com/stream-chain/-/stream-chain-2.2.5.tgz", + "integrity": "sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==" + }, + "node_modules/stream-json": { + "version": "1.7.4", + "resolved": "https://registry.npmmirror.com/stream-json/-/stream-json-1.7.4.tgz", + "integrity": "sha512-ja2dde1v7dOlx5/vmavn8kLrxvNfs7r2oNc5DYmNJzayDDdudyCSuTB1gFjH4XBVTIwxiMxL4i059HX+ZiouXg==", + "dependencies": { + "stream-chain": "^2.2.5" + } + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -2053,6 +2090,11 @@ "esprima": "^4.0.0" } }, + "json-stream-stringify": { + "version": "2.0.4", + "resolved": "https://registry.npmmirror.com/json-stream-stringify/-/json-stream-stringify-2.0.4.tgz", + "integrity": "sha512-gIPoa6K5w6j/RnQ3fOtmvICKNJGViI83A7dnTIL+0QJ/1GKuNvCPFvbFWxt0agruF4iGgDFJvge4Gua4ZoiggQ==" + }, "locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -2243,6 +2285,14 @@ "integrity": "sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q==", "dev": true }, + "node-interval-tree": { + "version": "1.3.3", + "resolved": "https://registry.npmmirror.com/node-interval-tree/-/node-interval-tree-1.3.3.tgz", + "integrity": "sha512-K9vk96HdTK5fEipJwxSvIIqwTqr4e3HRJeJrNxBSeVMNSC/JWARRaX7etOLOuTmrRMeOI/K5TCJu3aWIwZiNTw==", + "requires": { + "shallowequal": "^1.0.2" + } + }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -2369,6 +2419,11 @@ "randombytes": "^2.1.0" } }, + "shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -2386,6 +2441,19 @@ "nan": "^2.15.0" } }, + "stream-chain": { + "version": "2.2.5", + "resolved": "https://registry.npmmirror.com/stream-chain/-/stream-chain-2.2.5.tgz", + "integrity": "sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==" + }, + "stream-json": { + "version": "1.7.4", + "resolved": "https://registry.npmmirror.com/stream-json/-/stream-json-1.7.4.tgz", + "integrity": "sha512-ja2dde1v7dOlx5/vmavn8kLrxvNfs7r2oNc5DYmNJzayDDdudyCSuTB1gFjH4XBVTIwxiMxL4i059HX+ZiouXg==", + "requires": { + "stream-chain": "^2.2.5" + } + }, "string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", diff --git a/src/backend/backend.ts b/src/backend/backend.ts index ad9e73b..ebb579a 100644 --- a/src/backend/backend.ts +++ b/src/backend/backend.ts @@ -76,7 +76,7 @@ export interface IBackend { getStack(startFrame: number, maxLevels: number, thread: number): Thenable; getRegisters(): Promise; getStackVariables(thread: number, frame: number): Thenable; - evalExpression(name: string, thread: number, frame: number): Thenable; + evalExpression(name: string, thread: number, frame: number, suppressFailure:boolean): Thenable; isReady(): boolean; changeVariable(name: string, rawValue: string): Thenable; examineMemory(from: number, to: number): Thenable; @@ -85,6 +85,7 @@ export interface IBackend { export class VariableObject { name: string; + evaluateName:string; exp: string; numchild: number; type: string; @@ -97,6 +98,7 @@ export class VariableObject { id: number; constructor(node: any) { this.name = MINode.valueOf(node, "name"); + this.evaluateName = this.name; this.exp = MINode.valueOf(node, "exp"); this.numchild = parseInt(MINode.valueOf(node, "numchild")); this.type = MINode.valueOf(node, "type"); diff --git a/src/backend/gdb_expansion.ts b/src/backend/gdb_expansion.ts index 143e6d5..a88f37f 100644 --- a/src/backend/gdb_expansion.ts +++ b/src/backend/gdb_expansion.ts @@ -76,7 +76,11 @@ export function expandValue(variableCreate: Function, value: string, root: strin } namespace = namespace + pointerCombineChar + name; } else - namespace = name; + if (root && root.startsWith("*")) + namespace = name.substr(1); + else { + namespace = name; + } } } }); @@ -211,27 +215,36 @@ export function expandValue(variableCreate: Function, value: string, root: strin createValue = (name, val) => { let ref = 0; + let evaluateName; if (typeof val == "object") { ref = variableCreate(val); val = "Object"; } else if (typeof val == "string" && val.startsWith("*0x")) { if (extra && MINode.valueOf(extra, "arg") == "1") { - ref = variableCreate(getNamespace("*(" + name), { arg: true }); + const isVoid = MINode.valueOf(extra, "type") === "void *"; + evaluateName = getNamespace( ( isVoid ? "":"*") + name); + ref = variableCreate(getNamespace( ( isVoid ? "":"*") + "(" + name), { arg: true, isVoid }); val = ""; } else { - ref = variableCreate(getNamespace("*" + name)); + evaluateName = getNamespace("*" + name); + ref = variableCreate(evaluateName); val = "Object@" + val; } } else if (typeof val == "string" && val.startsWith("@0x")) { - ref = variableCreate(getNamespace("*&" + name.substr)); + evaluateName = getNamespace("*&" + name); + ref = variableCreate(evaluateName); val = "Ref" + val; } else if (typeof val == "string" && val.startsWith("<...>")) { - ref = variableCreate(getNamespace(name)); + evaluateName =getNamespace(name); + ref = variableCreate(evaluateName); val = "..."; + } else { + evaluateName = getNamespace(name); } return { name: name, value: val, + evaluateName, variablesReference: ref }; }; diff --git a/src/backend/mi2/mi2.ts b/src/backend/mi2/mi2.ts index 7451bc8..5a0fa21 100644 --- a/src/backend/mi2/mi2.ts +++ b/src/backend/mi2/mi2.ts @@ -824,7 +824,7 @@ export class MI2 extends EventEmitter implements IBackend { const type = MINode.valueOf(reg, "type"); ret.push({ name: name, - evaluateName: name, + evaluateName: '$'+name, //修复寄存器无法watch value: value, type: type, variablesReference: 0 @@ -895,7 +895,7 @@ export class MI2 extends EventEmitter implements IBackend { }, reject); }); } - async evalExpression(name: string, thread: number, frame: number): Promise { + async evalExpression(name: string, thread: number, frame: number, suppressFailure: boolean = false): Promise { if (trace) this.log("stderr", "evalExpression"); @@ -908,7 +908,7 @@ export class MI2 extends EventEmitter implements IBackend { } command += name; - return await this.sendCommand(command); + return await this.sendCommand(command, suppressFailure); } async varCreate(expression: string, name: string = "-", frame: string = "@"): Promise { diff --git a/src/mibase.ts b/src/mibase.ts index bf0e4bc..d1c43a9 100644 --- a/src/mibase.ts +++ b/src/mibase.ts @@ -10,6 +10,7 @@ import * as systemPath from "path"; import * as net from "net"; import * as os from "os"; import * as fs from "fs"; +import { hexFormat } from './backend/common'; class ExtendedVariable { constructor(public name, public options) { @@ -193,7 +194,25 @@ export class MI2DebugSession extends DebugSession { value: res.result("value") }; } else { - let name = args.variablesReference == VARIABLES_TAG_REGISTER ? `$${args.name}` : args.name; + /* 字符串不修改 */ + if (args.value[0] == "\"") { + this.sendErrorResponse(response, 20, "Could not modify string variable"); + return; + } + let name; + let id; + if (args.variablesReference >= VAR_HANDLES_START) { + const pointerCombineChar = "."; + id = this.variableHandles.get(args.variablesReference); + if (typeof id == "string") { + name = id[0] == '*' ? id.substr(1):id + pointerCombineChar + args.name; + } + } + /* 修复寄存器无法修改 */ + else if (args.variablesReference == VARIABLES_TAG_REGISTER) { + name = `$${args.name}`; + } + await this.miDebugger.changeVariable(name, args.value); response.body = { value: args.value @@ -459,6 +478,7 @@ export class MI2DebugSession extends DebugSession { this.sendResponse(response); return; } + if (args.variablesReference < VAR_HANDLES_START) { id = args.variablesReference - STACK_HANDLES_START; } else { @@ -539,8 +559,9 @@ export class MI2DebugSession extends DebugSession { } else variables.push({ name: variable.name, + evaluateName: variable.name, type: variable.type, - value: "", + value: variable.type, variablesReference: createVariable(variable.name) }); } @@ -617,7 +638,13 @@ export class MI2DebugSession extends DebugSession { // TODO: this evals on an (effectively) unknown thread for multithreaded programs. const variable = await this.miDebugger.evalExpression(JSON.stringify(`${varReq.name}+${arrIndex})`), 0, 0); try { - const expanded = expandValue(createVariable, variable.result("value"), varReq.name, variable); + let root = varReq.name; + const t = varReq.name.indexOf('(');//如果变量名称带 ( 说明它是一个参数 + let name:string = varReq.name; + if (t) { + root = name.substring(0,t) + name.substring(t+1); + } + const expanded = expandValue(createVariable, variable.result("value"), root, variable); if (!expanded) { this.sendErrorResponse(response, 15, `Could not expand variable`); } else { @@ -629,7 +656,7 @@ export class MI2DebugSession extends DebugSession { return submit(); } else if (expanded[0] != '"') { strArr.push({ - name: "[err]", + name: "value", value: expanded, variablesReference: 0 }); @@ -642,10 +669,17 @@ export class MI2DebugSession extends DebugSession { }); addOne(); } else { - strArr.push({ - name: "[err]", - value: expanded, - variablesReference: 0 + expanded.forEach(element => { + let evaluateName; + if (this.variableHandlesReverse.hasOwnProperty(element.name)) { + evaluateName = this.variableHandlesReverse[element.name]; + } + strArr.push({ + name: element.name, + evaluateName: element.evaluateName, + value: element.value, + variablesReference: element.variablesReference + }); }); submit(); } @@ -730,10 +764,11 @@ export class MI2DebugSession extends DebugSession { protected evaluateRequest(response: DebugProtocol.EvaluateResponse, args: DebugProtocol.EvaluateArguments): void { const [threadId, level] = this.frameIdToThreadAndLevel(args.frameId); if (args.context == "watch" || args.context == "hover") { - this.miDebugger.evalExpression(args.expression, threadId, level).then((res) => { + /* 悬停查看变量时不报错 */ + this.miDebugger.evalExpression(args.expression, threadId, level, args.context == "hover").then((res) => { response.body = { variablesReference: 0, - result: res.result("value") + result: args.expression[0] == '$' ? hexFormat(parseInt(res.result("value"))) : res.result("value") }; this.sendResponse(response); }, msg => {