Debugging in Vim

Vim 8.1 was released about a year ago, in May 2018. The “main new feature” was official support for running a terminal within vim. Along with this came a built-in debugger plugin, termdebug, which provides a visual interface for interacting with gdb. This post walks through an example session using termdebug.

Let’s use termdebug to step through and inspect the following C program that calculates the factorial of a number. I’ll be using Ubuntu 18.04, along with a version of vim installed from the Ubuntu repo—8.0.1453—that includes the relevant feature that was officially released as part of vim 8.1.

In addition to vim, a working version of gdb is required for debugging. For Ubuntu, this can be installed from the Ubuntu repo. For macOS, gdb will have to be code signed, and I’ve found that gdb versions earlier than 8.3 are problematic (tested on macOS Mojave). I haven’t tested debugging on Windows. Before trying to debug with vim, I suggest verifying that gdb works as expected on your system.

The path and/or name of gdb can be modified by setting the termdebugger variable before invoking the termdebug plugin.

Loading the termdebug Plugin

After loading the factorial.c source code, let’s load the plugin.

:packadd termdebug
:Termdebug

The tab will split into three windows, which I’ve rearranged so that the editor window is on the right, as shown below.

The top-left window is for interacting with gdb. The bottom-left window is for interacting with the program loaded by gdb. The editor window on the right—with the corresponding source code—will show breakpoints and highlight lines when stepping through a program. This window also has clickable buttons at the top for interacting with gdb.

Loading a Program

We’ll have to compile the code using the -g flag, which will include debugger information in the compiled program.

:!gcc -g factorial.c -o factorial

We can use the gdb window to load the program. In addition to <c-w> commands and/or mouse clicks, we can use the :Gdb command to jump to the gdb window. The following gdb command will load the program (highlighted in the image that follows).

(gdb) file factorial

Alternatively, we could have passed factorial as an argument when calling :Termdebug earlier.

Setting Breakpoints

Breakpoints can be set in the gdb window using ordinary gdb commands.

(gdb) b factorial
(gdb) b 23

Alternatively, breakpoints can be set by navigating to a line of code in the editor window and entering :Break.

Lines with breakpoints are indicated by >> in the editor window.

Breakpoints can be removed with gdb commands or by navigating to the relevant lines and entering :Delete. Update 2019/05/12 6:45pm ET: On my version of vim, :Delete is used to remove breakpoints, but this was changed to :Clear in a commit on March 3, 2018.

Program Execution

The :Run command starts the program.

:Run [args]

Or alternatively, a program can be launched by entering the run command directly in the gdb window.

(gdb) run [args]

In either case, [args] should be replaced by the program’s arguments. Let’s use the value 6 to run the factorial program.

Both :Run and (gdb) run will pause execution at the first breakpoint. An alternative way to launch a program is to use gdb’s start command, which will pause execution at the beginning of the program.

I’ve launched the program using the vim command :Run 6. Execution is paused at the first breakpoint, with the corresponding line highlighted.

Stepping through Code

There are various ways to step through a program.

  1. Invoking gdb stepping commands directly in the gdb window
  2. Clicking Step, Next, Finish, Cont, Stop, Eval in the editor window
  3. Issuing vim commands :Step, :Over, :Finish, :Continue, :Stop

Program Inspection

The values of variables can be inspected in various ways.

  1. Invoking gdb inspection commands directly in the gdb window
  2. Hovering your mouse over variables in the editor window (this worked for me in gvim, but didn’t work reliably when running vim in a terminal)
  3. Issuing vim command :Evaluate {expr}
    Omitting {expr} will evaluate the expression under the cursor, which can also be performed by pressing K

Conclusion

After passing all breakpoints and running the program until termination, we can see 720 in the program window, which is the expected output for the calculation of 6!.

The built-in help page includes thorough documentation.

:help terminal-debug
This entry was tagged , , . Bookmark the permalink.

4 Responses to Debugging in Vim

  1. Awesome! What else can be done with this terminal-in-Vim functionality?

  2. adynatos says:

    how can this be used with libtool-enabled programs?

Leave a Reply

Your email address will not be published. Required fields are marked *