asmimproved-dbgmits
Version:
Provides the ability to control GDB and LLDB programmatically via GDB/MI.
105 lines (93 loc) • 3.36 kB
text/typescript
// Copyright (c) 2015 Vadim Macagon
// MIT License, see LICENSE file for full terms.
import DebugSession from './debug_session';
import GDBDebugSession from './gdb_debug_session';
import { spawn, ChildProcess } from 'child_process';
import * as os from 'os';
import * as path from 'path';
import * as stream from 'stream';
function setProcessEnvironment(): void {
// HACK for LLDB on Windows (where users have to build their own Python)
if (os.platform() === 'win32') {
if (process.env['LLDB_PYTHON_SRC'] === undefined) {
throw new Error(
'LLDB_PYTHON_SRC environment variable is not set. It must be set to the source directory ' +
'of the Python version used in the LLDB build.'
);
}
if (process.env['LLVM_SRC_BUILD'] === undefined) {
throw new Error(
'LLVM_SRC_BUILD environment variable is not set. It must be set to the LLVM build output ' +
'directory.'
);
}
process.env['PATH'] =
process.env['PATH'] + ';' + path.join(process.env['LLDB_PYTHON_SRC'], 'PCbuild');
var pythonPath =
path.join(process.env['LLDB_PYTHON_SRC'], 'Lib') + ';' +
path.join(process.env['LLVM_SRC_BUILD'], 'lib\\site-packages');
if (process.env['PYTHONPATH']) {
process.env['PYTHONPATH'] = process.env['PYTHONPATH'] + ';' + pythonPath;
} else {
process.env['PYTHONPATH'] = pythonPath;
}
}
}
export enum DebuggerType {
GDB,
LLDB
}
/**
* Starts a new debugging session and spawns the debbuger process.
*
* Once the debug session has outlived its usefulness call [[DebugSession.end]] to ensure proper
* cleanup.
*
* @param debuggerFilename Full path to debugger executable, defaults to either `lldb-mi` or `gdb`
* (based on [[debuggerType]]).
* @returns A new debug session, or null if a new session couldn't be started.
*/
export function startDebugSession(debuggerType: DebuggerType, debuggerFilename?: string): DebugSession {
let debuggerArgs: string[];
switch (debuggerType) {
case DebuggerType.LLDB:
setProcessEnvironment();
if (!debuggerFilename) {
// lldb-mi.exe should be on the PATH
debuggerFilename = 'lldb-mi';
}
debuggerArgs = ['--interpreter'];
break;
case DebuggerType.GDB:
if (!debuggerFilename) {
debuggerFilename = 'gdb';
}
debuggerArgs = ['--interpreter', 'mi'];
break;
default:
throw new Error('Unknown debugger type!');
}
const debuggerProcess: ChildProcess = spawn(debuggerFilename, debuggerArgs);
let debugSession: DebugSession = null;
if (debuggerProcess) {
if (debuggerType === DebuggerType.GDB) {
debugSession = new GDBDebugSession(debuggerProcess.stdout, debuggerProcess.stdin);
} else {
debugSession = new DebugSession(debuggerProcess.stdout, debuggerProcess.stdin);
}
if (debugSession) {
debuggerProcess.once('exit',
(code: number, signal: string) => { debugSession.end(false); }
);
}
}
return debugSession;
};
export function startGDBDebugSessionFromExistingProcess(stdout: stream.Readable, stdin: stream.Writable, exitSubject: any) {
let debugSession: DebugSession = null;
debugSession = new DebugSession(stdout, stdin);
exitSubject.then(() => {
debugSession.end(false);
});
return debugSession;
}