headroomlabs-ai/headroom · error · RuntimeError

neither `objdump` nor `llvm-objdump` is on PATH; install bin

Error message

neither `objdump` nor `llvm-objdump` is on PATH; install binutils (Linux) or LLVM (macOS) to run this audit

What it means

audit_wheel_glibc_symbols.py shells out to objdump -T to enumerate undefined dynamic symbols of bundled .so files and compare their glibc version requirements against the wheel's manylinux tag. It requires either GNU objdump (binutils) or llvm-objdump on PATH; with neither found via shutil.which, it raises immediately rather than producing an incomplete audit.

Source

Thrown at scripts/audit_wheel_glibc_symbols.py:101

    """
    m = re.search(r"manylinux_(\d+)_(\d+)_", wheel_filename)
    if m:
        return (int(m.group(1)), int(m.group(2)))
    # `manylinux2014_x86_64` is the legacy alias for manylinux_2_17.
    if "manylinux2014_" in wheel_filename:
        return (2, 17)
    if "manylinux1_" in wheel_filename:
        return (2, 5)
    return None


def list_undef_symbols(so_path: Path) -> list[tuple[str, str]]:
    """Return [(symbol_name, glibc_version_or_empty), ...] for every
    UND (undefined) dynamic symbol in `so_path`.
    """
    objdump = shutil.which("objdump") or shutil.which("llvm-objdump")
    if not objdump:
        raise RuntimeError(
            "neither `objdump` nor `llvm-objdump` is on PATH; "
            "install binutils (Linux) or LLVM (macOS) to run this audit"
        )
    out = subprocess.run(
        [objdump, "-T", str(so_path)],
        check=True,
        capture_output=True,
        text=True,
    ).stdout
    found = []
    for line in out.splitlines():
        # `objdump -T` lines: `address SECTION ... NAME` where SECTION
        # contains `*UND*` for undefined references and a versioned
        # symbol name like `__isoc23_strtoll@GLIBC_2.38` or unversioned.
        if "*UND*" not in line:
            continue
        # The last whitespace-separated token is the (versioned) symbol.
        token = line.split()[-1]

View on GitHub (pinned to 322425c43b)

Solutions

  1. Linux/CI: install binutils (apt-get install -y binutils, or the distro equivalent)
  2. macOS: brew install llvm and ensure $(brew --prefix llvm)/bin is on PATH so llvm-objdump resolves
  3. Or point PATH at an existing toolchain image / run the audit inside a manylinux builder container that already has objdump

Example fix

# before
python scripts/audit_wheel_glibc_symbols.py dist/*.whl  # RuntimeError: no objdump

# after (Debian/CI)
apt-get update && apt-get install -y binutils
python scripts/audit_wheel_glibc_symbols.py dist/*.whl
Defensive patterns

Strategy: validation

Validate before calling

import shutil, sys

# Run before the audit script
def objdump_available() -> bool:
    return shutil.which("objdump") is not None or shutil.which("llvm-objdump") is not None

if not objdump_available():
    sys.exit("objdump/llvm-objdump missing — apt-get install binutils (or brew install llvm)")

Type guard

import shutil

def has_objdump() -> bool:
    """True when the wheel audit can run on this machine."""
    return shutil.which("objdump") is not None or shutil.which("llvm-objdump") is not None

Prevention

When it happens

Trigger: Running scripts/audit_wheel_glibc_symbols.py on a machine without binutils or LLVM installed — minimal Docker images (slim/distroless builders), fresh macOS without LLVM, CI containers that never installed binutils, or a PATH that hides /usr/bin.

Common situations: Running the wheel audit in a slim CI image (python:3.x-slim has no binutils); macOS where objdump is not part of default CLI tools and llvm-objdump is not installed; local venv scripts dir shadowing PATH.

Related errors


AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15). Data as JSON: /api/errors/08a18ba01766431c. Report an issue: GitHub.