Skip to content

new ssh.sourceFileMap configuration for multiple substitutions #323

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

Merged
merged 1 commit into from
Mar 8, 2022
Merged
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
* Breakpoints may be deleted when not recognized correctly #259 fixing #230 (@kvinwang)
* New `stopAtConnect` configuration #299, #302 (@brownts)
* New `stopAtEntry` configuration to run debugger to application's entry point #306 (@brownts)
* New `ssh.sourceFileMap` configuration to allow multiple substitutions between local and ssh-remote and separate ssh working directory #298 (@GitMensch)
* fix path translation for SSH to Win32 and for extended-remote without executable (attach to process) #323 (@GitMensch)
* fix for race conditions on startup where breakpoints were not hit #304 (@brownts)
* prevent "Not implemented stop reason (assuming exception)" in many cases #316 (@GitMensch),
initial recognition of watchpoints
Expand Down
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@ after connecting.
### Using ssh for debugging on remote

Debugging using ssh automatically converts all paths between client & server and also optionally
redirects X11 output from the server to the client. Simply add a `ssh` object in your `launch`
request.
redirects X11 output from the server to the client.
Simply add a `ssh` object in your `launch` request.

```
"request": "launch",
Expand All @@ -137,9 +137,12 @@ request.
}
```

`cwd` will be used to trim off local paths and `ssh.cwd` will map them to the server. This is
`ssh.sourceFileMap` will be used to trim off local paths and map them to the server. This is
required for basically everything except watched variables or user commands to work.

For backward compatibility you can also use `cwd` and `ssh.cwd` for the mapping, this is only used
if the newer `ssh.sourceFileMap` is not configured.

For X11 forwarding to work you first need to enable it in your Display Manager and allow the
connections. To allow connections you can either add an entry for applications or run `xhost +`
in the console while you are debugging and turn it off again when you are done using `xhost -`.
Expand Down
78 changes: 51 additions & 27 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@
},
"cwd": {
"type": "string",
"description": "Path of project"
"description": "project path"
},
"gdbpath": {
"type": "string",
Expand Down Expand Up @@ -173,8 +173,8 @@
"ssh": {
"required": [
"host",
"cwd",
"user"
"user",
"cwd"
],
"type": "object",
"description": "If this is set then the extension will connect to an ssh host and run GDB there",
Expand All @@ -183,10 +183,6 @@
"type": "string",
"description": "Remote host name/ip to connect to"
},
"cwd": {
"type": "string",
"description": "Path of project on the remote"
},
"port": {
"type": ["number", "string"],
"description": "Remote port number",
Expand All @@ -209,6 +205,17 @@
"description": "Auto-detect the running SSH agent (via SSH_AUTH_SOCK environment variable) and use it to perform authentication",
"default": false
},
"sourceFileMap": {
"type": "object",
"description": "Mapping of source paths (from GDB on ssh remote) to local (IDE) paths.",
"default": {
"<sourcePath>": "<localPath>"
}
},
"cwd": {
"type": "string",
"description": "Working directory for the debugger.\nIf `ssh.sourceFileMap` is not set, then this is also the project path on the remote for mapping with `cwd`."
},
"forwardX11": {
"type": "boolean",
"description": "If true, the server will redirect x11 to the local host",
Expand Down Expand Up @@ -300,7 +307,7 @@
},
"cwd": {
"type": "string",
"description": "Path of project",
"description": "project path",
"default": "${workspaceRoot}"
},
"autorun": {
Expand Down Expand Up @@ -331,10 +338,6 @@
"type": "string",
"description": "Remote host name/ip to connect to"
},
"cwd": {
"type": "string",
"description": "Path of project on the remote"
},
"port": {
"type": ["number", "string"],
"description": "Remote port number",
Expand All @@ -357,6 +360,17 @@
"description": "Auto-detect the running SSH agent (via SSH_AUTH_SOCK environment variable) and use it to perform authentication",
"default": false
},
"sourceFileMap": {
"type": "object",
"description": "Mapping of source paths (from GDB on ssh remote) to local (IDE) paths.",
"default": {
"<sourcePath>": "<localPath>"
}
},
"cwd": {
"type": "string",
"description": "Working directory for the debugger.\nIf `ssh.sourceFileMap` is not set, then this is also the project path on the remote for mapping with `cwd`."
},
"forwardX11": {
"type": "boolean",
"description": "If true, the server will redirect x11 to the local host",
Expand Down Expand Up @@ -446,9 +460,12 @@
"cwd": "^\"\\${workspaceRoot}\"",
"ssh": {
"host": "${2:127.0.0.1}",
"cwd": "${3:/home/remote_user/project/}",
"cwd": "${3:/tmp/working}",
"keyfile": "${4:/home/my_user/.ssh/id_rsa}",
"user": "${5:remote_user}"
"user": "${5:remote_user}",
"sourceFileMap": {
"${6:/home/remote_user/project/}": "^\"\\${workspaceRoot}\""
}
},
"valuesFormatting": "parseText"
}
Expand Down Expand Up @@ -542,7 +559,7 @@
},
"cwd": {
"type": "string",
"description": "Path of project"
"description": "project path"
},
"lldbmipath": {
"type": "string",
Expand Down Expand Up @@ -609,10 +626,6 @@
"type": "string",
"description": "Remote host name/ip to connect to"
},
"cwd": {
"type": "string",
"description": "Path of project on the remote"
},
"port": {
"type": ["number", "string"],
"description": "Remote port number",
Expand All @@ -635,21 +648,32 @@
"description": "Auto-detect the running SSH agent (via SSH_AUTH_SOCK environment variable) and use it to perform authentication",
"default": false
},
"sourceFileMap": {
"type": "object",
"description": "Mapping of source paths (from GDB on ssh remote) to local (IDE) paths.",
"default": {
"<sourcePath>": "<localPath>"
}
},
"cwd": {
"type": "string",
"description": "Working directory for the debugger.\nIf `ssh.sourceFileMap` is not set, then this is also the project path on the remote for mapping with `cwd`."
},
"forwardX11": {
"type": "boolean",
"description": "If true, the server will redirect x11 to the local host",
"default": true
},
"x11port": {
"type": ["number", "string"],
"description": "Port to redirect X11 data to (by default port = display + 6000)",
"default": 6000
},
"x11host": {
"type": "string",
"description": "Hostname/ip to redirect X11 data to",
"default": "localhost"
},
"x11port": {
"type": ["number", "string"],
"description": "Port to redirect X11 data to (by default port = display + 6000)",
"default": 6000
},
"remotex11screen": {
"type": "number",
"description": "Screen to start the application on the remote side",
Expand Down Expand Up @@ -720,7 +744,7 @@
},
"cwd": {
"type": "string",
"description": "Path of project",
"description": "project path",
"default": "${workspaceRoot}"
},
"autorun": {
Expand Down Expand Up @@ -842,7 +866,7 @@
},
"cwd": {
"type": "string",
"description": "Path of project"
"description": "project path"
},
"magomipath": {
"type": "string",
Expand Down Expand Up @@ -936,7 +960,7 @@
},
"cwd": {
"type": "string",
"description": "Path of project",
"description": "project path",
"default": "${workspaceRoot}"
},
"autorun": {
Expand Down
1 change: 1 addition & 0 deletions src/backend/backend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export interface SSHArguments {
x11port: number;
x11host: string;
bootstrap: string;
sourceFileMap: { [index: string]: string };
}

export interface IBackend {
Expand Down
20 changes: 14 additions & 6 deletions src/backend/mi2/mi2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,10 @@ export class MI2 extends EventEmitter implements IBackend {
sshCMD += " -p " + target;
this.sshConn.exec(sshCMD, execArgs, (err, stream) => {
if (err) {
this.log("stderr", "Could not run " + this.application + " over ssh!");
this.log("stderr", "Could not run " + this.application + "(" + sshCMD +") over ssh!");
if (err === undefined) {
err = "<reason unknown>"
}
this.log("stderr", err.toString());
this.emit("quit");
reject();
Expand All @@ -173,7 +176,10 @@ export class MI2 extends EventEmitter implements IBackend {
}, reject);
});
}).on("error", (err) => {
this.log("stderr", "Could not run " + this.application + " over ssh!");
this.log("stderr", "Error running " + this.application + " over ssh!");
if (err === undefined) {
err = "<reason unknown>"
}
this.log("stderr", err.toString());
this.emit("quit");
reject();
Expand Down Expand Up @@ -219,14 +225,15 @@ export class MI2 extends EventEmitter implements IBackend {
let args = [];
if (executable && !nativePath.isAbsolute(executable))
executable = nativePath.join(cwd, executable);
if (!executable)
executable = "-p";
let isExtendedRemote = false;
if (target.startsWith("extended-remote")) {
isExtendedRemote = true;
args = this.preargs;
} else
} else {
if (!executable)
executable = "-p";
args = args.concat([executable, target], this.preargs);
}
this.process = ChildProcess.spawn(this.application, args, { cwd: cwd, env: this.procEnv });
this.process.stdout.on("data", this.stdout.bind(this));
this.process.stderr.on("data", this.stderr.bind(this));
Expand All @@ -235,7 +242,8 @@ export class MI2 extends EventEmitter implements IBackend {
const promises = this.initCommands(target, cwd, false, true);
if (isExtendedRemote) {
promises.push(this.sendCommand("target-select " + target));
promises.push(this.sendCommand("file-symbol-file \"" + escape(executable) + "\""));
if (executable)
promises.push(this.sendCommand("file-symbol-file \"" + escape(executable) + "\""));
}
Promise.all(promises).then(() => {
this.emit("debug-ready");
Expand Down
6 changes: 2 additions & 4 deletions src/gdb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,7 @@ class GDBDebugSession extends MI2DebugSession {
if (args.ssh.remotex11screen === undefined)
args.ssh.remotex11screen = 0;
this.isSSH = true;
this.trimCWD = args.cwd.replace(/\\/g, "/");
this.switchCWD = args.ssh.cwd;
this.setSourceFileMap(args.ssh.sourceFileMap, args.ssh.cwd, args.cwd);
this.miDebugger.ssh(args.ssh, args.ssh.cwd, args.target, args.arguments, args.terminal, false).then(() => {
if (args.autorun)
args.autorun.forEach(command => {
Expand Down Expand Up @@ -126,8 +125,7 @@ class GDBDebugSession extends MI2DebugSession {
if (args.ssh.remotex11screen === undefined)
args.ssh.remotex11screen = 0;
this.isSSH = true;
this.trimCWD = args.cwd.replace(/\\/g, "/");
this.switchCWD = args.ssh.cwd;
this.setSourceFileMap(args.ssh.sourceFileMap, args.ssh.cwd, args.cwd);
this.miDebugger.ssh(args.ssh, args.ssh.cwd, args.target, "", undefined, true).then(() => {
if (args.autorun)
args.autorun.forEach(command => {
Expand Down
3 changes: 1 addition & 2 deletions src/lldb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,7 @@ class LLDBDebugSession extends MI2DebugSession {
if (args.ssh.remotex11screen === undefined)
args.ssh.remotex11screen = 0;
this.isSSH = true;
this.trimCWD = args.cwd.replace(/\\/g, "/");
this.switchCWD = args.ssh.cwd;
this.setSourceFileMap(args.ssh.sourceFileMap, args.ssh.cwd, args.cwd);
this.miDebugger.ssh(args.ssh, args.ssh.cwd, args.target, args.arguments, undefined, false).then(() => {
if (args.autorun)
args.autorun.forEach(command => {
Expand Down
Loading