rsleigh 0.3.0

SLEIGH (.slaspec) parser and Rust decoder/P-code emitter codegen — Ghidra-compatible disassembly in pure Rust
Documentation
# rsleigh Roadmap

Tracks in-flight and planned work. For shipped features, see `CLAUDE.md`
"Key Features". For test coverage, see `docs/TESTING.md`.

---

## Ghidra parity gap (PLM aarch64 baseline)

Current status on 50-function random sample of `plm-control-app.elf`:

| Metric | rsleigh | Ghidra |
|---|---|---|
| Avg lines per function | 21 | 27 |
| `lVar` leaks per 100 lines | 37 | ~0 |
| `DAT_` leaks per 100 lines | 5 | ~0 |
| `field_N` anon struct fields per 100 lines | 20 | ~0 |
| Unresolved direct call `func_X` per 100 lines | 10 | <5 |

rsleigh matches or beats Ghidra on function discovery count (4531 vs
4357) and leads on 15/21 binaries in the comparison corpus. Remaining
gap is concentrated in type recovery + control-flow shape.

---

## Active areas

### P0 — Control flow structure recovery
- **Parallel `if` collapsed to nested.** Diamond CFGs where both
  branches post-dominate the same join block currently emit nested
  form instead of sibling ifs. Root cause in `structure::emit_region`
  post-dominator picking. Needs test corpus of 10+ hand-labelled
  ARM64 functions before touching.
- **do-while vs while misclassification.** Back-edge post-test funcs
  (common in STL iterator loops) print as `while (cond) { ... return; }`
  with impossible mid-loop return. Fix in back-edge detection phase
  of structure recovery.
- **Dead-code reachability after return.** Basic-block flattener
  occasionally emits statements after an unconditional return inside
  a nested branch.

### P1 — Type recovery
- **Pointer propagation through callee-saved x19-x28.** Type inference
  almost never flags x19-x28 as Pointer even when only used via `->` /
  `*()`. Need explicit propagation: if a register-varnode use has
  InferredType::Pointer for the address of any Load/Store keyed off it,
  mark all versions of that register in the register-SSA chain.
- **Struct field naming.** `param_1->field_8` vs Ghidra's `param_1[1]`
  or `param_1->next`. Current heuristic struct-field namer only handles
  linked-list patterns. Expand to cover Qt `d_ptr` pattern, ref-counted
  object headers, common STL container headers.
- **Return-type inference.** Still guesses `long` for functions that
  take a pointer and return it unmodified (`this` return). Add
  "parameter-through" detection to the return-inference pass.

### P2 — Decoder / semantic
- **ExprValue::Context returns 0.** Used by some slaspecs for
  context-sensitive instruction semantics. Currently unused by
  x86/ARM/RISC-V but blocks PowerPC/SH-4 if we ever add them.
- **ExprNew / ExprCPool return 0.** JVM bytecode + WASM module
  instantiation. Not a real blocker.
- **ARM32 VFP/NEON float register propagation.** Instructions decode
  correctly (vmul.f64, vldr, vmov) but float register values don't
  thread through fold's expression inliner. Need float-specific
  handling in propagate_register_constants.

### P3 — Function ID database
- **Mask tuning for cross-compile match.** Current Qt5Core round-trip
  is 99% matched / 0% false-positive on same-binary lookup. Cross-compile
  (different gcc version / optlevel) unmeasured. Need labelled corpus
  of identical source + varied toolchains to tune x86 ModR/M + AArch64
  per-class masks.
- **Bundle Windows ntdll/kernel32.** Microsoft doesn't ship stable
  function bodies; lib authors rely on PDB symbols. Need PDB-backed
  match path (already partially wired via pdb_info.rs) before FID is
  useful on PE targets.
- **ARM32 / MIPS / RISC-V bundled DBs.** Today only x86_64 + aarch64
  ship. Add when we find a high-demand target (e.g. MIPS router
  firmware, ARM32 IoT).
- **Match telemetry in `--verbose` mode.** Print renamed count +
  examples when FID matches fire, so users can see which of 13,612
  signatures hit.
- **Auto-discover .fidb files in $HOME/.config/rsleigh/fid/.** Lets
  users drop Qt / OpenSSL / libcurl blobs without CLI flags.

### P4 — Analysis features
- **Indirect call resolution beyond MIPS.** Currently resolved via
  GP-relative GOT tracing on MIPS (77% resolved). Apply the same
  pattern on AArch64 (ADRP+LDR+BLR) and x86-64 (CALL [rip+off]).
- **Stack-buffer size recovery.** Array-sizing works from offset gaps
  but stops at the first pointer-to-stack-slot use. Extend to handle
  aliased stack pointers (`lea` / `add sp, N`).
- **Exception-aware dataflow.** `.eh_frame` try regions are annotated
  as comments; SSA fold doesn't treat catch handlers as alternate
  successors, so variables written in the try body are assumed live at
  the catch. Add virtual edges.

### P5 — Ecosystem
- **Spectra integration tests for FID.** `rsleigh-api::identify()` not
  exposed yet — Spectra still relies on symbol-table lookup. Surface
  via optional `ident: bool` flag on the Decoder API.
- **VSCode extension.** Decompile on hover, inline struct field rename,
  jump-to-xref. Protocol already supported via rsleigh-cli JSON mode.
- **Docker reproducible-builds.** `scripts/build-fid-dbs.sh` pulls from
  Debian/Alpine mirrors; pin via SHA256 plus provenance manifest so
  CI can re-verify the checked-in .fidb blobs match upstream.

---

## Recently shipped (current session)

- Custom-VM packer recon suite (15 modules, 110+ lib tests):
  vm_fingerprint, jmp_rax_trampoline, xor_vtable, vm_dispatch_extract,
  vm_handler_classify, tag_dispatch, handler_summary, vm_bytecode_disasm,
  api_resolver (ROR13/DJB2/DJB2a/FNV-1), peb_walk_detect, antidebug_timing,
  scratch_leak, sha256_func_detect, crypto_constants, rip_xref. CLI flags:
  `--vm-dispatch`, `--vm-classify-handlers`, `--tag-dispatch`,
  `--summarise-handlers`, `--vm-bytecode`/`--vm-handlers`, `--annotate-crypto`.
  Auto-banners on every PE64 binary surface family fingerprint, trampoline
  gadgets, hash resolvers, PEB-walk sites, timing probes, scratch leaks,
  SHA-256 regions.
- decode_func zero-padding skip — CALL rel32 targets landing on inter-function
  zero padding no longer flood disassembly with `ADD byte ptr [RAX], AL`.
- Qt5 signature database (23,274 entries extracted from bundled .so files)
- rsleigh-fid crate end-to-end (scaffold → CLI → match helper)
- Glibc / musl / libstdc++ bundled FID blobs (6 files, 287KB, 13,612 entries)
- AArch64 AAPCS64 x1-x7 + v0-v7 param recovery
- Stack-canary XOR epilogue elision (post-rename)
- ADRP page-address prologue leak strip (2 passes)
- `close` / GOT import name-collision fix (page-aligned skip)
- `InferredType::Pointer``void *` typing
- `lVar → puVar` rename when type=Pointer
- Callee-saved register prologue spill elision
- R_*_GLOB_DAT reloc parsing for `__stack_chk_guard` + vtable names

---

## Out of scope

- Windows PDB symbol server integration (complex licensing + network)
- Debugger integration (gdb / lldb) — use existing Spectra pipeline
- Interactive REPL — CLI is scripting-first by design
- JIT / dynamic code support — purely static analysis tool