feat(xexdb): port import-thunk naming + 16 schema foreign keys (rescued from an uncommitted tree) #35
Reference in New Issue
Block a user
Delete Branch "feat/xexdb-import-naming"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Carries
xenia-rsharvest/import-thunk-naming(b4f19f1) into the lifted crate.⚠️ Stacked on #32 — it ports into
crates/sylpheed-xexdb, which only exists there.Base is
feat/xexdb-tool, notmain, so this diff shows only the port instead ofburying it in #32's ~17,000 lines. Merge #32 first. If merging #32 deletes its branch,
retarget this to
main— by then #32's content is inmainand the diff is unchanged.Why this exists
That work was found uncommitted in the retired repo's working tree on 2026-09-14
— 468 lines plus an untracked 338-line
imports.rs, written 2026-09-10, in the verycrate Phase 3 lifted. It existed in exactly one place, and that place was not git:
imports.rsimport_addresszq.py impcallsiterate-4A(committed)CONSOLIDATION.mdPhase 5 ends with "delete the local clone" and Phase 7 drops theemulator, so a deletion was scheduled against it. The finding itself is written up in
docs/consolidation-dirty-tree-finding.What arrives
Import-thunk recognition (
imports.rs). An XEX import is not a PLT jump: thelinker emits a four-word thunk whose first two words are import records, rewritten
by the loader at module load. On disc they are still records, so a PowerPC-only
decoder prints two meaningless
.longs in front of an indirect branch. This mapsevery word of every thunk — and every direct branch into one — back to its
importsrow, so disassembly says
xboxkrnl.exe::RtlEnterCriticalSectioninstead of.long 0x01010194. Shape-validated, not trusted: an entry is indexed only when thefour words it points at actually have the thunk shape.
Adds
instructions.import_address(FK ontoimports.address) andimport_role(
'record'|'thunk'|'call', NULL iffimport_addressis NULL), plus an index.tools/zq.pygainsimpandimpcalls.Sixteen schema-wide foreign keys, wherever a column is derived from another table.
functionsis deliberately not an FK parent, and the golden test now assertszero inbound FKs onto it — DuckDB implements UPDATE as delete+insert, so one inbound
FK would make
functions.nameun-updatable and breakapply_re_symbols.sql.How it was ported — and the one conflict worth reading
Not a cherry-pick. The lift's base is exactly the harvest's parent (
8401d4d), soevery file was merged three-way (lifted / base / harvest).
10 conflicts, all caused by the lift's reformatting pass. Nine are the harvest's
additions landing inside blocks rustfmt had rewrapped — content kept, re-indented to
the lift's style. One is genuinely semantic and is the reviewable part:
🔴 Correction to the commit message: it says "9 of them pure rustfmt reflow". That
undersells them — they are reflow plus my content, not reflow alone. The table
above is the accurate description. Force-push is denied here, so the correction lives
in this description rather than in a rewritten commit.
Verification
db_schema_goldenis the one that matters: it locks the 16-FK set and theno-FK-onto-
functionsrule, and it builds an actual database rather than assertingagainst a string.
The database write path needed no change in the binary —
DbWriterbuilds its ownindex inside
ingest_instructionsfrominfo.import_libraries. Only the two outputpaths (
enrich_sectionfor JSONL,write_asm) take it as an argument.Phase 3 residue found while porting
tools/zq.py— fixed in38cc170. It hardcoded one absolute path, pointinginside
xenia-rs: a repository Phase 5 archives and Phase 7 drops. It resolved onexactly one machine, and on that machine it was days away from becoming a
duckdbexception about a missing file with nothing saying why.
Resolution is now
$SYLPH_XEXDB→<repo root>/sylpheed.db→ a refusal naming both.The repo-root path is relative to the script, not the caller's cwd. No fallback
beyond that, deliberately: the database is an untracked build artefact of a few
hundred MB, so there is nothing to fall back to, and a default that silently
resolves to the wrong database is worse than no default — issue #16's lesson, which
was this same shape in the test suite. The stale
xenia-rs disregeneration hint isnow
sylph-xexdb dis.Verified: usage still prints with no database (rc 0); missing database (rc 1, names
the build command);
$SYLPH_XEXDBset to a non-file (rc 1); and pointed at a real336 MB database, where
imp Rtlreturns its 1,280RtlLeaveCriticalSectioncallsites.
📌 That database turns out to have been generated from the uncommitted tree this
branch ports — it already carries
import_address,import_roleand all 16foreign keys. An independent confirmation of the schema the golden test now locks.
Still not fixed, and still reported rather than changed:
SCHEMA.mdis headed "xenia-analysisschema reference" and citesxenia-rs dis --db— both naming the retired repo and binary.and the binary's module doc), but two inline comments at
sylph-xexdb.rs:499and:874still say SQLite.🤖 Generated with Claude Code
CI stand-in: every leg green on the runner's own toolchain
This PR targets
feat/xexdb-tool, andci.ymlonly runs on PRs targetingmain— so it hasno CI statuses at all. Run instead in
sylph-ci:local, whoserustc 1.98.1 (48a229cea 2026-09-01)is byte-identical to the runner's, mirroringci.ymlstep for step, discnot mounted (as on the runner), head
38cc170:cargo check --workspacecargo build --workspacecargo test --workspacecargo clippy --workspace -- -D warningscargo fmt --all -- --checkcargo check --target wasm32-unknown-unknown -p sylpheed-viewer -p sylpheed-formatstrunk build --releaseCorpus report: ABSENT for all three, so this is parser-only coverage, same as the runner.
⚠️ Unrelated to this PR, and worth knowing before merging anything: with the disc present,
mainitself failsui_prm_primitives_discsince #23 — bisected, CI cannot see it.Two more commits (2026-09-15)
10150f7— ignore/sylpheed.db.38cc170madezq.pydefault to<repo root>/sylpheed.dbandtell people to put one there, but nothing ignored that path. One
git add -Awould have put aseveral-hundred-MB build artefact into public history. Anchored, so only the root file is ignored.
b57733a— harvestRE_SYMBOLS.md+apply_re_symbols.sql, which Phase 3 left inxenia-rs.This PR's own FK rule exists because
apply_re_symbols.sqlre-stamps names ontofunctions—Sylpheed referenced it three times and contained it on no branch.
docs/re/RE_SYMBOLS.mdis abyte-identical copy;
tools/apply_re_symbols.sqlkeeps every statement and re-paths two comments.Run against the real 336 MB database (all 16 FKs) in a rolled-back transaction: every statement
runs, 208 functions named, database unchanged.
Phase 3 lifted the DuckDB tool out of `xenia-rs` but not the two files that go with it, and this branch's own code already depends on one of them: the FK rule in `db.rs` and `db_schema_golden.rs` exists *because* `apply_re_symbols.sql` re-stamps reverse-engineered names onto `functions` after every regeneration. Sylpheed referenced that file three times and contained it nowhere — on no branch. CONSOLIDATION.md's end state is "Sylpheed holds everything", and the `xenia-rs` clone is scheduled for deletion. docs/re/RE_SYMBOLS.md byte-identical to xenia-rs/RE_SYMBOLS.md (cmp) tools/apply_re_symbols.sql every statement identical; the two comment lines that name paths now name this repo's paths Verified against the real 336 MB database, which carries all 16 foreign keys, inside a transaction that was rolled back (the database is unchanged): every statement runs, and 208 functions carry reverse-engineered names. Run from both the old location and this one. Not harvested: `xenia-rs/zq_dis.py`, an untracked six-line subset of `zq.py dis` with a hardcoded path — superseded, nothing to keep. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>