leaderboard
Decompilers have advanced significantly over the last 30 years, quickly approaching the point where they can recover the exact source code from various binaries. This benchmark ranks decompilers by their ability to recover exact source code, measured across three metrics. All metrics are shown as the percentage of functions on which a decompiler achieves a perfect score. Decompilers are initially ranked by Union — their ability to score perfectly on at least one of those metrics. Click a column to sort.
AI can also compete on these metrics, as seen on the sample-set leaderboard where Codex and Claude Code take on the traditional decompilers. You can find more information about these metrics, datasets, and methodology on the about page. You can also view some sample results on the view page.
For higher accuracy type measuring, DecBench requests decompilers to report addresses for each line of decompilation. Decompilers marked with the astrix did not provide those or the addresses can't be verified.
data
Benchmark-run data beyond the leaderboard's perfect rates: distance from perfection per metric, how often decompiled output compiles again, pipeline health (what our own tooling loses), and the cost of producing each decompiler's output.
distance
When a decompiler can't yet achieve a perfect score on a function, it can be helpful to understand the distance it is from perfection. For each metric, we measure distance as the number of edits required to convert that form of data into its source-code equivalent. For GED, that is the number of edits to control-flow structures. For types, that is the number of type-flips needed to reach ground truth. For recompilation, that is the number of assembly lines that must change to convert the recompiled assembly into the ground-truth assembly.
Each cell shows the mean, the median, and how many functions are already at distance 0 (perfect), averaged over the functions each decompiler was scored on.
Over the selected dataset (mean · median · #at-0 / #measured).
rows below the break are sample-set-only backends (LLM coding agents): they are scored only on the ~250-function sample-set slice, so on this dataset their numbers cover just its overlap with that slice — not directly comparable to the full-coverage rows above.
compiles
The share of each decompiler's byte_match-measured functions whose output actually recompiled after the uniform compilability-fixup pass — a fairness control, not a metric (type recovery is scored separately). The denominator is per-decompiler: functions where byte_match was measurable, so ARM / PE targets with no host recompiler never count against it. This rate moves with the selected dataset, like the columns on the leaderboard.
rows below the break: sample-set-only backends — their rate covers only this dataset's overlap with the sample-set slice.
pipeline health (our own tooling)
GED depends on Joern parsing both the source and the decompiler output. When Joern fails on the source, that's our tooling — those functions are excluded from GED for every decompiler (never counted against them). When Joern fails on a single decompiler's output, that's reported here (per decompiler), not folded into the headline score.
cost
What each decompiler's output costs to produce. The two halves of the table
are not directly comparable: traditional decompilers are timed from
whole-binary batch decompilation (a binary's wall time divided by its function
count), while the LLM coding agents are timed per function — one agentic call
each, including all their tool use (objdump runs, reasoning, retries). The
dollar figures are estimates: recorded token usage from the sample-set run,
priced at public list prices at render time — not billed amounts. - means
not applicable or no data (traditional decompilers have no per-token cost;
an unpriced model shows n/a rather than $0.00).
view
Original source next to a decompiler's output. Difficulty is derived from structural (GED) agreement across decompilers: easy — most decompilers recover the control flow perfectly; hard — the functions farthest from perfect for everyone (the old hall of shame); medium — in between. Pick a difficulty, a decompiler, and a metric to highlight.
decbench
Over the last 30 years, binary decompilers have made the steady march towards perfect decompilation: where decompilers recover the exact source code. However, that perfect has yet to be measured meaningfully, and is often defined across multiple axes.
DecBench is an experimental benchmark for comparing decompilers and modern LLMs on the task of recovering exact source code. This benchmark uses new and previously known metrics (perfect match percentage) and datasets that represent the various directions of exactness for decompilers: control flow structure, types, and precise recompilability. This benchmark is also living: as new decompiler/LLMs are released, their scores will be added to the leaderboard! Community feedback is welcome!
It is created by the Noelo Lab at the University of Georgia, led by Dr. Zion Leonahenahe Basque.
The project's code and data are open source.
Email [email protected] to get your decompiler added to the public site.
why
There have been two other academic benchmarks in the past for end-to-end decompilers: Decompile-Bench and DecompileBench (yes, I know the names are confusing). These works establish their own take on the problem, and are worth a read. Both have limitations: one relies on readability metrics (which we've shown in prior work to be flawed) the other on metrics that sacrifice correctness for other achievements (passing a subset of testcases on recompilation).
DecBench uses metrics that place correctness as a first-class citizen and attempt to measure perfection on a function-level rather than a macro level. Ideally, perfect decompilation is that which is correct. Each metric you will find here attempts to measure the correctness across three widely explored areas. Once a decompiler approaches 100% on all three metrics, you can consider that it nearly always recovers perfect decompilation (at least for this dataset!).
DecBench is also a response to static-benchmarks that often get outdated or fail to change when flaws are discovered. It is very likely there is bugs in the code that runs DecBench, or there is projects which pull too much weight than others. DecBench aims to change as the community changes: adding new decompilers, updating versions, and improving supported projects. As such, this is a living project, widely different from a paper and more similar to the popular SWEBench.
the three metrics
We define three metrics that explore the three areas we believe are representative of "perfect" decompilation.
- Code Structure
- Types (args and vars)
- Byte-match Recompilability
There are cases where these three metrics can conflict with each other.
As such, decompilers are scored by Union: the overlap where at least one of these metrics is perfect.
None of these metrics, themselves are perfect and all come with limitations, ironically. That speaks to the difficulty of measuring this field. Find the extended metrics limitations below.
Does the decompiled code branch and loop the same way the source does? We compare the control-flow graphs of the source and the decompilation with a Graph Edit Distance (GED) — the number of node/edge insertions, deletions, and substitutions needed to turn one CFG into the other.
how GED works: source → CFG → graph diff
// sum of |x[i]|
int sum_abs(int *x, int n) {
int i, s = 0;
for (i = 0; i < n; i++) {
if (x[i] < 0)
s -= x[i];
else
s += x[i];
}
return s;
}
Structural Correctness (GED): Joern lifts both the original source and each decompiler's C output to control-flow graphs, then counts the fewest node/edge edits needed to make them isomorphic — 0 means an identical shape. Only control structure is scored, so the signal is fair across decompilers.
Did the decompiler recover the right variable and argument types? We match decompiled variables against DWARF ground truth using name-independent evidence: arguments by ABI position, stack variables by calibrated offset, and remaining variables by validated instruction-address overlap. We then score the fraction recovered correctly.
how type matching works: DWARF ground truth ↔ recovered variables
Only variables carrying a DWARF location count as recoverable — fully optimized-out vars are dropped for everyone, so the denominator is identical across decompilers. Arguments match by ABI position (name-independent, so angr's a1/a2 get fair credit), stack locals by an auto-calibrated frame-offset shift (here +0x10, so ground-truth -0x18 aligns to the decompiler's -0x28), and residual variables require unambiguous validated instruction-address overlap. Names and recovered types are never correspondence evidence.
Does the decompiled code recompile to the same machine code? We run a uniform compilability fixup (define decompiler pseudo-types, strip illegal symbol-version tokens, declare missing symbols) so every decompiler gets a fair shot at building, recompile each function with the original toolchain, and compare the resulting assembly — normalizing link-time-dependent operands (call/jump targets, PC-relative offsets) so only real differences count.
The leaderboard's Compiles column reports the first half of this on its own — the share of a decompiler's output that the fixup got to build at all (before any assembly comparison). It is measured only where a matching recompiler exists (x86); ARM/PE firmware and malware abstain rather than count as failures.
how bytematch works: fixup → recompile → normalized asm diff
undefined4 scale(int a) {
uint x = a * 3;
log_val(x);
return x + limit;
}
typedefs for undefined4/uint — never rewrites logicscale:
push rbx
imul ebx, edi, 3
mov edi, ebx
call log_val
mov eax, ebx
add eax, [rip+limit]
pop rbx
ret
push rbxpush rbxlea ebx, [rdi+rdi*2]imul ebx, edi, 3mov edi, ebxmov edi, ebxcall ____call ____mov eax, ebxmov eax, ebxadd eax, [rip+____]add eax, [rip+____]pop rbxpop rbxretretcall target / [rip+disp])
✗ real difference (edit distance = changed asm lines)
Recompilation Bytematch rebuilds the decompiler's own C the SAME way the original was built — toolchain and -O*/-m* flags read from the DWARF producer — then compares assembly line by line. A compilability fixup injects only what gcc reports missing (typedefs for pseudo-types like undefined4/uint, decls for implicit functions) and never rewrites logic. Link-time-dependent operands — call/branch targets and [rip±disp] displacements — are normalized away, so an unlinked address difference is not a penalty. Type recovery is scored separately (type_match), so fixing types just to compile is fair.
metric limitations
Each metric comes with limitations, some due to the way they are measured, others due to their fundamental algorithm.
he first, and most wide-reaching limitation, is that we attempt to collect all metrics from only the decompilation text. This is to assure that all decompilers can compete on the benchmark even when they do not expose deep APIs. This also allows LLMs to compete, which may have no way to return to you something like an address mapping for a line reliably. This can inject error because things like variables may be hard to align across samples, which has been explored in prior work.
Graph Edit Distance
Every CFG pair receives an exact isomorphism test first, with no size limit, so a perfect graph is always scored correctly. Non-isomorphic graphs up to 200 nodes use the Vujosevic Janicic algorithm (VJ-GED). Like most GED algorithms, VJ-GED is an approximation and can report more distance than actually exists. Larger non-isomorphic graphs use a nonzero lower bound from their node and edge count differences.
There are other ways to inject error here.
We use Rust Joern, a Rust port of Joern's C/C++ front end, to parse the source and the decompilation of each project.
If Joern fails, we fail.
There is also ways the .i files, which we parse, can have false information left behind by the compiler.
When we sampled this process, we found it was small.
Type Edit Distance
Type recovery first has to determine which decompiled variable corresponds to which source variable. When a backend provides native pseudocode-to-instruction provenance, we use the variable's instruction addresses, plus ABI argument position and calibrated stack offsets; variable names are never evidence there. The heuristic deliberately leaves ambiguous candidates unmatched, so a backend that cannot expose sound provenance may conservatively undercount recovery.
A text-only backend can optionally report pseudocode-line-to-instruction addresses. Those addresses are checked against instruction starts in the target function and used for variable correspondence, but the backend's claimed line association cannot be independently verified. Functions without addresses use the older name-based correspondence: argument position, calibrated stack offset, then exact variable name. Name matching is weaker evidence and rewards a decompiler that happened to import debug names. The leaderboard marks agent-reported, fallback, and uncategorized historical Type percentages with an asterisk; scores and denominators are unchanged. A native row where the conservative matcher accepts no pair remains native and is not marked.
Recompilation Byte Edit Distance
The flaw here is that each function is evaluated alone. There are cases where cross-function compiler optimizations can make it impossible for a decompiler to achieve a perfect score. This is more common on the optimization dataset, and is a known limitation.
the dataset
summary
projects
Changelog
Significant changes to DecBench that introduce or update results, which can be viewable on the website.
2026-10-09
- Added Codex Astra 6 to optimized leaderboard
- Reworked CFG evaluation using rust-joern.
2026-08-28
- Added the Ventris decompiler.
2026-08-27
- Added dated scoreboard snapshots. Any page accepts
?snapshot=DD-MM-YYYYto render the numbers as they stood on that day, and/snapshots/lists them.
2026-08-08
- Update
Kunato versionv1.121, which has changed its rank. - Minor fix to GED correctness in PR #57. Changes the scores of all decompilers on structure, but has largely maintained the same order.
2026-07-27
- Added a warning about LLM based results having bias, based on Issue #43 discussion and analysis.
2026-07-25
- Fixed a caching bug in
sample-setthat prevented Codex/CC from having 3 samples graded/shown in the UI. Their scores have changed slightly. - External submission to DecBench are now open and can be done for closed source or private decompilers. See the README note for how.
2026-07-24
- Updated
aboutto include other related works and some limitations of the benchmark metrics.
2026-07-23
- DecBench v1.1
- Update
Kunato versionv1.0, which have shifted optimized results. - What was previously the
distancepage is now thedatapage and contains new info on LLM costs. - Removed
mirai-wintarget since it is not actually Windows, but just Linux binaries (which the benchmark already has).
2026-07-22
- DecBench goes live with support for 7 traditional decompilers, 2 LLMs (partial), and 3 defining metrics.
- An expanded evaluation of AI agents is planned after credits are secured for running those evaluations.
snapshots
A snapshot freezes the scoreboard on a given day, so a score you cite keeps a
stable link after the benchmark moves on. Open one by adding
?snapshot=DD-MM-YYYY to any page, or follow a date below.
Snapshots are recorded deliberately, not on a schedule — one is taken whenever a change moves published scores or breaks comparability, which is the same moment the changelog earns an entry. Use the filters to find the snapshots where a decompiler was on a particular version.
Each snapshot carries the leaderboard, metrics, data and about pages exactly as they stood. The view page is the one exception: its side-by-side source is ~31 MB per build, far too heavy to freeze per date, so it always shows live code.