Skip to content

Commit ba75182

Browse files
authored
Add preConnectCommands (#431)
feat(preConnectCommands): Introduce new set of commands which are executed before attaching This could contain setting the baudrate which has to be done before the connection is established.
1 parent 8d051fd commit ba75182

File tree

9 files changed

+182
-0
lines changed

9 files changed

+182
-0
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Change Log
22

3+
## Unreleased
4+
5+
- Fixes [`#432`](https://github.com/eclipse-cdt-cloud/cdt-gdb-adapter/issues/432): Fix initCommands behavior.
6+
37
## 1.6.0
48

59
- Fixes [`#421`](https://github.com/eclipse-cdt-cloud/cdt-gdb-adapter/issues/421): Using "commands" command for breakpoints locks up debugger.

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: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,4 +118,45 @@ describe('attach', function () {
118118
}
119119
}
120120
});
121+
122+
it('executes preConnectCommands before initCommands', async function () {
123+
if (isRemoteTest) {
124+
this.skip();
125+
}
126+
// Capture all stdout output
127+
const stdOutput: string[] = [];
128+
dc.on('output', (event) => {
129+
if (event.body.category === 'stdout') {
130+
stdOutput.push(event.body.output);
131+
}
132+
});
133+
134+
// Use unique markers to verify execution order
135+
const preMarker = 'pre?test?marker';
136+
const initMarker = 'init?test?marker';
137+
138+
const attachArgs = fillDefaults(this.test, {
139+
program: program,
140+
processId: `${inferior.pid}`,
141+
openGdbConsole: false,
142+
preConnectCommands: ['echo pre\\?test\\?marker\\n'],
143+
initCommands: ['echo init\\?test\\?marker\\n'],
144+
} as AttachRequestArguments);
145+
await dc.attachHitBreakpoint(attachArgs, { line: 25, path: src });
146+
147+
// Verify both commands produced output
148+
const allOutput = stdOutput.join('');
149+
expect(allOutput).to.include(preMarker);
150+
expect(allOutput).to.include(initMarker);
151+
152+
// Verify order: preConnectCommands should appear before initCommands in the output
153+
const preConnectPos = allOutput.indexOf(preMarker);
154+
const initPos = allOutput.indexOf(initMarker);
155+
expect(preConnectPos).to.be.greaterThan(-1);
156+
expect(initPos).to.be.greaterThan(-1);
157+
expect(preConnectPos).to.be.lessThan(
158+
initPos,
159+
'preConnectCommands should execute before initCommands'
160+
);
161+
});
121162
});

src/integration-tests/attachRemote.spec.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,4 +204,46 @@ 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 unique markers to verify execution order
218+
const preMarker = 'pre?test?marker';
219+
const initMarker = 'init?test?marker';
220+
221+
const attachArgs = fillDefaults(this.test, {
222+
program: program,
223+
openGdbConsole: false,
224+
preConnectCommands: ['echo pre\\?test\\?marker\\n'],
225+
initCommands: ['echo init\\?test\\?marker\\n'],
226+
target: {
227+
type: 'remote',
228+
parameters: [`localhost:${port}`],
229+
} as TargetAttachArguments,
230+
} as TargetAttachRequestArguments);
231+
232+
await dc.attachHitBreakpoint(attachArgs, { line: 25, path: src });
233+
234+
// Verify both commands produced output
235+
const allOutput = stdOutput.join('');
236+
expect(allOutput).to.include(preMarker);
237+
expect(allOutput).to.include(initMarker);
238+
239+
// Verify order: preConnectCommands should appear before initCommands in the output
240+
const preConnectPos = allOutput.indexOf(preMarker);
241+
const initPos = allOutput.indexOf(initMarker);
242+
expect(preConnectPos).to.be.greaterThan(-1);
243+
expect(initPos).to.be.greaterThan(-1);
244+
expect(preConnectPos).to.be.lessThan(
245+
initPos,
246+
'preConnectCommands should execute before initCommands'
247+
);
248+
});
207249
});

src/integration-tests/launch.spec.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,4 +151,45 @@ 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+
// Capture all stdout output
160+
const stdOutput: string[] = [];
161+
dc.on('output', (event) => {
162+
if (event.body.category === 'stdout') {
163+
stdOutput.push(event.body.output);
164+
}
165+
});
166+
167+
// Use unique markers to verify execution order
168+
const preMarker = 'pre?test?marker';
169+
const initMarker = 'init?test?marker';
170+
171+
await dc.launchRequest(
172+
fillDefaults(this.test, {
173+
program: emptyProgram,
174+
openGdbConsole: false,
175+
preConnectCommands: ['echo pre\\?test\\?marker\\n'],
176+
initCommands: ['echo init\\?test\\?marker\\n'],
177+
} as LaunchRequestArguments)
178+
);
179+
180+
// Verify both commands produced output
181+
const allOutput = stdOutput.join('');
182+
expect(allOutput).to.include(preMarker);
183+
expect(allOutput).to.include(initMarker);
184+
185+
// Verify order: preConnectCommands should appear before initCommands in the output
186+
const preConnectPos = allOutput.indexOf(preMarker);
187+
const initPos = allOutput.indexOf(initMarker);
188+
expect(preConnectPos).to.be.greaterThan(-1);
189+
expect(initPos).to.be.greaterThan(-1);
190+
expect(preConnectPos).to.be.lessThan(
191+
initPos,
192+
'preConnectCommands should execute before initCommands'
193+
);
194+
});
154195
});

src/integration-tests/launchRemote.spec.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,4 +284,45 @@ 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 unique markers to verify execution order
298+
const preMarker = 'pre?test?marker';
299+
const initMarker = 'init?test?marker';
300+
301+
await dc.launchRequest(
302+
fillDefaults(this.test, {
303+
program: emptyProgram,
304+
openGdbConsole: false,
305+
preConnectCommands: ['echo pre\\?test\\?marker\\n'],
306+
initCommands: ['echo init\\?test\\?marker\\n'],
307+
target: {
308+
type: 'remote',
309+
} as TargetLaunchArguments,
310+
} as TargetLaunchRequestArguments)
311+
);
312+
313+
// Verify both commands produced output
314+
const allOutput = stdOutput.join('');
315+
expect(allOutput).to.include(preMarker);
316+
expect(allOutput).to.include(initMarker);
317+
318+
// Verify order: preConnectCommands should appear before initCommands in the output
319+
const preConnectPos = allOutput.indexOf(preMarker);
320+
const initPos = allOutput.indexOf(initMarker);
321+
expect(preConnectPos).to.be.greaterThan(-1);
322+
expect(initPos).to.be.greaterThan(-1);
323+
expect(preConnectPos).to.be.lessThan(
324+
initPos,
325+
'preConnectCommands should execute before initCommands'
326+
);
327+
});
287328
});

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)