Skip to content

Commit 1ff878c

Browse files
committed
hardwareBreakpoints to force HW only bpts
1 parent 9fb01a6 commit 1ff878c

File tree

8 files changed

+278
-91
lines changed

8 files changed

+278
-91
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# ChangeLog
22

3+
# V1.13.0-pre8
4+
* Added `hardwareBreakpoints: {required: boolean, limit: numer}` to debug configuration. You can force all breakpoints to use hardware breakpoints. You can also ask cortex-debug to limit the number such breakpoints or you can let gdb or your gdb-server enforce a limit. Please use `hardwareBreakpoints` with caution as in most cases it is better to let gdb decide which type of breakpoint to use based on memory types while making sure you are not over the limit -- this is especially true for devices with large SRAMs where you can have near inifite breakpoints and not even have a performance penalty. HW breakpoints are not inherently better than SW breakpoints so long as GDB can read/write to memory locations.
5+
36
# V1.13.0-pre7
47
* Added `overridePreEndSessionCommands` to control how a session ends. If the session does not end your way, we sill end the session the normal way
58
* We try `monitor exit` to exit the server before we try `target-disconnect` for those servers that do not follow the GDB rules

debug_attributes.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ If the type is marked as `{...}` it means that it is a complex item can have mul
3636
| 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. |
3737
| 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 |
3838
| graphConfig | {object} | Both | Description of how graphing can be done. See our Wiki for details |
39+
| hardwareBreakpoints | object | Both | WARNING: Force only HW breakpoints to be used. By default GDB will use HW or SW breakpoints depending on memory type. Use this only in rare circumstances to work around issues in your gdb-server or hardware. This setting is NOT recommended for general use. |
40+
| hardwareBreakpoints<br>.limit | number | Both | If limit > 0, enforce a limit on the number of hardware breakpoints that can be used |
41+
| hardwareBreakpoints<br>.required | boolean | Both | If true, forces the use of hardware breakpoints |
3942
| interface | string | Both | Debug Interface type to use for connections (defaults to SWD) - Used for J-Link, ST-LINK and BMP probes. |
4043
| ipAddress | string | Both | IP Address for networked J-Link Adapter |
4144
| jlinkscript | string | Both | J-Link script file - optional input file for customizing J-Link actions. |

package.json

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"version": "1.13.0-pre7",
2+
"version": "1.13.0-pre8",
33
"preview": false,
44
"activationEvents": [
55
"onDebugResolve:cortex-debug",
@@ -800,6 +800,24 @@
800800
"maximum": 9,
801801
"default": 0
802802
},
803+
"hardwareBreakpoints": {
804+
"description": "WARNING: Force only HW breakpoints to be used. By default GDB will use HW or SW breakpoints depending on memory type. Use this only in rare circumstances to work around issues in your gdb-server or hardware. This setting is NOT recommended for general use.",
805+
"type": "object",
806+
"properties": {
807+
"required": {
808+
"type": "boolean",
809+
"default": false,
810+
"description": "If true, forces the use of hardware breakpoints"
811+
},
812+
"limit": {
813+
"type": "number",
814+
"minimum": 0,
815+
"multipleOf": 1,
816+
"default": 0,
817+
"description": "If limit > 0, enforce a limit on the number of hardware breakpoints that can be used"
818+
}
819+
}
820+
},
803821
"liveWatch": {
804822
"description": "An object with parameters for Live Watch",
805823
"properties": {
@@ -1950,6 +1968,24 @@
19501968
"maximum": 9,
19511969
"default": 0
19521970
},
1971+
"hardwareBreakpoints": {
1972+
"description": "WARNING: Force only HW breakpoints to be used. By default GDB will use HW or SW breakpoints depending on memory type. Use this only in rare circumstances to work around issues in your gdb-server or hardware. This setting is NOT recommended for general use.",
1973+
"type": "object",
1974+
"properties": {
1975+
"required": {
1976+
"type": "boolean",
1977+
"default": false,
1978+
"description": "If true, forces the use of hardware breakpoints"
1979+
},
1980+
"limit": {
1981+
"type": "number",
1982+
"minimum": 0,
1983+
"multipleOf": 1,
1984+
"default": 0,
1985+
"description": "If limit > 0, enforce a limit on the number of hardware breakpoints that can be used"
1986+
}
1987+
}
1988+
},
19531989
"liveWatch": {
19541990
"description": "An object with parameters for Live Watch",
19551991
"properties": {

src/backend/backend.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,18 @@ import { hexFormat } from '../frontend/utils';
66
export interface OurSourceBreakpoint extends DebugProtocol.SourceBreakpoint {
77
file?: string;
88
raw?: string; // Used for function name as well and old style address breakpoints
9+
isFunction?: boolean;
10+
isTemporary?: boolean;
911
// What we get from gdb below
1012
address?: string;
1113
number?: number;
14+
hwOpt?: string; // The gdb MI argument to use for hardware breakpoint allocation
1215
}
1316

1417
export interface OurInstructionBreakpoint extends DebugProtocol.InstructionBreakpoint {
1518
address: number;
1619
number: number;
20+
htOpt?: string; // The gdb MI argument to use for hardware breakpoint allocation
1721
}
1822

1923
export interface OurDataBreakpoint extends DebugProtocol.DataBreakpoint {

src/backend/mi2/mi2.ts

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,9 @@ export class MI2 extends EventEmitter implements IBackend {
366366
fid = item[1]; // for future use, available for thread-selected
367367
}
368368
}
369-
if (record.asyncClass === 'thread-created') {
369+
if (record.asyncClass === 'breakpoint-deleted') {
370+
this.emit('breakpoint-deleted', { bkptId: parseInt(tid) });
371+
} else if (record.asyncClass === 'thread-created') {
370372
this.emit('thread-created', { threadId: parseInt(tid), threadGroupId: gid });
371373
} else if (record.asyncClass === 'thread-exited') {
372374
this.emit('thread-exited', { threadId: parseInt(tid), threadGroupId: gid });
@@ -567,20 +569,6 @@ export class MI2 extends EventEmitter implements IBackend {
567569
});
568570
}
569571

570-
public goto(filename: string, line: number): Thenable<boolean> {
571-
if (trace) {
572-
this.log('stderr', 'goto');
573-
}
574-
return new Promise((resolve, reject) => {
575-
const target: string = '"' + (filename ? escape(filename) + ':' : '') + line.toString() + '"';
576-
this.sendCommand('break-insert -t ' + target).then(() => {
577-
this.sendCommand('exec-jump ' + target).then((info) => {
578-
resolve(info.resultRecords.resultClass === 'running');
579-
}, reject);
580-
}, reject);
581-
});
582-
}
583-
584572
public restart(commands: string[]): Thenable<boolean> {
585573
if (trace) {
586574
this.log('stderr', 'restart');
@@ -653,10 +641,24 @@ export class MI2 extends EventEmitter implements IBackend {
653641
bkptArgs += `-c "${breakpoint.condition}" `;
654642
}
655643

656-
if (breakpoint.raw) {
644+
if (breakpoint.isTemporary) {
645+
bkptArgs += '-t ';
646+
}
647+
648+
if (breakpoint.isFunction) {
649+
bkptArgs += '--function ' + '"' + escape(breakpoint.raw) + '" ';
650+
} else if (breakpoint.raw) {
657651
bkptArgs += '*' + escape(breakpoint.raw);
658652
} else {
659-
bkptArgs += '"' + escape(breakpoint.file) + ':' + breakpoint.line + '"';
653+
bkptArgs += '"' + escape(breakpoint.file) + ':' + breakpoint.line + '" ';
654+
}
655+
656+
if (breakpoint.hwOpt) {
657+
if (breakpoint.logMessage) {
658+
reject(new MIError('Hardware breakpoints not supported by gdb with logpoints (dprintf) ' + bkptArgs, 'internal'));
659+
return;
660+
}
661+
bkptArgs = breakpoint.hwOpt + ' ' + bkptArgs;
660662
}
661663

662664
const cmd = breakpoint.logMessage ? 'dprintf-insert' : 'break-insert';
@@ -699,7 +701,7 @@ export class MI2 extends EventEmitter implements IBackend {
699701

700702
bkptArgs += '*' + hexFormat(breakpoint.address);
701703

702-
this.sendCommand(`break-insert ${bkptArgs}`).then((result) => {
704+
this.sendCommand(`break-insert ${breakpoint.htOpt || ''} ${bkptArgs}`).then((result) => {
703705
if (result.resultRecords.resultClass === 'done') {
704706
const bkptNum = parseInt(result.result('bkpt.number'));
705707
breakpoint.number = bkptNum;

src/common.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,10 @@ export function defSymbolFile(file: string): SymbolFile {
252252
return ret;
253253
}
254254

255+
export interface HWBreakpointInfo {
256+
required: boolean;
257+
limit: number;
258+
}
255259
export interface ConfigurationArguments extends DebugProtocol.LaunchRequestArguments {
256260
name: string;
257261
request: string;
@@ -307,6 +311,7 @@ export interface ConfigurationArguments extends DebugProtocol.LaunchRequestArgum
307311
registerUseNaturalFormat: boolean;
308312
variableUseNaturalFormat: boolean;
309313
chainedConfigurations: ChainedConfigurations;
314+
hardwareBreakpoints: HWBreakpointInfo;
310315

311316
pvtIsReset: boolean;
312317
pvtPorts: { [name: string]: number };

0 commit comments

Comments
 (0)