Skip to content
Draft
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
5ccec73
Add multi-process support
LeszekSwirski Feb 21, 2018
92c61ff
Improvements to multi-processing
JulianvDoorn Nov 21, 2025
96a1909
POC for multiple debug sessions
JulianvDoorn Nov 22, 2025
8fd02d8
Fixed passing of events. Now it properly shows two stack traces in su…
JulianvDoorn Nov 22, 2025
d81d63d
Reuse threadRequest code between superior and inferior
JulianvDoorn Nov 22, 2025
99d76f1
Stability improvements
JulianvDoorn Nov 23, 2025
4df215d
Remove dependency on vscode-debugadapter-node changes
JulianvDoorn Nov 23, 2025
1807c8d
Fixed improved thread-specific commands
JulianvDoorn Nov 23, 2025
a67e92e
More improvements
JulianvDoorn Nov 23, 2025
4f08c34
Removed logging
JulianvDoorn Nov 23, 2025
4198fde
Large refactoring
JulianvDoorn Nov 23, 2025
ccc295c
Cleaned up miinferior.ts
JulianvDoorn Nov 23, 2025
bc6a0b8
Removed excessive whitespace
JulianvDoorn Nov 23, 2025
261a4b5
Improved exit handling
JulianvDoorn Nov 23, 2025
10c496d
Added multiProcess guards
JulianvDoorn Nov 23, 2025
22e915b
Moved constructor up and formatted fields
JulianvDoorn Nov 23, 2025
74d6e61
Fixed access specifiers
JulianvDoorn Nov 23, 2025
cc77c0e
Remove unused variables
JulianvDoorn Nov 23, 2025
d6f7ea4
Commit package.json changes
JulianvDoorn Nov 23, 2025
f1c6115
Change type to mi-inferior
JulianvDoorn Nov 23, 2025
6194b23
Let OS pick port
JulianvDoorn Nov 23, 2025
62c4073
Improved startDebugging event of children
JulianvDoorn Nov 23, 2025
7ada83d
Removed required attach attributes
JulianvDoorn Nov 23, 2025
4bcd7f7
Introduce sendEventToDebugSession and use it
JulianvDoorn Nov 23, 2025
3a13804
Add program exit logging statement
JulianvDoorn Nov 23, 2025
7b26d45
Improved subprocess exit handling
JulianvDoorn Nov 24, 2025
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
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,11 @@
"description": "Prints all GDB calls to the console",
"default": false
},
"multiProcess": {
"type": "boolean",
"description": "Allow multiple process debugging",
"default": false
},
"showDevDebugOutput": {
"type": "boolean",
"description": "Prints all GDB responses to the console",
Expand Down
4 changes: 2 additions & 2 deletions src/backend/backend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ export interface IBackend {
start(runToStart: boolean): Thenable<boolean>;
stop(): void;
detach(): void;
interrupt(): Thenable<boolean>;
continue(): Thenable<boolean>;
interrupt(threadId?: number): Thenable<boolean>;
continue(reverse?: boolean, threadId?: number): Thenable<boolean>;
next(): Thenable<boolean>;
Copy link
Copy Markdown
Author

@JulianvDoorn JulianvDoorn Nov 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This interface does not correspond with the actual implementation

step(): Thenable<boolean>;
stepOut(): Thenable<boolean>;
Expand Down
31 changes: 23 additions & 8 deletions src/backend/mi2/mi2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@
target = debuggerPath.join(cwd, target);

const cmds = [
this.sendCommand("gdb-set target-async on", true),
this.sendCommand("gdb-set mi-async on", true),
new Promise(resolve => {
this.sendCommand("list-features").then(done => {
this.features = done.result("features");
Expand All @@ -269,6 +269,16 @@
cmds.push(this.sendCommand("enable-pretty-printing"));
if (this.frameFilters)
cmds.push(this.sendCommand("enable-frame-filters"));
if (this.multiProcess) {
cmds.push(
this.sendCommand("gdb-set follow-fork-mode parent"),

Check failure on line 274 in src/backend/mi2/mi2.ts

View workflow job for this annotation

GitHub Actions / lint

Mixed spaces and tabs.
this.sendCommand("gdb-set detach-on-fork off"),
this.sendCommand("gdb-set non-stop on"),
this.sendCommand("gdb-set schedule-multiple on"),

this.sendCommand("interpreter-exec console \"handle SIGSYS nostop noprint\"")
);
}
for (const cmd of this.extraCommands) {
cmds.push(this.sendCommand(cmd));
}
Expand Down Expand Up @@ -462,7 +472,7 @@
this.emit("exited-normally", parsed);
break;
case "exited": // exit with error code != 0
this.log("stderr", "Program exited with code " + parsed.record("exit-code"));
this.log("stderr", "Inferior exited with code " + parsed.record("exit-code"));
Comment thread
JulianvDoorn marked this conversation as resolved.
Outdated
this.emit("exited-normally", parsed);
break;
// case "exited-signalled": // consider handling that explicit possible
Expand All @@ -483,6 +493,10 @@
this.emit("thread-created", parsed);
} else if (record.asyncClass === "thread-exited") {
this.emit("thread-exited", parsed);
} else if (record.asyncClass == "thread-group-started") {
this.emit("thread-group-started", parsed);
} else if (record.asyncClass == "thread-group-exited") {
this.emit("thread-group-exited", parsed);
}
}
}
Expand Down Expand Up @@ -546,21 +560,21 @@
this.sendRaw("-target-detach");
}

interrupt(): Thenable<boolean> {
interrupt(threadId?: number): Thenable<boolean> {
if (trace)
this.log("stderr", "interrupt");
this.log("stderr", "interrupt" + (threadId ? " --thread-group i" + threadId : ""));
return new Promise((resolve, reject) => {
this.sendCommand("exec-interrupt").then((info) => {
this.sendCommand("exec-interrupt" + (threadId ? " --thread-group i" + threadId : "")).then((info) => {
resolve(info.resultRecords.resultClass === "done");
}, reject);
});
}

continue(reverse: boolean = false): Thenable<boolean> {
continue(reverse: boolean = false, threadId?: number): Thenable<boolean> {
if (trace)
this.log("stderr", "continue");
this.log("stderr", "continue" + (reverse ? " --reverse" : "") + (threadId ? " --thread-group i" + threadId : ""));
return new Promise((resolve, reject) => {
this.sendCommand("exec-continue" + (reverse ? " --reverse" : "")).then((info) => {
this.sendCommand("exec-continue" + (reverse ? " --reverse" : "") + (threadId ? " --thread-group i" + threadId : "")).then((info) => {
resolve(info.resultRecords.resultClass === "running");
}, reject);
});
Expand Down Expand Up @@ -1023,6 +1037,7 @@

prettyPrint: boolean = true;
frameFilters: boolean = true;
multiProcess: boolean = false;
printCalls: boolean;
debugOutput: boolean;
features: string[];
Expand Down
101 changes: 101 additions & 0 deletions src/backend/mi2/mi2inferior.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { Breakpoint, IBackend, SSHArguments, Stack, Thread, Variable } from "../backend";
import { MI2 } from "./mi2";

export class MI2Inferior implements IBackend {
load(cwd: string, target: string, procArgs: string, separateConsole: string, autorun: string[]): Thenable<any> {
return this.superior.load(cwd, target, procArgs, separateConsole, autorun);
}

ssh(args: SSHArguments, cwd: string, target: string, procArgs: string, separateConsole: string, attach: boolean, autorun: string[]): Thenable<any> {
return this.superior.ssh(args, cwd, target, separateConsole, procArgs, attach, autorun);
}

attach(cwd: string, executable: string, target: string, autorun: string[]): Thenable<any> {
return this.superior.attach(cwd, executable, target, autorun);
}

connect(cwd: string, executable: string, target: string, autorun: string[]): Thenable<any> {
return this.superior.attach(cwd, executable, target, autorun);
}

start(runToStart: boolean): Thenable<boolean> {
return this.superior.start(runToStart);
}

stop(): void {
this.superior.stop();
}

detach(): void {
this.superior.detach();
}

interrupt(threadId?: number): Thenable<boolean> {
return this.superior.interrupt(threadId);
}

continue(reverse?: boolean, threadId?: number): Thenable<boolean> {
return this.superior.continue(reverse, threadId);
}

next(): Thenable<boolean> {
return this.superior.next();
}
step(): Thenable<boolean> {
return this.superior.step();
}

stepOut(): Thenable<boolean> {
return this.superior.stepOut();
}

loadBreakPoints(breakpoints: Breakpoint[]): Thenable<[boolean, Breakpoint][]> {
return this.superior.loadBreakPoints(breakpoints);
}

addBreakPoint(breakpoint: Breakpoint): Thenable<[boolean, Breakpoint]> {
return this.superior.addBreakPoint(breakpoint);
}

removeBreakPoint(breakpoint: Breakpoint): Thenable<boolean> {
return this.superior.removeBreakPoint(breakpoint);
}

clearBreakPoints(source?: string): Thenable<any> {
return this.superior.clearBreakPoints(source);
}

getThreads(): Thenable<Thread[]> {
return this.superior.getThreads();
}

getStack(startFrame: number, maxLevels: number, thread: number): Thenable<Stack[]> {
return this.superior.getStack(startFrame, maxLevels, thread);
}

getStackVariables(thread: number, frame: number): Thenable<Variable[]> {
return this.superior.getStackVariables(thread, frame);
}

evalExpression(name: string, thread: number, frame: number): Thenable<any> {
return this.superior.evalExpression(name, thread, frame);
}

isReady(): boolean {
return this.superior.isReady();
}

changeVariable(name: string, rawValue: string): Thenable<any> {
return this.superior.changeVariable(name, rawValue);
}

examineMemory(from: number, to: number): Thenable<any> {
return this.superior.examineMemory(from, to);
}

Check failure on line 95 in src/backend/mi2/mi2inferior.ts

View workflow job for this annotation

GitHub Actions / lint

Trailing spaces not allowed.
private superior: MI2;

contructor(superior: MI2) {
this.superior = superior

Check failure on line 99 in src/backend/mi2/mi2inferior.ts

View workflow job for this annotation

GitHub Actions / lint

Missing semicolon.
}
Comment thread
JulianvDoorn marked this conversation as resolved.
Outdated
};

Check failure on line 101 in src/backend/mi2/mi2inferior.ts

View workflow job for this annotation

GitHub Actions / lint

Newline required at end of file but not found.

Check failure on line 101 in src/backend/mi2/mi2inferior.ts

View workflow job for this annotation

GitHub Actions / lint

Unnecessary semicolon.
6 changes: 5 additions & 1 deletion src/gdb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export interface LaunchRequestArguments extends DebugProtocol.LaunchRequestArgum
valuesFormatting: ValuesFormattingMode;
frameFilters: boolean;
printCalls: boolean;
multiProcess: boolean;
showDevDebugOutput: boolean;
registerLimit: string;
}
Expand All @@ -39,11 +40,12 @@ export interface AttachRequestArguments extends DebugProtocol.AttachRequestArgum
valuesFormatting: ValuesFormattingMode;
frameFilters: boolean;
printCalls: boolean;
multiProcess: boolean;
showDevDebugOutput: boolean;
registerLimit: string;
}

class GDBDebugSession extends MI2DebugSession {
export class GDBDebugSession extends MI2DebugSession {
protected override initializeRequest(response: DebugProtocol.InitializeResponse, args: DebugProtocol.InitializeRequestArguments): void {
response.body.supportsGotoTargetsRequest = true;
response.body.supportsHitConditionalBreakpoints = true;
Expand Down Expand Up @@ -75,6 +77,7 @@ class GDBDebugSession extends MI2DebugSession {
this.setValuesFormattingMode(args.valuesFormatting);
this.miDebugger.frameFilters = !!args.frameFilters;
this.miDebugger.printCalls = !!args.printCalls;
this.miDebugger.multiProcess = !!args.multiProcess;
this.miDebugger.debugOutput = !!args.showDevDebugOutput;
this.stopAtEntry = args.stopAtEntry;
this.miDebugger.registerLimit = args.registerLimit ?? "";
Expand Down Expand Up @@ -121,6 +124,7 @@ class GDBDebugSession extends MI2DebugSession {
this.setValuesFormattingMode(args.valuesFormatting);
this.miDebugger.frameFilters = !!args.frameFilters;
this.miDebugger.printCalls = !!args.printCalls;
this.miDebugger.multiProcess = !!args.multiProcess;
this.miDebugger.debugOutput = !!args.showDevDebugOutput;
this.stopAtEntry = args.stopAtEntry;
this.miDebugger.registerLimit = args.registerLimit ?? "";
Expand Down
Loading