rust-lang/rust · critical · Exception

llvm-readelf failed for binary {binary} with output {stdout}

Error message

llvm-readelf failed for binary {binary} with output {stdout}

What it means

Raised by TestEnvironment.build_id() when the llvm-readelf subprocess returns a non-zero exit code while extracting ELF notes from a binary. The runner shells out to {toolchain_dir}/bin/llvm-readelf -n --elf-output-style=JSON to read the GNU build-id, and any non-zero returncode is treated as fatal because the build-id is required to name and locate the stripped test package. The message echoes the captured stdout so the underlying llvm-readelf diagnostic is visible.

Source

Thrown at src/ci/docker/scripts/fuchsia-test-runner.py:198

                verbose=test_env["verbose"],
            )

    def build_id(self, binary):
        llvm_readelf = Path(self.toolchain_dir).joinpath("bin", "llvm-readelf")
        process = subprocess.run(
            args=[
                llvm_readelf,
                "-n",
                "--elf-output-style=JSON",
                binary,
            ],
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT,
        )
        if process.returncode:
            e = f"llvm-readelf failed for binary {binary} with output {process.stdout}"
            self.env_logger.error(e)
            raise Exception(e)

        try:
            elf_output = json.loads(process.stdout)
        except Exception as e:
            e.add_note(f"Failed to read JSON from llvm-readelf for binary {binary}")
            e.add_note(f"stdout: {process.stdout}")
            raise

        try:
            note_sections = elf_output[0]["NoteSections"]
        except Exception as e:
            e.add_note(
                f'Failed to read "NoteSections" from llvm-readelf for binary {binary}'
            )
            e.add_note(f"elf_output: {elf_output}")
            raise

        for entry in note_sections:

View on GitHub (pinned to 7088e4b63a)

Solutions

  1. Verify the binary is a valid ELF for the target: run `llvm-readelf -n {binary}` manually and confirm it prints a .note.gnu.build-id section.
  2. Confirm {toolchain_dir}/bin/llvm-readelf exists and is executable, and that --toolchain-dir on the 'start' subcommand points at a complete LLVM toolchain bin dir.
  3. Rebuild the Rust toolchain so the test binary is fully linked (look for partial link / LTO failures in the build log).
  4. Upgrade or align the LLVM version so `--elf-output-style=JSON` is supported and emits valid JSON.

Example fix

// before
$ fuchsia-test-runner.py run <n> <bin_path> <shared_libs...>
# llvm-readelf failed for binary ... with output b'...'

// after - run llvm-readelf manually first to confirm the binary is valid
$ $TOOLCHAIN_DIR/bin/llvm-readelf -n --elf-output-style=JSON <bin_path> | head
# then, if it prints valid JSON with a build-id, re-run the test runner
Defensive patterns

Strategy: validation

Validate before calling

import os, subprocess
from pathlib import Path

def validate_for_build_id(toolchain_dir, binary):
    readelf = Path(toolchain_dir) / "bin" / "llvm-readelf"
    if not readelf.is_file() or not os.access(readelf, os.X_OK):
        return False, f"llvm-readelf missing/not executable at {readelf}"
    if not Path(binary).is_file():
        return False, f"binary missing: {binary}"
    proc = subprocess.run([str(readelf), "-n", str(binary)],
                          stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    return proc.returncode == 0, (proc.stdout.decode(errors="replace") if proc.returncode else "ok")

ok, msg = validate_for_build_id(env.toolchain_dir, bin_path)
if not ok:
    raise SystemExit(f"refusing to run: {msg}")
env.build_id(bin_path)

Type guard

null

Try / catch

try:
    build_id = test_env.build_id(bin_path)
except Exception as e:
    # log and surface the llvm-readelf output already embedded in the message
    logging.error("build_id extraction failed: %s", e)
    raise

Prevention

When it happens

Trigger: Calling TestEnvironment.build_id(binary) (indirectly via the 'run' subcommand, fuchsia-test-runner.py:696) where {toolchain_dir}/bin/llvm-readelf is missing, not executable, the wrong architecture, or the passed binary is not a valid ELF object (corrupt, truncated, wrong format). process.returncode being truthy at line 195 is the sole condition.

Common situations: Pointing --toolchain-dir at a build that lacks llvm-readelf; passing a host x86 binary to an arm64 llvm-readelf (or vice versa); the Rust build produced a partially-linked or non-ELF artifact; llvm-readelf version mismatch where the JSON style flag is unsupported.

Related errors


AI-assisted analysis of rust-lang/rust@7088e4b63a (2026-08-10). Data as JSON: /api/errors/79fc1a42284ad3ad. Report an issue: GitHub.