Skip to content

Commit 3c5221f

Browse files
MiguelBarrochrisbra
andcommitted
runtime(termdebug): Add remote debugging capabilities
closes: #18429 Co-authored-by: Christian Brabandt <cb@256bit.org> Signed-off-by: Miguel Barro <miguel.barro@live.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
1 parent 143686b commit 3c5221f

File tree

4 files changed

+475
-52
lines changed

4 files changed

+475
-52
lines changed

runtime/doc/tags

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10952,8 +10952,12 @@ termdebug-example terminal.txt /*termdebug-example*
1095210952
termdebug-frames terminal.txt /*termdebug-frames*
1095310953
termdebug-mappings terminal.txt /*termdebug-mappings*
1095410954
termdebug-prompt terminal.txt /*termdebug-prompt*
10955+
termdebug-remote terminal.txt /*termdebug-remote*
10956+
termdebug-remote-example terminal.txt /*termdebug-remote-example*
10957+
termdebug-remote-window terminal.txt /*termdebug-remote-window*
1095510958
termdebug-starting terminal.txt /*termdebug-starting*
1095610959
termdebug-stepping terminal.txt /*termdebug-stepping*
10960+
termdebug-substitute-path terminal.txt /*termdebug-substitute-path*
1095710961
termdebug-timeout terminal.txt /*termdebug-timeout*
1095810962
termdebug-variables terminal.txt /*termdebug-variables*
1095910963
termdebug_contributing terminal.txt /*termdebug_contributing*

runtime/doc/terminal.txt

Lines changed: 103 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*terminal.txt* For Vim version 9.1. Last change: 2025 Sep 15
1+
*terminal.txt* For Vim version 9.1. Last change: 2025 Oct 08
22

33

44
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -44,6 +44,7 @@ If the result is "1" you have it.
4444
Prompt mode |termdebug-prompt|
4545
Mappings |termdebug-mappings|
4646
Communication |termdebug-communication|
47+
Remote Debugging |termdebug-remote|
4748
Customizing |termdebug-customizing|
4849

4950
{only available when compiled with the |+terminal| feature}
@@ -1635,26 +1636,125 @@ interrupt the running program. But after using the MI command
16351636
communication channel.
16361637

16371638

1639+
Remote debugging ~
1640+
*termdebug-remote*
1641+
One of the main issues of remote debugging is the access to the debuggee's
1642+
source files. The plugin can profit from system and vim's networking
1643+
capabilities to workaround this.
1644+
*termdebug-remote-example*
1645+
The |termdebug-example| can be replicated by running the `gdb` debugger to
1646+
debug Vim on a remote Linux machine accessible via `ssh`.
1647+
1648+
- Build Vim as explained in the local example.
1649+
1650+
- If "socat" is not available in the remote machine 'terminal' mode will not
1651+
work properly. Fall back to |termdebug_use_prompt|: >
1652+
:let g:termdebug_config = {}
1653+
:let g:termdebug_config['use_prompt'] = v:true
1654+
1655+
- Specify the command line to run the remote `gdb` instance: >
1656+
:let g:termdebug_config['command'] = ['ssh', 'hostname', 'gdb']
1657+
< Explaining `ssh` is beyond the scope of this example, but notice the
1658+
command line can be greatly simplified by specifying the user, keys and
1659+
other options into the `$HOME/.ssh/config` file.
1660+
1661+
- Provide a hint for translating remote paths into |netrw| paths: >
1662+
:let g:termdebug_config['substitute_path'] = { '/': 'scp://hostname//' }
1663+
1664+
- Load the termdebug plugin and start debugging Vim: >
1665+
:packadd termdebug
1666+
:Termdebug vim
1667+
1668+
You now have the same three windows of the local example and can follow the
1669+
very same steps. The only difference is that the source windows displays a
1670+
netrw buffer instead of a local one.
1671+
1672+
*termdebug-substitute-path*
1673+
Use the `g:termdebug_config['substitute_path']` entry to map remote to local
1674+
files using the same strategy that gdb's `substitute-path` command uses.
1675+
For example:
1676+
- Use |netrw| to access files remoting via ssh: >
1677+
let g:termdebug_config['command'] = ['ssh', 'hostname', 'gdb']
1678+
let g:termdebug_config['substitute_path'] = { '/': 'scp://hostname//' }
1679+
< Note: that the key specifies the remote machine root path and the value
1680+
the local one.
1681+
- Use Windows' `UNC` paths to access `WSL2` sources: >
1682+
let g:termdebug_config['command'] = ['wsl', 'gdb']
1683+
let g:termdebug_config['substitute_path'] = {
1684+
\ '/': '\\wsl.localhost\Ubuntu-22.04\',
1685+
\ '/mnt/c/': 'C:/' }
1686+
< Note: that several mappings are required: one for each drive unit
1687+
and one for the linux filesystem (queried via `wslpath`).
1688+
1689+
In this mode any `ssh` or `wsl` command would be detected and a similar
1690+
command would be used to launch `socat` in a remote `tty` terminal session
1691+
and connect it to `gdb`.
1692+
If `socat` is not available a plain remote terminal would be used as
1693+
fallback.
1694+
The next session shows how to override this default behaviour.
1695+
1696+
*termdebug-remote-window*
1697+
In order to use another remote terminal client, set "remote_window" entry
1698+
in `g:termdebug_config` variable before invoking `:Termdebug`. For example:
1699+
- Debugging inside a docker container using "prompt" mode: >
1700+
let g:termdebug_config['use_prompt'] = v:true
1701+
let g:termdebug_config['command'] = ['docker', 'run', '-i',
1702+
\ '--rm', '--name', 'container-name', 'image-name', 'gdb']
1703+
let g:termdebug_config['remote_window'] =
1704+
\ ['docker', 'exec', '-ti', 'container-name'
1705+
\ ,'socat', '-dd', '-', 'PTY,raw,echo=0']
1706+
1707+
- Debugging inside a docker container using a "terminal buffer".
1708+
The container should be already running because unlike the previous
1709+
case for `terminal mode` "program" and "communication" ptys are created
1710+
before the gdb one: >
1711+
$ docker run -ti --rm --name container-name immage-name
1712+
1713+
< Then, launch the debugger: >
1714+
let g:termdebug_config['use_prompt'] = v:false " default
1715+
let g:termdebug_config['command'] =
1716+
\ ['docker', 'exec', '-ti', 'container-name', 'gdb']
1717+
let g:termdebug_config['remote_window'] =
1718+
\ ['docker', 'exec', '-ti', 'container-name'
1719+
\ ,'socat', '-dd', '-', 'PTY,raw,echo=0']
1720+
1721+
Note: "command" cannot use `-t` on |termdebug-prompt| mode because prompt
1722+
buffers cannot handle `tty` connections.
1723+
The "remote_window" command must use `-t` because otherwise it will lack
1724+
a `pty slave device` for gdb to connect.
1725+
Note: "socat" must be available in the remote machine on "terminal" mode.
1726+
Note: docker container sources can be accessible combining `volumes`
1727+
with mappings (see |termdebug-substitute-path|).
1728+
16381729
GDB command ~
16391730
*g:termdebugger*
16401731
To change the name of the gdb command, set "debugger" entry in
16411732
g:termdebug_config or the "g:termdebugger" variable before invoking
16421733
`:Termdebug`: >
16431734
let g:termdebug_config['command'] = "mygdb"
1735+
16441736
If there is no g:termdebug_config you can use: >
16451737
let g:termdebugger = "mygdb"
16461738
16471739
However, the latter form will be deprecated in future releases.
16481740

16491741
If the command needs an argument use a List: >
16501742
let g:termdebug_config['command'] = ['rr', 'replay', '--']
1743+
16511744
If there is no g:termdebug_config you can use: >
16521745
let g:termdebugger = ['rr', 'replay', '--']
16531746
16541747
Several arguments will be added to make gdb work well for the debugger.
16551748
If you want to modify them, add a function to filter the argument list: >
16561749
let g:termdebug_config['command_filter'] = MyDebugFilter
16571750
1751+
A "command_filter" scenario is solving escaping issues on remote debugging
1752+
over "ssh". For convenience a default filter is provided for escaping
1753+
whitespaces inside the arguments. It is automatically configured for "ssh",
1754+
but can be employed in other use cases like this: >
1755+
let g:termdebug_config['command_filter'] =
1756+
/ function('g:Termdebug_escape_whitespace')
1757+
16581758
If you do not want the arguments to be added, but you do need to set the
16591759
"pty", use a function to add the necessary arguments: >
16601760
let g:termdebug_config['command_add_args'] = MyAddArguments
@@ -1717,7 +1817,8 @@ than 99 will be displayed as "9+".
17171817
If you want to customize the breakpoint signs to show `>>` in the signcolumn: >
17181818
let g:termdebug_config['sign'] = '>>'
17191819
You can also specify individual signs for the first several breakpoints: >
1720-
let g:termdebug_config['signs'] = ['>1', '>2', '>3', '>4', '>5', '>6', '>7', '>8', '>9']
1820+
let g:termdebug_config['signs'] = ['>1', '>2', '>3', '>4', '>5',
1821+
\ '>6', '>7', '>8', '>9']
17211822
let g:termdebug_config['sign'] = '>>'
17221823
If you would like to use decimal (base 10) breakpoint signs: >
17231824
let g:termdebug_config['sign_decimal'] = 1

0 commit comments

Comments
 (0)