Skip to content

Commit ecb2da4

Browse files
committed
new ssh.sourceFileMap configuration for multiple substitutions
fixes #298 also allows to have an actual separate ssh working directory additional: * fix for extended-remote without executable * fix for SSH to Win32
1 parent 92c83b1 commit ecb2da4

File tree

8 files changed

+130
-58
lines changed

8 files changed

+130
-58
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
* Breakpoints may be deleted when not recognized correctly #259 fixing #230 (@kvinwang)
1111
* New `stopAtConnect` configuration #299, #302 (@brownts)
1212
* New `stopAtEntry` configuration to run debugger to application's entry point #306 (@brownts)
13+
* New `ssh.sourceFileMap` configuration to allow multiple substitutions between local and ssh-remote and separate ssh working directory #298 (@GitMensch)
14+
* fix path translation for SSH to Win32 and for extended-remote without executable (attach to process) #323 (@GitMensch)
1315
* fix for race conditions on startup where breakpoints were not hit #304 (@brownts)
1416
* prevent "Not implemented stop reason (assuming exception)" in many cases #316 (@GitMensch),
1517
initial recognition of watchpoints

README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,8 @@ after connecting.
115115
### Using ssh for debugging on remote
116116

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

121121
```
122122
"request": "launch",
@@ -137,9 +137,12 @@ request.
137137
}
138138
```
139139

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

143+
For backward compatibility you can also use `cwd` and `ssh.cwd` for the mapping, this is only used
144+
if the newer `ssh.sourceFileMap` is not configured.
145+
143146
For X11 forwarding to work you first need to enable it in your Display Manager and allow the
144147
connections. To allow connections you can either add an entry for applications or run `xhost +`
145148
in the console while you are debugging and turn it off again when you are done using `xhost -`.

package.json

Lines changed: 51 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@
116116
},
117117
"cwd": {
118118
"type": "string",
119-
"description": "Path of project"
119+
"description": "project path"
120120
},
121121
"gdbpath": {
122122
"type": "string",
@@ -173,8 +173,8 @@
173173
"ssh": {
174174
"required": [
175175
"host",
176-
"cwd",
177-
"user"
176+
"user",
177+
"cwd"
178178
],
179179
"type": "object",
180180
"description": "If this is set then the extension will connect to an ssh host and run GDB there",
@@ -183,10 +183,6 @@
183183
"type": "string",
184184
"description": "Remote host name/ip to connect to"
185185
},
186-
"cwd": {
187-
"type": "string",
188-
"description": "Path of project on the remote"
189-
},
190186
"port": {
191187
"type": ["number", "string"],
192188
"description": "Remote port number",
@@ -209,6 +205,17 @@
209205
"description": "Auto-detect the running SSH agent (via SSH_AUTH_SOCK environment variable) and use it to perform authentication",
210206
"default": false
211207
},
208+
"sourceFileMap": {
209+
"type": "object",
210+
"description": "Mapping of source paths (from GDB on ssh remote) to local (IDE) paths.",
211+
"default": {
212+
"<sourcePath>": "<localPath>"
213+
}
214+
},
215+
"cwd": {
216+
"type": "string",
217+
"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`."
218+
},
212219
"forwardX11": {
213220
"type": "boolean",
214221
"description": "If true, the server will redirect x11 to the local host",
@@ -300,7 +307,7 @@
300307
},
301308
"cwd": {
302309
"type": "string",
303-
"description": "Path of project",
310+
"description": "project path",
304311
"default": "${workspaceRoot}"
305312
},
306313
"autorun": {
@@ -331,10 +338,6 @@
331338
"type": "string",
332339
"description": "Remote host name/ip to connect to"
333340
},
334-
"cwd": {
335-
"type": "string",
336-
"description": "Path of project on the remote"
337-
},
338341
"port": {
339342
"type": ["number", "string"],
340343
"description": "Remote port number",
@@ -357,6 +360,17 @@
357360
"description": "Auto-detect the running SSH agent (via SSH_AUTH_SOCK environment variable) and use it to perform authentication",
358361
"default": false
359362
},
363+
"sourceFileMap": {
364+
"type": "object",
365+
"description": "Mapping of source paths (from GDB on ssh remote) to local (IDE) paths.",
366+
"default": {
367+
"<sourcePath>": "<localPath>"
368+
}
369+
},
370+
"cwd": {
371+
"type": "string",
372+
"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`."
373+
},
360374
"forwardX11": {
361375
"type": "boolean",
362376
"description": "If true, the server will redirect x11 to the local host",
@@ -446,9 +460,12 @@
446460
"cwd": "^\"\\${workspaceRoot}\"",
447461
"ssh": {
448462
"host": "${2:127.0.0.1}",
449-
"cwd": "${3:/home/remote_user/project/}",
463+
"cwd": "${3:/tmp/working}",
450464
"keyfile": "${4:/home/my_user/.ssh/id_rsa}",
451-
"user": "${5:remote_user}"
465+
"user": "${5:remote_user}",
466+
"sourceFileMap": {
467+
"${6:/home/remote_user/project/}": "^\"\\${workspaceRoot}\""
468+
}
452469
},
453470
"valuesFormatting": "parseText"
454471
}
@@ -542,7 +559,7 @@
542559
},
543560
"cwd": {
544561
"type": "string",
545-
"description": "Path of project"
562+
"description": "project path"
546563
},
547564
"lldbmipath": {
548565
"type": "string",
@@ -609,10 +626,6 @@
609626
"type": "string",
610627
"description": "Remote host name/ip to connect to"
611628
},
612-
"cwd": {
613-
"type": "string",
614-
"description": "Path of project on the remote"
615-
},
616629
"port": {
617630
"type": ["number", "string"],
618631
"description": "Remote port number",
@@ -635,21 +648,32 @@
635648
"description": "Auto-detect the running SSH agent (via SSH_AUTH_SOCK environment variable) and use it to perform authentication",
636649
"default": false
637650
},
651+
"sourceFileMap": {
652+
"type": "object",
653+
"description": "Mapping of source paths (from GDB on ssh remote) to local (IDE) paths.",
654+
"default": {
655+
"<sourcePath>": "<localPath>"
656+
}
657+
},
658+
"cwd": {
659+
"type": "string",
660+
"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`."
661+
},
638662
"forwardX11": {
639663
"type": "boolean",
640664
"description": "If true, the server will redirect x11 to the local host",
641665
"default": true
642666
},
643-
"x11port": {
644-
"type": ["number", "string"],
645-
"description": "Port to redirect X11 data to (by default port = display + 6000)",
646-
"default": 6000
647-
},
648667
"x11host": {
649668
"type": "string",
650669
"description": "Hostname/ip to redirect X11 data to",
651670
"default": "localhost"
652671
},
672+
"x11port": {
673+
"type": ["number", "string"],
674+
"description": "Port to redirect X11 data to (by default port = display + 6000)",
675+
"default": 6000
676+
},
653677
"remotex11screen": {
654678
"type": "number",
655679
"description": "Screen to start the application on the remote side",
@@ -720,7 +744,7 @@
720744
},
721745
"cwd": {
722746
"type": "string",
723-
"description": "Path of project",
747+
"description": "project path",
724748
"default": "${workspaceRoot}"
725749
},
726750
"autorun": {
@@ -842,7 +866,7 @@
842866
},
843867
"cwd": {
844868
"type": "string",
845-
"description": "Path of project"
869+
"description": "project path"
846870
},
847871
"magomipath": {
848872
"type": "string",
@@ -936,7 +960,7 @@
936960
},
937961
"cwd": {
938962
"type": "string",
939-
"description": "Path of project",
963+
"description": "project path",
940964
"default": "${workspaceRoot}"
941965
},
942966
"autorun": {

src/backend/backend.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ export interface SSHArguments {
4646
x11port: number;
4747
x11host: string;
4848
bootstrap: string;
49+
sourceFileMap: { [index: string]: string };
4950
}
5051

5152
export interface IBackend {

src/backend/mi2/mi2.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,10 @@ export class MI2 extends EventEmitter implements IBackend {
149149
sshCMD += " -p " + target;
150150
this.sshConn.exec(sshCMD, execArgs, (err, stream) => {
151151
if (err) {
152-
this.log("stderr", "Could not run " + this.application + " over ssh!");
152+
this.log("stderr", "Could not run " + this.application + "(" + sshCMD +") over ssh!");
153+
if (err === undefined) {
154+
err = "<reason unknown>"
155+
}
153156
this.log("stderr", err.toString());
154157
this.emit("quit");
155158
reject();
@@ -173,7 +176,10 @@ export class MI2 extends EventEmitter implements IBackend {
173176
}, reject);
174177
});
175178
}).on("error", (err) => {
176-
this.log("stderr", "Could not run " + this.application + " over ssh!");
179+
this.log("stderr", "Error running " + this.application + " over ssh!");
180+
if (err === undefined) {
181+
err = "<reason unknown>"
182+
}
177183
this.log("stderr", err.toString());
178184
this.emit("quit");
179185
reject();
@@ -219,14 +225,15 @@ export class MI2 extends EventEmitter implements IBackend {
219225
let args = [];
220226
if (executable && !nativePath.isAbsolute(executable))
221227
executable = nativePath.join(cwd, executable);
222-
if (!executable)
223-
executable = "-p";
224228
let isExtendedRemote = false;
225229
if (target.startsWith("extended-remote")) {
226230
isExtendedRemote = true;
227231
args = this.preargs;
228-
} else
232+
} else {
233+
if (!executable)
234+
executable = "-p";
229235
args = args.concat([executable, target], this.preargs);
236+
}
230237
this.process = ChildProcess.spawn(this.application, args, { cwd: cwd, env: this.procEnv });
231238
this.process.stdout.on("data", this.stdout.bind(this));
232239
this.process.stderr.on("data", this.stderr.bind(this));
@@ -235,7 +242,8 @@ export class MI2 extends EventEmitter implements IBackend {
235242
const promises = this.initCommands(target, cwd, false, true);
236243
if (isExtendedRemote) {
237244
promises.push(this.sendCommand("target-select " + target));
238-
promises.push(this.sendCommand("file-symbol-file \"" + escape(executable) + "\""));
245+
if (executable)
246+
promises.push(this.sendCommand("file-symbol-file \"" + escape(executable) + "\""));
239247
}
240248
Promise.all(promises).then(() => {
241249
this.emit("debug-ready");

src/gdb.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,7 @@ class GDBDebugSession extends MI2DebugSession {
7878
if (args.ssh.remotex11screen === undefined)
7979
args.ssh.remotex11screen = 0;
8080
this.isSSH = true;
81-
this.trimCWD = args.cwd.replace(/\\/g, "/");
82-
this.switchCWD = args.ssh.cwd;
81+
this.setSourceFileMap(args.ssh.sourceFileMap, args.ssh.cwd, args.cwd);
8382
this.miDebugger.ssh(args.ssh, args.ssh.cwd, args.target, args.arguments, args.terminal, false).then(() => {
8483
if (args.autorun)
8584
args.autorun.forEach(command => {
@@ -126,8 +125,7 @@ class GDBDebugSession extends MI2DebugSession {
126125
if (args.ssh.remotex11screen === undefined)
127126
args.ssh.remotex11screen = 0;
128127
this.isSSH = true;
129-
this.trimCWD = args.cwd.replace(/\\/g, "/");
130-
this.switchCWD = args.ssh.cwd;
128+
this.setSourceFileMap(args.ssh.sourceFileMap, args.ssh.cwd, args.cwd);
131129
this.miDebugger.ssh(args.ssh, args.ssh.cwd, args.target, "", undefined, true).then(() => {
132130
if (args.autorun)
133131
args.autorun.forEach(command => {

src/lldb.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,7 @@ class LLDBDebugSession extends MI2DebugSession {
7373
if (args.ssh.remotex11screen === undefined)
7474
args.ssh.remotex11screen = 0;
7575
this.isSSH = true;
76-
this.trimCWD = args.cwd.replace(/\\/g, "/");
77-
this.switchCWD = args.ssh.cwd;
76+
this.setSourceFileMap(args.ssh.sourceFileMap, args.ssh.cwd, args.cwd);
7877
this.miDebugger.ssh(args.ssh, args.ssh.cwd, args.target, args.arguments, undefined, false).then(() => {
7978
if (args.autorun)
8079
args.autorun.forEach(command => {

0 commit comments

Comments
 (0)