Expand description
Parse and inspect Nim-compiled native binaries.
This crate provides a pure-Rust parser and forensic-artifact extractor for binaries produced by the Nim compiler via its C, C++, or Objective-C backends. A Nim-compiled program is a normal ELF, PE, or Mach-O executable — there is no Nim-specific container. The crate recovers Nim runtime artifacts left inside an otherwise-ordinary native binary.
§What it extracts
| Artifact | Method | Notes |
|---|---|---|
| Detection verdict | NimBinary::is_nim | 11 independent probes |
| Format / arch / GC mode | NimBinary::format, NimBinary::gc_mode | ELF, PE, Mach-O; refc vs ARC/ORC |
| Entry shims | NimBinary::entry_shims | NimMain, PreMain, etc. |
| Init functions | NimBinary::init_functions | With decoded module paths |
| Module map | NimBinary::module_map | Per-module: symbols, sizes, init VAs, leaked paths |
| RTTI globals | NimBinary::rtti_symbols | V1 (TNimType) and V2 (TNimTypeV2) with parsed fields |
| Type graph | NimBinary::types | Cross-linked types: members, offsets, sizes, layout, inheritance, enum values, destructors |
| Code entrypoints | NimBinary::code_entrypoints | One VA-tagged stream of shims, inits, procs, raise-enclosing fns, RTTI procs |
| String literals | NimBinary::string_literals_v2 | V2 NIM_STRLIT_FLAG scan |
| Stack-trace metadata | NimBinary::stack_trace | Proc names + .nim file paths (build-host leaks) |
| Nimble path leaks | NimBinary::nimble_paths | Package name, version, hash, username, OS |
| Exception types | NimBinary::exception_types | *Error, *Defect cstrings in rodata |
| Raise sites | NimBinary::raise_sites | Full (type, proc, file, line) tuples via instruction analysis |
| Demangled symbols | demangle::symbol::parse | Identifier, module, item ID |
§Quick start
use nimrod::NimBinary;
let data = std::fs::read("sample").unwrap();
let bin = NimBinary::from_bytes(&data).unwrap();
if !bin.is_nim() {
eprintln!("not a Nim binary");
return;
}
// Detection and classification
println!("format: {:?}, gc: {:?}", bin.format(), bin.gc_mode());
// Module map: which Nim modules are compiled in, with every function
let mmap = bin.module_map();
for (name, info) in &mmap.modules {
println!("{name}: {} functions", info.symbol_count());
for sym in &info.symbols {
// sym.name = demangled Nim identifier
// sym.address = VA (start disassembling here)
// sym.size = byte count (ELF; 0 on Mach-O/PE)
let _ = (sym.name.as_str(), sym.address, sym.size);
}
}
// Raise sites: exception type + enclosing function + source location
for rs in bin.raise_sites() {
let _ = (
rs.exception_type.as_deref(), // "ValueError"
rs.enclosing_function.as_deref(), // "parseHexInt__strutils_u1234"
rs.file.as_deref(), // "strutils.nim"
rs.line, // Some(1242)
);
}§Design
- Pure Rust,
#![deny(unsafe_code)]. - Cross-format: ELF, PE, Mach-O via
goblin. - Zero-copy where possible — borrows from the input byte slice.
- Forensic-oriented: prioritises attribution-grade artifacts (build-host paths, package refs, exception locations) over pretty-printing.
The format-level research backing every probe and struct layout is
documented in RESEARCH.md at the crate root.
§Robustness contract
nimrod parses adversarial input, so every public artifact iterator obeys a uniform contract:
- Never panics on malformed input. The crate denies
unwrap,expect,panic, unchecked indexing, and unchecked arithmetic in library code (see the[lints]table inCargo.toml). - Returns empty on missing data. A walker whose artifact is absent (no V2 strings in a refc build, no raise sites in a binary that never raises) returns an empty slice, not an error.
- Skips malformed records individually. A single undecodable record
(e.g. an RTTI global whose struct bytes are not file-backed) is dropped or
degraded to a name-only entry; the rest of the scan still completes.
Name-only RTTI entries are flagged by
NimType::is_readable.
§Address space
Every address-bearing field returned by this crate is a virtual address
in the input image’s load space, never a file offset. Convert to a
disassembler-relative RVA with the *_rva helpers on NimBinary, with
Container::va_to_rva, or with va_to_i64 for signed-integer storage.
§Thread safety
NimBinary is Send + Sync (enforced by a compile-time assertion), so it
can be shared across threads or held across .await points. Its scan caches
use std::sync::OnceLock.
Re-exports§
pub use addr::va_to_i64;pub use container::Arch;pub use container::Container;pub use container::Format;pub use container::Section;pub use container::SectionKind;pub use container::Symbol;pub use container::SymbolKind;pub use detect::DetectionMatches;pub use detect::DetectionReport;pub use entrypoints::CodeEntrypoint;pub use entrypoints::EntrypointKind;pub use error::Error;pub use error::Result;pub use inits::InitFunction;pub use inits::InitKind;pub use metadata::GcMode;pub use metadata::NimVersionHint;pub use modules::ModuleInfo;pub use modules::ModuleMap;pub use modules::ModuleSymbol;pub use paths::NimblePath;pub use paths::PathOs;pub use raises::ExceptionRef;pub use rtti::symbols::RttiSymbol;pub use rtti::symbols::RttiVersion;pub use rtti::v1::NimKind;pub use rtti::v1::NimTypeFlag;pub use shims::EntryShim;pub use shims::ShimKind;pub use sites::RaiseSite;pub use stacktrace::FilePath;pub use stacktrace::StackTraceHarvest;pub use strings::v1::StringLiteralV1;pub use strings::v2::StringLiteral;pub use types::CodeRef;pub use types::EnumValue;pub use types::NimType;pub use types::TypeField;pub use types::TypeFlags;pub use types::TypeRef;pub use types::TypeShape;
Modules§
- addr
- Address-space helpers.
- container
- Container-format abstraction over ELF, PE, and Mach-O.
- demangle
- Symbol and module-path demangling.
- detect
- Nim-binary fingerprint detection.
- entrypoints
- Aggregated code entrypoints.
- error
- Error types for Nim binary parsing.
- inits
- Module init-function scanner.
- metadata
- Nim binary metadata detection.
- modules
- Cross-referenced module map.
- paths
- Build-host attribution via nimble package path leaks.
- raises
- Exception raise-site recovery (phase 1).
- rtti
- Run-time type information (RTTI) recovery.
- shims
- Entry-point shim locator.
- sites
- Exception raise-site recovery (phase 2).
- stacktrace
- Stack-trace metadata harvester.
- strings
- Nim string literal scanning.
- types
- Cross-referenced Nim type graph recovered from RTTI.
Structs§
- NimBinary
- Parsed view of a Nim-compiled native binary.