Merge pull request #60 from Tai7sy/deadcode-optimization-fix

Change the stack_pointer expression to relative position in `is_used`
This commit is contained in:
Duncan Ogilvie 2022-01-11 00:36:40 +01:00 committed by GitHub
commit 4215e43876
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 138 additions and 3 deletions

View file

@ -137,7 +137,7 @@ namespace vtil::optimizer::aux
symbolic::expression exp =
local_var.mem().decay()
- local_var.at.block->sp_offset
+ symbolic::variable{ it.block->begin(), REG_SP }.to_expression()
+ rel_ptr( symbolic::variable{ it.block->begin(), REG_SP } )
- symbolic::variable{ local_var.at.block->begin(), REG_SP }.to_expression();
local_var = symbolic::variable{ it.block->begin(), { symbolic::pointer{ exp }, local_var.mem().bit_count } };
}

View file

@ -8,9 +8,13 @@ namespace registers
#if _M_X64 || __x86_64__
constexpr auto ax = X86_REG_RAX;
constexpr auto bx = X86_REG_RBX;
constexpr auto cx = X86_REG_RCX;
constexpr auto dx = X86_REG_RDX;
#elif _M_IX86 || __i386__
constexpr auto ax = X86_REG_EAX;
constexpr auto bx = X86_REG_EBX;
constexpr auto cx = X86_REG_ECX;
constexpr auto dx = X86_REG_EDX;
#endif
}
@ -40,8 +44,9 @@ DOCTEST_TEST_CASE("Optimization stack_pinning_pass")
vtil::register_desc reg_ax(vtil::register_physical, registers::ax, vtil::arch::bit_count, 0);
block->mov(reg_ax, (uintptr_t) 0);
block->mov(reg_ax, (uintptr_t)0);
block->sub(vtil::REG_SP, vtil::arch::size);
block->mov(reg_ax, (uintptr_t)0);
block->push(reg_ax);
block->pop(reg_ax);
block->mov(reg_ax, vtil::arch::size);
@ -57,7 +62,7 @@ DOCTEST_TEST_CASE("Optimization stack_pinning_pass")
vtil::logger::log(":: After:\n");
vtil::debug::dump(block->owner);
CHECK(block->size() == 5);
CHECK(block->size() == 6);
CHECK(block->sp_offset == 0);
}
@ -275,6 +280,136 @@ DOCTEST_TEST_CASE("Optimization symbolic_rewrite_pass<true>")
}
DOCTEST_TEST_CASE("Optimization dead_code_elimination_pass")
{
vtil::logger::log("\n\n>> %s \n", __FUNCTION__);
// simple single block
{
auto block = vtil::basic_block::begin( 0x1337 );
vtil::register_desc reg_eax( vtil::register_physical, registers::ax, vtil::arch::bit_count, 0 );
vtil::register_desc reg_ebx( vtil::register_physical, registers::bx, vtil::arch::bit_count, 0 );
// push eax
block->push( reg_eax );
// push ebx
block->push( reg_ebx );
// sp -= 0x10
block->shift_sp( 0x10 );
// mov eax, 0
block->mov( reg_eax, (uintptr_t)0 );
// vexit 0
block->vexit( 0ull ); // marks the end of a basic_block
vtil::logger::log( ":: Before:\n" );
vtil::debug::dump( block->owner );
vtil::optimizer::dead_code_elimination_pass{}( block->owner );
vtil::logger::log( ":: After:\n" );
vtil::debug::dump( block->owner );
// mov eax, 0
// vexit 0
CHECK( block->size() == 2 );
}
// with jmp
{
auto block1 = vtil::basic_block::begin( 0x1337 );
vtil::register_desc reg_eax( vtil::register_physical, registers::ax, vtil::arch::bit_count, 0 );
vtil::register_desc reg_ebx( vtil::register_physical, registers::bx, vtil::arch::bit_count, 0 );
{
// push eax
block1->push( reg_eax );
// push ebx
block1->push( reg_ebx );
// jmp 0x2000
block1->jmp( (uintptr_t) 0x2000 );
}
auto block2 = block1->fork( 0x2000 );
{
// sp -= 0x10
block2->shift_sp( 0x10 );
// mov eax, 0
block2->mov( reg_eax, (uintptr_t)0 );
// vexit 0
block2->vexit( 0ull ); // marks the end
}
vtil::logger::log( ":: Before:\n" );
vtil::debug::dump( block1->owner );
vtil::optimizer::dead_code_elimination_pass{}( block1->owner );
vtil::logger::log( ":: After:\n" );
vtil::debug::dump( block1->owner );
// jmp 0x2000
CHECK( block1->size() == 1 );
}
// with te jmp
{
auto block1 = vtil::basic_block::begin( 0x1337 );
vtil::register_desc reg_eax( vtil::register_physical, registers::ax, vtil::arch::bit_count, 0 );
vtil::register_desc reg_ebx( vtil::register_physical, registers::bx, vtil::arch::bit_count, 0 );
vtil::register_desc reg_ecx( vtil::register_physical, registers::cx, vtil::arch::bit_count, 0 );
{
// push eax
block1->push( reg_eax );
// push ebx
block1->push( reg_ebx );
// ecx = ecx == 0xAABB
block1->te( reg_ecx, reg_ecx, (uintptr_t)0xAABB );
// js ecx ? 0x2000, 0x3000
block1->js( reg_ecx, (uintptr_t)0x2000, (uintptr_t)0x3000 );
}
auto block2 = block1->fork( 0x2000 );
{
// sp -= 0x10
block2->shift_sp( 0x10 );
// mov eax, 0
block2->add( reg_eax, (uintptr_t)1 ); // need this to contains [shift_sp]
// vexit 0
block2->vexit( 0ull ); // marks the end
}
auto block3 = block1->fork( 0x3000 );
{
// mov ecx, [esp - 8]
block3->ldd( reg_eax, vtil::REG_SP, -8 );
// sp -= 0x10
block3->shift_sp( 0x10 );
// add eax, 1
block3->add( reg_eax, (uintptr_t)1 ); // need this to contains [shift_sp]
// vexit 0
block3->vexit( 0ull ); // marks the end
}
vtil::logger::log( ":: Before:\n" );
vtil::debug::dump( block1->owner );
vtil::optimizer::dead_code_elimination_pass{}( block1->owner );
vtil::logger::log( ":: After:\n" );
vtil::debug::dump( block1->owner );
// Cant optimize the block1 (strq) because we use it in block3
CHECK( block1->size() == 4 );
}
}
DOCTEST_TEST_CASE("Simplification")
{
vtil::logger::log("\n\n>> %s \n", __FUNCTION__);