Dev_tools

Nvim :help pages, generated from source using the tree-sitter-vimdoc parser.


Tools and techniques for developing Nvim
The following advice is helpful when working on or debugging issues with Nvim itself.
TODO: merge debug.txt into here.

Backtraces dev-tools-backtrace

LINUX

Core dumps are disabled by default on Ubuntu, CentOS and others. To enable core dumps:
ulimit -c unlimited
On systemd-based systems getting a backtrace is as easy as:
coredumpctl -1 gdb
coredumpctl is an optional tool, so you may need to install it:
sudo apt install systemd-coredump
The full backtrace is most useful; please send us the backtrace.txt file when reporting a bug related to a crash:
2>&1 coredumpctl -1 gdb | tee -a backtrace.txt
(gdb) thread apply all bt full
On systems without coredumpctl, you may find a core dump file appearing in the current directory or in other locations. On Linux systems where apport is installed (such as Ubuntu), the directory where core dump files are saved can be /var/lib/apport/coredump or elsewhere, depending on the system configuration (see /proc/sys/kernel/core_pattern). See also: https://stackoverflow.com/a/18368068
To get a backtrace from the ./core dump file:
gdb build/bin/nvim ./core 2>&1 | tee backtrace.txt
(gdb) thread apply all bt full

MACOS

If nvim crashes, you can see the backtrace in Console.app (under "Crash Reports" or "User Diagnostic Reports" for older macOS versions).
open -a Console
You may also want to enable core dumps on macOS. To do this, first make sure the /cores/ directory exists and is writable:
sudo mkdir /cores
sudo chown root:admin /cores
sudo chmod 1775 /cores
Then set the core size limit to unlimited:
ulimit -c unlimited
Note that this is done per shell process. If you want to make this the default for all shells, add the above line to your shell's init file (e.g. ~/.bashrc or similar).
You can then open the core file in lldb:
lldb -c /cores/core.12345
Apple's documentation archive has some other useful information https://developer.apple.com/library/archive/technotes/tn2124/_index.html#//apple_ref/doc/uid/DTS10003391-CH1-SECCOREDUMPS, but note that some of the things on this page are out of date (such as enabling core dumps with /etc/launchd.conf).

USING GDB TO STEP THROUGH FUNCTIONAL TESTS

Use TEST_TAG to run tests matching busted tags (of the form #foo e.g. it("test #foo ...", ...)):
GDB=1 TEST_TAG=foo make functionaltest
Then, in another terminal:
gdb build/bin/nvim
(gdb) target remote localhost:7777
-- See nvim_argv in https://github.com/neovim/neovim/blob/master/test/functional/testnvim.lua.

USING LLDB TO STEP THROUGH UNIT TESTS

lldb .deps/usr/bin/luajit -- .deps/usr/bin/busted --lpath="./build/?.lua" test/unit/

USING GDB

To attach to a running nvim process with a pid of 1234 (Tip: the pid of a running Nvim instance can be obtained by calling getpid()), for instance:
gdb -tui -p 1234 build/bin/nvim
The gdb interactive prompt will appear. At any time you can:
break foo to set a breakpoint on the foo() function
n to step over the next statement
<Enter> to repeat the last command
s to step into the next statement
c to continue
finish to step out of the current function
p zub to print the value of zub
bt to see a backtrace (callstack) from the current location
CTRL-x CTRL-a or tui enable to show a TUI view of the source file in the current debugging context. This can be extremely useful as it avoids the need for a gdb "frontend".
<up> and <down> to scroll the source file view

GDB REVERSE DEBUGGING

set record full insn-number-max unlimited
continue for a bit (at least until main() is executed
record
provoke the bug, then use revert-next, reverse-step, etc. to rewind the debugger

USING GDBSERVER

You may want to connect multiple gdb clients to the same running nvim process, or you may want to connect to a remote nvim process with a local gdb. Using gdbserver, you can attach to a single process and control it from multiple gdb clients.
Open a terminal and start gdbserver attached to nvim like this:
gdbserver :6666 build/bin/nvim 2> gdbserver.log
gdbserver is now listening on port 6666. You then need to attach to this debugging session in another terminal:
gdb build/bin/nvim
Once you've entered gdb, you need to attach to the remote session:
(gdb) target remote localhost:6666
In case gdbserver puts the TUI as a background process, the TUI can become unable to read input from pty (and receives SIGTTIN signal) and/or output data (SIGTTOU signal). To force the TUI as the foreground process, you can add
signal (SIGTTOU, SIG_IGN);
if (!tcsetpgrp(data->input.in_fd, getpid())) {
    perror("tcsetpgrp failed");
}
to tui.c:terminfo_start.

USING GDBSERVER IN TMUX

Consider using a custom makefile https://github.com/neovim/neovim/blob/master/BUILD.md#custom-makefile to quickly start debugging sessions using the gdbserver method mentioned above. This example local.mk will create the debugging session when you typemake debug`.
.PHONY: dbg-start dbg-attach debug build
build:
    @$(MAKE) nvim
dbg-start: build
    @tmux new-window -n 'dbg-neovim' 'gdbserver :6666 ./build/bin/nvim -D'
dbg-attach:
    @tmux new-window -n 'dbg-cgdb' 'cgdb -x gdb_start.sh ./build/bin/nvim'
debug: dbg-start dbg-attach
Here gdb_start.sh includes gdb commands to be called when the debugger starts. It needs to attach to the server started by the dbg-start rule. For example:
(gdb) target remote localhost:6666
(gdb) br main
Main
Commands index
Quick reference