UNPKG

asmimproved-dbgmits

Version:

Provides the ability to control GDB and LLDB programmatically via GDB/MI.

177 lines 21 kB
// Copyright (c) 2015 Vadim Macagon // MIT License, see LICENSE file for full terms. "use strict"; 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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