vosen/ZLUDA · error · io::Error

io::Error::new(io::ErrorKind::InvalidData, e.to_string())

Error message

io::Error::new(io::ErrorKind::InvalidData, e.to_string())

What it means

`write_object` wraps any failure from parsing the supplied `main_elf` bytes as an ELF64 file header into an `io::Error` with kind `InvalidData`. The library needs the input ELF's OS/ABI, machine type, and flags to emit a companion metadata object file, so if the bytes are not a valid ELF64 the whole write is aborted. This keeps the failure surfaced as a plain `io::Result` error rather than a panic.

Source

Thrown at kernel_metadata/src/lib.rs:80

    }

    pub fn copy_object<'a>(elf_bytes: &'a [u8]) -> Option<ModuleMetadata32Bit> {
        read_object::<ArchivedModuleMetadata32Bit>(elf_bytes, Self::SECTION, Self::VERSION)
            .and_then(|archived| rkyv::deserialize::<_, rkyv::rancor::Failure>(archived).ok())
    }
}

pub fn write_object(
    this: &impl for<'a, 'b> Serialize<
        HighSerializer<AlignedVec, ArenaHandle<'b>, rkyv::rancor::Failure>,
    >,
    section: &str,
    version: u64,
    main_elf: &[u8],
    writer: &mut impl io::Write,
) -> io::Result<()> {
    let main_header = elf::FileHeader64::<object::Endianness>::parse(main_elf)
        .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e.to_string()))?;
    let endian = main_header
        .endian()
        .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e.to_string()))?;
    let data = rkyv::to_bytes::<rkyv::rancor::Failure>(this)
        .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
    let mut buf = Vec::new();
    let mut writer_elf = elf_write::Writer::new(endian, true, &mut buf);
    writer_elf.reserve_file_header();
    let section_name = writer_elf.add_section_name(section.as_bytes());
    writer_elf.reserve_section_index();
    let section_offset = writer_elf.reserve(data.len() + mem::size_of::<u64>(), 8);
    writer_elf.reserve_shstrtab_section_index();
    writer_elf.reserve_shstrtab();
    writer_elf.reserve_section_headers();
    writer_elf
        .write_file_header(&elf_write::FileHeader {
            os_abi: main_header.e_ident().os_abi,
            abi_version: main_header.e_ident().abi_version,

View on GitHub (pinned to 9c8b43f242)

Solutions

  1. Verify `main_elf` begins with the 4-byte ELF magic `\x7fELF` before calling `write_object`
  2. Check the file is a complete ELF64 (e_ident[EI_CLASS] == ELFCLASS64) and at least 64 bytes long
  3. Make sure you pass the final linked ELF (e.g. from the CUDA/cubin compilation step), not a PTX file or a partial buffer
  4. Log the first 16 bytes of `main_elf` when the error occurs to spot wrong-file wiring

Example fix

// before
let mut elf = Vec::new();
File::open("kernel.ptx")?.read_to_end(&mut elf)?;
write_object(&meta, ".zluda", 1, &elf, &mut out)?;
// after
let mut elf = Vec::new();
File::open("kernel.cubin")?.read_to_end(&mut elf)?;
assert_eq!(&elf[..4], b"\x7fELF", "not an ELF file");
write_object(&meta, ".zluda", 1, &elf, &mut out)?;
Defensive patterns

Strategy: validation

Validate before calling

fn is_elf64(bytes: &[u8]) -> bool {
    bytes.len() >= 64 && &bytes[..4] == b"\x7fELF" && bytes[4] == 2 // EI_CLASS = ELFCLASS64
}
if !is_elf64(&main_elf) {
    return Err(io::Error::new(io::ErrorKind::InvalidData, "main_elf is not a valid ELF64"));
}

Type guard

fn looks_like_elf(bytes: &[u8]) -> bool {
    bytes.len() >= 4 && &bytes[..4] == b"\x7fELF"
}

Try / catch

match write_object(&meta, ".zluda", VERSION, &main_elf, &mut out) {
    Ok(()) => (),
    Err(e) if e.kind() == io::ErrorKind::InvalidData =>
        eprintln!("bad ELF input: {e}"),
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling `write_object` (directly or via `ModuleMetadata::write_object`) with a `main_elf` slice that is truncated (<64 bytes), empty, starts with bytes other than the `\x7fELF` magic, is a 32-bit ELF where a 64-bit header is expected, or is otherwise a corrupted/non-ELF binary.

Common situations: Pointing the build script at a wrong file path, passing a `.ptx`/text file or an intermediate object instead of the final ELF, a compiler/linker change producing ELF32 output, or the ELF being cut off by a failed write/read upstream.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of vosen/ZLUDA@9c8b43f242 (2026-09-06). Data as JSON: /api/errors/49db5cbd4f3075ce. Report an issue: GitHub.