Skip to content

Debuggers

This page provides additional debugger configurations beyond the default ones included with Helix, which can be found in languages.toml ↗.

lldb-vscode

Helix natively supports debugging Rust, Zig, C, and C++ with lldb-vscode, which is part of llvm/lldb.

Installation Instructions

For macOS Users

  1. Install LLVM using Homebrew:
    Terminal window
    brew install llvm
  2. Add LLVM to your PATH by including $(brew --prefix)/opt/llvm/bin in your ~/.bashrc or ~/.zshrc file.
  3. Restart your shell to apply the changes.

For Debian 12 Users

  1. Install lldb-15:
    Terminal window
    sudo apt install lldb-15
  2. Navigate to the directory containing lldb-vscode-15:
    Terminal window
    cd $(dirname $(which lldb-vscode-15))
  3. Create a symbolic link for lldb-vscode (or since #10091 ↗ lldb-dap):
    Terminal window
    sudo ln -s lldb-vscode-15 lldb-dap

For Arch Linux users

Terminal window
pacman -S lldb

For Fedora Users

Terminal window
sudo dnf install lldb

For General Linux Users: Installing from Official Pre-compiled Binaries

  1. Download the latest pre-compiled LLVM binaries for Linux from the releases page ↗. For example, at the time of writing, the latest version is available at:
    https://github.com/llvm/llvm-project/releases/download/llvmorg-17.0.6/clang+llvm-17.0.6-x86_64-linux-gnu-ubuntu-22.04.tar.xz
  2. Unpack the binaries to a directory within your system’s $PATH, such as ~/bin, and create a symbolic link to the lldb-vscode executable located in the bin directory.

Screenshot depicting the unpacking process

Configuration for Rust

An issue exists where string variables display as memory addresses instead of their actual values ↗. To address this, rust-lldb offers a workaround by running specific lldb commands before loading the program. The paths may differ based on your Rust installation:

Terminal window
rust-lldb target/debug/hello_cargo
(lldb) command script import "/opt/homebrew/Cellar/rust/1.71.0/lib/rustlib/etc/lldb_lookup.py"
(lldb) command source -s 0 '/opt/homebrew/Cellar/rust/1.71.0/lib/rustlib/etc/lldb_commands'

By executing these commands, the debugger can display the contents of local string variables as shown below:

(lldb) b src/main.rs:5
Breakpoint 1: where = hello_cargo`hello_cargo::main::h24135e338b19c0c6 + 212 at main.rs:5:5, address = 0x0000000100003cc0
(lldb) run
Process 62497 launched: '/path/to/hello_cargo/target/debug/hello_cargo' (arm64)
Process 62497 stopped
* thread #1, name = 'main', queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x0000000100003cc0 hello_cargo`hello_cargo::main::h24135e338b19c0c6 at main.rs:5:5
2 let s = "world";
3 let x = 2;
4 let b = true;
-> 5 println!("Hello, {} {} {}!", s, x, b);
6 }
(lldb) frame variable
(&str) s = "world" {
data_ptr = 0x0000000100039d70 "worldHello, !\n"
length = 5
}
(int) x = 2
(bool) b = true
(lldb)

For lldb-vscode, replicate this functionality using initCommands ↗. Save the following Python snippet as /usr/local/etc/lldb_vscode_rustc_primer.py (create the directory if necessary):

import subprocess
import pathlib
import lldb
# Determine the sysroot for the active Rust interpreter
rustlib_etc = pathlib.Path(subprocess.getoutput('rustc --print sysroot')) / 'lib' / 'rustlib' / 'etc'
if not rustlib_etc.exists():
raise RuntimeError('Unable to determine rustc sysroot')
# Load lldb_lookup.py and execute lldb_commands with the correct path
lldb.debugger.HandleCommand(f"""command script import "{rustlib_etc / 'lldb_lookup.py'}" """)
lldb.debugger.HandleCommand(f"""command source -s 0 "{rustlib_etc / 'lldb_commands'}" """)

This script locates your active Rust installation and executes the lldb setup scripts as rust-lldb would. Update your ~/.config/helix/languages.toml accordingly:

[[language]]
name = "rust"
[language.debugger]
name = "lldb-vscode"
transport = "stdio"
command = "lldb-vscode"
[[language.debugger.templates]]
name = "binary"
request = "launch"
completion = [ { name = "binary", completion = "filename" } ]
args = { program = "{0}", initCommands = [ "command script import /usr/local/etc/lldb_vscode_rustc_primer.py" ] }

Codelldb

Installation Instructions for Linux (Tested on Ubuntu)

  1. Navigate to your home directory:
    Terminal window
    cd ~
  2. Determine your CPU’s architecture to download the correct version of codelldb:
    Terminal window
    lscpu | grep -oP 'Architecture:\s*\K.+'
  3. Create a bin directory and access it:
    Terminal window
    mkdir bin && cd bin
  4. Use curl to download codelldb:
    Terminal window
    sudo curl -L "https://github.com/vadimcn/vscode-lldb/releases/download/v1.7.0/codelldb-x86_64-linux.vsix" -o "codelldb-x86_64-linux.zip"
  5. Unzip only the required folders (extension/adapter and extension/lldb):
    Terminal window
    unzip "codelldb-x86_64-linux.zip" "extension/adapter/*" "extension/lldb/*"
  6. Rename the extension/ directory to codelldb_adapter/:
    Terminal window
    mv extension/ codelldb_adapter
  7. Remove the downloaded zip file:
    Terminal window
    sudo rm "codelldb-x86_64-linux.zip"
  8. Create a symbolic link from codelldb_adapter/adapter/codelldb to /usr/bin/codelldb:
    Terminal window
    ln -s $(pwd)/codelldb_adapter/adapter/codelldb /usr/bin/codelldb

Test the installation by running codelldb -h.

Configuration for Rust

You can also use vscode-lldb’s codelldb adapter for debugging Rust:

[[language]]
name = "rust"
[language.debugger]
command = "codelldb"
name = "codelldb"
port-arg = "--port {}"
transport = "tcp"
[[language.debugger.templates]]
name = "binary"
request = "launch"
[[language.debugger.templates.completion]]
completion = "filename"
name = "binary"
[language.debugger.templates.args]
program = "{0}"
runInTerminal = true

Test with debug-start binary target/debug/zellij, for example. Starting/stopping debugging and setting breakpoints should work as expected.

Additional Information for Users Unable to Attach to a Running Process

If you’re on Linux and unable to attach to a running process due to an “Operation not permitted” error, check if ptrace is blocking you. Consult this Microsoft troubleshooting guide ↗ for solutions.

Possible solutions include:

  1. Setting the value of /proc/sys/kernel/yama/ptrace_scope to 0 rather than 1.
  2. If the file is not present or Yama is not used, use libcap2-bin to grant ptrace permissions to the debug adapter (typically configured in languages.toml).