ExeBench-FHD: Addressing Fidelity Issues in Decompiler Evaluation
Organizations: Singapore Institute of Technology · A*STAR Institute of Advanced Intelligence and Computing
Abstract
ExeBench is one of the most widely used benchmarks for evaluating LLM-based decompilers. We analyze ExeBench and identify nine issues that affect how faithfully a test measures a decompiler. Three of them prevent LLM decompilers from recovering C code from ExeBench's function. These are ambiguous parameter order when integer and floating-point types are mixed, unused parameters that optimized assembly may drop, and constants stored outside the function's assembly code. Six more affect test validity: non-void functions without a return, placeholder types, static or inline functions removed by the optimizer, functions named main, trivial bodies and truncated definitions. We present ExeBench-FHD, a backward-compatible revision of ExeBench that adds 16 new fields: call-site assembly, data sections, test wrappers, linked-binary disassembly and five warning flags. In ExeBench, 38.9% of functions have at least one of the five flags; dropping records with any of the four warning flags (all except unused_param, which marks functions that the new wrappers make evaluable) keeps 63.9% of the corpus. In an evaluation at -O2 on four architectures, the new fields raise GPT 6 Sol's re-execution rate by up to 26.5%, 19.1% and 21.0% on functions that read data sections, mix parameter types and have unused parameters, respectively.
Figures & tables
| Split | Functions |
| train_not_compilable | 715,700 |
| train_real_compilable | 885,074 |
| train_synth_compilable | 4,159,373 |
| train_real_simple_io | 42,769 |
| train_synth_simple_io | 640,116 |
| train_synth_rich_io | 107,250 |
| ID | Issue | Corpus % | test_real % |
| P1 | Mixed int/float parameters | 1.46 | 11.48 |
| P2 | Unused parameter | 7.56 | 7.40 |
| P3 | Reads a data section ( -O2 ) | 16.18 | 16.31 |
| P4 | Non-void without return | 1.73 | 0.19 |
| P5 | Dummy UDT dependency | 9.27 | 0.52 |
| P6 | static / inline definition | 36.31 | 28.73 |
| Arch. | int | float |
| x86 | stack | stack |
| x86-64 | rdi,rsi,rdx,rcx,r8,r9 | xmm0 - xmm7 |
| ARM32 | r0 - r3 | s0 - s15 |
| ARM64 | x0 - x7 | s0 - s7 |
| Field | Type | Issue |
| func_call | dict | P1 |
| unused_param | bool | P2 |
| opt_real_exe_wrapper opt_angha_exe_wrapper | str | P2 |
| data_section | dict | P3 |
| no_return | bool | P4 |
| dummy_udt | bool | P5 |
| Split | x86 | x86-64 | ARM32 | ARM64 |
| test_real | 9.4 | 15.8 | 2.5 | 5.9 |
| test_synth | 27.6 | 28.3 | 26.9 | 27.6 |
| valid_real | 10.2 | 16.5 | 3.0 | 6.5 |
| valid_synth | 25.9 | 26.5 | 25.2 | 25.8 |
| train_real_compilable | 16.9 | 22.2 | 18.9 | 20.0 |
| train_synth_compilable | 16.4 | 17.4 | 16.6 | 17.0 |
| Subset | x86-64 | x86 | ARM64 | ARM32 |
| Non-empty data sec. (P3) | +19.5 | +18.1 | +26.5 | +10.0 |
| Mixed param. types (P1) | +17.0 | +9.8 | +19.1 | +12.5 |
| Unused param. (P2) | +17.6 | +18.0 | +17.1 | +21.0 |
Appendix figures & tables20 assets
Supplementary material from the paper’s appendix.
Appendix
| Field | Origin | Issue |
| asm | ExeBench | — |
| real_iospec , angha_iospec | ExeBench | — |
| real_io_pairs , angha_io_pairs | ExeBench | — |
| func_call | New | P1 |
| func_call_errors | New | P1 (diag.) |
| data_section | New | P3 |
| Field | Origin | Issue |
| path , ref , fname , doc | ExeBench | — |
| func_def , func_head , func_head_types | ExeBench | — |
| real_deps , angha_deps | ExeBench | — |
| real_error , angha_error | ExeBench | — |
| real_io_error , angha_io_error | ExeBench | — |
| real_exe_wrapper , angha_exe_wrapper | ExeBench | — |
| Field | Origin | Issue |
| real_io_pairs_are_trivial | ExeBench | — |
| angha_io_pairs_are_trivial | ExeBench | — |
| signature (list of strings) | ExeBench | — |
| unused_param | New | P2 |
| no_return | New | P4 |
| dummy_udt | New | P5 |
| Split | Mixed types | Mismatch |
| test_real | 11.5 | 3.8 |
| test_synth | 3.3 | 0.1 |
| valid_real | 11.1 | 4.2 |
| valid_synth | 3.2 | 0.2 |
| train_real_compilable | 2.1 | 1.9 |
| train_synth_compilable | 1.4 | 0.9 |
| Split | no_ret. | dummy | trivial | trunc. | unused |
| test_real | 0.2 | 0.5 | 27.4 | 0.0 | 7.4 |
| test_synth | 0.3 | 6.2 | 31.7 | 0.0 | 5.9 |
| valid_real | 0.2 | 0.4 | 25.4 | 0.0 | 7.3 |
| valid_synth | 0.3 | 6.0 | 33.0 | 0.0 | 6.2 |
| train_real_compilable | 1.5 | 4.1 | 36.1 | 0.07 | 6.2 |
| train_synth_compilable | 0.7 | 11.2 | 24.7 | 0.03 | 6.9 |
| Split | Records | Disassembled | 1 of 20 (%) | All 20 (%) |
| test_real | 2,134 | 2,108 | 98.8 | 85.8 |
| test_synth | 5,000 | 2,269 | 45.4 | 44.8 |
| valid_real | 2,133 | 2,107 | 98.8 | 86.2 |
| valid_synth | 5,000 | 2,225 | 44.5 | 43.8 |
| train_real_compilable | 885,074 | 534,111 | 60.3 | 49.4 |
| train_synth_compilable | 4,159,373 | 1,384,908 | 33.3 | 31.4 |
| Split | no_ret. | dummy | trivial | trunc. | unused |
| test_real | 0.2 / 0.2 | 0.5 / 0.5 | 27.4 / 27.5 | 0.0 / 0.0 | 7.4 / 7.3 |
| test_synth | 0.3 / 0.4 | 6.2 / 3.5 | 31.7 / 46.3 | 0.0 / 0.0 | 5.9 / 6.9 |
| valid_real | 0.2 / 0.2 | 0.4 / 0.4 | 25.4 / 25.3 | 0.0 / 0.0 | 7.3 / 7.3 |
| valid_synth | 0.3 / 0.2 | 6.0 / 4.0 | 33.0 / 48.4 | 0.0 / 0.0 | 6.2 / 8.2 |
| train_real_compilable | 1.5 / 1.6 | 4.1 / 1.9 | 36.1 / 39.3 | 0.07 / 0.03 | 6.2 / 7.9 |
| train_synth_compilable | 0.7 / 1.0 | 11.2 / 5.1 | 24.7 / 35.6 | 0.03 / 0.02 | 6.9 / 8.0 |
| Flag pair | Records | % |
| trivial & unused_param | 229,487 | 3.496 |
| dummy_udt & trivial | 160,783 | 2.449 |
| dummy_udt & unused_param | 112,514 | 1.714 |
| no_return & trivial | 44,305 | 0.675 |
| no_return & unused_param | 41,105 | 0.626 |
| trivial & truncated | 9,044 | 0.138 |
| Split | Raw | Dropped | Kept (%) |
| test_real | 2,134 | 592 | 72.26 |
| test_synth | 5,000 | 1,847 | 63.06 |
| valid_real | 2,133 | 547 | 74.36 |
| valid_synth | 5,000 | 1,902 | 61.96 |
| Split | Raw | After filter (%) |
| test_real | 2,134 | 72.21 |
| test_synth | 5,000 | 62.90 |
| valid_real | 2,133 | 74.31 |
| valid_synth | 5,000 | 61.72 |
| train_real_compilable | 885,074 | 60.73 |
| train_synth_compilable | 4,159,373 | 66.06 |
| Split | Raw | dummy_udt (%) | All four flags (%) | func_call elig. (%) | data_section elig. (%) | IO-executable (%) |
| test_real | 2,134 | 99.48 | 72.21 | 92.74 | 98.78 | 100.00 |
| test_synth | 5,000 | 93.78 | 62.90 | 37.82 | 44.58 | 100.00 |
| valid_real | 2,133 | 99.58 | 74.31 | 92.36 | 98.78 | 100.00 |
| valid_synth | 5,000 | 93.96 | 61.72 | 36.82 | 43.94 | 100.00 |
| train_real_compilable | 885,074 | 95.90 | 60.73 | 44.29 | 58.47 | 16.11 |
| train_synth_compilable | 4,159,373 | 88.78 | 66.06 | 20.22 | 32.69 | 17.94 |
| Arch | Test form | Re-compile (%) | Re-execute (%) | ||||
| asm | +ctx | asm | +ctx | ||||
| x86-64 | original | 153 | 30.7 | 77.1 | 29.4 | 75.2 | +45.8 |
| ExeBench-FHD | 153 | 82.4 | 83.0 | 63.4 | 81.0 | +17.6 | |
| x86 | original | 144 | 31.2 | 64.6 | 29.2 | 63.2 | +34.0 |
| ExeBench-FHD | 144 | 84.0 | 84.7 | 63.9 | 81.9 | +18.0 | |
| ARM64 | original | 152 | 31.6 | 72.4 | 30.9 | 69.7 | +38.8 |
| Arch | Re-compile (%) | Re-execute (%) | ||||
| asm | +ctx | asm | +ctx | |||
| x86-64 | 1857 | 88.0 | 89.8 | 80.5 | 84.1 | +3.6 |
| x86 | 1657 | 86.9 | 86.8 | 76.0 | 78.8 | +2.8 |
| ARM64 | 1773 | 86.5 | 87.9 | 73.8 | 76.8 | +3.0 |
| ARM32 | 1752 | 79.9 | 81.4 | 73.6 | 75.1 | +1.5 |
| Functions evaluable on all four architectures | ||||||
| Arch | Re-compile (%) | Re-execute (%) | ||||
| asm | +ctx | asm | +ctx | |||
| x86-64 | 287 | 82.9 | 87.8 | 56.1 | 75.6 | +19.5 |
| x86 | 177 | 83.6 | 85.3 | 42.9 | 61.0 | +18.1 |
| ARM64 | 117 | 85.5 | 88.9 | 47.0 | 73.5 | +26.5 |
| ARM32 | 50 | 72.0 | 74.0 | 46.0 | 56.0 | +10.0 |
| Arch | Re-compile (%) | Re-execute (%) | ||||
| asm | +ctx | asm | +ctx | |||
| x86-64 | 199 | 62.8 | 75.9 | 52.8 | 69.8 | +17.0 |
| x86 | 195 | 88.7 | 91.3 | 65.6 | 75.4 | +9.8 |
| ARM64 | 199 | 62.3 | 81.9 | 44.7 | 63.8 | +19.1 |
| ARM32 | 199 | 59.8 | 73.4 | 51.3 | 63.8 | +12.5 |
| Arch | Compile fail (%) | Link fail (%) | OK (%) |
| x86 | 15.69 | 53.62 | 30.69 |
| x86-64 | 11.86 | 55.04 | 33.10 |
| ARM32 | 12.26 | 54.94 | 32.80 |
| ARM64 | 12.25 | 54.97 | 32.78 |
| Has data (%) | Build fails (%) | |||||||
| Split | x86 | x86-64 | ARM32 | ARM64 | x86 | x86-64 | ARM32 | ARM64 |
| test_real | 9.4 | 15.8 | 2.5 | 5.9 | 9.6 | 0.6 | 4.5 | 4.5 |
| test_synth | 27.6 | 28.3 | 26.9 | 27.6 | 55.1 | 54.6 | 54.7 | 54.7 |
| valid_real | 10.2 | 16.5 | 3.0 | 6.5 | 9.4 | 1.1 | 5.5 | 5.5 |
| valid_synth | 25.9 | 26.5 | 25.2 | 25.8 | 55.8 | 55.4 | 55.4 | 55.4 |
| train_real_compilable | 16.9 | 22.2 | 18.9 | 20.0 | 48.9 | 39.8 | 41.4 | 41.4 |
| Split | All 4 | 2–3 of 4 | 1 of 4 | Failed on all | Skipped |
| test_real | 80.6 | 10.7 | 1.4 | 7.1 | 0.1 |
| test_synth | 1.1 | 36.7 | 0.1 | 53.6 | 8.6 |
| valid_real | 80.2 | 10.6 | 1.6 | 7.6 | 0.0 |
| valid_synth | 1.0 | 35.8 | 0.0 | 53.3 | 9.9 |
| train_real_compilable | 33.7 | 9.9 | 0.6 | 39.5 | 16.2 |
| train_synth_compilable | 3.4 | 16.8 | 0.1 | 62.9 | 16.8 |
| Largest instance (lines) | Records |
| 301–1,000 | 45,969 |
| 1,001–5,000 | 4,135 |
| 5,001–10,000 | 220 |
| 10,001–50,000 | 113 |
| 50,001–100,000 | 28 |
| 100,001–500,000 | 10 |
Benchmark Design
Benchmark design creates tasks, datasets, metrics, and protocols that make AI capabilities measurable and comparisons credible.
See all 394 papers