From e3dd5923c5a9abaf475f96ceb75d990f67643a07 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 | 16 ++++++++++++++++ 4 files changed, 45 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..7a6a1c3e 100644 --- a/src/integration-tests/attachRemote.spec.ts +++ b/src/integration-tests/attachRemote.spec.ts @@ -10,6 +10,7 @@ import * as cp from 'child_process'; import * as path from 'path'; +import * as os from 'os'; import { TargetAttachRequestArguments, TargetAttachArguments, @@ -74,4 +75,19 @@ 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 () { + if (os.platform() === 'win32') { + // win32 host does support this use case + this.skip(); + } + 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'); + }); });