Files
Sylpheed/crates/sylpheed-xexdb
sim 124b9a1561
All checks were successful
CI / Native — linux (pull_request) Successful in 2h4m59s
CI / WASM — Web (pull_request) Successful in 30m45s
CI / Formatting (pull_request) Successful in 1m11s
docs: stop telling people to use the retired xenia-rs
Instructions and generated text that still sent readers to `xenia-rs`, which is
archived and deleted locally. Provenance and dated research records are left as
they are — "lifted from xenia-rs", or a finding stating what database it was
measured against, is still true, and rewriting it would falsify the record.

Changed, because each one tells someone what to do today or writes stale text:

  docs/re/README.md          the RE toolchain guide queried `xenia-rs/sylpheed.db`
                             with `xenia-rs/zq.py`, and its "Dynamic" bullet said
                             to prefer xenia-rs's probe suite OVER Canary. Now:
                             `sylpheed.db` at the repo root (how to build it and
                             re-stamp names), `tools/zq.py`, dynamic = Canary, and
                             `.rdata` reads from the `.pe` (offset = VA - 0x82000000)
                             in place of `--dump-addr`.
  challenge-mission-gate.md, structures/achievements.md
                             reproduction commands `python3 xenia-rs/zq.py dis …`
  crates/sylpheed-xexdb/SCHEMA.md
                             titled after the retired `xenia-analysis` crate,
                             citing `xenia-rs dis`, pointing at a `xenia-analysis`
                             source path
  sylpheed-xexdb/src/formatter.rs
                             WROTE "generated by xenia-rs" into every disassembly
                             it produced (no test pins the banner)
  sylph-xexdb.rs, db.rs      "SQLite" / "DuckDB writer for xenia-rs"
  sylpheed-formats/src/hash.rs
                             pointed at `xenia-rs/RE_SYMBOLS.md`, now at
                             `docs/re/RE_SYMBOLS.md`

Verified: every rewritten reproduction command was extracted from the doc and
run as written against the regenerated database — all 5 exit 0 and return the
disassembly they describe. The README's function count (25 676) is the database's
own. `cargo fmt --all -- --check` clean.

Not changed, deliberately: the README's Oracle bullet says Canary's native Linux
ELF "crashes / does not run". That is about Canary, not xenia-rs, and it conflicts
with a July note that the native build works — unverified either way here.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 20:37:08 +02:00
..

sylph-xexdb — the title's XEX, as a queryable database

sylph-xexdb dis <disc.iso|default.xex> --db sylpheed.db --analyze sql
tools/zq.py dis 0x82341a20 0x82341b00      # then query it

Extract the PE image, disassemble it, detect functions, resolve cross-references and RTTI, and write the lot to DuckDB.

Where it came from, and what did not come with it

This was xenia-rs — a from-scratch Rust Xbox 360 emulator, started because Canary would not run on Linux. Canary later did, with fixes from us, and the emulator was retired. The static analysis is the part that stayed useful, so it came here and the emulator did not: no interpreter, no JIT, no scheduler, no GPU, no kernel. About 17,000 lines of ~71,000.

That was possible because the coupling was three symbols — decoder::decode, disasm::DisasmItem, disasm::format — now sylpheed-ppc.

crate what it is
sylpheed-xex the XEX2 container: decrypt, LZX, PE image, resources, and the disc image it may live in
sylpheed-ppc PowerPC decode and disassembly
sylpheed-xexdb the analysis passes, the schema, and this binary

⚠️ Two things that will mislead you

The database is DuckDB. xenia-rs's own --db help said "SQLite" in two places and was wrong. Query it with python3 -c "import duckdb", or zq.py.

indirect_dispatch_candidates is deliberately not a cross product. A bcctrl through this->vptr at offset 0 matches nearly every class, so one site can claim 700+ callees. Sites past --max-indirect-candidates record a truthful candidate_count with truncated set and emit no candidate rows. On this title that is 6,556 of 6,983 sites, standing for 1,801,075 candidates that are counted rather than materialised. An older database built without the ceiling has ~1.8M more rows in that table and in xrefs, and they say nothing extra.

The export table

Import names come from docs/reference/xbox360-exports.json — 2,913 ordinals, compiled in by build.rs.

🔴 It used to come from Canary's xboxkrnl_table.inc through a relative path to a sibling checkout, which printed a warning and produced an empty table whenever that checkout was not there. Every import in the database then resolved to nothing, and the build still succeeded. Now the source is in this repository and a missing file fails the build.