added some more lifters... need to fix alignment... need to add RFLAGS

alloca register and also code to update its bits.... getting there!
colton
_xeroxz 3 years ago
parent 9af7ad9a93
commit 8053fca586

@ -40,14 +40,14 @@ set(CMKR_TARGET vmdevirt)
set(vmdevirt_SOURCES "") set(vmdevirt_SOURCES "")
list(APPEND vmdevirt_SOURCES list(APPEND vmdevirt_SOURCES
"src/lifters/add.cpp"
"src/lifters/lconst.cpp" "src/lifters/lconst.cpp"
"src/lifters/lreg.cpp" "src/lifters/lreg.cpp"
"src/lifters/pushvsp.cpp"
"src/lifters/read.cpp"
"src/lifters/sreg.cpp" "src/lifters/sreg.cpp"
"src/main.cpp" "src/main.cpp"
"src/vmp_rtn.cpp" "src/vmp_rtn.cpp"
"src/lifters/lconst.cpp"
"src/lifters/lreg.cpp"
"src/lifters/sreg.cpp"
"include/vm_lifters.hpp" "include/vm_lifters.hpp"
"include/vmp_rtn.hpp" "include/vmp_rtn.hpp"
) )

@ -7,7 +7,6 @@ type = "executable"
sources = [ sources = [
"src/**.cpp", "src/**.cpp",
"src/lifters/**.cpp",
"include/**.hpp", "include/**.hpp",
] ]
include-directories = [ include-directories = [

@ -1 +1 @@
Subproject commit ef9e9c1cb2f69abfc5ea070db71ef57b4316bb87 Subproject commit 16aeb2d6d48c4822b89497ad660911eb0f5e54bd

@ -23,10 +23,17 @@ namespace vmp2::lifters
const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) >; const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) >;
extern lifter_callback_t lconstq; extern lifter_callback_t lconstq;
extern lifter_callback_t lconstdwsxq;
extern lifter_callback_t pushvsp;
extern lifter_callback_t addq;
extern lifter_callback_t sregq; extern lifter_callback_t sregq;
extern lifter_callback_t lregq;
inline std::map< vm::handler::mnemonic_t, lifter_callback_t * > lifters = { { vm::handler::LCONSTQ, &lconstq }, inline std::map< vm::handler::mnemonic_t, lifter_callback_t * > lifters = {
{ vm::handler::SREGQ, &sregq } }; { vm::handler::LCONSTQ, &lconstq }, { vm::handler::LCONSTDWSXQ, &lconstdwsxq },
{ vm::handler::ADDQ, &addq }, { vm::handler::PUSHVSP, &pushvsp },
{ vm::handler::SREGQ, &sregq }, { vm::handler::LREGQ, &lregq } };
inline bool lift( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block, inline bool lift( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block,
const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder )

@ -20,26 +20,34 @@ namespace vm
class vmp_rtn_t class vmp_rtn_t
{ {
public: public:
explicit vmp_rtn_t( llvm::LLVMContext *llvm_ctx, llvm::Module *llvm_module, std::uintptr_t rtn_begin, explicit vmp_rtn_t( llvm::LLVMContext *llvm_ctx, llvm::Module *llvm_module, vm::ctx_t *vm_ctx,
std::vector< vm::instrs::code_block_t > vmp2_code_blocks ); std::uintptr_t rtn_begin, std::vector< vm::instrs::code_block_t > vmp2_code_blocks );
llvm::Function *lift( void ); llvm::Function *lift( void );
llvm::LLVMContext *llvm_ctx; llvm::LLVMContext *llvm_ctx;
vm::ctx_t *vm_ctx;
llvm::Module *llvm_module; llvm::Module *llvm_module;
std::uintptr_t rtn_begin; std::uintptr_t rtn_begin;
llvm::Function *llvm_fptr; llvm::Function *llvm_fptr;
std::shared_ptr< llvm::IRBuilder<> > ir_builder; std::shared_ptr< llvm::IRBuilder<> > ir_builder;
llvm::AllocaInst *virtual_stack, *stack_ptr; llvm::AllocaInst *virtual_stack, *stack_ptr;
std::map< ZydisRegister, llvm::Constant * > native_registers; std::map< ZydisRegister, llvm::GlobalVariable * > native_registers;
std::vector< llvm::AllocaInst * > virtual_registers; std::vector< llvm::AllocaInst * > virtual_registers;
std::vector< llvm::BasicBlock * > llvm_code_blocks; std::vector< llvm::BasicBlock * > llvm_code_blocks;
std::vector< vm::instrs::code_block_t > vmp2_code_blocks; std::vector< vm::instrs::code_block_t > vmp2_code_blocks;
void push( std::uint8_t byte_size, llvm::Value *input_val );
llvm::Value *pop( std::uint8_t byte_size );
llvm::Value *peek( std::uint8_t byte_size, std::uint8_t byte_offset = 0u );
llvm::Value *load_value( std::uint8_t byte_size, llvm::GlobalValue *global );
llvm::Value *load_value( std::uint8_t byte_size, llvm::AllocaInst *var );
private: private:
void create_native_registers( void ); void create_native_registers( void );
void create_virtual_registers( void ); void create_virtual_registers( void );
void create_routine( void ); void create_routine( void );
void create_virtual_stack( void ); void create_virtual_stack( void );
void lift_vm_entry( void );
}; };
} // namespace vm } // namespace vm

@ -0,0 +1,17 @@
#include <vm_lifters.hpp>
namespace vmp2::lifters
{
lifter_callback_t addq = [ & ]( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block,
const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) {
auto t1 = rtn->pop( 8 );
auto t2 = rtn->pop( 8 );
auto t3 = ir_builder->CreateAdd( t1, t2 );
rtn->push( 8, t1 );
rtn->push( 8, t3 );
// TODO: compute and update RFLAGS...
rtn->push( 8, rtn->load_value( 8, rtn->native_registers[ ZYDIS_REGISTER_RFLAGS ] ) );
};
}

@ -3,8 +3,12 @@
namespace vmp2::lifters namespace vmp2::lifters
{ {
lifter_callback_t lconstq = [ & ]( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block, lifter_callback_t lconstq = [ & ]( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block,
const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) { const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) {
auto push_val = llvm::ConstantInt::get( llvm::IntegerType::getInt64Ty( *rtn->llvm_ctx ), vinstr.operand.imm.u ); rtn->push( 8, llvm::ConstantInt::get( ir_builder->getInt64Ty(), vinstr.operand.imm.u ) );
};
lifter_callback_t lconstdwsxq = [ & ]( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block,
const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) {
rtn->push( 8, llvm::ConstantInt::get( ir_builder->getInt64Ty(), vinstr.operand.imm.u ) );
}; };
} } // namespace vmp2::lifters

@ -0,0 +1,10 @@
#include <vm_lifters.hpp>
namespace vmp2::lifters
{
lifter_callback_t lregq = [ & ]( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block,
const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) {
auto vreg = rtn->virtual_registers[ vinstr.operand.imm.u ? vinstr.operand.imm.u / 8 : 0 ];
rtn->push( 8, rtn->load_value( 8, vreg ) );
};
}

@ -0,0 +1,20 @@
#include <vm_lifters.hpp>
namespace vmp2::lifters
{
lifter_callback_t pushvsp = [ & ]( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block,
const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) {
// Load the current stack index into a temporary variable
auto current_stack_index =
ir_builder->CreateLoad( llvm::IntegerType::get( *rtn->llvm_ctx, 64 ), rtn->stack_ptr, false );
// Get a pointer to the top byte of the stack
llvm::Value *i64_zero = llvm::ConstantInt::get( *rtn->llvm_ctx, llvm::APInt( 64, 0 ) );
llvm::Value *indices[ 2 ] = { i64_zero, current_stack_index };
auto stack_ptr =
ir_builder->CreateInBoundsGEP( rtn->virtual_stack, llvm::ArrayRef< llvm::Value * >( indices, 2 ) );
auto stack_ptr_val = ir_builder->CreatePtrToInt( stack_ptr, ir_builder->getInt64Ty() );
rtn->push( 8, stack_ptr_val );
};
}

@ -7,16 +7,8 @@ namespace vmp2::lifters
// %vregX = %1 // %vregX = %1
lifter_callback_t sregq = [ & ]( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block, lifter_callback_t sregq = [ & ]( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block,
const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) { const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) {
auto old_sp = auto t1 = rtn->pop( 8 );
ir_builder->CreateLoad( llvm::IntegerType::get( *rtn->llvm_ctx, 64 ), rtn->stack_ptr, false, "old_sp" ); auto vreg = rtn->virtual_registers[ vinstr.operand.imm.u ? vinstr.operand.imm.u / 8 : 0 ];
ir_builder->CreateStore( t1, vreg );
auto new_sp = ir_builder->CreateSub(
old_sp, llvm::ConstantInt::get( llvm::IntegerType::get( *rtn->llvm_ctx, 64 ), 8 ), "new_sp" );
ir_builder->CreateStore( new_sp, rtn->stack_ptr );
auto top_stack =
ir_builder->CreateGEP( llvm::ArrayType::get( llvm::IntegerType::get( *rtn->llvm_ctx, 8 ), 1024 ),
rtn->virtual_stack, new_sp, "top_stack" );
}; };
} // namespace vmp2::lifters } // namespace vmp2::lifters

@ -62,8 +62,19 @@ int main( int argc, const char *argv[] )
} }
LLVMContext llvm_ctx; LLVMContext llvm_ctx;
Module llvm_module( "VMProtect 2 Static Devirtualizer", llvm_ctx ); Module llvm_module( "", llvm_ctx );
vm::vmp_rtn_t vmp_rtn( &llvm_ctx, &llvm_module, first_block->vip_begin, vmp_code_blocks ); vm::ctx_t vm_ctx( reinterpret_cast< std::uintptr_t >( file_header ) + file_header->module_offset,
file_header->image_base, file_header->module_size, file_header->vm_entry_rva );
if ( !vm_ctx.init() )
{
std::printf( "> failed to init vm::ctx_t... this can be for many reason... make sure you are using the correct "
"vmemu version for this project...\n" );
return false;
}
vm::vmp_rtn_t vmp_rtn( &llvm_ctx, &llvm_module, &vm_ctx, first_block->vip_begin, vmp_code_blocks );
vmp_rtn.lift(); vmp_rtn.lift();
} }

@ -3,13 +3,11 @@
namespace vm namespace vm
{ {
vmp_rtn_t::vmp_rtn_t( llvm::LLVMContext *llvm_ctx, llvm::Module *llvm_module, std::uintptr_t rtn_begin, vmp_rtn_t::vmp_rtn_t( llvm::LLVMContext *llvm_ctx, llvm::Module *llvm_module, vm::ctx_t *vm_ctx,
std::vector< vm::instrs::code_block_t > vmp2_code_blocks ) std::uintptr_t rtn_begin, std::vector< vm::instrs::code_block_t > vmp2_code_blocks )
: llvm_ctx( llvm_ctx ), llvm_module( llvm_module ), rtn_begin( rtn_begin ), vmp2_code_blocks( vmp2_code_blocks ) : llvm_ctx( llvm_ctx ), llvm_module( llvm_module ), vm_ctx( vm_ctx ), rtn_begin( rtn_begin ),
vmp2_code_blocks( vmp2_code_blocks )
{ {
// create native registers...
create_native_registers();
// create llvm::Function and llvm::BasicBlock's... // create llvm::Function and llvm::BasicBlock's...
create_routine(); create_routine();
@ -17,65 +15,102 @@ namespace vm
ir_builder = std::make_shared< llvm::IRBuilder<> >( *llvm_ctx ); ir_builder = std::make_shared< llvm::IRBuilder<> >( *llvm_ctx );
ir_builder->SetInsertPoint( llvm_code_blocks[ 0 ] ); ir_builder->SetInsertPoint( llvm_code_blocks[ 0 ] );
// create native registers...
create_native_registers();
// create stack and stack pointer... // create stack and stack pointer...
create_virtual_stack(); create_virtual_stack();
// lift vm enter pushes to llvm ir...
lift_vm_entry();
// create virtual registers... // create virtual registers...
create_virtual_registers(); create_virtual_registers();
} }
void vmp_rtn_t::lift_vm_entry( void )
{
for ( const auto &instr : vm_ctx->vm_entry )
{
if ( instr.instr.mnemonic == ZYDIS_MNEMONIC_PUSH )
{
// push [xxxxx] we know this is zero and the next push is the image base...
if ( instr.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY )
{
push( 8, llvm::ConstantInt::get( ir_builder->getInt64Ty(), 0ull ) );
push( 8, llvm::ConstantInt::get( ir_builder->getInt64Ty(), vm_ctx->image_base ) );
break; // dont make these if statements a switch case because we need to use this break...
}
else if ( instr.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE )
{
push( 8, llvm::ConstantInt::get( ir_builder->getInt64Ty(), instr.instr.operands[ 0 ].imm.value.u,
false ) );
}
else if ( instr.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER )
{
push( 8, load_value( 8, native_registers[ instr.instr.operands[ 0 ].reg.value ] ) );
}
}
else if ( instr.instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ )
{
// just push 0 as the value itself wont matter...
push( 8, load_value( 8, native_registers[ ZYDIS_REGISTER_RFLAGS ] ) );
}
}
}
void vmp_rtn_t::create_native_registers( void ) void vmp_rtn_t::create_native_registers( void )
{ {
native_registers[ ZYDIS_REGISTER_RAX ] = llvm_module->getOrInsertGlobal( "rax", ir_builder->getInt64Ty() );
llvm_module->getOrInsertGlobal( "rax", llvm::IntegerType::get( *llvm_ctx, 64 ) ); native_registers[ ZYDIS_REGISTER_RAX ] = llvm_module->getGlobalVariable( "rax" );
native_registers[ ZYDIS_REGISTER_RBX ] = llvm_module->getOrInsertGlobal( "rbx", ir_builder->getInt64Ty() );
llvm_module->getOrInsertGlobal( "rbx", llvm::IntegerType::get( *llvm_ctx, 64 ) ); native_registers[ ZYDIS_REGISTER_RBX ] = llvm_module->getGlobalVariable( "rbx" );
native_registers[ ZYDIS_REGISTER_RCX ] = llvm_module->getOrInsertGlobal( "rcx", ir_builder->getInt64Ty() );
llvm_module->getOrInsertGlobal( "rcx", llvm::IntegerType::get( *llvm_ctx, 64 ) ); native_registers[ ZYDIS_REGISTER_RCX ] = llvm_module->getGlobalVariable( "rcx" );
native_registers[ ZYDIS_REGISTER_RDX ] = llvm_module->getOrInsertGlobal( "rdx", ir_builder->getInt64Ty() );
llvm_module->getOrInsertGlobal( "rdx", llvm::IntegerType::get( *llvm_ctx, 64 ) ); native_registers[ ZYDIS_REGISTER_RDX ] = llvm_module->getGlobalVariable( "rdx" );
native_registers[ ZYDIS_REGISTER_RSI ] = llvm_module->getOrInsertGlobal( "rsi", ir_builder->getInt64Ty() );
llvm_module->getOrInsertGlobal( "rsi", llvm::IntegerType::get( *llvm_ctx, 64 ) ); native_registers[ ZYDIS_REGISTER_RSI ] = llvm_module->getGlobalVariable( "rsi" );
native_registers[ ZYDIS_REGISTER_RDI ] = llvm_module->getOrInsertGlobal( "rdi", ir_builder->getInt64Ty() );
llvm_module->getOrInsertGlobal( "rdi", llvm::IntegerType::get( *llvm_ctx, 64 ) ); native_registers[ ZYDIS_REGISTER_RDI ] = llvm_module->getGlobalVariable( "rdi" );
native_registers[ ZYDIS_REGISTER_RBP ] = llvm_module->getOrInsertGlobal( "rbp", ir_builder->getInt64Ty() );
llvm_module->getOrInsertGlobal( "rbp", llvm::IntegerType::get( *llvm_ctx, 64 ) ); native_registers[ ZYDIS_REGISTER_RBP ] = llvm_module->getGlobalVariable( "rbp" );
native_registers[ ZYDIS_REGISTER_RSP ] = llvm_module->getOrInsertGlobal( "rsp", ir_builder->getInt64Ty() );
llvm_module->getOrInsertGlobal( "rsp", llvm::IntegerType::get( *llvm_ctx, 64 ) ); native_registers[ ZYDIS_REGISTER_RSP ] = llvm_module->getGlobalVariable( "rsp" );
native_registers[ ZYDIS_REGISTER_R8 ] = llvm_module->getOrInsertGlobal( "r8", ir_builder->getInt64Ty() );
llvm_module->getOrInsertGlobal( "r8", llvm::IntegerType::get( *llvm_ctx, 64 ) ); native_registers[ ZYDIS_REGISTER_R8 ] = llvm_module->getGlobalVariable( "r8" );
native_registers[ ZYDIS_REGISTER_R9 ] = llvm_module->getOrInsertGlobal( "r9", ir_builder->getInt64Ty() );
llvm_module->getOrInsertGlobal( "r9", llvm::IntegerType::get( *llvm_ctx, 64 ) ); native_registers[ ZYDIS_REGISTER_R9 ] = llvm_module->getGlobalVariable( "r9" );
native_registers[ ZYDIS_REGISTER_R10 ] = llvm_module->getOrInsertGlobal( "r10", ir_builder->getInt64Ty() );
llvm_module->getOrInsertGlobal( "r10", llvm::IntegerType::get( *llvm_ctx, 64 ) ); native_registers[ ZYDIS_REGISTER_R10 ] = llvm_module->getGlobalVariable( "r10" );
native_registers[ ZYDIS_REGISTER_R11 ] = llvm_module->getOrInsertGlobal( "r11", ir_builder->getInt64Ty() );
llvm_module->getOrInsertGlobal( "r11", llvm::IntegerType::get( *llvm_ctx, 64 ) ); native_registers[ ZYDIS_REGISTER_R11 ] = llvm_module->getGlobalVariable( "r11" );
native_registers[ ZYDIS_REGISTER_R12 ] = llvm_module->getOrInsertGlobal( "r12", ir_builder->getInt64Ty() );
llvm_module->getOrInsertGlobal( "r12", llvm::IntegerType::get( *llvm_ctx, 64 ) ); native_registers[ ZYDIS_REGISTER_R12 ] = llvm_module->getGlobalVariable( "r12" );
native_registers[ ZYDIS_REGISTER_R13 ] = llvm_module->getOrInsertGlobal( "r13", ir_builder->getInt64Ty() );
llvm_module->getOrInsertGlobal( "r13", llvm::IntegerType::get( *llvm_ctx, 64 ) ); native_registers[ ZYDIS_REGISTER_R13 ] = llvm_module->getGlobalVariable( "r13" );
native_registers[ ZYDIS_REGISTER_R14 ] = llvm_module->getOrInsertGlobal( "r14", ir_builder->getInt64Ty() );
llvm_module->getOrInsertGlobal( "r14", llvm::IntegerType::get( *llvm_ctx, 64 ) ); native_registers[ ZYDIS_REGISTER_R14 ] = llvm_module->getGlobalVariable( "r14" );
native_registers[ ZYDIS_REGISTER_R15 ] = llvm_module->getOrInsertGlobal( "r15", ir_builder->getInt64Ty() );
llvm_module->getOrInsertGlobal( "r15", llvm::IntegerType::get( *llvm_ctx, 64 ) ); native_registers[ ZYDIS_REGISTER_R15 ] = llvm_module->getGlobalVariable( "r15" );
native_registers[ ZYDIS_REGISTER_RFLAGS ] = llvm_module->getOrInsertGlobal( "rflags", ir_builder->getInt64Ty() );
llvm_module->getOrInsertGlobal( "rflags", llvm::IntegerType::get( *llvm_ctx, 64 ) ); native_registers[ ZYDIS_REGISTER_RFLAGS ] = llvm_module->getGlobalVariable( "rflags" );
} }
void vmp_rtn_t::create_virtual_registers( void ) void vmp_rtn_t::create_virtual_registers( void )
@ -109,6 +144,114 @@ namespace vm
} }
} }
void vmp_rtn_t::push( std::uint8_t byte_size, llvm::Value *input_value )
{
// Load the current stack index into a temporary variable
auto current_stack_index = ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, 64 ), stack_ptr, false );
// Subtract the input value size from the current stack index
auto new_stack_index = ir_builder->CreateSub(
current_stack_index, llvm::ConstantInt::get( llvm::IntegerType::get( *llvm_ctx, 64 ), byte_size ) );
// Store the newly calculated stack index into VSP
ir_builder->CreateStore( new_stack_index, stack_ptr );
// Get a pointer to the top byte of the stack
llvm::Value *i64_zero = llvm::ConstantInt::get( *llvm_ctx, llvm::APInt( 64, 0 ) );
llvm::Value *indices[ 2 ] = { i64_zero, new_stack_index };
auto stack_ptr = ir_builder->CreateInBoundsGEP( virtual_stack, llvm::ArrayRef< llvm::Value * >( indices, 2 ) );
// Store the input value at the calculated stack address
if ( byte_size == 1 )
{
ir_builder->CreateStore( input_value, stack_ptr );
}
else
{
// Cast the pointer so the stack item width matches the width of the input value
auto casted_ptr = ir_builder->CreatePointerCast(
stack_ptr, llvm::PointerType::get( llvm::IntegerType::get( *llvm_ctx, byte_size * 8 ), 0 ) );
ir_builder->CreateStore( input_value, casted_ptr );
}
}
llvm::Value *vmp_rtn_t::pop( std::uint8_t byte_size )
{
// Load the current stack index into a temporary variable
auto current_stack_index = ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, 64 ), stack_ptr, false );
// Get a pointer to the top byte of the stack
llvm::Value *i64_zero = llvm::ConstantInt::get( *llvm_ctx, llvm::APInt( 64, 0 ) );
llvm::Value *indices[ 2 ] = { i64_zero, current_stack_index };
auto stack_ptr = ir_builder->CreateInBoundsGEP( virtual_stack, llvm::ArrayRef< llvm::Value * >( indices, 2 ) );
// Read the value at the top of the stack
llvm::Value *output_value = nullptr;
if ( byte_size == 1 )
{
output_value = ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, 8 ), stack_ptr );
}
else
{
// Cast the current stack pointer so the stack item width matches the width of the output value
auto casted_ptr = ir_builder->CreatePointerCast(
stack_ptr, llvm::PointerType::get( llvm::IntegerType::get( *llvm_ctx, byte_size * 8 ), 0 ) );
output_value = ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, byte_size * 8 ), casted_ptr );
}
// Subtract the input value size from the current stack index
auto new_stack_index = ir_builder->CreateAdd(
current_stack_index, llvm::ConstantInt::get( llvm::IntegerType::get( *llvm_ctx, 64 ), byte_size ) );
// Store the newly calculated stack index into VSP
ir_builder->CreateStore( new_stack_index, this->stack_ptr );
return output_value;
}
llvm::Value *vmp_rtn_t::peek( std::uint8_t byte_size, std::uint8_t byte_offset )
{
// Load the current stack index into a temporary variable
auto current_stack_index = ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, 64 ), stack_ptr, false );
if ( byte_offset )
{
auto t1 = ir_builder->CreateAdd(
current_stack_index, llvm::ConstantInt::get( llvm::IntegerType::get( *llvm_ctx, 64 ), byte_offset ) );
current_stack_index = ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, 64 ), t1, false );
}
// Get a pointer to the top byte of the stack + byte_offset (if any)
llvm::Value *i64_zero = llvm::ConstantInt::get( *llvm_ctx, llvm::APInt( 64, 0 ) );
llvm::Value *indices[ 2 ] = { i64_zero, current_stack_index };
auto stack_ptr = ir_builder->CreateInBoundsGEP( virtual_stack, llvm::ArrayRef< llvm::Value * >( indices, 2 ) );
if ( byte_size != 1 )
{
auto casted_ptr = ir_builder->CreatePointerCast(
stack_ptr, llvm::PointerType::get( llvm::IntegerType::get( *llvm_ctx, byte_size * 8 ), 0 ) );
return ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, byte_size * 8 ), casted_ptr );
}
else
{
return ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, byte_size * 8 ), stack_ptr );
}
}
llvm::Value *vmp_rtn_t::load_value( std::uint8_t byte_size, llvm::GlobalValue *global )
{
return ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, byte_size * 8 ), global );
}
llvm::Value *vmp_rtn_t::load_value( std::uint8_t byte_size, llvm::AllocaInst *var )
{
return ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, byte_size * 8 ), var );
}
void vmp_rtn_t::create_virtual_stack( void ) void vmp_rtn_t::create_virtual_stack( void )
{ {
// allocate stack space... // allocate stack space...
@ -117,7 +260,6 @@ namespace vm
// allocate stack pointer... // allocate stack pointer...
stack_ptr = ir_builder->CreateAlloca( llvm::IntegerType::get( *llvm_ctx, 64 ), nullptr, "sp" ); stack_ptr = ir_builder->CreateAlloca( llvm::IntegerType::get( *llvm_ctx, 64 ), nullptr, "sp" );
ir_builder->CreateStore( llvm::ConstantInt::get( llvm::IntegerType::getInt64Ty( *llvm_ctx ), 1024 ), ir_builder->CreateStore( llvm::ConstantInt::get( llvm::IntegerType::getInt64Ty( *llvm_ctx ), 1024 ),
stack_ptr ); stack_ptr );
} }
@ -131,8 +273,7 @@ namespace vm
{ {
if ( !vmp2::lifters::lift( this, vmp2_code_blocks[ idx ], vinstr, ir_builder.get() ) ) if ( !vmp2::lifters::lift( this, vmp2_code_blocks[ idx ], vinstr, ir_builder.get() ) )
{ {
std::printf( "> failed to devirtualize virtual instruction with vm handler index = %d\n", std::printf( "> failed to devirtualize virtual instruction with opcode = %d\n", vinstr.opcode );
vinstr.opcode );
llvm_module->print( llvm::outs(), nullptr ); llvm_module->print( llvm::outs(), nullptr );
return nullptr; return nullptr;

Loading…
Cancel
Save