Skip to content

Commit

Permalink
Indeed, the instruction numbers were not portable
Browse files Browse the repository at this point in the history
  • Loading branch information
colin-grant-work committed Oct 31, 2023
1 parent 5dfef94 commit 7d0e04a
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 50 deletions.
8 changes: 6 additions & 2 deletions src/GDBDebugSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1004,7 +1004,9 @@ export class GDBDebugSession extends LoggingDebugSession {
args: DebugProtocol.NextArguments
): Promise<void> {
try {
await (args.granularity === 'instruction' ? mi.sendExecNextInstruction(this.gdb, args.threadId) : mi.sendExecNext(this.gdb, args.threadId));
await (args.granularity === 'instruction'
? mi.sendExecNextInstruction(this.gdb, args.threadId)
: mi.sendExecNext(this.gdb, args.threadId));
this.sendResponse(response);
} catch (err) {
this.sendErrorResponse(
Expand All @@ -1020,7 +1022,9 @@ export class GDBDebugSession extends LoggingDebugSession {
args: DebugProtocol.StepInArguments
): Promise<void> {
try {
await (args.granularity === 'instruction' ? mi.sendExecStepInstruction(this.gdb, args.threadId) : mi.sendExecStep(this.gdb, args.threadId));
await (args.granularity === 'instruction'
? mi.sendExecStepInstruction(this.gdb, args.threadId)
: mi.sendExecStep(this.gdb, args.threadId));
this.sendResponse(response);
} catch (err) {
this.sendErrorResponse(
Expand Down
174 changes: 126 additions & 48 deletions src/integration-tests/stepping-granularity.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,8 @@
import * as path from 'path';
import { expect } from 'chai';
import { CdtDebugClient } from './debugClient';
import {
standardBeforeEach,
testProgramsDir,
// getScopes,
// verifyVariable,
// gdbVersionAtLeast,
fillDefaults,
// gdbAsync,
// isRemoteTest,
// hardwareBreakpoint,
} from './utils';
import { standardBeforeEach, testProgramsDir, fillDefaults } from './utils';
import { DebugProtocol } from '@vscode/debugprotocol';
// import * as os from 'os';

interface StackState {
main: DebugProtocol.StackFrame | undefined;
Expand All @@ -33,22 +22,21 @@ interface StackState {
interface StackStateCheck {
elsewhereDefined: boolean;
line: number;
// instruction: string;
}

describe.only('Stepping', async function() {
describe.only('Stepping', async function () {
let dc: CdtDebugClient;
const steppingProgram = path.join(testProgramsDir, 'stepping');
const steppingSource = path.join(testProgramsDir, 'stepping.c');

beforeEach(async function() {
beforeEach(async function () {
dc = await standardBeforeEach();

await dc.hitBreakpoint(
fillDefaults(this.currentTest, { program: steppingProgram }),
{
path: steppingSource,
line: 8
line: 8,
}
);
});
Expand All @@ -59,8 +47,12 @@ describe.only('Stepping', async function() {

async function getFrameState(threadId: number) {
const stack = await dc.stackTraceRequest({ threadId });
const main = stack.body.stackFrames.find(frame => frame.name === 'main');
const elsewhere = stack.body.stackFrames.find(frame => frame.name === 'getFromElsewhere');
const main = stack.body.stackFrames.find(
(frame) => frame.name === 'main'
);
const elsewhere = stack.body.stackFrames.find(
(frame) => frame.name === 'getFromElsewhere'
);
return { main, elsewhere };
}

Expand All @@ -72,58 +64,144 @@ describe.only('Stepping', async function() {
}
const target = check.elsewhereDefined ? 'elsewhere' : 'main';
expect(state[target]).not.to.be.undefined;
expect(state[target]?.line).equal(check.line, `It should have stopped at line ${check.line}`);
// expect(state[target]?.instructionPointerReference).equal(check.instruction, `It should have stopped here in ${target}!`);
expect(state[target]?.line).equal(
check.line,
`It should have stopped at line ${check.line}`
);
}

it('steps in by line', async () => {
const threads = await dc.threadsRequest();
const threadId = threads.body.threads[0].id;
expectStackState(await getFrameState(threadId), { elsewhereDefined: false, line: 8, /* instruction: '0x00000000004005bc' */ });
await Promise.all([dc.stepInRequest({ threadId, granularity: 'statement' }), dc.waitForEvent('stopped')]);
expectStackState(await getFrameState(threadId), { elsewhereDefined: true, line: 15, /* instruction: '0x0000000000400600' */ });
await Promise.all([dc.stepInRequest({ threadId, granularity: 'statement' }), dc.waitForEvent('stopped')]);
expectStackState(await getFrameState(threadId), { elsewhereDefined: true, line: 16, /* instruction: '0x0000000000400606' */ });
expectStackState(await getFrameState(threadId), {
elsewhereDefined: false,
line: 8,
});
await Promise.all([
dc.stepInRequest({ threadId, granularity: 'statement' }),
dc.waitForEvent('stopped'),
]);
expectStackState(await getFrameState(threadId), {
elsewhereDefined: true,
line: 15,
});
await Promise.all([
dc.stepInRequest({ threadId, granularity: 'statement' }),
dc.waitForEvent('stopped'),
]);
expectStackState(await getFrameState(threadId), {
elsewhereDefined: true,
line: 16,
});
});

it('steps in by instruction', async () => {
const threads = await dc.threadsRequest();
const threadId = threads.body.threads[0].id;
expectStackState(await getFrameState(threadId), { elsewhereDefined: false, line: 8, /* instruction: '0x00000000004005bc' */ });
await Promise.all([dc.stepInRequest({ threadId, granularity: 'instruction' }), dc.waitForEvent('stopped')]);
expectStackState(await getFrameState(threadId), {
elsewhereDefined: false,
line: 8,
});
await Promise.all([
dc.stepInRequest({ threadId, granularity: 'instruction' }),
dc.waitForEvent('stopped'),
]);
// First step should not take us straight to the function.
expectStackState(await getFrameState(threadId), { elsewhereDefined: false, line: 8, /* instruction: '0x00000000004005c0' */ });
expectStackState(await getFrameState(threadId), {
elsewhereDefined: false,
line: 8,
});
// Step several times to get into the function.
await Promise.all([dc.stepInRequest({ threadId, granularity: 'instruction' }), dc.waitForEvent('stopped')]);
await Promise.all([dc.stepInRequest({ threadId, granularity: 'instruction' }), dc.waitForEvent('stopped')]);
await Promise.all([dc.stepInRequest({ threadId, granularity: 'instruction' }), dc.waitForEvent('stopped')]);
expectStackState(await getFrameState(threadId), { elsewhereDefined: true, line: 14, /* instruction: '0x00000000004005f5' */ });
await Promise.all([
dc.stepInRequest({ threadId, granularity: 'instruction' }),
dc.waitForEvent('stopped'),
]);
await Promise.all([
dc.stepInRequest({ threadId, granularity: 'instruction' }),
dc.waitForEvent('stopped'),
]);
await Promise.all([
dc.stepInRequest({ threadId, granularity: 'instruction' }),
dc.waitForEvent('stopped'),
]);
expectStackState(await getFrameState(threadId), {
elsewhereDefined: true,
line: 14,
});
});

it('steps next by line and skips a function', async () => {
const threads = await dc.threadsRequest();
const threadId = threads.body.threads[0].id;
expectStackState(await getFrameState(threadId), { elsewhereDefined: false, line: 8, /* instruction: '0x00000000004005bc' */ });
await Promise.all([dc.nextRequest({ threadId, granularity: 'statement' }), dc.waitForEvent('stopped')]);
expectStackState(await getFrameState(threadId), { elsewhereDefined: false, line: 9, /* instruction: '0x00000000004005cf' */ });
await Promise.all([dc.nextRequest({ threadId, granularity: 'statement' }), dc.waitForEvent('stopped')]);
expectStackState(await getFrameState(threadId), { elsewhereDefined: false, line: 6, /* instruction: '0x00000000004005e4' */ });
expectStackState(await getFrameState(threadId), {
elsewhereDefined: false,
line: 8,
});
await Promise.all([
dc.nextRequest({ threadId, granularity: 'statement' }),
dc.waitForEvent('stopped'),
]);
expectStackState(await getFrameState(threadId), {
elsewhereDefined: false,
line: 9,
});
await Promise.all([
dc.nextRequest({ threadId, granularity: 'statement' }),
dc.waitForEvent('stopped'),
]);
expectStackState(await getFrameState(threadId), {
elsewhereDefined: false,
line: 6,
});
});

it('steps next by instruction and skips a function', async () => {
const threads = await dc.threadsRequest();
const threadId = threads.body.threads[0].id;
expectStackState(await getFrameState(threadId), { elsewhereDefined: false, line: 8, /* instruction: '0x00000000004005bc' */ });
expectStackState(await getFrameState(threadId), {
elsewhereDefined: false,
line: 8,
});
// Step several times to prove that we go straight from 8 to 9.
await Promise.all([dc.nextRequest({ threadId, granularity: 'instruction' }), dc.waitForEvent('stopped')]);
expectStackState(await getFrameState(threadId), { elsewhereDefined: false, line: 8, /* instruction: '0x00000000004005c0' */ });
await Promise.all([dc.nextRequest({ threadId, granularity: 'instruction' }), dc.waitForEvent('stopped')]);
expectStackState(await getFrameState(threadId), { elsewhereDefined: false, line: 8, /* instruction: '0x00000000004005c2' */ });
await Promise.all([dc.nextRequest({ threadId, granularity: 'instruction' }), dc.waitForEvent('stopped')]);
expectStackState(await getFrameState(threadId), { elsewhereDefined: false, line: 8, /* instruction: '0x00000000004005c7' */ });
await Promise.all([dc.nextRequest({ threadId, granularity: 'instruction' }), dc.waitForEvent('stopped')]);
expectStackState(await getFrameState(threadId), { elsewhereDefined: false, line: 8, /* instruction: '0x00000000004005cc' */ });
await Promise.all([dc.nextRequest({ threadId, granularity: 'instruction' }), dc.waitForEvent('stopped')]);
expectStackState(await getFrameState(threadId), { elsewhereDefined: false, line: 9, /* instruction: '0x00000000004005cf' */ });
await Promise.all([
dc.nextRequest({ threadId, granularity: 'instruction' }),
dc.waitForEvent('stopped'),
]);
expectStackState(await getFrameState(threadId), {
elsewhereDefined: false,
line: 8,
});
await Promise.all([
dc.nextRequest({ threadId, granularity: 'instruction' }),
dc.waitForEvent('stopped'),
]);
expectStackState(await getFrameState(threadId), {
elsewhereDefined: false,
line: 8,
});
await Promise.all([
dc.nextRequest({ threadId, granularity: 'instruction' }),
dc.waitForEvent('stopped'),
]);
expectStackState(await getFrameState(threadId), {
elsewhereDefined: false,
line: 8,
});
await Promise.all([
dc.nextRequest({ threadId, granularity: 'instruction' }),
dc.waitForEvent('stopped'),
]);
expectStackState(await getFrameState(threadId), {
elsewhereDefined: false,
line: 8,
});
await Promise.all([
dc.nextRequest({ threadId, granularity: 'instruction' }),
dc.waitForEvent('stopped'),
]);
expectStackState(await getFrameState(threadId), {
elsewhereDefined: false,
line: 9,
});
});
});

0 comments on commit 7d0e04a

Please sign in to comment.