Expand description
§darwinscope: Mach-O / Objective-C / Swift binary parser
A Rust library for statically analyzing Mach-O binaries - the container format used by macOS, iOS, watchOS, tvOS, visionOS, and Mac Catalyst - and the rich Apple-runtime metadata they embed.
Given an arbitrary byte slice, darwinscope decodes:
- The Mach-O container itself: header, load commands, segments,
sections, nlist symbol table, bind / export tries, fat-binary
slices, dylib graph,
LC_FUNCTION_STARTS, and the data rangesLC_DATA_IN_CODEdeclares inside code sections. - The embedded code-signature SuperBlob: CodeDirectory identifier and Team ID, signing flags, CodeDirectory hash type, embedded CMS signature size, entitlements XML plist (key / value pairs).
- The Objective-C runtime tables: classes, metaclasses,
methods (legacy and small-method-list), instance variables,
properties, protocols, categories, and the cross-section
reference tables (
__objc_selrefs,__objc_classrefs,__objc_superrefs,__objc_protorefs). - The Swift 5 type metadata: type descriptors
(
__swift5_types), protocol descriptors (__swift5_protos), field descriptors (__swift5_fieldmd), protocol conformances (__swift5_proto), and class vtable entries. - CoreFoundation constant strings (
__cfstring) - both ASCII / UTF-8 (__TEXT,__cstring) and UTF-16 LE (__TEXT,__ustring) bodies. - Apple Blocks-runtime metadata - bind sites for
_NSConcrete{Global,Stack}Blockplus the fullBlock_descriptor_{1,2,3}decode for global block literals (invoke pointer, signature, layout string).
The crate handles arm64e pointer authentication (PAC) by
canonicalising signed pointers before every dereference, and
supports both the legacy bind-opcode pointer format and
LC_DYLD_CHAINED_FIXUPS chains.
§Motivation
Apple binaries are unusually rich static-analysis targets. Stripped Mach-O dylibs and executables still carry:
- Obj-C class hierarchy + selectors - required at runtime for message dispatch.
- Swift type names + field layouts - required for runtime reflection, generic specialization, and protocol witness lookup.
- Code-signing identity - Team ID and bundle identifier, embedded for system-wide code-signing enforcement.
- Entitlements XML - explicit list of every privileged API the binary requested.
- Function entry points -
LC_FUNCTION_STARTSULEB128 table, used bydyldfor the unwinder.
This metadata survives stripping because the OS depends on it for linking, dispatch, and code-signing enforcement.
§Architecture
The crate is organised in layers:
- Container (
binary): wrapsgoblin::mach::MachOand exposes typed views over the structural layer (Header,Segment,Section,Symbol,Import,Export,Dylib,LoadCommand). - Code signing (
codesign): SuperBlob walker, CodeDirectory parser, entitlements plist decoder. - Objective-C (
objc): aggregateObjcRuntimewalker withclass_t/class_ro_t/method_list_t(legacy + small) /ivar_list_t/property_list_t/protocol_t/category_tdecoders, cross-section reference readers, and class ↔ protocol conformance edges. - Swift (
swift): type / protocol / field / conformance / vtable descriptor walkers. - Support (
ptrauth,util): pointer-authentication stripping, ULEB128 decoding, virtual-to-file-offset translation.
§Quick start
use darwinscope::MachoBinary;
let bytes = std::fs::read("/usr/bin/codesign")?;
let binary = MachoBinary::parse(&bytes)?;
let header = binary.header();
println!("cputype=0x{:x} ncmds={}", header.cputype(), header.ncmds());
if let Some(uuid) = header.uuid() {
println!("uuid={:02x?}", uuid);
}§Status
v0.1 is under active development. The public API will remain unstable until v0.1 ships.
Re-exports§
pub use binary::MachoBinary;pub use error::Error;pub use error::Result;pub use cfstring::CFString;pub use cfstring::CFStringBody;pub use cfstring::CFStringEncoding;pub use cfstring::CFStringIter;pub use cfstring::CFStringRuntime;pub use block::BlockDescriptor;pub use block::BlockIsa;pub use block::BlockLiteral;pub use block::BlockReference;pub use block::BlockRuntime;pub use block::LiteralIter;pub use block::ReferenceIter;pub use objc::ClassIter;pub use objc::ClassRefIter;pub use objc::ConformanceEdge;pub use objc::ConformanceIter;pub use objc::ImageInfo;pub use objc::Ivar;pub use objc::IvarIter;pub use objc::Method;pub use objc::MethodIter;pub use objc::MethodKind;pub use objc::ObjcCategory;pub use objc::ObjcClass;pub use objc::ObjcProtocol;pub use objc::ObjcRuntime;pub use objc::ParsedAttribute;pub use objc::ParsedAttributes;pub use objc::Property;pub use objc::PropertyIter;pub use objc::ProtoRefIter;pub use objc::ProtocolIter;pub use objc::ProtocolNameIter;pub use objc::RefTarget;pub use objc::SelRefIter;pub use objc::SuperRefIter;pub use swift::CaptureDescriptor;pub use swift::CaptureIter;pub use swift::Conformance;pub use swift::ConformanceFlags;pub use swift::ConformanceIter as SwiftConformanceIter;pub use swift::ContextDescriptorFlags;pub use swift::ContextDescriptorKind;pub use swift::DefaultOverrideEntry;pub use swift::DefaultOverrideEntryIter;pub use swift::DefaultOverrideTableHeader;pub use swift::DynamicReplacementScope;pub use swift::FieldDescriptor;pub use swift::FieldDescriptorKind;pub use swift::FieldIter;pub use swift::FieldRecord;pub use swift::FieldRecordFlags;pub use swift::FieldRecordIter;pub use swift::ForeignMetadataInit;pub use swift::GenericContextHeader;pub use swift::InvertibleProtocolSet;pub use swift::MetadataInitializationKind;pub use swift::MethodDescriptorFlags;pub use swift::ObjcResilientClassStubInfo;pub use swift::OverrideEntry;pub use swift::OverrideEntryIter;pub use swift::OverrideTableHeader;pub use swift::ParentChain;pub use swift::ParentContext;pub use swift::PrespecializationIter;pub use swift::ProtocolIter as SwiftProtocolIter;pub use swift::ReplacementIter;pub use swift::ResilientSuperclass;pub use swift::SingletonMetadataInit;pub use swift::SingletonMetadataPointer;pub use swift::SwiftMethodKind;pub use swift::SwiftProtocol;pub use swift::SwiftRuntime;pub use swift::TypeContextDescriptorFlags;pub use swift::TypeDescriptor;pub use swift::TypeIter;pub use swift::TypeKindBody;pub use swift::TypeReference;pub use swift::TypeReferenceKind;pub use swift::VTableEntry;pub use swift::VTableHeader;pub use swift::VTableIter;
Modules§
- binary
- Top-level
MachoBinaryview. - block
- Apple Blocks runtime metadata.
- cfstring
- CoreFoundation constant strings (
__cfstring). - codesign
- Apple Code Signing decoder.
- dataincode
LC_DATA_IN_CODE: the linker’s account of data inside code sections.- dylib
- Dylib graph (
LC_LOAD_*_DYLIB) and load-command summary. - error
- Error and result types for
darwinscope. - export
- Exports - symbols this image makes available to other dylibs.
- fixup
LC_DYLD_CHAINED_FIXUPSdecoder.- import
- Imports - dyld bind targets.
- objc
- Objective-C 2 / non-fragile-ABI runtime metadata walker.
- ptrauth
- Pointer authentication and chained-fixup canonicalisation.
- segment
- Segments and sections (
LC_SEGMENT_64/LC_SEGMENT). - swift
- Swift 5 type-metadata walker.
- symbol
- Nlist symbol table iterator (
LC_SYMTAB). - unwind
__TEXT,__unwind_info: the compact unwind table.- util
- Shared low-level helpers - ULEB128 / SLEB128 decoding, virtual-to-file-offset translation, primitive byte readers.