atosl is a Rust CLI and library for local symbolication. It resolves raw binary addresses into function names and source locations using DWARF when available and falls back to symbol tables when debug info is missing.
It is designed for cross-platform tooling, CI pipelines, crash-processing utilities, and developer workflows that need atos-style symbolication without depending on Apple's host environment.
Apple's atos is useful, but it is tightly coupled to Apple's runtime environment. atosl focuses on the parts teams usually need in build systems and tooling:
- A single local binary and embeddable Rust API
- Script-friendly output in
text,json, andjson-pretty - DWARF-first resolution with symbol-table fallback
- Fat Mach-O slice selection by architecture or UUID
- Reproducible regression coverage for Apple-specific behavior
clapv4 CLI with explicit long-form flags- Structured JSON and pretty JSON output
- Unit tests for parsing, UUID handling, architecture aliases, and address math
- Integration tests that build a real fixture binary and validate end-to-end symbolization
- Apple-specific Mach-O/DWARF golden tests with reproducible fixtures and checked-in snapshots
- Fat Mach-O slice-selection goldens for
--archand--uuid - JSON output goldens for Apple single-slice and fat-binary workflows
- Verbose diagnostic goldens for resolver selection and per-frame lookup tracing
- Criterion benchmark target for batch symbolication throughput
- GitHub Actions CI for
fmt,clippy, tests, and release builds
- Local symbolication from executables, object files, and dSYM payloads
- Multi-address lookups in a single invocation
- Mach-O fat binaries with explicit slice selection
- Machine-readable integration through JSON output
- Debugging symbolication decisions through verbose diagnostics
From crates.io:
cargo install atoslFrom source:
git clone https://github.com/everettjf/atosl-rs.git
cd atosl-rs
cargo build --release
./target/release/atosl --helpatosl -o <OBJECT_PATH> -l <LOAD_ADDRESS> [OPTIONS] <ADDRESS>...Required arguments:
-o, --object <OBJECT_PATH>: object file, executable, or dSYM payload-l, --load-address <LOAD_ADDRESS>: runtime image load address<ADDRESS>...: one or more addresses to symbolize
Key options:
-f, --file-offsets: interpret addresses as file offsets-a, --arch <ARCH>: choose a Mach-O slice in a fat binary--uuid <UUID>: choose a Mach-O slice by UUID--format <text|json|json-pretty>: select output format-v, --verbose: print resolver diagnostics to stderr
Symbolize a single address:
atosl -o MyApp.app/MyApp -l 0x100000000 0x100001234Symbolize multiple addresses:
atosl -o MyApp.app/MyApp -l 0x100000000 0x100001234 0x100004321 0x100008888Select a specific fat Mach-O slice:
atosl -o Flutter -l 0x100000000 --arch arm64 0x100001234Emit machine-readable output:
atosl -o MyApp.app/MyApp -l 0x100000000 --format json 0x100001234Use verbose diagnostics to inspect resolver behavior:
atosl -v -o MyApp.app/MyApp -l 0x100000000 --arch arm64 0x100001234Example JSON shape:
{
"object_path": "MyApp.app/MyApp",
"object_name": "MyApp",
"selected_slice": {
"arch": "arm64",
"uuid": "34FBD46D-4A1F-3B41-A0F1-4E57D7E25B04"
},
"frames": [
{
"status": "resolved",
"requested_address": 4294971956,
"lookup_address": 4660,
"symbol": "main",
"object_name": "MyApp",
"offset": 0,
"resolver": "symbol_table",
"location": {
"file": "src/main.rs",
"line": 12
}
}
]
}When DWARF source information is available:
my::function (in MyApp) (src/main.rs:42)
When only the symbol table is available:
my::function (in MyApp) + 16
When symbolication fails:
N/A - failed to search symbol table
atosl now exposes a library API as well as the CLI:
use atosl::{atosl, OutputFormat, SymbolizeOptions};
let report = atosl::symbolize_path(&SymbolizeOptions {
object_path: "fixture_bin".into(),
load_address: 0,
addresses: vec![0x1234],
verbose: false,
file_offsets: false,
arch: None,
uuid: None,
format: OutputFormat::Json,
})?;The returned SymbolizeReport preserves the selected slice, per-address resolver choice, lookup address, symbol name, and optional source location.
Apple-specific behavior is protected by checked-in goldens under tests/golden/apple/:
- Text output for DWARF-backed and symbol-table-backed Mach-O inputs
- JSON output for single-slice and fat Mach-O workflows
- Verbose diagnostics for resolver tracing and slice selection
- Negative-path coverage for ambiguous fat binaries
Refresh those snapshots on macOS with:
./scripts/refresh_apple_goldens.shcargo fmt
cargo clippy --all-targets -- -D warnings
cargo test --all-targets
cargo build --release
./scripts/refresh_apple_goldens.sh
cargo bench --bench batch_symbolizeRun the benchmark binary without executing it in CI-style validation:
cargo bench --bench batch_symbolize --no-runRelease steps are documented in RELEASING.md.
For a one-command release flow, run ./deploy.sh [patch|minor|major|X.Y.Z].
- This is still not a 1:1 clone of Apple's
atos - Symbolication quality depends on the symbol and DWARF data in the target binary
- Mach-O workflows remain the primary design target; other object formats work best when symbols are present
- Apple UUIDs and dSYM layouts are covered in tests, but real crash-log ingestion is still out of scope
MIT. See LICENSE.