mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 22:02:23 +01:00
This should handle over-long lines. I had tried to make the normalize method work, but it doesn't seem promising and so let's at least enable this version. Assisted-by: Antigravity with Gemini
255 lines
9.2 KiB
Markdown
255 lines
9.2 KiB
Markdown
# Debugging tools and techniques
|
|
|
|
<!--
|
|
Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
|
Exceptions. See /LICENSE for license information.
|
|
SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
-->
|
|
|
|
<!-- toc -->
|
|
|
|
## Table of contents
|
|
|
|
- [Interactive debugger setup](#interactive-debugger-setup)
|
|
- [Debugging with LLDB](#debugging-with-lldb)
|
|
- [MacOS](#macos)
|
|
- [VS Code integration](#vs-code-integration)
|
|
- [Debugging with GDB](#debugging-with-gdb)
|
|
- [VS Code integration](#vs-code-integration-1)
|
|
- [Toolchain-specific debugging techniques](#toolchain-specific-debugging-techniques)
|
|
- [Dumping objects in interactive debuggers](#dumping-objects-in-interactive-debuggers)
|
|
- [The LLDB `dump` command](#the-lldb-dump-command)
|
|
- [Verbose output](#verbose-output)
|
|
- [Stack traces](#stack-traces)
|
|
- [Dumping prelude files](#dumping-prelude-files)
|
|
|
|
<!-- tocstop -->
|
|
|
|
## Interactive debugger setup
|
|
|
|
The toolchain codebase should work with either GDB or LLDB, but using GDB
|
|
requires a little more setup and may not have quite as many conveniences.
|
|
|
|
Pass `-c dbg` to `bazel build` in order to compile with debugging enabled. For
|
|
example:
|
|
|
|
```shell
|
|
bazel build -c dbg //toolchain
|
|
```
|
|
|
|
This produces a compiled binary with debug symbols at
|
|
`bazel-bin/toolchain/carbon`. For the best debugging experience you may want to
|
|
pass additional flags when building and/or running the debugger, but the
|
|
specifics depend on your environment; see the following sections for details.
|
|
|
|
If you have an issue that only reproduces with another build mode, you can still
|
|
enable debug information in that mode by passing `--feature=debug_info_flags` to
|
|
Bazel.
|
|
|
|
### Debugging with LLDB
|
|
|
|
The output of a `-c dbg` build should be usable with any version of LLDB as
|
|
recent as the installed Clang used for building:
|
|
|
|
```shell
|
|
lldb bazel-bin/toolchain/carbon
|
|
```
|
|
|
|
However, we recommend running LLDB with the `--local-lldbinit` flag, to enable
|
|
our preset configuration (which enables the
|
|
[`dump` command](#the-lldb-dump-command) among other features). This requires
|
|
running from the repository root:
|
|
|
|
```shell
|
|
lldb --local-lldbinit bazel-bin/toolchain/carbon
|
|
```
|
|
|
|
To debug a single `file_test`, use the following command, pointing it to an
|
|
actual carbon test file.
|
|
|
|
```shell
|
|
bazel build -c dbg //toolchain/testing:file_test && \
|
|
lldb --local-lldbinit bazel-bin/toolchain/testing/file_test -- \
|
|
--dump_output --file_tests /path/to/some/test.carbon
|
|
```
|
|
|
|
#### MacOS
|
|
|
|
Bazel sandboxes builds, which on MacOS makes it hard for the debugger to locate
|
|
symbols on linked binaries when debugging. See this
|
|
[Bazel issue](https://github.com/bazelbuild/bazel/issues/2537#issuecomment-449089673)
|
|
for more information. To workaround, provide the `--spawn_strategy=local` option
|
|
to Bazel for the debug build, like:
|
|
|
|
```shell
|
|
bazel build --spawn_strategy=local -c dbg //toolchain
|
|
```
|
|
|
|
You should then be able to debug with `lldb`.
|
|
|
|
If this build command doesn't seem to produce a debuggable binary you might need
|
|
to both clear the build disk cache and clean the build. Running
|
|
`scripts/clean_disk_cache.sh` may not be enough, you might try deleting all the
|
|
files within the disk cache, typically located at
|
|
`~/.cache/carbon-lang-build-cache`. Deleting the disk cache, followed by a
|
|
`bazel clean` should allow your next rebuild, with the recommended options, to
|
|
supply the symbols for debugging.
|
|
|
|
#### VS Code integration
|
|
|
|
VS Code's integrated debugger support can be configured to use LLDB, with custom
|
|
support for debugging the toolchain tests. To set that up:
|
|
|
|
1. In the `.vscode` subdirectory, symlink `lldb_launch.json` to `launch.json`.
|
|
For example: `ln -s lldb_launch.json .vscode/launch.json`
|
|
2. Install the
|
|
[`llvm-vs-code-extensions.lldb-dap` extension](https://marketplace.visualstudio.com/items?itemName=llvm-vs-code-extensions.lldb-dap).
|
|
3. In VS Code settings, it may be necessary to set `lldb-dap.executable-path`
|
|
to the path of `lldb-dap`.
|
|
|
|
A typical debug session looks like:
|
|
|
|
1. `bazel build -c dbg //toolchain/testing:file_test`
|
|
2. Open a `.carbon` testdata file to debug. This must be the active file in VS
|
|
Code.
|
|
3. Go to the "Run and debug" panel in VS Code.
|
|
4. Select and run the `file_test (lldb)` configuration.
|
|
|
|
For debugging on MacOS using VSCode, some people have had success using the
|
|
CodeLLDB extension. In order for LLDB to connect the project source files with
|
|
the symbols you will need to add a `"sourceMap": { ".": "${workspaceRoot}" }`
|
|
line to the CodeLLDB `launch.json` configuration, for example:
|
|
|
|
```json
|
|
{
|
|
"version": "0.2.0",
|
|
"configurations": [
|
|
{
|
|
"name": "explorer",
|
|
"type": "lldb",
|
|
"request": "launch",
|
|
"program": "${workspaceRoot}/bazel-bin/explorer/explorer",
|
|
"args": [],
|
|
"cwd": "${workspaceRoot}",
|
|
"sourceMap": {
|
|
".": "${workspaceRoot}"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Debugging with GDB
|
|
|
|
If you prefer using GDB, you may want to pass some extra flags to the build:
|
|
|
|
```shell
|
|
bazel build -c dbg --features=-lldb_flags --features=gdb_flags //toolchain
|
|
```
|
|
|
|
Or you can add them to your `user.bazelrc`, they are designed to be safe to pass
|
|
at all times and only have effect when building with `-c dbg`:
|
|
|
|
```shell
|
|
echo "build --features=-lldb_flags --features=gdb_flags" >> user.bazelrc
|
|
```
|
|
|
|
Note that on Linux we use Split DWARF and DWARF v5 debug symbols, which means
|
|
that GDB version 10.1 or newer is required. If you see an error like this:
|
|
|
|
```shell
|
|
Dwarf Error: DW_FORM_strx1 found in non-DWO CU
|
|
```
|
|
|
|
It means that the version of GDB used is too old, and does not support the DWARF
|
|
v5 format.
|
|
|
|
#### VS Code integration
|
|
|
|
VS Code's integrated debugger support can be configured to use GDB, with custom
|
|
support for debugging the toolchain tests. To set that up:
|
|
|
|
1. In the `.vscode` subdirectory, symlink `gdb_launch.json` to `launch.json`.
|
|
For example: `ln -s gdb_launch.json .vscode/launch.json`
|
|
2. Install the
|
|
[`coolchyni.beyond-debug` extension](https://marketplace.visualstudio.com/items?itemName=coolchyni.beyond-debug).
|
|
|
|
A typical debug session looks like:
|
|
|
|
1. `bazel build -c dbg --features=-lldb_flags --features=gdb_flags
|
|
//toolchain/testing:file_test`
|
|
2. Open a `.carbon` testdata file to debug. This must be the active file in VS
|
|
Code.
|
|
3. Go to the "Run and debug" panel in VS Code.
|
|
4. Select and run the `file_test (gdb)` configuration.
|
|
|
|
## Toolchain-specific debugging techniques
|
|
|
|
### Dumping objects in interactive debuggers
|
|
|
|
We provide namespace-scoped `Dump` functions in several components, such as
|
|
[check/dump.cpp](/toolchain/check/dump.cpp). These `Dump` functions will print
|
|
contextual information about an object to stderr. The files contain details
|
|
regarding support.
|
|
|
|
Objects which inherit from `Printable` also have `Dump` member functions, but
|
|
these will lack contextual information.
|
|
|
|
IDs are dumped in hexadecimal, so it's often convenient to set your interactive
|
|
debugger to print integers in hexadecimal as well. In LLDB you can do this with
|
|
`type format add --format hex int`.
|
|
|
|
#### The LLDB `dump` command
|
|
|
|
Our LLDB configuration includes a `dump` command (see
|
|
[above](#debugging-with-lldb) for how to enable that configuration), which
|
|
allows you to dump the contents of a value associated with an id. Since most
|
|
data in the toolchain is referenced by id, this ends up being a very frequent
|
|
task.
|
|
|
|
The debugger command `dump <context> <id_expr>` gets roughly translated into a
|
|
C++ call to `Dump(<context>, <id_expr>)`.
|
|
|
|
Run the `dump` command without any arguments to see the builtin help on how to
|
|
use it.
|
|
|
|
### Verbose output
|
|
|
|
The `-v` flag can be passed to trace state, and should be specified before the
|
|
subcommand name: `carbon -v compile ...`. `CARBON_VLOG` is used to print output
|
|
in this mode. There is currently no control over the degree of verbosity.
|
|
|
|
To include VLOG output when debugging a file test, add an `ARGS: -v compile %s`
|
|
line to the file, such as:
|
|
|
|
```
|
|
// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon
|
|
// ARGS: -v compile %s
|
|
// EXTRA-ARGS: --dump-sem-ir-ranges=if-present
|
|
```
|
|
|
|
This will also include the VLOG output when running the test in an interactive
|
|
debugger. Note that using `-v compile` with `autoupdate.py` will deeply mangle
|
|
your test file, so avoid doing that.
|
|
|
|
### Stack traces
|
|
|
|
While the iterative processing pattern means function stack traces will have
|
|
minimal context for how the current function is reached, we use LLVM's
|
|
`PrettyStackTrace` to include details about the state stack. The state stack
|
|
will be above the function stack in crash output.
|
|
|
|
You can also use the `--sem-ir-crash-dump=path/to/file` flag to get a raw SemIR
|
|
dump in the event of a crash in the check phase. This can be particularly useful
|
|
for interpreting IDs you encounter during interactive debugging.
|
|
|
|
### Dumping prelude files
|
|
|
|
By default, prelude files are excluded from SemIR dumps by
|
|
`--exclude-dump-file-prefix`. To enable dumps for specific files, add
|
|
`//@include-in-dumps`. This works for every phase after lex, but may be most
|
|
helpful to debug check and lower output. This can also be used to view
|
|
cross-file SemIR, such as imports from a prelude, by adding
|
|
`//@include-in-dumps` to the prelude file and looking at the SemIR of the
|
|
importing file.
|