asmimproved-dbgmits
Version:
Provides the ability to control GDB and LLDB programmatically via GDB/MI.
177 lines • 21 kB
JavaScript
// Copyright (c) 2015 Vadim Macagon
// MIT License, see LICENSE file for full terms.
;
require('source-map-support').install();
var chai = require('chai');
var chaiAsPromised = require('chai-as-promised');
var dbgmits = require('../lib/index');
var test_utils_1 = require('./test_utils');
chai.use(chaiAsPromised);
// aliases
var expect = chai.expect;
// the directory in which Gruntfile.js resides is also Mocha's working directory,
// so any relative paths will be relative to that directory
var localTargetExe = './build/Debug/data_tests_target';
test_utils_1.logSuite(describe("Debug Session", function () {
describe("Data Inspection and Manipulation", function () {
var debugSession;
var mainFuncLineNum;
before(function () {
var lineResolver = test_utils_1.SourceLineResolver.loadSourceFileSync('./test/data_tests_target.cpp');
mainFuncLineNum = lineResolver.getMatchingLineNumber(/^int main\(/);
});
test_utils_1.beforeEachTestWithLogger(function (logger) {
debugSession = test_utils_1.startDebugSession(logger);
return debugSession.setExecutableFile(localTargetExe);
});
afterEach(function () {
return debugSession.end();
});
it("#evaluateExpression", function () {
return test_utils_1.runToFuncAndStepOut(debugSession, 'expressionEvaluationBreakpoint', function () {
return debugSession.evaluateExpression('a')
.then(function (value) { expect(value).to.equal('1'); })
.then(function () { return debugSession.evaluateExpression('a + b'); })
.then(function (value) { expect(value).to.equal('3'); })
.then(function () { return debugSession.evaluateExpression('c.x * c.y'); })
.then(function (value) { expect(value).to.equal('25'); })
.then(function () { return debugSession.evaluateExpression('get10()'); })
.then(function (value) { expect(value).to.equal('10'); })
.then(function () { return debugSession.evaluateExpression('get10() * get10()'); })
.then(function (value) { expect(value).to.equal('100'); })
.then(function () { return debugSession.evaluateExpression('get10() == 10'); })
.then(function (value) { expect(value).to.equal('true'); })
.then(function () { return debugSession.evaluateExpression('get10() == getInt(10)'); })
.then(function (value) { expect(value).to.equal('true'); })
.then(function () {
return debugSession.evaluateExpression('a == 1', { threadId: 1, frameLevel: 0 });
})
.then(function (value) { expect(value).to.equal('true'); });
});
});
describe("#readMemory", function () {
it("reads memory at an address specified as a hex literal", function () {
return test_utils_1.runToFuncAndStepOut(debugSession, 'memoryAccessBreakpoint', function () {
return debugSession.evaluateExpression('&array')
.then(function (address) {
return debugSession.readMemory(address, 4)
.then(function (blocks) {
expect(blocks.length).to.equal(1);
expect(blocks[0]).to.have.property('begin');
expect(parseInt(blocks[0].begin, 16)).to.equal(parseInt(address, 16));
expect(blocks[0]).to.have.property('end');
expect(blocks[0]).to.have.property('offset');
expect(blocks[0]).to.have.property('contents', '01020304');
});
});
});
});
it("reads memory at an address obtained from an expression", function () {
return test_utils_1.runToFuncAndStepOut(debugSession, 'memoryAccessBreakpoint', function () {
return debugSession.readMemory('&array', 4)
.then(function (blocks) {
expect(blocks.length).to.equal(1);
expect(blocks[0]).to.have.property('contents', '01020304');
});
});
});
it("reads memory at an address with an offset", function () {
return test_utils_1.runToFuncAndStepOut(debugSession, 'memoryAccessBreakpoint', function () {
return debugSession.evaluateExpression('&array')
.then(function (address) {
return debugSession.readMemory(address, 2, { byteOffset: 2 });
})
.then(function (blocks) {
expect(blocks.length).to.equal(1);
expect(blocks[0]).to.have.property('contents', '0304');
});
});
});
});
it("#getRegisterNames", function () {
return test_utils_1.runToFunc(debugSession, 'main', function () {
return debugSession.getRegisterNames()
.then(function (registerNames) { expect(registerNames.length).to.be.greaterThan(0); })
.then(function () { return debugSession.getRegisterNames([1, 2, 3]); })
.then(function (registerNames) { expect(registerNames.length).to.equal(3); });
});
});
it("#getRegisterValues", function () {
return test_utils_1.runToFunc(debugSession, 'main', function () {
return debugSession.getRegisterValues(dbgmits.RegisterValueFormatSpec.Hexadecimal)
.then(function (registerValues) {
expect(registerValues.size).to.be.greaterThan(0);
/* FIXME: LLDB-MI produces some malformed values, needs to be fixed.
var hexRe = /^0x[0-9a-f]+$/i;
registerValues.forEach((value) => {
expect(value).to.match(hexRe);
});
*/
})
.then(function () {
return debugSession.getRegisterValues(dbgmits.RegisterValueFormatSpec.Hexadecimal, { registers: [1, 2, 3] });
})
.then(function (registerValues) {
expect(registerValues.size).to.equal(3);
});
});
});
it("#disassembleAddressRange", function () {
return test_utils_1.runToFunc(debugSession, 'main', function () {
return debugSession.evaluateExpression('&main')
.then(function (value) {
var matches = /^0x[0-9a-f]+/i.exec(value);
expect(matches).not.null;
var end = '0x' + (parseInt(matches[0], 16) + 10).toString(16);
return debugSession.disassembleAddressRange(matches[0], end);
})
.then(function (instructions) {
expect(instructions.length).to.be.greaterThan(0);
expect(instructions[0]).to.have.property('address');
expect(instructions[0]).to.have.property('func');
expect(instructions[0]).to.have.property('offset');
expect(instructions[0]).to.have.property('inst');
});
});
});
// FIXME: LLDB-MI doesn't format the output correctly in mixed mode, re-enable when it does
it("#disassembleAddressRangeByLine @skipOnLLDB", function () {
return test_utils_1.runToFunc(debugSession, 'main', function () {
return debugSession.evaluateExpression('&main')
.then(function (value) {
var matches = /^0x[0-9a-f]+/i.exec(value);
expect(matches).not.null;
var end = parseInt(matches[0], 16) + 10;
return debugSession.disassembleAddressRangeByLine(matches[0], '0x' + end.toString(16));
})
.then(function (lines) {
expect(lines.length).to.be.greaterThan(0);
expect(lines[0].instructions.length).to.be.greaterThan(0);
});
});
});
// FIXME: LLDB-MI doesn't support file/line arguments yet, re-enable when it does
it("#disassembleFile a file @skipOnLLDB", function () {
return test_utils_1.runToFunc(debugSession, 'main', function () {
// disassemble main()
return debugSession.disassembleFile('data_tests_target.cpp', mainFuncLineNum, -1)
.then(function (instructions) {
expect(instructions.length).to.be.greaterThan(0);
});
});
});
// FIXME: LLDB-MI doesn't support file/line arguments yet, and it doesn't format output correctly
// in mixed mode, re-enable when it does both of those things properly
it("#disassembleFileByLine @skipOnLLDB", function () {
return test_utils_1.runToFunc(debugSession, 'main', function () {
// disassemble main()
return debugSession.disassembleFileByLine('data_tests_target.cpp', mainFuncLineNum, -1)
.then(function (lines) {
expect(lines.length).to.be.greaterThan(0);
expect(lines[0].instructions.length).to.be.greaterThan(0);
});
});
});
});
}));
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0YV90ZXN0cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3Rlc3QvZGF0YV90ZXN0cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxtQ0FBbUM7QUFDbkMsZ0RBQWdEOztBQUVoRCxPQUFPLENBQUMsb0JBQW9CLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztBQUV4QyxJQUFZLElBQUksV0FBTSxNQUFNLENBQUMsQ0FBQTtBQUM3QixJQUFPLGNBQWMsV0FBVyxrQkFBa0IsQ0FBQyxDQUFDO0FBRXBELElBQVksT0FBTyxXQUFNLGNBQWMsQ0FBQyxDQUFBO0FBQ3hDLDJCQUdPLGNBQWMsQ0FBQyxDQUFBO0FBRXRCLElBQUksQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDLENBQUM7QUFFekIsVUFBVTtBQUNWLElBQUksTUFBTSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUM7QUFHekIsaUZBQWlGO0FBQ2pGLDJEQUEyRDtBQUMzRCxJQUFJLGNBQWMsR0FBVyxpQ0FBaUMsQ0FBQztBQUUvRCxxQkFBRyxDQUFDLFFBQVEsQ0FBQyxlQUFlLEVBQUU7SUFDNUIsUUFBUSxDQUFDLGtDQUFrQyxFQUFFO1FBQzNDLElBQUksWUFBMEIsQ0FBQztRQUMvQixJQUFJLGVBQXVCLENBQUM7UUFFNUIsTUFBTSxDQUFDO1lBQ0wsSUFBTSxZQUFZLEdBQUcsK0JBQWtCLENBQUMsa0JBQWtCLENBQUMsOEJBQThCLENBQUMsQ0FBQztZQUMzRixlQUFlLEdBQUcsWUFBWSxDQUFDLHFCQUFxQixDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQ3RFLENBQUMsQ0FBQyxDQUFDO1FBRUgscUNBQXdCLENBQUMsVUFBQyxNQUFxQjtZQUM3QyxZQUFZLEdBQUcsOEJBQWlCLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDekMsTUFBTSxDQUFDLFlBQVksQ0FBQyxpQkFBaUIsQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUN4RCxDQUFDLENBQUMsQ0FBQztRQUVILFNBQVMsQ0FBQztZQUNSLE1B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