Decompile compete — capability + measured scoreboard
How Spark competes at every level on SPARK_BC without false marketing. Spark / SparkLang only.
Never publish “Spark beats Ghidra / IDA / Binary Ninja /
LLM4Decompile / OpenBin” without the measured JSON from
make decompile-bench. Measurement only.
Do not copy OpenBin code.
Related: Decompile · research/LLM_DECOMPILE.md · site /docs/decompile-compete.html.
Beat-axes (SPARK_BC domain — where we can actually win)
| Axis | Why it is a Spark win |
|---|---|
| 100% round-trip | compile → dump → recompile same .spark → identical sha256 on published fixtures (tools/spark-bc-dump/roundtrip.py) |
| Best structured dump | Sections + string symbols + const/op xrefs + txt/JSON/HTML export (bc_dump.analyze_bc) |
| Best local privacy | No upload — analysis project stays on disk |
| Integrated train / weights | Same BC drives TRAIN/STEP + init safetensors |
Classic RE tools win ELF/PE/mach-O interactive decompile. That is loss / N/A for Spark SoT — not a silent claim.
Feature parity matrix
Legend: win / tie / loss / na (wrong domain) /
not probed (tool absent, or no scripted byte-level probe on the
bench box). Every badge is computed by
tools/spark-bc-dump/decompile_bench.py from measured
probe output — round-trip %, symbol/xref extraction on real bytes, the local
ELF probe, and byte-level probes of any competitor tool actually present.
The matrix is rendered from
website/data/decompile-scoreboard.json in the
measured scoreboard below —
there is no hand-painted table on this page.
Commands
make spark-bootstrap spark
make test-decompile-compete # unit: richer dump + project
make decompile-roundtrip # compile→dump→recompile hash
make decompile-bench # metrics + scoreboard JSON
# also records elf_local_probe from ./spark-binary-probe --elf
./spark-binary-probe --elf ./spark
Local ELF probe emits claim: local_elf_probe_not_ghidra and a
sections[] index — still a loss on Multi-format ELF/PE vs
Ghidra/IDA/Binja/OpenBin. Status note, not a domain flip.
Analysis project (single file):
PYTHONPATH=python python3 tools/spark-bc-dump/analyze_project.py \
docs/examples/spark-train-step.sparkbc \
-o out/analyze/train-step \
--source examples/spark_train_step.spark
Richer dump exports:
PYTHONPATH=python python3 tools/spark-bc-dump/dump.py \
docs/examples/spark-train-step.sparkbc --json -o /tmp/bc.json
PYTHONPATH=python python3 tools/spark-bc-dump/dump.py \
docs/examples/spark-train-step.sparkbc --html -o /tmp/bc.html
Measured scoreboard (data-driven)
After make decompile-bench:
website/data/decompile-scoreboard.jsondocs/examples/decompile-scoreboard.json(mirror)- sample project:
out/decompile-bench/sample-project/
The site page loads the JSON and renders win/tie/loss/na/not-probed from disk data — no hand-painted green checkmarks, no author-declared badges.
External tools (objdump, r2, ghidra, ida, binaryninja, openbin)
are probed; if absent → status: absent / verdict: skip
and every parity cell for that tool is not probed. If
present but not a SPARK_BC decoder → verdict: na-sparkbc,
with byte-level probe results (e.g. objdump -d on a
real .sparkbc, objdump -h on
./spark) driving the measured cells.
What is still not claimed
| Claim | Status |
|---|---|
Lossless BC → .spark source |
not implemented |
| Spark beats Ghidra on ELF | false / loss |
| LLM perfectly decompiles SPARK_BC | never |
| OpenBin clone | never — local SoT only |
Related
Live measured scoreboard — loaded from
/data/decompile-scoreboard.json after
make decompile-bench. Empty box means regenerate JSON.