A multi-format binary file parser library and CLI tool, written in Rust.
Strata parses binary object files and exposes their structure - headers, sections, segments, symbols, and debug information - through a unified, format-neutral API. It is designed as a library first; the CLI is a thin consumer of that library.
Inspired by readelf(1), otool(1), objdump(1),
llios, and
ipsw.
Early development. ELF support is actively being built out.
| Format | Status |
|---|---|
| ELF | In progress |
| Mach-O | Planned |
| DWARF | Planned |
ar |
Planned |
Strata/
├── strata-core/ # Format-neutral traits, types, and parsing primitives
├── strata-elf/ # ELF format parser (implements strata-core traits)
└── strata/ # CLI binary
Each format is an independent crate. Consumers that only need ELF parsing
depend only on strata-elf - there is no need to pull in unrelated format
code.
Requires Rust 1.75 or later.
git clone https://github.com/PranavRJoshi/Strata
cd Strata
cargo buildcargo run -- <file>Example output against a Linux ELF binary:
=== Header ===
Architecture : Aarch64
Byte order : Little
Object kind : Executable
Entry point : 0x0000000000005880
ELF class : Elf64
OS/ABI : SystemV
Flags : 0x00000000
Sections : 28 entries at offset 0x1e428
Segments : 9 entries at offset 0x40
=== Sections (28) ===
Name Kind Address Size
...
=== Segments (9) ===
VirtAddr FileSz MemSz Flags
...
Add the relevant crate to your Cargo.toml:
[dependencies]
strata-elf = { path = "strata-elf" }
strata-core = { path = "strata-core" }Parse an ELF file and access it through the format-neutral trait surface:
use strata_core::BinaryObject;
use strata_elf::ElfObject;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let data = std::fs::read("/bin/ls")?;
let obj = ElfObject::parse(&data)?;
println!("arch: {:?}", obj.arch());
println!("kind: {:?}", obj.kind());
println!("entry: {:?}", obj.entry_point());
println!("sections: {}", obj.sections().len());
println!("symbols: {}", obj.symbols().len());
// Access raw section bytes - the foundation for DWARF parsing.
if let Some(text) = obj.section_by_name(".text") {
println!(".text is {} bytes", text.data().len());
}
Ok(())
}Access ELF-specific fields that are not part of the neutral trait:
let hdr = obj.header();
println!("e_phnum: {}", hdr.ph_count);
println!("e_shnum: {}", hdr.sh_count);strata-core defines the traits that all format parsers implement:
BinaryObject- top-level interface: arch, kind, entry point, sections, segments, symbolsSection- name, kind, address, size, raw bytesSegment- virtual/physical address, file/memory size, flags, raw bytesSymbol- name, address, size, kind, visibility
No format-specific type ever appears in these trait definitions. A consumer
that works through BinaryObject can switch from an ELF file to a Mach-O
file without changing any code.
The library crates (strata-core, strata-elf) perform no I/O. They operate
on &[u8] slices. Reading files, memory-mapping, and output formatting are
the CLI's responsibility.
All fallible operations return Result. The error type hierarchy is:
StrataError
├── Io(std::io::Error)
├── Parse(ParseError) - structural errors in the binary
└── UnsupportedFormat - format not recognised
Panics do not occur in library code.
cargo testGPLv3