Skip to content

Debugger Configurations

Salar Nosrati-Ershad edited this page Oct 5, 2024 · 26 revisions

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

lldb-vscode

💡lldb-vscode has recently changed its name to lldb-dap. You can find the source code here. If you are using the Helix master branch, since #10091 lldb-dap is used

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:
    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:
    sudo apt install lldb-15
  2. Navigate to the directory containing lldb-vscode-15:
    cd $(dirname $(which lldb-vscode-15))
  3. Create a symbolic link for lldb-vscode (or since #10091 lldb-dap):
    sudo ln -s lldb-vscode-15 lldb-dap

For Arch Linux users

pacman -S lldb

For Fedora Users

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:

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:
    cd ~
  2. Determine your CPU's architecture to download the correct version of codelldb:
    lscpu | grep -oP 'Architecture:\s*\K.+'
  3. Create a bin directory and access it:
    mkdir bin && cd bin
  4. Use curl to download codelldb:
    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):
    unzip "codelldb-x86_64-linux.zip" "extension/adapter/*" "extension/lldb/*"
  6. Rename the extension/ directory to codelldb_adapter/:
    mv extension/ codelldb_adapter
  7. Remove the downloaded zip file:
    sudo rm "codelldb-x86_64-linux.zip"
  8. Create a symbolic link from codelldb_adapter/adapter/codelldb to /usr/bin/codelldb:
    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).