From ea8e74de75995a2ede6a39600d75738c772533fc Mon Sep 17 00:00:00 2001 From: Jonah Graham Date: Thu, 13 Apr 2023 09:42:39 -0400 Subject: [PATCH] Allow attaching (remote and local) with no program There is no strict need to have a program passed to GDB when attaching (remote or local). Either the program can be downloaded from the remote or otherwise read by GDB, or if not possible then GDB can do symbol-free debugging. Previously in #228 some work was done to better error when program was not specified. This change loosens the restrictions slightly. If the program is not specified, it is still a warning in VSCode because of [package.json](https://github.com/eclipse-cdt-cloud/cdt-gdb-vscode/blob/22a9f1048f9030689ed1f5f2b3e5d5e48df9047d/package.json#L205-L207) See this comment for how it is presented to a user: https://github.com/eclipse-cdt-cloud/cdt-gdb-adapter/issues/261#issuecomment-1505209833 Part of #261 --- src/GDBDebugSession.ts | 22 +++++++++++++--------- src/GDBTargetDebugSession.ts | 4 +++- src/integration-tests/attach.spec.ts | 13 +++++++++++++ src/integration-tests/attachRemote.spec.ts | 11 +++++++++++ 4 files changed, 40 insertions(+), 10 deletions(-) diff --git a/src/GDBDebugSession.ts b/src/GDBDebugSession.ts index ababf773..736c9051 100644 --- a/src/GDBDebugSession.ts +++ b/src/GDBDebugSession.ts @@ -338,15 +338,19 @@ export class GDBDebugSession extends LoggingDebugSession { ); await this.spawn(args); - if (!args.program) { - this.sendErrorResponse( - response, - 1, - 'The program must be specified in the request arguments' - ); - return; + if (request == 'launch') { + if (!args.program) { + this.sendErrorResponse( + response, + 1, + 'The program must be specified in the request arguments' + ); + return; + } + } + if (args.program) { + await this.gdb.sendFileExecAndSymbols(args.program); } - await this.gdb.sendFileExecAndSymbols(args.program); await this.gdb.sendEnablePrettyPrint(); if (request === 'attach') { @@ -997,7 +1001,7 @@ export class GDBDebugSession extends LoggingDebugSession { } response.body = { allThreadsContinued: isAllThreadsContinued, - } + }; this.sendResponse(response); } catch (err) { this.sendErrorResponse( diff --git a/src/GDBTargetDebugSession.ts b/src/GDBTargetDebugSession.ts index 2f2e33d6..638ca419 100644 --- a/src/GDBTargetDebugSession.ts +++ b/src/GDBTargetDebugSession.ts @@ -275,7 +275,9 @@ export class GDBTargetDebugSession extends GDBDebugSession { try { this.isAttach = true; await this.spawn(args); - await this.gdb.sendFileExecAndSymbols(args.program); + if (args.program) { + await this.gdb.sendFileExecAndSymbols(args.program); + } await this.gdb.sendEnablePrettyPrint(); if (args.imageAndSymbols) { if (args.imageAndSymbols.symbolFileName) { diff --git a/src/integration-tests/attach.spec.ts b/src/integration-tests/attach.spec.ts index 4f76b7dc..63d6dba5 100644 --- a/src/integration-tests/attach.spec.ts +++ b/src/integration-tests/attach.spec.ts @@ -51,4 +51,17 @@ describe('attach', function () { await dc.attachHitBreakpoint(attachArgs, { line: 25, path: src }); expect(await dc.evaluate('argv[1]')).to.contain('running-from-spawn'); }); + + it('can attach and hit a breakpoint with no program specified', async function () { + if (isRemoteTest) { + // attachRemote.spec.ts is the test for when isRemoteTest + this.skip(); + } + + const attachArgs = fillDefaults(this.test, { + processId: `${inferior.pid}`, + } as AttachRequestArguments); + await dc.attachHitBreakpoint(attachArgs, { line: 25, path: src }); + expect(await dc.evaluate('argv[1]')).to.contain('running-from-spawn'); + }); }); diff --git a/src/integration-tests/attachRemote.spec.ts b/src/integration-tests/attachRemote.spec.ts index ef9c53b8..499366ab 100644 --- a/src/integration-tests/attachRemote.spec.ts +++ b/src/integration-tests/attachRemote.spec.ts @@ -74,4 +74,15 @@ describe('attach remote', function () { await dc.attachHitBreakpoint(attachArgs, { line: 3, path: emptySrc }); expect(await dc.evaluate('argv[1]')).to.contain('running-from-spawn'); }); + + it('can attach remote and hit a breakpoint without a program', async function () { + const attachArgs = fillDefaults(this.test, { + target: { + type: 'remote', + parameters: [`localhost:${port}`], + } as TargetAttachArguments, + } as TargetAttachRequestArguments); + await dc.attachHitBreakpoint(attachArgs, { line: 3, path: emptySrc }); + expect(await dc.evaluate('argv[1]')).to.contain('running-from-spawn'); + }); });