vtil-project / VTIL-Core

Virtual-machine Translation Intermediate Language
BSD 3-Clause "New" or "Revised" License
1.35k stars 163 forks source link

Symbolic rewrite corruption #40

Open ghost opened 4 years ago

ghost commented 4 years ago

The following code is producing corrupt results:

void run_err_test_1()
{
    auto b = vtil::basic_block::begin(0);
    auto first = vtil::register_desc(vtil::register_flag::register_local, 0, 64);
    auto second_ptr = vtil::register_desc(vtil::register_flag::register_local, 5, 64);
    auto second = vtil::register_desc(vtil::register_flag::register_local, 4, 64);
    auto result = vtil::register_desc(vtil::register_flag::register_local, 6, 64);
    auto dest = vtil::register_desc(vtil::register_flag::register_local, 37, 64);

    // load first value
    b->ldd(first, X86_REG_R11, 0x0);

    // load second value
    b->mov(second_ptr, X86_REG_R11);
    b->add(second_ptr, 0x8);
    b->ldd(second, second_ptr, 0x0);

    // calculate the result
    b->mov(result, first);
    b->add(result, second);

    // store the result
    b->mov(dest, X86_REG_R11);
    b->add(dest, 0x8);
    b->str(dest, 0x0, result);

    apply_optimizations(b, 0, optimization_type::optimization_type_symbolic_rewrite_pass_forced, 0);
    vtil::debug::dump(b);
}
 | | 0000: [ PSEUDO ]     +0x0     movq     t0           r11
 | | 0001: [ PSEUDO ]     +0x0     lddq     t1           t0           0x0
 | | 0002: [ PSEUDO ]     +0x0     movq     t2           t0
 | | 0003: [ PSEUDO ]     +0x0     addq     t2           0x8
 | | 0004: [ PSEUDO ]     +0x0     lddq     t3           t0           0x8
 | | 0005: [ PSEUDO ]     +0x0     movq     t4           t1
 | | 0006: [ PSEUDO ]     +0x0     addq     t4           t3
 | | 0007: [ PSEUDO ]     +0x0     movq     t0           t1
 | | 0008: [ PSEUDO ]     +0x0     movq     t5           t2
 | | 0009: [ PSEUDO ]     +0x0     movq     t4           t3
 | | 0010: [ PSEUDO ]     +0x0     movq     t6           t4
 | | 0011: [ PSEUDO ]     +0x0     movq     t37          t2
 | | 0012: [ PSEUDO ]     +0x0     strq     t0           0x8          t4

After a bit of messing around, I've narrowed down the cause to the register naming. Rewriting all register names to a higher index produces the following instead:

 | | 0000: [ PSEUDO ]     +0x0     movq     t0           r11
 | | 0001: [ PSEUDO ]     +0x0     lddq     t1           t0           0x0
 | | 0002: [ PSEUDO ]     +0x0     movq     t2           t0
 | | 0003: [ PSEUDO ]     +0x0     addq     t2           0x8
 | | 0004: [ PSEUDO ]     +0x0     lddq     t3           t0           0x8
 | | 0005: [ PSEUDO ]     +0x0     movq     t4           t1
 | | 0006: [ PSEUDO ]     +0x0     addq     t4           t3
 | | 0007: [ PSEUDO ]     +0x0     movq     t1500        t1
 | | 0008: [ PSEUDO ]     +0x0     movq     t1501        t2
 | | 0009: [ PSEUDO ]     +0x0     movq     t1502        t3
 | | 0010: [ PSEUDO ]     +0x0     movq     t1503        t4
 | | 0011: [ PSEUDO ]     +0x0     movq     t1504        t2
 | | 0012: [ PSEUDO ]     +0x0     strq     t0           0x8          t4

The pass appears to be restoring to the original registers, and is clobbering them in the process.

can1357 commented 4 years ago

Could you show apply_optimizations? If you are re-using the same optimizer (structure) instance that could be causing it.