fix: 修复无法查看指针变量的的问题

修复无法查看/设置寄存器的问题;
修复无法设置变量值的问题.

Signed-off-by: Haoyang Chen <chenhaoyang@kylinos.cn>
This commit is contained in:
Haoyang Chen 2022-10-14 14:25:29 +08:00
parent fc6a3de435
commit 65a2acc2c7
6 changed files with 141 additions and 22 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@ out
node_modules node_modules
*.vsix *.vsix
.vscode-test .vscode-test
package-lock.json

72
package-lock.json generated
View File

@ -1,15 +1,18 @@
{ {
"name": "debug", "name": "debug",
"version": "0.26.0", "version": "0.26.1",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "debug", "name": "debug",
"version": "0.26.0", "version": "0.26.1",
"license": "public domain", "license": "public domain",
"dependencies": { "dependencies": {
"json-stream-stringify": "^2.0.4",
"node-interval-tree": "^1.3.3",
"ssh2": "^1.6.0", "ssh2": "^1.6.0",
"stream-json": "^1.7.3",
"vscode-debugadapter": "^1.45.0", "vscode-debugadapter": "^1.45.0",
"vscode-debugprotocol": "^1.45.0" "vscode-debugprotocol": "^1.45.0"
}, },
@ -719,6 +722,11 @@
"js-yaml": "bin/js-yaml.js" "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": { "node_modules/locate-path": {
"version": "6.0.0", "version": "6.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "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": "^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": { "node_modules/normalize-path": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
@ -1159,6 +1178,11 @@
"randombytes": "^2.1.0" "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": { "node_modules/sprintf-js": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
@ -1182,6 +1206,19 @@
"nan": "^2.15.0" "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": { "node_modules/string-width": {
"version": "4.2.3", "version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
@ -2053,6 +2090,11 @@
"esprima": "^4.0.0" "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": { "locate-path": {
"version": "6.0.0", "version": "6.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
@ -2243,6 +2285,14 @@
"integrity": "sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q==", "integrity": "sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q==",
"dev": true "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": { "normalize-path": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
@ -2369,6 +2419,11 @@
"randombytes": "^2.1.0" "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": { "sprintf-js": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
@ -2386,6 +2441,19 @@
"nan": "^2.15.0" "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": { "string-width": {
"version": "4.2.3", "version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",

View File

@ -76,7 +76,7 @@ export interface IBackend {
getStack(startFrame: number, maxLevels: number, thread: number): Thenable<Stack[]>; getStack(startFrame: number, maxLevels: number, thread: number): Thenable<Stack[]>;
getRegisters(): Promise<any[]>; getRegisters(): Promise<any[]>;
getStackVariables(thread: number, frame: number): Thenable<Variable[]>; getStackVariables(thread: number, frame: number): Thenable<Variable[]>;
evalExpression(name: string, thread: number, frame: number): Thenable<any>; evalExpression(name: string, thread: number, frame: number, suppressFailure:boolean): Thenable<any>;
isReady(): boolean; isReady(): boolean;
changeVariable(name: string, rawValue: string): Thenable<any>; changeVariable(name: string, rawValue: string): Thenable<any>;
examineMemory(from: number, to: number): Thenable<any>; examineMemory(from: number, to: number): Thenable<any>;
@ -85,6 +85,7 @@ export interface IBackend {
export class VariableObject { export class VariableObject {
name: string; name: string;
evaluateName:string;
exp: string; exp: string;
numchild: number; numchild: number;
type: string; type: string;
@ -97,6 +98,7 @@ export class VariableObject {
id: number; id: number;
constructor(node: any) { constructor(node: any) {
this.name = MINode.valueOf(node, "name"); this.name = MINode.valueOf(node, "name");
this.evaluateName = this.name;
this.exp = MINode.valueOf(node, "exp"); this.exp = MINode.valueOf(node, "exp");
this.numchild = parseInt(MINode.valueOf(node, "numchild")); this.numchild = parseInt(MINode.valueOf(node, "numchild"));
this.type = MINode.valueOf(node, "type"); this.type = MINode.valueOf(node, "type");

View File

@ -76,9 +76,13 @@ export function expandValue(variableCreate: Function, value: string, root: strin
} }
namespace = namespace + pointerCombineChar + name; namespace = namespace + pointerCombineChar + name;
} else } else
if (root && root.startsWith("*"))
namespace = name.substr(1);
else {
namespace = name; namespace = name;
} }
} }
}
}); });
stack.pop(); stack.pop();
return prefix + namespace; return prefix + namespace;
@ -211,27 +215,36 @@ export function expandValue(variableCreate: Function, value: string, root: strin
createValue = (name, val) => { createValue = (name, val) => {
let ref = 0; let ref = 0;
let evaluateName;
if (typeof val == "object") { if (typeof val == "object") {
ref = variableCreate(val); ref = variableCreate(val);
val = "Object"; val = "Object";
} else if (typeof val == "string" && val.startsWith("*0x")) { } else if (typeof val == "string" && val.startsWith("*0x")) {
if (extra && MINode.valueOf(extra, "arg") == "1") { 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 = "<args>"; val = "<args>";
} else { } else {
ref = variableCreate(getNamespace("*" + name)); evaluateName = getNamespace("*" + name);
ref = variableCreate(evaluateName);
val = "Object@" + val; val = "Object@" + val;
} }
} else if (typeof val == "string" && val.startsWith("@0x")) { } else if (typeof val == "string" && val.startsWith("@0x")) {
ref = variableCreate(getNamespace("*&" + name.substr)); evaluateName = getNamespace("*&" + name);
ref = variableCreate(evaluateName);
val = "Ref" + val; val = "Ref" + val;
} else if (typeof val == "string" && val.startsWith("<...>")) { } else if (typeof val == "string" && val.startsWith("<...>")) {
ref = variableCreate(getNamespace(name)); evaluateName =getNamespace(name);
ref = variableCreate(evaluateName);
val = "..."; val = "...";
} else {
evaluateName = getNamespace(name);
} }
return { return {
name: name, name: name,
value: val, value: val,
evaluateName,
variablesReference: ref variablesReference: ref
}; };
}; };

View File

@ -824,7 +824,7 @@ export class MI2 extends EventEmitter implements IBackend {
const type = MINode.valueOf(reg, "type"); const type = MINode.valueOf(reg, "type");
ret.push({ ret.push({
name: name, name: name,
evaluateName: name, evaluateName: '$'+name, //修复寄存器无法watch
value: value, value: value,
type: type, type: type,
variablesReference: 0 variablesReference: 0
@ -895,7 +895,7 @@ export class MI2 extends EventEmitter implements IBackend {
}, reject); }, reject);
}); });
} }
async evalExpression(name: string, thread: number, frame: number): Promise<MINode> { async evalExpression(name: string, thread: number, frame: number, suppressFailure: boolean = false): Promise<MINode> {
if (trace) if (trace)
this.log("stderr", "evalExpression"); this.log("stderr", "evalExpression");
@ -908,7 +908,7 @@ export class MI2 extends EventEmitter implements IBackend {
} }
command += name; command += name;
return await this.sendCommand(command); return await this.sendCommand(command, suppressFailure);
} }
async varCreate(expression: string, name: string = "-", frame: string = "@"): Promise<VariableObject> { async varCreate(expression: string, name: string = "-", frame: string = "@"): Promise<VariableObject> {

View File

@ -10,6 +10,7 @@ import * as systemPath from "path";
import * as net from "net"; import * as net from "net";
import * as os from "os"; import * as os from "os";
import * as fs from "fs"; import * as fs from "fs";
import { hexFormat } from './backend/common';
class ExtendedVariable { class ExtendedVariable {
constructor(public name, public options) { constructor(public name, public options) {
@ -193,7 +194,25 @@ export class MI2DebugSession extends DebugSession {
value: res.result("value") value: res.result("value")
}; };
} else { } 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); await this.miDebugger.changeVariable(name, args.value);
response.body = { response.body = {
value: args.value value: args.value
@ -459,6 +478,7 @@ export class MI2DebugSession extends DebugSession {
this.sendResponse(response); this.sendResponse(response);
return; return;
} }
if (args.variablesReference < VAR_HANDLES_START) { if (args.variablesReference < VAR_HANDLES_START) {
id = args.variablesReference - STACK_HANDLES_START; id = args.variablesReference - STACK_HANDLES_START;
} else { } else {
@ -539,8 +559,9 @@ export class MI2DebugSession extends DebugSession {
} else } else
variables.push({ variables.push({
name: variable.name, name: variable.name,
evaluateName: variable.name,
type: variable.type, type: variable.type,
value: "<unknown>", value: variable.type,
variablesReference: createVariable(variable.name) variablesReference: createVariable(variable.name)
}); });
} }
@ -617,7 +638,13 @@ export class MI2DebugSession extends DebugSession {
// TODO: this evals on an (effectively) unknown thread for multithreaded programs. // TODO: this evals on an (effectively) unknown thread for multithreaded programs.
const variable = await this.miDebugger.evalExpression(JSON.stringify(`${varReq.name}+${arrIndex})`), 0, 0); const variable = await this.miDebugger.evalExpression(JSON.stringify(`${varReq.name}+${arrIndex})`), 0, 0);
try { 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) { if (!expanded) {
this.sendErrorResponse(response, 15, `Could not expand variable`); this.sendErrorResponse(response, 15, `Could not expand variable`);
} else { } else {
@ -629,7 +656,7 @@ export class MI2DebugSession extends DebugSession {
return submit(); return submit();
} else if (expanded[0] != '"') { } else if (expanded[0] != '"') {
strArr.push({ strArr.push({
name: "[err]", name: "value",
value: expanded, value: expanded,
variablesReference: 0 variablesReference: 0
}); });
@ -642,10 +669,17 @@ export class MI2DebugSession extends DebugSession {
}); });
addOne(); addOne();
} else { } else {
expanded.forEach(element => {
let evaluateName;
if (this.variableHandlesReverse.hasOwnProperty(element.name)) {
evaluateName = this.variableHandlesReverse[element.name];
}
strArr.push({ strArr.push({
name: "[err]", name: element.name,
value: expanded, evaluateName: element.evaluateName,
variablesReference: 0 value: element.value,
variablesReference: element.variablesReference
});
}); });
submit(); submit();
} }
@ -730,10 +764,11 @@ export class MI2DebugSession extends DebugSession {
protected evaluateRequest(response: DebugProtocol.EvaluateResponse, args: DebugProtocol.EvaluateArguments): void { protected evaluateRequest(response: DebugProtocol.EvaluateResponse, args: DebugProtocol.EvaluateArguments): void {
const [threadId, level] = this.frameIdToThreadAndLevel(args.frameId); const [threadId, level] = this.frameIdToThreadAndLevel(args.frameId);
if (args.context == "watch" || args.context == "hover") { 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 = { response.body = {
variablesReference: 0, variablesReference: 0,
result: res.result("value") result: args.expression[0] == '$' ? hexFormat(parseInt(res.result("value"))) : res.result("value")
}; };
this.sendResponse(response); this.sendResponse(response);
}, msg => { }, msg => {