Skip to content

Commit

Permalink
addressed feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
richkadel committed Nov 2, 2020
1 parent a8dfb26 commit 6d94911
Showing 1 changed file with 24 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@ When running a coverage-instrumented program, the counter values are written to

## Enable coverage profiling in the Rust compiler

*IMPORTANT:* Rust's coverage profiling features may not be enabled, by default. To enable them, you may need to build a version of the Rust compiler with the `profiler` feature enabled.
Rust's source-based code coverage requires the Rust "profiler runtime". Without it, compiling with `-Zinstrument-coverage` generates an error that the profiler runtime is missing.

First, edit the `config.toml` file, and find the `profiler` feature entry. Uncomment it and set it to `true`:
The Rust `nightly` distribution channel should include the profiler runtime, by default.

*IMPORTANT:* If you are building the Rust compiler from the source distribution, the profiler runtime is *not* enabled in the default `config.toml.example`, and may not be enabled in your `config.toml`. Edit the `config.toml` file, and find the `profiler` feature entry. Uncomment it and set it to `true`:

```toml
# Build the profiler runtime (required when compiling with options that depend
Expand All @@ -40,7 +42,15 @@ Then rebuild the Rust compiler (see [rustc-dev-guide-how-to-build-and-run]).

### Building the demangler

LLVM coverage reporting tools generate results that can include function names and other symbol references, and the raw coverage results report symbols using the compiler's "mangled" version of the symbol names, which can be difficult to interpret. To work around this issue, LLVM coverage tools also support a user-specified symbol name demangler. Rust's symbol name demangler can be built with:
LLVM coverage reporting tools generate results that can include function names and other symbol references, and the raw coverage results report symbols using the compiler's "mangled" version of the symbol names, which can be difficult to interpret. To work around this issue, LLVM coverage tools also support a user-specified symbol name demangler.

One option for a Rust demangler is [`rustfilt`](https://crates.io/crates/rustfilt), which can be installed with:

```shell
cargo install rustfilt
```

Another option, if you are building from the Rust compiler source distribution, is to use the `rust-demangler` tool included in the Rust source distribution, which can be built with:

```shell
$ ./x.py build rust-demangler
Expand Down Expand Up @@ -102,25 +112,24 @@ If `LLVM_PROFILE_FILE` contains a path to a non-existent directory, the missing

## Creating coverage reports

LLVM's tools to process coverage data and coverage maps have some version dependencies. If you encounter a version mismatch, try updating your LLVM tools, or use the LLVM tools bundled with the same Rust distrubition used to rebuild the Rust compiler (as shown in the following examples).
LLVM's tools to process coverage data and coverage maps have some version dependencies. If you encounter a version mismatch, try updating your LLVM tools.

If you are building the Rust compiler from source, you can optionally use the bundled LLVM tools, built from source. Those tool binaries can typically be found in your build platform directory at something like: `rust/build/x86_64-unknown-linux-gnu/llvm/bin/llvm-*`. (Look for `llvm-profdata` and `llvm-cov`.)

Raw profiles have to be indexed before they can be used to generate coverage reports. This is done using [`llvm-profdata merge`] (which can combine multiple raw profiles and index them at the same time):

```shell
$ $HOME/rust/build/x86_64-unknown-linux-gnu/llvm/bin/llvm-profdata merge \
-sparse formatjson5.profraw -o formatjson5.profdata
$ llvm-profdata merge -sparse formatjson5.profraw -o formatjson5.profdata
```

Finally, the `.profdata` file is used, in combination with the coverage map (from the program binary) to generate coverage reports using [`llvm-cov report`]--for a coverage summaries--and [`llvm-cov show`]--to see detailed coverage of lines and regions (character ranges), overlaid on the original source code.

These commands have several display and filtering options. For example:

```shell
$ $HOME/rust/build/x86_64-unknown-linux-gnu/llvm/bin/llvm-cov show \
$ llvm-cov show -Xdemangler=rustfilt target/debug/examples/formatjson5 \
-instr-profile=formatjson5.profdata \
target/debug/examples/formatjson5 \
-show-line-counts-or-regions \
-Xdemangler=$HOME/rust/build/x86_64-unknown-linux-gnu/stage0-tools-bin/rust-demangler \
-show-instantiations \
-name=add_quoted_string
```
Expand All @@ -131,9 +140,9 @@ $ $HOME/rust/build/x86_64-unknown-linux-gnu/llvm/bin/llvm-cov show \

Some of the more notable options in this example include:

* `--instr-profile=<path-to-file>.profdata` - the location of the `.profdata` file created by `llvm-profdata merge`
* `target/debug/examples/formatjson5` - the binary that generated the coverage profiling data (originally as a `.profraw` file)
* `--Xdemangler=<path-to>/rust-demangler` - the location of the `rust-demangler` tool
* `--Xdemangler=rustfilt` - the command name or path used to demangle Rust symbols (`rustfilt` in the example, but this could also be a path to the `rust-demangler` tool)
* `target/debug/examples/formatjson5` - the instrumented binary (from which to extract the coverage map)
* `--instr-profile=<path-to-file>.profdata` - the location of the `.profdata` file created by `llvm-profdata merge` (from the `.profraw` file generated by the instrumented binary)
* `--name=<exact-function-name>` - to show coverage for a specific function (or, consider using another filter option, such as `--name-regex=<pattern>`)

## Interpreting reports
Expand All @@ -155,6 +164,6 @@ Rust's implementation and workflow for source-based code coverage is based on th
[`llvm.instrprof.increment`]: https://llvm.org/docs/LangRef.html#llvm-instrprof-increment-intrinsic
[LLVM Code Coverage Mapping Format]: https://llvm.org/docs/CoverageMappingFormat.html
[rustc-dev-guide-how-to-build-and-run]: https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html
[`llvm-profdata merge`]: https://llvm.org/docs/CommandGuide/llvm-profdata.html#profdata-merge
[`llvm-cov report`]: https://llvm.org/docs/CommandGuide/llvm-cov.html#llvm-cov-report
[`llvm-cov show`]: https://llvm.org/docs/CommandGuide/llvm-cov.html#llvm-cov-show
[`llvm-profdata merge`]: https://llvm.org/docs/CommandGuide/llvm-profdata.html#profdata-merge
[`llvm-cov report`]: https://llvm.org/docs/CommandGuide/llvm-cov.html#llvm-cov-report
[`llvm-cov show`]: https://llvm.org/docs/CommandGuide/llvm-cov.html#llvm-cov-show

0 comments on commit 6d94911

Please sign in to comment.