macho-header-syntax 0.4.0

Process-free typed C, C++, and Objective-C header syntax
Documentation

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

cargo install --path crates/macho-cli
mise run verify

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

macho info <binary>
macho info <binary> --arch arm64 --validate
macho symbols <binary> --defined-only --demangle
macho imports <binary> --format json
macho objc <binary> --headers
macho objc <binary> --kind class --presence defined --selector viewDidLoad
macho swift <binary> --state metadata-defined --name MyModule
macho disassemble <binary> --arch arm64e --symbol _main
macho disassemble <binary> --address 0x100003f50 --count 8 --format json
macho disassemble <binary> --address 0x100003f50 --end-address 0x100003f80
macho disassemble <binary> --symbol _main --no-addresses --no-bytes
macho disassemble <binary> --section __TEXT,__text --no-labels --no-targets
macho strings <binary> --min-length 8 --offsets
macho strings <binary> --search "secret" --exact
macho xrefs <binary> --import malloc --kind stub
macho ranges <binary> --name main --source nlist --demangle
macho diff <old-binary> <new-binary> --ignore-codesign --fail-on breaking
macho audit <binary> --min-severity warning --format sarif
macho snapshot <binary> --format json
macho patch <binary> --add-rpath @executable_path/../Frameworks --dry-run
macho patch <binary> --sign-adhoc --output <signed-binary>
macho patch <binary> --sign-p12 <identity.p12> --p12-password-file <password-file> --in-place
macho cache <dyld-cache> --info

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 = std::fs::read("/usr/bin/true")?;
let container = macho::parse(&bytes)?;
let image = container.first_macho().ok_or("container has no image")?;
println!("{}", image.header().file_type.name());
# Ok::<(), Box<dyn std::error::Error>>(())

Mutation plans borrow added-section payloads and validate concrete placement before rebuilding:

let bytes = std::fs::read("MyApp")?;
let container = macho::parse(&bytes)?;
let image = container.first_macho().ok_or("container has no image")?;
let section = macho::mutate::AddSection::new("__LINKEDIT", "__meta", b"payload")?
    .with_alignment(3)?;
let mut transaction = macho::mutate::PatchTransaction::new(image);
transaction.add_section(section);
let rebuilt = transaction.commit()?;
std::fs::write("MyApp.patched", rebuilt)?;
# Ok::<(), Box<dyn std::error::Error>>(())

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 architecture enforces dependency direction and source ownership.
  • cargo xtask docs --check binds this reference and diagnostic registry to code.
  • cargo xtask release --check binds workspace packaging, CLI, changelog, and lockfiles.
  • cargo xtask release --check --require-tag additionally requires clean version-bearing inputs and an exact matching vX.Y.Z tag.
  • cargo xtask verify runs the stable format, lint, docs, test, and benchmark gate.
  • cargo xtask verify-fuzz builds all fuzz targets and requires nightly Rust.
  • mise run verify composes 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.