Decompiler
the decompiler is experimental
It lifts x86, x86-64, ARM, and ARM64 through LLIR, SSA, and an AST, then prints C-like pseudocode. The test suite recompiles that C and runs it.
Pass or fail
recompile it and call both versions
Graph edit distance, type match, and byte match compare representations. This test calls the original function and the recovered one with the same inputs.
# tools/diff_decompile.py, in outline:
#
# 1. decompile the function to C
# 2. compile that C into a shared object
# 3. in an ISOLATED SUBPROCESS, dlopen BOTH the original
# binary and the recompiled decompilation
# 4. call both with the same deterministic, seeded inputs
# 5. compare the full-width return value AND every mutable buffer
#
# A mismatch means the decompilation is behaviorally unfaithful.
# type_match, GED and byte_match cannot see that.
A passing lane cannot regress without stopping the build. baseline.json pins gcc
11.4.0, clang 14.0.0, and glibc 2.35 because changing the compiler can move the score more than
a decompiler patch.
Corpus
213 small programs, six build lanes
Open any fixture to see its source, recovered C, and verdict in each compiler lane. Browse all 213 fixtures →
83.9%
of function-lanes behave the same as the original (2,895 of 3,449)
baseline.json @ 356be614, 2026-08-27
119
of 213 fixtures pass every lane they have
baseline.json
98.1%
of emitted C/C++ functions read nothing they never wrote (207 of 11,166 do)
defuse_baseline.json
By compiler and optimization level
| lane | pass | fail | rate |
|---|---|---|---|
| clang -O0 | 715 | 83 | 89.6% |
| gcc -O0 | 715 | 83 | 89.6% |
| gcc -O2 | 704 | 94 | 88.2% |
| clang -O2 | 691 | 107 | 86.6% |
| rustc -O2 | 49 | 19 | 72.1% |
| rustc -O0 | 21 | 47 | 30.9% |
Rate is over pass-or-fail verdicts; structural-only lanes are excluded from the denominator.
By architecture
| architecture | pass rate |
|---|---|
| x86-64 (gcc 11.4, pinned) | 85.4% |
| x86-64 (gcc 15.2) | 84.2% |
| aarch64 | 76.3% |
| i386 | 73.0% |
| armv7 (Thumb) | 69.0% |
| armv7 (-marm) | 68.1% |
2,472 cells over 206 fixtures, 9,805 function-lanes, from arch_baseline.json. Cross-compiled with GCC 15.2.0 and run under qemu-arm / qemu-i386 with randomization
disabled.
DecBench
fifth of nine on type_match
Glaurung produced a measurement for 86,660 of 86,671 functions, the widest coverage on this board.
93 stripped functions
| measure | Glaurung | Ghidra 12.1.2 | angr 9.3.1 | RetDec v5.0 |
|---|---|---|---|---|
| decompile succeeds, stripped | 93 / 93 | 75 / 93 | 87 / 93 | 87 / 93 |
| output parses as C | 90% | 20% | 51% | 74% |
| `undefined`-width types per function | 0.00 | 2.61 | 0.00 | 0.00 |
| invented calls per function | 0.00 | 0.00 | 0.00 | 0.00 |
From the project's gap-plan measurements, 2026-08-01 to 2026-08-03. On the same run Glaurung went from the second-slowest of the four to the fastest by roughly five times, and function-discovery recall on stripped binaries went from 0.183 to 1.000.
Quality — DecBench type_match, full 86,671-function corpus
| backend | type_match | functions measured |
|---|---|---|
| Binary Ninja 5.3 | 9.227% | 76,295 |
| angr | 8.526% | 84,151 |
| Ghidra 12.1 | 7.794% | 80,005 |
| IDA 9.2 | 7.527% | 82,581 |
| Glaurung | 6.905% | 86,660 |
| Kuna | 6.131% | 86,662 |
| Phoenix | 4.530% | 44,481 |
| r2dec | 1.884% | 60,274 |
| Reko | 0.264% | 22,419 |
Glaurung ranks fifth on type_match. It produced a measurement for 86,660 of
86,671 functions. Three merged pull requests added the backend to DecBench.