Skip to content

Commit 7ef86ec

Browse files
committed
feat(preConnectCommands): Introduce new set of commands which are executed
before attaching This could contains setting the baudrate which has to be done before the connection is established.
1 parent 8d051fd commit 7ef86ec

File tree

8 files changed

+211
-0
lines changed

8 files changed

+211
-0
lines changed

src/desktop/GDBTargetDebugSession.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ export class GDBTargetDebugSession extends GDBDebugSession {
172172
},
173173
// Clear fields only relevant to main connection
174174
openGdbConsole: undefined,
175+
preConnectCommands: undefined,
175176
initCommands: undefined,
176177
};
177178
}
@@ -676,6 +677,10 @@ export class GDBTargetDebugSession extends GDBDebugSession {
676677

677678
await this.setSessionState(SessionState.GDB_READY);
678679

680+
await this.executeOrAbort(this.gdb.sendCommands.bind(this.gdb))(
681+
args.preConnectCommands
682+
);
683+
679684
const targetPort = target.port;
680685
const targetHost = targetPort
681686
? (target.host ?? 'localhost')

src/gdb/GDBDebugSessionBase.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,8 @@ export abstract class GDBDebugSessionBase extends LoggingDebugSession {
494494
}
495495
await this.gdb.sendEnablePrettyPrint();
496496

497+
await this.gdb.sendCommands(args.preConnectCommands);
498+
497499
if (request === 'attach') {
498500
this.isAttach = true;
499501
const attachArgs = args as AttachRequestArguments;

src/integration-tests/attach.spec.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,4 +118,57 @@ describe('attach', function () {
118118
}
119119
}
120120
});
121+
122+
it('executes preConnectCommands before initCommands', async function () {
123+
if (isRemoteTest) {
124+
this.skip();
125+
}
126+
127+
// Capture all stdout output
128+
const stdOutput: string[] = [];
129+
dc.on('output', (event) => {
130+
if (event.body.category === 'stdout') {
131+
stdOutput.push(event.body.output);
132+
}
133+
});
134+
135+
// Use shell echo with string concatenation to avoid the marker strings
136+
// appearing literally in the command definition
137+
const preMarker = 'PRE_CMD_EXEC';
138+
const initMarker = 'INIT_CMD_EXEC';
139+
140+
const attachArgs = fillDefaults(this.test, {
141+
program: program,
142+
processId: `${inferior.pid}`,
143+
openGdbConsole: false,
144+
preConnectCommands: [
145+
`shell echo ${preMarker.substring(0, 7)}${preMarker.substring(7)}`,
146+
],
147+
initCommands: [
148+
`shell echo ${initMarker.substring(0, 8)}${initMarker.substring(8)}`,
149+
],
150+
} as AttachRequestArguments);
151+
152+
await Promise.all([
153+
dc
154+
.waitForEvent('initialized')
155+
.then(() => dc.configurationDoneRequest()),
156+
dc.initializeRequest().then(() => dc.attachRequest(attachArgs)),
157+
]);
158+
159+
// Verify both commands produced output
160+
const allOutput = stdOutput.join('');
161+
expect(allOutput).to.include(preMarker);
162+
expect(allOutput).to.include(initMarker);
163+
164+
// Verify order: preConnectCommands should appear before initCommands in the output
165+
const preConnectPos = allOutput.indexOf(preMarker);
166+
const initPos = allOutput.indexOf(initMarker);
167+
expect(preConnectPos).to.be.greaterThan(-1);
168+
expect(initPos).to.be.greaterThan(-1);
169+
expect(preConnectPos).to.be.lessThan(
170+
initPos,
171+
'preConnectCommands should execute before initCommands'
172+
);
173+
});
121174
});

src/integration-tests/attachRemote.spec.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,4 +204,56 @@ describe('attach remote', function () {
204204
// we are testing is whether afterEach() can still disconnect after
205205
// having killed the gdbserver.
206206
});
207+
208+
it('executes preConnectCommands before target connection and initCommands', async function () {
209+
// Capture all stdout output
210+
const stdOutput: string[] = [];
211+
dc.on('output', (event) => {
212+
if (event.body.category === 'stdout') {
213+
stdOutput.push(event.body.output);
214+
}
215+
});
216+
217+
// Use shell echo with string concatenation to avoid the marker strings
218+
// appearing literally in the command definition
219+
const preMarker = 'PRE_CMD_EXEC';
220+
const initMarker = 'INIT_CMD_EXEC';
221+
222+
const attachArgs = fillDefaults(this.test, {
223+
program: program,
224+
openGdbConsole: false,
225+
preConnectCommands: [
226+
`shell echo ${preMarker.substring(0, 7)}${preMarker.substring(7)}`,
227+
],
228+
initCommands: [
229+
`shell echo ${initMarker.substring(0, 8)}${initMarker.substring(8)}`,
230+
],
231+
target: {
232+
type: 'remote',
233+
parameters: [`localhost:${port}`],
234+
} as TargetAttachArguments,
235+
} as TargetAttachRequestArguments);
236+
237+
await Promise.all([
238+
dc
239+
.waitForEvent('initialized')
240+
.then(() => dc.configurationDoneRequest()),
241+
dc.initializeRequest().then(() => dc.attachRequest(attachArgs)),
242+
]);
243+
244+
// Verify both commands produced output
245+
const allOutput = stdOutput.join('');
246+
expect(allOutput).to.include(preMarker);
247+
expect(allOutput).to.include(initMarker);
248+
249+
// Verify order: preConnectCommands should appear before initCommands in the output
250+
const preConnectPos = allOutput.indexOf(preMarker);
251+
const initPos = allOutput.indexOf(initMarker);
252+
expect(preConnectPos).to.be.greaterThan(-1);
253+
expect(initPos).to.be.greaterThan(-1);
254+
expect(preConnectPos).to.be.lessThan(
255+
initPos,
256+
'preConnectCommands should execute before initCommands'
257+
);
258+
});
207259
});

src/integration-tests/launch.spec.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,4 +151,51 @@ describe('launch', function () {
151151
msg.includes('program must be specified')
152152
);
153153
});
154+
155+
it('executes preConnectCommands before initCommands', async function () {
156+
if (isRemoteTest) {
157+
this.skip();
158+
}
159+
160+
// Capture all stdout output
161+
const stdOutput: string[] = [];
162+
dc.on('output', (event) => {
163+
if (event.body.category === 'stdout') {
164+
stdOutput.push(event.body.output);
165+
}
166+
});
167+
168+
// Use shell echo with string concatenation to avoid the marker strings
169+
// appearing literally in the command definition
170+
const preMarker = 'PRE_CMD_EXEC';
171+
const initMarker = 'INIT_CMD_EXEC';
172+
173+
await dc.launchRequest(
174+
fillDefaults(this.test, {
175+
program: emptyProgram,
176+
openGdbConsole: false,
177+
preConnectCommands: [
178+
`shell echo ${preMarker.substring(0, 7)}${preMarker.substring(7)}`,
179+
],
180+
initCommands: [
181+
`shell echo ${initMarker.substring(0, 8)}${initMarker.substring(8)}`,
182+
],
183+
} as LaunchRequestArguments)
184+
);
185+
186+
// Verify both commands produced output
187+
const allOutput = stdOutput.join('');
188+
expect(allOutput).to.include(preMarker);
189+
expect(allOutput).to.include(initMarker);
190+
191+
// Verify order: preConnectCommands should appear before initCommands in the output
192+
const preConnectPos = allOutput.indexOf(preMarker);
193+
const initPos = allOutput.indexOf(initMarker);
194+
expect(preConnectPos).to.be.greaterThan(-1);
195+
expect(initPos).to.be.greaterThan(-1);
196+
expect(preConnectPos).to.be.lessThan(
197+
initPos,
198+
'preConnectCommands should execute before initCommands'
199+
);
200+
});
154201
});

src/integration-tests/launchRemote.spec.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,4 +284,50 @@ describe('launch remote', function () {
284284
)
285285
).to.be.true;
286286
});
287+
288+
it('can execute preConnectCommands before initCommands', async function () {
289+
// Capture all stdout output
290+
const stdOutput: string[] = [];
291+
dc.on('output', (event) => {
292+
if (event.body.category === 'stdout') {
293+
stdOutput.push(event.body.output);
294+
}
295+
});
296+
297+
// Use shell echo with string concatenation to avoid the marker strings
298+
// appearing literally in the command definition
299+
const preMarker = 'PRE_CMD_EXEC';
300+
const initMarker = 'INIT_CMD_EXEC';
301+
302+
await dc.launchRequest(
303+
fillDefaults(this.test, {
304+
program: emptyProgram,
305+
openGdbConsole: false,
306+
preConnectCommands: [
307+
`shell echo ${preMarker.substring(0, 7)}${preMarker.substring(7)}`,
308+
],
309+
initCommands: [
310+
`shell echo ${initMarker.substring(0, 8)}${initMarker.substring(8)}`,
311+
],
312+
target: {
313+
type: 'remote',
314+
} as TargetLaunchArguments,
315+
} as TargetLaunchRequestArguments)
316+
);
317+
318+
// Verify both commands produced output
319+
const allOutput = stdOutput.join('');
320+
expect(allOutput).to.include(preMarker);
321+
expect(allOutput).to.include(initMarker);
322+
323+
// Verify order: preConnectCommands should appear before initCommands in the output
324+
const preConnectPos = allOutput.indexOf(preMarker);
325+
const initPos = allOutput.indexOf(initMarker);
326+
expect(preConnectPos).to.be.greaterThan(-1);
327+
expect(initPos).to.be.greaterThan(-1);
328+
expect(preConnectPos).to.be.lessThan(
329+
initPos,
330+
'preConnectCommands should execute before initCommands'
331+
);
332+
});
287333
});

src/types/session.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ export interface RequestArguments extends DebugProtocol.LaunchRequestArguments {
2323
verbose?: boolean;
2424
logFile?: string;
2525
openGdbConsole?: boolean;
26+
// Optional commands to issue before initCommands and before any target connection
27+
preConnectCommands?: string[];
2628
initCommands?: string[];
2729
hardwareBreakpoint?: boolean;
2830
customResetCommands?: string[];

src/web/GDBTargetDebugSession.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,10 @@ export class GDBTargetDebugSession extends GDBDebugSession {
484484

485485
await this.setSessionState(SessionState.GDB_READY);
486486

487+
await this.executeOrAbort(this.gdb.sendCommands.bind(this.gdb))(
488+
args.preConnectCommands
489+
);
490+
487491
// Connect to remote server
488492
if (target.connectCommands === undefined) {
489493
this.targetType =

0 commit comments

Comments
 (0)