A small, validation-first ELF64 parser for the EriX project, written in Rust.
Find a file
Erik Inkinen c729d797c2
All checks were successful
CI / test (push) Successful in 4s
CI / security (push) Successful in 1m26s
CI / minimal-versions (push) Successful in 10s
lib-elf: drop unstable rustfmt options for stable toolchains
2026-03-23 10:19:54 +02:00
.github refactor: Update milestone terminology to component milestone tracking for clarity 2026-03-05 11:54:32 +02:00
docs docs: Document API intent 2026-02-26 10:29:48 +02:00
src lib-elf: split parser implementation from test suites 2026-03-23 09:37:41 +02:00
.editorconfig Initial commit 2026-02-26 09:19:12 +01:00
.gitignore Initial commit 2026-02-26 09:19:12 +01:00
ARCHITECTURE.md docs: Revise ARCHITECTURE.md to clarify purpose, responsibilities, and architectural goals for ELF64 parser 2026-02-26 11:16:16 +02:00
Cargo.toml Scaffold crate 2026-02-26 10:32:40 +02:00
CODE_OF_CONDUCT.md Initial commit 2026-02-26 09:19:12 +01:00
CONTRIBUTING.md refactor: Update milestone terminology to component milestone tracking for clarity 2026-03-05 11:54:32 +02:00
LICENSE Initial commit 2026-02-26 09:19:12 +01:00
README.md refactor: Update milestone terminology to component milestone tracking for clarity 2026-03-05 11:54:32 +02:00
ROADMAP.md refactor: Update ROADMAP.md to clarify project milestones and current status 2026-02-28 04:53:17 +02:00
rustfmt.toml lib-elf: drop unstable rustfmt options for stable toolchains 2026-03-23 10:19:54 +02:00
SECURITY.md docs: align security policy phase numbering 2026-03-11 05:28:13 +02:00

lib-elf

A small, validation-first ELF64 parser for the EriX project, written in Rust.

This crate is intentionally not a general-purpose ELF toolkit. It exists to support the boot chain and early kernel bring-up with a tight, auditable surface area and strong invariants.


Goals

  • Parse ELF64, little-endian binaries.
  • Provide a borrowed view over the input (&[u8]) with zero-copy access to segment bytes.
  • Focus on what a bootloader needs:
    • ELF header
    • program headers
    • PT_LOAD segments
    • entry point
  • Be validation-first: parse() succeeds only if the file is structurally sound for our use.

Non-goals (for now)

  • ELF32 support
  • Big-endian support
  • Symbol tables, debug info, section parsing (beyond whats needed for correctness)
  • Relocations / dynamic linking
  • “Best-effort” parsing of malformed inputs

If we need any of these later, they should be added deliberately and with clear invariants.


Supported formats

  • Class: ELFCLASS64
  • Endianness: ELFDATA2LSB
  • ABI: no strict requirements (we validate what we need)
  • Machine: initially x86_64 is the primary target; other e_machine values may be accepted/rejected depending on current policy.

API design principles

  • Parse returns a validated representation.
    • If Elf64::parse() returns Ok, then all documented invariants hold.
  • No hidden allocations required.
    • Parsed structures borrow from the input slice where possible.
  • Errors are explicit and stable.
    • Failures return structured error variants (not strings).

Core invariants (success means…)

When Elf64::parse(bytes) returns Ok(elf):

  • The input begins with a valid ELF identification for ELF64 little-endian.
  • Header fields used by the crate are validated and do not overflow arithmetic.
  • The program header table is fully in-bounds.
  • Every PT_LOAD segment satisfies:
    • p_filesz <= p_memsz
    • segment file range is in-bounds
    • address/size calculations do not overflow
    • alignment rules are sane (as defined by the crate)
  • Segment iteration is safe and cannot panic on malformed files.
  • (Policy choice) the entry point is either:
    • within at least one PT_LOAD segment, or
    • explicitly allowed to be outside (documented behavior).
      This is a policy toggle; the crate documents whichever rule is implemented.

Example (intended usage)

Note: exact names may evolve while the API is being finalized.

use elf::Elf64;

fn inspect(bytes: &[u8]) -> Result<(), elf::Error> {
    let elf = Elf64::parse(bytes)?;
    println!("entry = 0x{:016x}", elf.entry());

    for seg in elf.load_segments() {
        println!(
            "LOAD vaddr=0x{:x} memsz=0x{:x} filesz=0x{:x} flags={:?}",
            seg.vaddr(),
            seg.mem_size(),
            seg.file_size(),
            seg.flags(),
        );

        // Borrowed bytes for this segment as it appears in the file.
        let file_bytes = seg.file_bytes(bytes)?;
        println!("segment bytes: {}", file_bytes.len());
    }

    Ok(())
}

Testing strategy

This repo prefers deterministic, authored tests:

  • Hand-authored fixtures (small ELF binaries built as part of the workspace or encoded as byte arrays).
  • Negative tests for each validation rule (bad magic, truncated headers, out-of-bounds segments, overflow cases, etc.).
  • Optional internal mutation harnesses (randomized byte flips) as a smoke test, without relying on external fuzzing infrastructure.

Repository layout

  • src/

    • lib.rs — public API surface
    • error.rs — error types
    • elf64/ — internal parsing/validation modules
  • tests/

    • conformance and regression tests
  • docs/

    • api-intent.md (if/when needed)

Dependency policy

  • No crates.io dependencies.
  • Only Rust core/alloc/std (as appropriate for the current build context) and internal path dependencies.

License

ISC. See LICENSE in the repository root.