Attach over ssh with gdb (fix #83)
This commit is contained in:
parent
c9be6b0634
commit
4f8ae4eb24
6 changed files with 132 additions and 30 deletions
|
|
@ -38,7 +38,7 @@ export interface SSHArguments {
|
|||
|
||||
export interface IBackend {
|
||||
load(cwd: string, target: string, procArgs: string, separateConsole: string): Thenable<any>;
|
||||
ssh(args: SSHArguments, cwd: string, target: string, procArgs: string, separateConsole: string): Thenable<any>;
|
||||
ssh(args: SSHArguments, cwd: string, target: string, procArgs: string, separateConsole: string, attach: boolean): Thenable<any>;
|
||||
attach(cwd: string, executable: string, target: string): Thenable<any>;
|
||||
connect(cwd: string, executable: string, target: string): Thenable<any>;
|
||||
start(): Thenable<boolean>;
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ export class MI2 extends EventEmitter implements IBackend {
|
|||
});
|
||||
}
|
||||
|
||||
ssh(args: SSHArguments, cwd: string, target: string, procArgs: string, separateConsole: string): Thenable<any> {
|
||||
ssh(args: SSHArguments, cwd: string, target: string, procArgs: string, separateConsole: string, attach: boolean): Thenable<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.isSSH = true;
|
||||
this.sshReady = false;
|
||||
|
|
@ -125,6 +125,8 @@ export class MI2 extends EventEmitter implements IBackend {
|
|||
}
|
||||
let sshCMD = this.application + " " + this.preargs.join(" ");
|
||||
if (args.bootstrap) sshCMD = args.bootstrap + " && " + sshCMD;
|
||||
if (attach)
|
||||
sshCMD += " -p " + target;
|
||||
this.sshConn.exec(sshCMD, execArgs, (err, stream) => {
|
||||
if (err) {
|
||||
this.log("stderr", "Could not run " + this.application + " over ssh!");
|
||||
|
|
@ -141,9 +143,9 @@ export class MI2 extends EventEmitter implements IBackend {
|
|||
this.emit("quit");
|
||||
this.sshConn.end();
|
||||
}).bind(this));
|
||||
let promises = this.initCommands(target, cwd, true);
|
||||
let promises = this.initCommands(target, cwd, true, attach);
|
||||
promises.push(this.sendCommand("environment-cd \"" + escape(cwd) + "\""));
|
||||
if (procArgs && procArgs.length)
|
||||
if (procArgs && procArgs.length && !attach)
|
||||
promises.push(this.sendCommand("exec-arguments " + procArgs));
|
||||
Promise.all(promises).then(() => {
|
||||
this.emit("debug-ready")
|
||||
|
|
@ -159,7 +161,7 @@ export class MI2 extends EventEmitter implements IBackend {
|
|||
});
|
||||
}
|
||||
|
||||
protected initCommands(target: string, cwd: string, ssh: boolean = false) {
|
||||
protected initCommands(target: string, cwd: string, ssh: boolean = false, attach: boolean = false) {
|
||||
if (ssh) {
|
||||
if (!path.isAbsolute(target))
|
||||
target = path.join(cwd, target);
|
||||
|
|
@ -168,11 +170,13 @@ export class MI2 extends EventEmitter implements IBackend {
|
|||
if (!nativePath.isAbsolute(target))
|
||||
target = nativePath.join(cwd, target);
|
||||
}
|
||||
return [
|
||||
this.sendCommand("gdb-set target-async on"),
|
||||
this.sendCommand("environment-directory \"" + escape(cwd) + "\""),
|
||||
this.sendCommand("file-exec-and-symbols \"" + escape(target) + "\"")
|
||||
var cmds = [
|
||||
this.sendCommand("gdb-set target-async on", true),
|
||||
this.sendCommand("environment-directory \"" + escape(cwd) + "\"", true)
|
||||
];
|
||||
if (!attach)
|
||||
cmds.push(this.sendCommand("file-exec-and-symbols \"" + escape(target) + "\""));
|
||||
return cmds;
|
||||
}
|
||||
|
||||
attach(cwd: string, executable: string, target: string): Thenable<any> {
|
||||
|
|
@ -651,12 +655,18 @@ export class MI2 extends EventEmitter implements IBackend {
|
|||
this.process.stdin.write(raw + "\n");
|
||||
}
|
||||
|
||||
sendCommand(command: string): Thenable<MINode> {
|
||||
sendCommand(command: string, suppressFailure: boolean = false): Thenable<MINode> {
|
||||
let sel = this.currentToken++;
|
||||
return new Promise((resolve, reject) => {
|
||||
this.handlers[sel] = (node: MINode) => {
|
||||
if (node && node.resultRecords && node.resultRecords.resultClass === "error")
|
||||
reject(node.result("msg") || "Internal error");
|
||||
if (node && node.resultRecords && node.resultRecords.resultClass === "error") {
|
||||
if (suppressFailure) {
|
||||
this.log("stderr", "WARNING: Error executing command '" + command + "'");
|
||||
resolve(node);
|
||||
}
|
||||
else
|
||||
reject((node.result("msg") || "Internal error") + " (from " + command + ")");
|
||||
}
|
||||
else
|
||||
resolve(node);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import * as nativePath from "path"
|
|||
let path = posix;
|
||||
|
||||
export class MI2_LLDB extends MI2 {
|
||||
protected initCommands(target: string, cwd: string, ssh: boolean = false) {
|
||||
protected initCommands(target: string, cwd: string, ssh: boolean = false, attach: boolean = false) {
|
||||
if (ssh) {
|
||||
if (!path.isAbsolute(target))
|
||||
target = path.join(cwd, target);
|
||||
|
|
@ -15,10 +15,12 @@ export class MI2_LLDB extends MI2 {
|
|||
if (!nativePath.isAbsolute(target))
|
||||
target = nativePath.join(cwd, target);
|
||||
}
|
||||
return [
|
||||
this.sendCommand("gdb-set target-async on"),
|
||||
this.sendCommand("file-exec-and-symbols \"" + escape(target) + "\"")
|
||||
var cmds = [
|
||||
this.sendCommand("gdb-set target-async on")
|
||||
];
|
||||
if (!attach)
|
||||
cmds.push(this.sendCommand("file-exec-and-symbols \"" + escape(target) + "\""));
|
||||
return cmds;
|
||||
}
|
||||
|
||||
attach(cwd: string, executable: string, target: string): Thenable<any> {
|
||||
|
|
|
|||
56
src/gdb.ts
56
src/gdb.ts
|
|
@ -25,6 +25,7 @@ export interface AttachRequestArguments {
|
|||
executable: string;
|
||||
remote: boolean;
|
||||
autorun: string[];
|
||||
ssh: SSHArguments;
|
||||
printCalls: boolean;
|
||||
showDevDebugOutput: boolean;
|
||||
}
|
||||
|
|
@ -67,7 +68,7 @@ class GDBDebugSession extends MI2DebugSession {
|
|||
this.isSSH = true;
|
||||
this.trimCWD = args.cwd.replace(/\\/g, "/");
|
||||
this.switchCWD = args.ssh.cwd;
|
||||
this.miDebugger.ssh(args.ssh, args.ssh.cwd, args.target, args.arguments, args.terminal).then(() => {
|
||||
this.miDebugger.ssh(args.ssh, args.ssh.cwd, args.target, args.arguments, args.terminal, false).then(() => {
|
||||
if (args.autorun)
|
||||
args.autorun.forEach(command => {
|
||||
this.miDebugger.sendUserInput(command);
|
||||
|
|
@ -120,27 +121,56 @@ class GDBDebugSession extends MI2DebugSession {
|
|||
this.debugReady = false;
|
||||
this.miDebugger.printCalls = !!args.printCalls;
|
||||
this.miDebugger.debugOutput = !!args.showDevDebugOutput;
|
||||
if (args.remote) {
|
||||
this.miDebugger.connect(args.cwd, args.executable, args.target).then(() => {
|
||||
if (args.ssh !== undefined) {
|
||||
if (args.ssh.forwardX11 === undefined)
|
||||
args.ssh.forwardX11 = true;
|
||||
if (args.ssh.port === undefined)
|
||||
args.ssh.port = 22;
|
||||
if (args.ssh.x11port === undefined)
|
||||
args.ssh.x11port = 6000;
|
||||
if (args.ssh.x11host === undefined)
|
||||
args.ssh.x11host = "localhost";
|
||||
if (args.ssh.remotex11screen === undefined)
|
||||
args.ssh.remotex11screen = 0;
|
||||
this.isSSH = true;
|
||||
this.trimCWD = args.cwd.replace(/\\/g, "/");
|
||||
this.switchCWD = args.ssh.cwd;
|
||||
this.miDebugger.ssh(args.ssh, args.ssh.cwd, args.target, "", undefined, true).then(() => {
|
||||
if (args.autorun)
|
||||
args.autorun.forEach(command => {
|
||||
this.miDebugger.sendUserInput(command);
|
||||
});
|
||||
setTimeout(() => {
|
||||
this.miDebugger.emit("ui-break-done");
|
||||
}, 50);
|
||||
this.sendResponse(response);
|
||||
}, err => {
|
||||
this.sendErrorResponse(response, 102, `Failed to attach: ${err.toString()}`)
|
||||
this.sendErrorResponse(response, 102, `Failed to SSH: ${err.toString()}`)
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.miDebugger.attach(args.cwd, args.executable, args.target).then(() => {
|
||||
if (args.autorun)
|
||||
args.autorun.forEach(command => {
|
||||
this.miDebugger.sendUserInput(command);
|
||||
});
|
||||
this.sendResponse(response);
|
||||
}, err => {
|
||||
this.sendErrorResponse(response, 101, `Failed to attach: ${err.toString()}`)
|
||||
});
|
||||
if (args.remote) {
|
||||
this.miDebugger.connect(args.cwd, args.executable, args.target).then(() => {
|
||||
if (args.autorun)
|
||||
args.autorun.forEach(command => {
|
||||
this.miDebugger.sendUserInput(command);
|
||||
});
|
||||
this.sendResponse(response);
|
||||
}, err => {
|
||||
this.sendErrorResponse(response, 102, `Failed to attach: ${err.toString()}`)
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.miDebugger.attach(args.cwd, args.executable, args.target).then(() => {
|
||||
if (args.autorun)
|
||||
args.autorun.forEach(command => {
|
||||
this.miDebugger.sendUserInput(command);
|
||||
});
|
||||
this.sendResponse(response);
|
||||
}, err => {
|
||||
this.sendErrorResponse(response, 101, `Failed to attach: ${err.toString()}`)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ class LLDBDebugSession extends MI2DebugSession {
|
|||
this.isSSH = true;
|
||||
this.trimCWD = args.cwd.replace(/\\/g, "/");
|
||||
this.switchCWD = args.ssh.cwd;
|
||||
this.miDebugger.ssh(args.ssh, args.ssh.cwd, args.target, args.arguments, undefined).then(() => {
|
||||
this.miDebugger.ssh(args.ssh, args.ssh.cwd, args.target, args.arguments, undefined, false).then(() => {
|
||||
if (args.autorun)
|
||||
args.autorun.forEach(command => {
|
||||
this.miDebugger.sendUserInput(command);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue