[Solved] How to step into std source code when debugging in VS Code?

I’m using VS Code with the CodeLLDB extension on macOS.

I’m using this step to step through my rust unit tests in the debugger. This is working well, but I would also like to step into rust’s std libraries and see debug symbols. Currently I can step into std, but just see assembly. How do I set things up so that I can step into std and see debug symbols?

I did run rustup component add rust-src but it said I was already up-to-date.

4 Likes

The std binaries distributed by the Rust organization do not contain debugging information, so this is not possible out of the box. If you really want it, you can compile std yourself with debug info enabled.

1 Like

std does contain debuginfo.

I believe you’ll just need to add a source map entry pointing the debugger to where your rust-src is located: https://github.com/vadimcn/vscode-lldb/blob/master/MANUAL.md#source-path-remapping

1 Like

Huh ok, you’re right, I was mistaken.

Edit: oh yeah, I was thinking about rustc debug info, not std.

Thanks for help. After a few missteps I think I figured it out:

First I found rust std sources on my computer at:

/Users/jessegrosjean/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/src/rust/

Next what I tried to step into Vec::new() I saw (which contains a “Source location”):

; id = {0x00000180}, range = [0x0000000100002760-0x00000001000027b0), name="_$LT$alloc..vec..Vec$LT$T$GT$$GT$::new::h50925563cb2ee1ff", mangled="_ZN33_$LT$alloc..vec..Vec$LT$T$GT$$GT$3new17h50925563cb2ee1ffE"
; Source location: /rustc/9fda7c2237db910e41d6a712e9a2139b352e558b/src/liballoc/vec.rs:329
100002760: 55                         pushq  %rbp
100002761: 48 89 E5                   movq   %rsp, %rbp
100002764: 48 83 EC 20                subq   $0x20, %rsp
...

I then combined these two things in .vscode/settings.json like this:

{
  "lldb.executable": "rust-lldb",
  "lldb.launch.sourceLanguages": ["rust"],
  "lldb.launch.sourceMap": {
    "/rustc/9fda7c2237db910e41d6a712e9a2139b352e558b/": "/Users/jessegrosjean/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/src/rust/"
  },
}

And I can step into std! Yeah and thank you!

10 Likes

In case someone uses Visual Studio Code with GDB and wants to achieve the same behavior, here is how I do it:

In launch.json:

{
    "version": "0.2.0",
    "configurations": [
        {
            "type": "gdb",
            ...,
            "autorun": [
                "set substitute-path /rustc/2aa4c46cfdd726e97360c2734835aa3515e8c858 <your-home-dir>/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust"
            ],
        }
    ]
}

Notice that /rustc/2aa4c46cfdd726e97360c2734835aa3515e8c858 depends on the exact toolchain you’re using. So updating your toolchain will probably require modifying this string. The way I easily find the hash is by running the following command in the project directory:

$ strings target/debug/<your-binary-name> | grep -o '^/rustc/[^/]\+/' | uniq

The idea is that Visual Studio Code will issue the GDB commands specified in the autorun array right after GDB is initialized, before actual debugging is started. The command set substitute-path of GDB is documented in Specifying Source Directories.

5 Likes

In case of someone in Fedora 30 / VSCode 1.41 / CodeLLDB / rustup 1.20.2 / stable-x86_64-unknown-linux-gnu:

$ cat ~/.config/Code/User/settings.json

{
    "lldb.executable": "rust-lldb",
    "lldb.launch.sourceLanguages": [
        "rust"
    ],
    "lldb.launch.sourceMap": {
        "/rustc/4560ea788cb760f0a34127156c78e2552949f734": "/home/<USER-NAME>/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust"
    }
}
2 Likes

FWIW future visitors might try this script. I'm meant to be learning Rust, but I don't know much about it yet so the script's in Python.

Sample output:

Add this to your .vscode/settings.json if you're using the vadimcn.vscode-lldb extension:

    "lldb.launch.sourceMap": {
        "/rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src": "/Users/joeuser/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/src/rust/src"
    }
Script
#!/usr/bin/env python3
import sys

if len(sys.argv) > 1 and sys.argv[1] in ('-h', '--help'):
    print(
        'This script will try to generate a "lldb.launch.sourceMap" entry you can add '
        "to your .vsode/settings.json file for use with the 'vadimcn.vscode-lldb' "
        'extension. This script also requirest that the python package `requests` '
        'be installed for "{}"'.format(sys.executable)
    )
    sys.exit(1)

import requests  # noqa: E402
import json  # noqa: E402
from subprocess import Popen, PIPE  # noqa: E402

PATH_MAP_DOC_URL = 'https://github.com/vadimcn/vscode-lldb/blob/master/MANUAL.md#source-path-remapping'


def get_active_toolchain_root():
    sout2, _ = Popen(['rustc', '--print', 'sysroot'], stdout=PIPE).communicate()
    sysroot = sout2.decode('utf_8').strip()
    return '{}/lib/rustlib/src/rust/src'.format(sysroot)


def get_full_commit_hash():
    sout1, _ = Popen(['rustc', '--version'], stdout=PIPE).communicate()
    hsh = sout1.decode().split('(')[1].split()[0]
    rsp = requests.get(
        url='https://api.github.com/repos/rust-lang/rust/commits/{}'.format(hsh),
        headers={'Accept': 'application/vnd.github.v3+json'}
    )
    rsp.raise_for_status()
    return rsp.json()['sha']


def get_suggested_src_mapping(fullhash, localsrcs):
    compiletime_srcdir = '/rustc/{}/src'.format(fullhash)
    return json.dumps({compiletime_srcdir: localsrcs}, indent=4)


if __name__ == '__main__':

    srcdir = get_active_toolchain_root()
    print("\nYour active toolchain's local sources: '{}'".format(srcdir))

    fullhash = get_full_commit_hash()
    print("Full hash of your active toolchain's git commit: {}".format(fullhash))

    sourceMap = get_suggested_src_mapping(fullhash, srcdir)
    print("Add this to your .vscode/settings.json if you're using the vadimcn.vscode-lldb extension:")
    print('\n\t"lldb.launch.sourceMap": {}\n'.format(sourceMap.replace('\n', '\n\t')))
    print('You can read more about it here: {}\n'.format(PATH_MAP_DOC_URL))

For intellij-rust (CLion, ...) users having the same issue: https://github.com/intellij-rust/intellij-rust/issues/4924.

You can add source-map setting in your "~/.lldbinit" as a quick fix.
settings set target.source-map /rustc/<COMMIT_HASH>/ <RUSTUP_HOME>/toolchains/<TOOLCHAIN>/lib/rustlib/src/rust/

where:

  • RUSTUP_HOME = $ rustup show home
  • COMMIT_HASH = $ rustc -Vv | grep commit-hash | cut -d' ' -f 2
  • TOOLCHAIN = $ rustup toolchain list | grep '(default)' | cut -d' ' -f 1
1 Like

Paste the following code into "lldb.launch.preRunCommands" to do that automatically

script lldb.debugger.HandleCommand('settings set target.source-map /rustc/{} "{}/lib/rustlib/src/rust"'.format(os.popen('rustc --version --verbose').read().split('commit-hash: ')[1].split('\n')[0].strip(), os.popen('rustc --print sysroot').readline().strip()))

Or add it directly to VSCode's settings.json

"lldb.launch.preRunCommands": [
    "script lldb.debugger.HandleCommand('settings set target.source-map /rustc/{} \"{}/lib/rustlib/src/rust\"'.format(os.popen('rustc --version --verbose').read().split('commit-hash: ')[1].split('\\n')[0].strip(), os.popen('rustc --print sysroot').readline().strip()))"
]
2 Likes

This topic was automatically closed 7 days after the last reply. We invite you to open a new topic if you have further questions or comments.