macho
macho is a Rust workspace for Mach-O parsing, selective analysis, structural
mutation, and command-line inspection. The workspace separates a byte-safe
core, metadata leaves, analysis, mutation, semantic workflow, façade, and CLI.
Library users depend only on the capabilities they select.
Install and develop
The CLI uses one flat command grammar. Every command accepts --format text or
--format json and --color auto|always|never; audit also accepts
--format sarif. JSON results use a versioned envelope. Machine formats never
contain ANSI escapes. Errors go only to stderr. Human output is colored on
interactive terminals and plain when redirected. Semantic roles and the
compatibility color theme come from the pinned Termosaic presentation library;
reusable Mach-O crates stay output-neutral.
Examples
Mach-O signing is performed and verified in process. It does not require Xcode,
xcrun, or the macOS Keychain. The same ad-hoc and PKCS#12 inputs work on
macOS, Linux, and Windows. Passwords are accepted only through a file path so
they do not appear on the command line.
Command reference
This table is generated from the production Clap router and checked by
cargo xtask docs --check.
| Command | Purpose |
|---|---|
info |
Mach-O structure (header, segments, sections, load commands) |
deps |
Linked libraries and compatibility versions |
codesign |
Code signature, entitlements, and CMS info |
dwarf |
DWARF debug sections (view or extract with --output-dir) |
symbols |
Symbol table with filtering |
imports |
Imported symbols |
exports |
Exported symbols |
fixups |
Chained fixup entries |
relocations |
Relocation entries |
ranges |
Function and symbol address ranges |
strings |
String literals with heuristic scanning |
xrefs |
Cross-references between addresses |
vtables |
C++ virtual tables |
objc |
Objective-C classes, protocols, selectors |
swift |
Swift type metadata |
cpp |
C++ RTTI type hierarchies |
c |
C type declarations from debug info |
disassemble |
Decode selected executable instructions |
diff |
Compare two binaries semantically |
audit |
Security and configuration audit |
container |
Multi-architecture container analysis |
snapshot |
JSON structural snapshot |
patch |
Apply structural patches (rpaths, dylibs, signatures, bytes) |
header-infer |
Reconstruct Mach-O headers from evidence |
fileset |
Inspect fileset entries |
cache |
Inspect dyld shared cache |
Library usage
Core parsing is always available. Feature-selected metadata, analysis,
mutation, workflow, dyld-cache, and header-inference APIs are reexported by the
macho façade; narrow consumers can depend on leaf crates directly.
External transformation engines admit one immutable selected image through
macho::evidence::SelectedImageEvidence and consume strict language evidence
without Macho's report, workflow, mutation, or CLI policy. Swift ABI parsers
and their syntax trees stay private to Macho leaves. External engines receive
bounded, conserved Macho-owned evidence and own only their downstream semantic
projection.
let bytes = read?;
let container = parse?;
let image = container.first_macho.ok_or?;
println!;
# Ok::
Mutation plans borrow added-section payloads and validate concrete placement before rebuilding:
let bytes = read?;
let container = parse?;
let image = container.first_macho.ok_or?;
let section = new?
.with_alignment?;
let mut transaction = new;
transaction.add_section;
let rebuilt = transaction.commit?;
write?;
# Ok::
File-backed additions extend only the final file-backed segment when its
declared range ends exactly at the slice boundary. Load commands may grow only
through existing zero-filled header slack. Mutation never relocates existing
payload, symbols, or fixups. Zero-fill additions extend virtual storage only.
AddSection::new accepts any borrowed AsRef<[u8]>, including a raw byte slice,
Vec<u8>, or caller-owned read-only memmap2::Mmap. It stores the payload as a
slice, copies only the two fixed-width Mach-O names into inline storage, and
allocates no heap of its own. For a file, retain the mapping until the
transaction has committed; a bare File cannot expose borrowed bytes.
Injected SignatureProvider implementations may return a known ad-hoc or
certificate kind. External providers that omit kind() are opaque and do not
expose credentials or provider-specific signing mechanics. Opaque providers own
signature verification. The generic verifier accepts only the ad-hoc and
certificate mechanisms it understands.
Selective analysis builds an AnalysisPlan before execution. Snapshot
documents use schema version 3 and preserve not_requested, complete,
unsupported, and failed as distinct states.
Repository authorities
cargo xtask architectureenforces dependency direction and source ownership.cargo xtask docs --checkbinds this reference and diagnostic registry to code.cargo xtask release --checkbinds workspace packaging, CLI, changelog, and lockfiles.cargo xtask release --check --require-tagadditionally requires clean version-bearing inputs and an exact matchingvX.Y.Ztag.cargo xtask verifyruns the stable format, lint, docs, test, and benchmark gate.cargo xtask verify-fuzzbuilds all fuzz targets and requires nightly Rust.mise run verifycomposes both gates while scoping nightly to fuzzing only.
See CHANGELOG.md for release history and docs/diagnostic-codes.md for stable machine codes.
Macho is licensed under the MIT License.