Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Backend Comparison

The --decompile flag runs the full LLVM pipeline: PVM bytecode is lifted to LLVM IR, then decompiled to C code. Several backends are available for the final decompilation step.

Available Backends

BackendFlagStatus
builtin--backend=builtinWorks locally, no extra dependencies
retdec--backend=retdecRequires RetDec installation
rellic--backend=rellicRequires Rellic installation
rellic-docker--backend=rellic-dockerRequires Docker with Rellic image
llvm-cbe--backend=llvm-cbeRequires LLVM C Backend Emitter

For most users, builtin is the easiest option since it needs no external tools.

Example: builtin Backend

Using simple-add.pvm, a minimal hand-crafted PVM binary (21 bytes, 6 instructions):

./target/release/pvm-decompiler --decompile --backend=builtin examples/compiled/simple-add.pvm
int64_t main(void) {
    int64_t r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12;
    r0 = r1 = r2 = r3 = r4 = r5 = r6 = r7 = r8 = r9 = r10 = r11 = r12 = 0;
    goto bb_0000;
bb_0000:
    r0 = 42;
    r1 = 100;
    r2 = %t5;
    goto bb_000f;
bb_000f:
    return %t6;
}

The C output preserves the basic block structure from the LLVM IR. Variables like %t5 are LLVM temporaries that the backend has not yet resolved into concrete expressions. This is expected for the builtin backend – it prioritizes correctness over readability.

Example: br-table Through builtin

A larger example showing how the builtin backend handles branching:

./target/release/pvm-decompiler --decompile --backend=builtin examples/compiled/br-table.pvm

The output is a C function with labeled basic blocks (bb_0000, bb_000a, etc.), goto statements for control flow, and if/else for conditional branches. The switch table from the source becomes a chain of conditional jumps.

When to Use Which Output

GoalRecommended mode
Quick understanding of program logicDefault pseudo-code (no flags)
Better variable names for review--refine
Integration with C toolchains--decompile --backend=builtin
Deep analysis of the binary--verbose or --debug
Generating LLVM IR for custom pipelines--llvm

The default pseudo-code mode is usually the most readable. Use --decompile when you need actual C code, for example to compile and test the decompiled output.