rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
98.17k stars 12.7k forks source link

Coverage is not generated when using rust-lld as linker #79555

Open briansmith opened 3 years ago

briansmith commented 3 years ago

First:

cargo init --lib

No changes to the generated crate are necessary. Then:

rm -Rf target/x86_64-unknown-linux-musl && \
CARGO_INCREMENTAL=0 RUSTFLAGS="-Zinstrument-coverage -Clink-self-contained=yes -Clinker=rust-lld" cargo +nightly test --target=x86_64-unknown-linux-musl && \
find . -name "*.profraw"

and

rm -Rf target/x86_64-unknown-linux-musl && \
CARGO_INCREMENTAL=0 RUSTFLAGS="-Zprofile -Clinker=rust-lld" cargo +nightly test --target=x86_64-unknown-linux-musl && \
find . -name "*.gcda"

I expected to see this happen:

The profiling data is generated; i.e. each find command outputs at least one result.

Instead, this happened:

No profiling data is generated.

This seems very similar to Issue #71233: "Coverage is not generated when using lld as linker" and it may be a regression.

Note that the specific combination of RUSTFLAGS that I'm trying to use is RUSTFLAGS="-Zinstrument-coverage -Clink-self-contained=yes -Clinker=rust-lld" so that I can use the new self-contained linking support for musl targets when profiling; see https://github.com/rust-lang/rust/blob/master/RELEASES.md#compiler. I think this combination of flags will become commonplace soon.

$ rustc +nightly --version --verbose
rustc 1.50.0-nightly (349b3b324 2020-11-29)
binary: rustc
commit-hash: 349b3b324dade7ca638091db93ba08bbc443c63d
commit-date: 2020-11-29
host: x86_64-unknown-linux-gnu
release: 1.50.0-nightly
briansmith commented 3 years ago

Please label this "label:A-code-coverage"

briansmith commented 3 years ago

I forgot to add these important details:

richkadel commented 3 years ago

Just a follow-up regarding the implementation of -Zinstrument-coverage (I'm not sure if this is obvious): The entire rust-side of the implementation, through codegen, ends at the generation of LLVM-IR. There were no special Rust-specific mods to the linkage, so I assume the limitation is in rust-lld.

For someone familiar with rust-lld (which I am not), It may be worth looking into the Coverage Mapping Format, which does describe some linkage-specific directives, and maybe relevant assumptions/implications that aren't handled in rust-lld. Elements of the coverage map do have to be merged across libraries, etc. I don't know how that process works exactly. And there are runtime expectations, specifically things like exit hooks to write out the profiling data.

djc commented 3 years ago

Information from https://bugs.chromium.org/p/chromium/issues/detail?id=919499#c16 suggests that passing --no-rosegment might help:

[target.x86_64-unknown-linux-gnu]
linker = "/usr/bin/clang"
rustflags = ["-Clink-arg=-fuse-ld=lld", "-Clink-arg=-Wl,--no-rosegment"]

(As came up in https://github.com/flamegraph-rs/flamegraph/pull/157.)