mirror of
https://github.com/radareorg/r2sleigh.git
synced 2026-11-07 06:36:00 -10:00
e2159180cbd059f0f703db61a58b483f90b51af4
`import_stub` took the import's name from discovery (`import_at(entry)`) and its signature from the callee the body transfers to, and checked only that the callee's class was an import. A container-stated stub whose bytes jump through another import's slot (a patched Mach-O `__stubs` entry) passed: `free` rendered as `extern void* free(uint64_t)`, `malloc`'s types under `free`'s name. The address the transfer reaches must now be bound, by `import_at`, to the same import the entry is stated as. Both sides are the container's statement (the stub table, the loader's write into the slot), not the callee identity's spelling. Otherwise the function is no stub: it renders as a body, and `R2DEC_TRACE_REFUSAL` prints the stated import, the address reached and what is bound there. `import_stub` now asks `Program` itself, so `stub_of` takes the program; the body proof is split out as `lone_transfer` to stay under the function-length ratchet. Test `a_stub_whose_jump_goes_to_another_import_is_a_body_not_the_stated_stub` fails at298ae95bwith `/* r2sleigh: import stub at 0x1010; this symbol is the import `free` ... */ extern void* free(uint64_t);` and now renders the function with its `UnresolvedIndirectBranch` gap. `a_stub_the_container_states_is_its_import_s_declaration_where_its_jump_agrees` pins the container-stated stub whose jump agrees. Measured, release, base298ae95bagainst this tree: pdd of every function of bash and pumasim (16,866) is byte-identical, 0 changed (pumasim's 522 import stubs unchanged); pdd of all 6,878 `sym.imp.*` functions of the 781 small radare2 test ELF, Mach-O and PE binaries (2,222 ELF and 2,814 Mach-O stub renderings) identical, afl identical. cargo test -p r2engine --all-targets 628 passed; golden 442 and stable_temporaries 24 unmoved; structure-report.sh exit 0, counts unmoved; fmt, clippy --tests -D warnings and comment_runs --base clean. Co-Authored-By: Claude Sonnet 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01456qmqCGpCWJkrg6JUZNNM
Roadmap W1: stable op identity, written-lane result widths, provenance facts, and the shell/visual surface (#67)
r2sleigh
A binary analysis engine and certifying decompiler in Rust, with r2s as its
shell. Semantics come from Ghidra's Sleigh specifications rather than
hand-written per-architecture models, and the decompiler refuses rather than
guesses when it cannot prove what it would print. r2s speaks radare2's
command language with no radare2 in the process; radare2 is the differential
target the engine is graded against.
bytes --> Sleigh --> r2il (low) --> r2ssa (medium) --> r2dec (high) --> C
| | |
r2image r2types r2rewrite
ELF/Mach-O/DWARF type inference term rewriting
Quick start
cargo build --release -p r2s --features sleigh
target/release/r2s -q -c 'afl' /bin/ls # functions, and why each is believed
target/release/r2s -q -c 'iz' /bin/ls # strings
target/release/r2s -q -c 'axt 0x100003f10' /bin/ls # references to an address
target/release/r2s -q -c 's main; pdd' /bin/ls # decompile
target/release/r2s -q -c 's main; wx 9090; pdd' /bin/ls # patch in memory, then decompile
target/release/r2s -q -c 's main; pd 16' /bin/ls # disassemble
target/release/r2s /bin/ls # interactive; V for the visual mode
pdil prints r2il as lifted and pddo a function's source obligations, so a
defect is either in the lift or in the rendering. R2DEC_TRACE_REFUSAL=1 names
the predicate and site behind a refusal.
Architectures
| Architecture | Feature | Status |
|---|---|---|
| x86-64, x86 | x86 |
decompiles |
| aarch64 | arm |
decompiles |
| ARM 32-bit | arm |
disassembles; pdd not yet admitted |
| RISC-V, MIPS | riscv, mips |
lift |
Crates
| Crate | Purpose |
|---|---|
r2s |
The shell: radare2's command language over the engine |
r2s-tui |
The visual mode |
r2engine |
Query orchestration, discovery, routes, summaries |
r2image |
ELF and Mach-O parsing, DWARF through gimli |
r2abi |
Library prototypes, syscalls, cited ABI rows |
r2sleigh-lift |
Sleigh decoding to r2il; the machine profile from the .cspec |
r2il |
The low IL (Varnode, R2ILOp, R2ILBlock) and its semantics |
r2ssa |
The IR: SSA, indexes, liveness, values, memory, certificates |
r2source |
Contracts between the layers |
r2types |
Type inference, layouts, signatures |
r2rewrite |
Term rewriting with proved rules |
r2dec |
Structuring, binding and C rendering |
r2sleigh-cli |
The Sleigh toolchain and the instruction exporter |
Extending
- An opcode:
R2ILOpincrates/r2il/src/opcode.rs, its P-code translation incrates/r2sleigh-lift/src/translate.rs, text intext.rs,SSAOpincrates/r2ssa/src/op.rs, its C incrates/r2dec/src/render/terms.rs. - An architecture: a trusted language in
crates/r2sleigh-lift(TrustedSleighProfile,embedded_machine) whose compiler specification theLanguageProfileparses; nothing below the lifter matches its name (doc/adr-machine-profile.md). - A command: one entry in
VERBSincrates/r2s/src/commands.rs, spelled as radare2 spells it.
Documentation
| Document | What |
|---|---|
| ROADMAP.md | What is done, what is left, in order |
| AGENTS.md | Working rules: ownership, anti-hack standard, validation bar |
| BUILDING.md | Build, features, profiles, troubleshooting |
| CONTRIBUTING.md | Issues, commits, pull requests |
| doc/engine-vision.md | What this is becoming, and why |
| doc/testing.md | Gates and where a test goes |
doc/r2il.md, doc/ssa.md, doc/decompiler.md, doc/types.md |
The tiers |
doc/adr-*.md |
One design decision each, linked from the roadmap |
doc/drafts/ |
Designs not yet adopted |
Requirements
Rust 1.99 (edition 2024, pinned in rust-toolchain.toml). radare2 only for the differential harnesses. Z3
optional. License: LGPL-3.0-only.
Languages
Rust
91.1%
Python
7.4%
C
1.1%
Shell
0.3%