A small, validation-first ELF64 parser for the EriX project, written in Rust.
- Rust 100%
| .github | ||
| docs | ||
| src | ||
| .editorconfig | ||
| .gitignore | ||
| ARCHITECTURE.md | ||
| Cargo.toml | ||
| CODE_OF_CONDUCT.md | ||
| CONTRIBUTING.md | ||
| LICENSE | ||
| README.md | ||
| ROADMAP.md | ||
| rustfmt.toml | ||
| SECURITY.md | ||
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_LOADsegments- 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 what’s 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_64is the primary target; othere_machinevalues may be accepted/rejected depending on current policy.
API design principles
- Parse returns a validated representation.
- If
Elf64::parse()returnsOk, then all documented invariants hold.
- If
- 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_LOADsegment 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_LOADsegment, or - explicitly allowed to be outside (documented behavior).
This is a policy toggle; the crate documents whichever rule is implemented.
- within at least one
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 surfaceerror.rs— error typeself64/— 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.