si-debug
Version:
GDB, LLDB & Mago-MI Debugger support for SuperIDE
74 lines (67 loc) • 3.13 kB
text/typescript
import { MI2, escape } from "./mi2";
import { Breakpoint } from "../backend";
import * as ChildProcess from "child_process";
import * as path from "path";
export class MI2_LLDB extends MI2 {
protected override initCommands(target: string, cwd: string, attach: boolean = false) {
// We need to account for the possibility of the path type used by the debugger being different
// than the path type where the extension is running (e.g., SSH from Linux to Windows machine).
// Since the CWD is expected to be an absolute path in the debugger's environment, we can test
// that to determine the path type used by the debugger and use the result of that test to
// select the correct API to check whether the target path is an absolute path.
const debuggerPath = path.posix.isAbsolute(cwd) ? path.posix : path.win32;
if (!debuggerPath.isAbsolute(target))
target = debuggerPath.join(cwd, target);
const cmds = [
this.sendCommand("gdb-set target-async on"),
new Promise(resolve => {
this.sendCommand("list-features").then(done => {
this.features = done.result("features");
resolve(undefined);
}, err => {
this.features = [];
resolve(undefined);
});
})
];
if (!attach)
cmds.push(this.sendCommand("file-exec-and-symbols \"" + escape(target) + "\""));
for (const cmd of this.extraCommands) {
cmds.push(this.sendCliCommand(cmd));
}
return cmds;
}
override attach(cwd: string, executable: string, target: string, autorun: string[]): Thenable<any> {
return new Promise((resolve, reject) => {
const args = this.preargs.concat(this.extraargs || []);
this.process = ChildProcess.spawn(this.application, args, { cwd: cwd, env: this.procEnv });
this.process.stdout.on("data", this.stdout.bind(this));
this.process.stderr.on("data", this.stderr.bind(this));
this.process.on("exit", (() => { this.emit("quit"); }).bind(this));
this.process.on("error", ((err) => { this.emit("launcherror", err); }).bind(this));
const promises = this.initCommands(target, cwd, true);
promises.push(this.sendCommand("file-exec-and-symbols \"" + escape(executable) + "\""));
promises.push(this.sendCommand("target-attach " + target));
promises.push(...autorun.map(value => { return this.sendUserInput(value); }));
Promise.all(promises).then(() => {
this.emit("debug-ready");
resolve(undefined);
}, reject);
});
}
override setBreakPointCondition(bkptNum: number, condition: string): Thenable<any> {
return this.sendCommand("break-condition " + bkptNum + " \"" + escape(condition) + "\" 1");
}
override goto(filename: string, line: number): Thenable<Boolean> {
return new Promise((resolve, reject) => {
// LLDB parses the file differently than GDB...
// GDB doesn't allow quoting only the file but only the whole argument
// LLDB doesn't allow quoting the whole argument but rather only the file
const target: string = (filename ? '"' + escape(filename) + '":' : "") + line;
this.sendCliCommand("jump " + target).then(() => {
this.emit("step-other", undefined);
resolve(true);
}, reject);
});
}
}