A universal compiler and decompiler suite.
Given a compiled binaryB, produce sourceSsuch that compilingSreproducesBbyte for byte.
The headline property
lower_to_elf(parse(decompile_to_text(elf))) == elf-bytes
Most decompilers paraphrase. They lose the choices a compiler made — register allocation, instruction encoding, instruction order, padding, jump-table layout — and a recompile of their output is structurally similar but not identical. univdreams treats those choices as first-class information in the source language: they live in attributes and directives that pin the compiler back to the same shape on the way out.
What works today
- ELF64 and PE reader/writer with byte-identical round-trip.
- x86 (16/32/64) decode + dual-path emit (preserved bytes for round-trip; iced re-encode for analysis).
- Function discovery across
.symtab,.dynsym,.eh_frame, signatures, and a size-filling pass. - Structural lifting: if/else, switch, loops, goto + labels, calling-convention detection, prologue/epilogue codec.
- DWARF reader for typed function signatures.
- Compiler-profile defaults (MSVC
/Oy-,/Oy) auto-derive prologue/epilogue bytes from#[autogen]/#[noframe]markers.
What it looks like
A decompiled function in .ud form — structured statements alongside pinned bytes that guarantee the recompile is identical:
@addr(0x2456)
fn sub_2856() #[abi="stdcall", autogen] {
let arg_8: u32;
let edi: u32 @reg;
let esi: u32 @reg;
let ebx: u32 @reg;
IsBadWritePtr(arg_8, 24h, edi, esi) [0x8b, 0x5d, 0x08, 0x56, 0x57, ...]
if (eax != 0) return 0; [0x85, 0xc0, 0x75, 0x31]
IsBadReadPtr(arg_8, 24h) [0x6a, 0x24, 0x53, 0xff, 0x15, ...]
if (eax != 0) return 0; [0x85, 0xc0, 0x75, 0x24]
@epilogue("saves-imm", saves: [edi, esi, ebx], pop_frame, ret_imm: 0x4)
}
Try it
The browser playground runs the full pipeline in WebAssembly. Upload an ELF, PE, Mach-O, or 6502 raw image — it decompiles to .ud. Edit the source — it recompiles to bytes you can download. Same code path as the ud CLI; same round-trip guarantee.