rust-lang / rust-lang/rust

`-Zcoverage-options=branch`: `llvm-cov export` SIGSEGVs in `llvm::coverage::CoverageMapping::getInstantiationGroups` (regression in LLVM 21.1.1)

Open
#157,358 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-code-coverage A-LLVM C-bug needs-triage T-compiler
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

Summary

Generating branch coverage (cargo llvm-cov --branch, i.e. -Zcoverage-options=branch)
for a generic, async_trait-using crate makes the bundled llvm-cov crash with SIGSEGV
while reading the coverage mapping. The same crate exports fine:

  • with line coverage (no --branch), and
  • with branch coverage on older toolchains (LLVM ≤ 21.1.0).

The crash first appears around LLVM 21.1.4/21.1.5 (rustc 1.93.0-nightly) and is also present
in the current nightly (LLVM 22); LLVM ≤ 21.1.3 is fine. It is a hard crash, so branch coverage
is currently unusable on affected toolchains for such crates.

Steps to reproduce

git clone https://github.com/cloudflare/pingora   # any recent checkout
cd pingora
rustup toolchain install nightly-2025-12-01 --component llvm-tools   # rustc 1.93.0-nightly, LLVM 21.1.5
cargo +nightly-2025-12-01 install cargo-llvm-cov --locked

# crashes:
cargo +nightly-2025-12-01 llvm-cov --branch --cobertura \
  --output-path cov.xml -p pingora-memory-cache --lib

Result:

error: failed to generate report: process didn't exit successfully:
  `.../nightly-2025-12-01-.../bin/llvm-cov export -format=lcov ... -object .../pingora_memory_cache-<hash>` (signal: 11 (SIGSEGV) (core dumped))
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/

(cargo-llvm-cov only shells out to llvm-cov export; calling that llvm-cov directly on
the single object + profdata reproduces the SIGSEGV, so this is not a cargo-llvm-cov issue.)

Backtrace

 #0 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int)
 #1 SignalHandler(int, siginfo_t*, void*)
 #2 __restore_rt
 #3 llvm::coverage::CoverageMapping::getInstantiationGroups(llvm::StringRef) const
    libLLVM.so.21.1-rust-1.93.0-nightly
 #4 llvm::CoverageReport::prepareSingleFileReport(...)               CoverageReport.cpp
 #5 std::_Function_handler<void (), ...>::_M_invoke(...)              CoverageReport.cpp
 #6 ...                                                              CodeCoverage.cpp
 #7 std::__future_base::_State_baseV2::_M_do_set(...)                CodeCoverage.cpp
 #8 __pthread_once_slow
 ...

What narrows it down

  • Branch-specific: removing --branch (plain line coverage) exports fine on the same toolchain.
  • Module-specific: the crate has two modules. Building coverage for lib.rs alone (sync,
    generic MemoryCache) exports fine even on LLVM 22. Re-adding the async_trait-based
    read_through.rs (#[async_trait] trait Lookup/MultiLookup, generic RTCache<K, T, CB>)
    is what triggers the crash → the trigger involves async_trait + generics + branch regions
    (getInstantiationGroups handles per-instantiation grouping of monomorphized functions).
  • A trivial generic+branch crate, and a small async_trait+generic+branch crate, did not
    reproduce — the trigger needs the fuller generic-async-cache shape, so the smallest
    self-contained reproducer I have is the pingora-memory-cache crate above.

Version bisection (export of the same crate, --branch)

Exporting --branch for the pingora-memory-cache crate, per toolchain (actually tested):

toolchain rustc LLVM branch export
nightly-2025-08-01 1.90.0-nightly 20.1.8 ✅ ok
nightly-2025-09-01 1.91.0-nightly 21.1.0 ✅ ok
nightly-2025-09-15 1.92.0-nightly 21.1.1 ✅ ok
nightly-2025-10-01 1.92.0-nightly 21.1.2 ✅ ok
nightly-2025-11-01 1.93.0-nightly 21.1.3 ✅ ok
nightly-2025-12-01 1.93.0-nightly 21.1.5 ❌ SIGSEGV
latest (2026-05) 1.98.0-nightly 22.1.6 ❌ SIGSEGV

→ regression introduced between LLVM 21.1.3 and 21.1.5 (21.1.4 not tested).

Note on attribution: each toolchain rebuilds the objects with its own rustc/LLVM, so I cannot
cleanly separate "rustc emits bad mapping" from "llvm-cov mishandles valid mapping" — the
coverage-mapping format version also changes across LLVM releases. Reporting the observation;
attribution is for the maintainers.

rustc -Vv (a crashing version)

rustc 1.93.0-nightly (b84478a1c 2025-11-30)
host: x86_64-unknown-linux-gnu
release: 1.93.0-nightly
LLVM version: 21.1.5

Host OS: Alibaba Cloud Linux 3 (glibc 2.32), x86_64. cargo-llvm-cov 0.8.7.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the crash with the pingora-memory-cache command and affected nightly toolchain, then inspect llvm::coverage::CoverageMapping::getInstantiationGroups in the backtrace and CoverageReport.cpp. Compare branch exports with LLVM 21.1.3 and 21.1.5; done means the affected generic async_trait crate exports branch coverage without SIGSEGV.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.