Skip to content

feat: gdb SIGINT interrupt mode #1124

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions debug_attributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ If the type is marked as `{...}` it means that it is a complex item can have mul
| debuggerArgs | array | Both | Additional arguments to pass to GDB command line |
| device | string | Both | Target Device Identifier |
| executable | string | Both | Path of executable for symbols and program information. See also `loadFiles`, `symbolFiles` |
| gdbInterruptMode | string | Both | Whether GDB shall be interrupted using "exec-interrupt" (default) or by signaling "SIGINT" |
| gdbPath | string | Both | This setting can be used to override the GDB path user/workspace setting for a particular launch configuration. This should be the full pathname to the executable (or name of the executable if it is in your PATH). Note that other toolchain executables with the configured prefix must still be available. |
| gdbTarget | string | Both | For externally (servertype = "external") controlled GDB Servers you must specify the GDB target to connect to. This can either be a "hostname:port" combination or path to a serial port |
| graphConfig | {object} | Both | Description of how graphing can be done. See our Wiki for details |
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,15 @@
},
"default": null
},
"gdbInterruptMode": {
"default": "exec-interrupt",
"description": "Whether GDB shall be interrupted using \"exec-interrupt\" (default) or by signaling \"SIGINT\"",
"type": "string",
"enum": [
"exec-interrupt",
"SIGINT"
]
},
"gdbTarget": {
"default": null,
"description": "For externally (servertype = \"external\") controlled GDB Servers you must specify the GDB target to connect to. This can either be a \"hostname:port\" combination or path to a serial port",
Expand Down Expand Up @@ -1883,6 +1892,15 @@
},
"default": null
},
"gdbInterruptMode": {
"default": "exec-interrupt",
"description": "Whether GDB shall be interrupted using \"exec-interrupt\" (default) or by signaling \"SIGINT\"",
"type": "string",
"enum": [
"exec-interrupt",
"SIGINT"
]
},
"gdbTarget": {
"default": null,
"description": "For externally (servertype = \"external\") controlled GDB Servers you must specify the GDB target to connect to. This can either be a \"hostname:port\" combination or path to a serial port",
Expand Down
23 changes: 17 additions & 6 deletions src/backend/mi2/mi2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { posix } from 'path';
import * as os from 'os';
import { ServerConsoleLog } from '../server';
import { hexFormat } from '../../frontend/utils';
import { ADAPTER_DEBUG_MODE } from '../../common';
import { ADAPTER_DEBUG_MODE, GDBInterruptMode } from '../../common';
const path = posix;

export interface ReadMemResults {
Expand Down Expand Up @@ -47,6 +47,7 @@ const trace = false;

export class MI2 extends EventEmitter implements IBackend {
public debugOutput: ADAPTER_DEBUG_MODE;
public interruptMode: GDBInterruptMode = GDBInterruptMode.EXEC_INTERRUPT;
public procEnv: any;
protected currentToken: number = 1;
protected nextTokenComing = 1; // This will be the next token output from gdb
Expand Down Expand Up @@ -495,11 +496,21 @@ export class MI2 extends EventEmitter implements IBackend {
if (trace) {
this.log('stderr', 'interrupt ' + arg);
}
return new Promise((resolve, reject) => {
this.sendCommand(`exec-interrupt ${arg}`).then((info) => {
resolve(info.resultRecords.resultClass === 'done');
}, reject);
});
if (this.interruptMode == GDBInterruptMode.EXEC_INTERRUPT) {
return new Promise((resolve, reject) => {
this.sendCommand(`exec-interrupt ${arg}`).then((info) => {
resolve(info.resultRecords.resultClass === 'done');
}, reject);
});
} else if (this.interruptMode == GDBInterruptMode.SIGINT) {
if (this.process.kill('SIGINT')) {
return Promise.resolve(true);
} else {
return Promise.reject(new Error('Could not send SIGINT to gdb'));
}
} else {
this.log('stderr', `WARNING: Invalid GDB interrupt mode '${this.interruptMode as string}'`);
}
}

public continue(threadId: number): Thenable<boolean> {
Expand Down
6 changes: 6 additions & 0 deletions src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ export interface ConfigurationArguments extends DebugProtocol.LaunchRequestArgum
serverpath: string;
gdbPath: string;
gdbServerConsolePort: number;
gdbInterruptMode: GDBInterruptMode;
objdumpPath: string;
serverArgs: string[];
serverCwd: string;
Expand Down Expand Up @@ -365,6 +366,11 @@ export enum CTIAction {
'resume'
}

export enum GDBInterruptMode {
EXEC_INTERRUPT = 'exec-interrupt',
SIGINT = 'SIGINT'
}

export interface GDBServerController extends EventEmitter {
portsNeeded: string[];
name: string;
Expand Down
12 changes: 9 additions & 3 deletions src/gdb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -938,6 +938,9 @@ export class GDBDebugSession extends LoggingDebugSession {

this.miDebugger = new MI2(gdbExePath, gdbargs);
this.miDebugger.debugOutput = this.args.showDevDebugOutput;
if (this.args.gdbInterruptMode) {
this.miDebugger.interruptMode = this.args.gdbInterruptMode;
}
this.miDebugger.on('launcherror', (err) => {
const msg = 'Could not start GDB process, does the program exist in filesystem?\n' + err.toString() + '\n';
this.launchErrorResponse(response, 103, msg);
Expand Down Expand Up @@ -1001,6 +1004,9 @@ export class GDBDebugSession extends LoggingDebugSession {
liveGdb.setupEvents(mi2);
const commands = [...this.gdbInitCommands];
mi2.debugOutput = this.args.showDevDebugOutput;
if (this.args.gdbInterruptMode) {
mi2.interruptMode = this.args.gdbInterruptMode;
}
commands.push('interpreter-exec console "set stack-cache off"');
commands.push('interpreter-exec console "set remote interrupt-on-connect off"');
if (this.serverController) {
Expand Down Expand Up @@ -1591,7 +1597,7 @@ export class GDBDebugSession extends LoggingDebugSession {
}
});
try {
await this.miDebugger.sendCommand('exec-interrupt');
await this.miDebugger.interrupt();
} catch (e) {
// The timeout will take care of it...
this.handleMsg('log', `Could not interrupt program. Trying to end session anyways ${e}\n`);
Expand Down Expand Up @@ -1675,7 +1681,7 @@ export class GDBDebugSession extends LoggingDebugSession {
restartProcessing();
} else {
this.miDebugger.once('generic-stopped', restartProcessing);
this.miDebugger.sendCommand('exec-interrupt');
this.miDebugger.interrupt();
}
});
}
Expand Down Expand Up @@ -2158,7 +2164,7 @@ export class GDBDebugSession extends LoggingDebugSession {
this.miDebugger.once('generic-stopped', () => {
createBreakpoints();
});
this.miDebugger.sendCommand('exec-interrupt');
this.miDebugger.interrupt();
}
}

Expand Down