Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

thebabush/xr

Open more actions menu

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

91 Commits
91 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

xr — fast binary cross-reference extractor

xr is a standalone Rust CLI that extracts cross-references — calls, jumps, and data references — from stripped binaries (ELF, Mach-O, PE, and the Apple dyld shared cache) in seconds. It emits (from_va, to_va, kind) tuples orders of magnitude faster than loading the binary into a full disassembler like IDA, Ghidra, or Binary Ninja, making it a fast building block for reverse-engineering pipelines, binary diffing, and large-scale program analysis.

Install

cargo install xrefs        # crate is `xrefs`, binary is `xr`

Or build from source with cargo build --release (binary at target/release/xr).

Quick Start

# Analyse a binary at the recommended depth
xr /path/to/binary --depth paired

# Output as JSONL or CSV
xr /path/to/binary --depth paired --format jsonl
xr /path/to/binary --depth paired --format csv

# Filter to a specific xref kind
xr /path/to/binary --depth paired --kind call

# Show disasm context around each xref site (like grep -A/-B)
xr /path/to/binary --depth paired -A 3 -B 2

Performance

206 million xrefs from a 4.6 GB dyld shared cache (3240 images) in under 6 seconds:

$ xr /System/Library/dyld/dyld_shared_cache_x86_64 > /dev/null
dyld shared cache: arch=X86_64  mappings=24  images=3240  subcaches=5
xrefs: 206432528  |  5.7s  |  4620.3 MB scanned  |  24 segments

Example Output

Default text output:

$ xr binary --depth paired --limit 4
0x00000000006a268f -> 0x00000000006a2699  jump  [linear-immediate]
0x00000000006a26a1 -> 0x00000000006a25ea  call  [linear-immediate]
0x00000000006a26b7 -> 0x0000000000798345  call  [linear-immediate]
0x00000000006a26cf -> 0x00000000006a2368  data_ptr  [linear-immediate]

With disassembly context (-B 2 -A 1):

$ xr binary -k call --limit 2 -B 2 -A 1
0x00000000006a26d6 -> 0x00000000006a2393  call  [linear-immediate]
    0x00000000006a26ca  48 8d 4c 24 0c            lea rcx, [rsp+0Ch]
    0x00000000006a26cf  48 8d 15 92 fc ff ff      lea rdx, [6A2368h]
  > 0x00000000006a26d6  e8 b8 fc ff ff            call 00000000006A2393h
    0x00000000006a26db  48 83 c4 18               add rsp, 18h

With Rust string heuristics (--rust):

$ xr target/release/my_app --rust -k data_ptr
...
0x00000001002b0238 -> 0x0000000100243834  data_ptr  [byte-scan]  "STRIKETHROUGH"
0x00000001002b4b68 -> 0x00000001002744d2  data_ptr  [byte-scan]  "failed to write the buffered data"
0x00000001002b5de0 -> 0x000000010022e8b0  data_ptr  [byte-scan]  "src/arch/arm64.rs"
0x00000001002b5e10 -> 0x000000010022e8c2  data_ptr  [byte-scan]  "src/arch/x86_64.rs"

Analysis Depths

Flag Name What it does
--depth scan ByteScan Pointer-sized byte scan of data sections
--depth linear Linear Linear disasm, immediate targets + RIP-relative
--depth paired Paired ADRP+ADD/LDR pairs (ARM64) or register prop (x86-64), recommended

Accuracy

See docs/STATUS.md for architecture details and known gaps.

Supported Formats

  • ELF (x86-64, AArch64), including PIE (ET_DYN)
  • Single-arch Mach-O (x86-64, ARM64). Fat binaries require lipo -extract first
  • PE / COFF (x86-64, ARM64)
  • ELF ARM32 (Thumb-2 / A32), with per-section mode detection
  • COFF object files / .o / .obj (x86-64, ARM64, x86-32, ARM32)
  • Apple dyld shared cache
  • Raw flat binary (treated as single executable segment)

COFF object files have no fixed load address; xr assigns VAs by stacking sections sequentially from 0 (matching the convention used by common disassemblers).

x86-32 binaries are loaded but not scanned (architecture stub only).

Options

USAGE:
    xr [OPTIONS] <BINARY>

OPTIONS:
    -d, --depth <DEPTH>         Analysis depth: scan | linear | paired [default: paired]
    -j, --workers <N>           Worker threads; 0 = all CPUs [default: 0]
    -f, --format <FORMAT>       Output format: text | jsonl | csv [default: text]
    -k, --kind <KIND>           Filter by kind: call | jump | data_read | data_write | data_ptr
        --base <VA>             Override PIE ELF load base (hex or decimal)
        --arm32-mode <MODE>     ARM32 decode mode: auto (default) | thumb | arm
        --min-ref-va <VA>       Drop xrefs whose 'to' VA is below this value
        --start <VA>            Scan only 'from' addresses >= VA
        --end <VA>              Scan only 'from' addresses < VA
        --ref-start <VA>        Retain only xrefs with 'to' >= VA
        --ref-end <VA>          Retain only xrefs with 'to' < VA
        --limit <N>             Cap output at N xrefs (0 = unlimited)
    -A, --after-context <N>     Show N instructions after each xref site
    -B, --before-context <N>    Show N instructions before each xref site
        --rust                  Extract Rust string literals from data_ptr xrefs
        --rust-min-blob <N>     Min UTF-8 blob size in bytes [default: 16]
        --rust-string-max <N>   Max display width for strings (0 = unlimited) [default: 100]

Benchmarking

The benchmark helper ships as an example (it is not installed by cargo install):

# Run against a ground-truth file
cargo run --release --example benchmark -- \
    --binary /path/to/binary \
    --ground-truth /path/to/binary.xrefs.json \
    --depth paired

Claude Code Skill

This project includes a Claude Code skill in .claude/skills/xrefs/ that teaches Claude how to use xr for binary reverse-engineering workflows: finding callers/callees, data references, pointer hunting, and more.

License

Licensed under either of Apache License, Version 2.0 or MIT license at your option.

About

Fast binary cross-reference extractor for ELF, Mach-O, PE, and dyld shared caches

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages

Morty Proxy This is a proxified and sanitized view of the page, visit original site.