|
|
|
@ -13,14 +13,9 @@ namespace vm
|
|
|
|
|
ir_builder = std::make_shared< llvm_irbuilder_t >( *llvm_ctx );
|
|
|
|
|
ir_builder->SetInsertPoint( llvm_code_blocks[ 0 ].second );
|
|
|
|
|
flags = ir_builder->CreateAlloca( ir_builder->getInt64Ty(), nullptr, "flags" );
|
|
|
|
|
stack = ir_builder->CreateAlloca( llvm::PointerType::get( ir_builder->getInt8Ty(), 0ull ), nullptr, "sp" );
|
|
|
|
|
|
|
|
|
|
create_virtual_stack();
|
|
|
|
|
for ( auto idx = 0u; idx < 21; ++idx )
|
|
|
|
|
{
|
|
|
|
|
auto val = ir_builder->CreateLoad( llvm_fptr->getArg( idx ) );
|
|
|
|
|
val->setAlignment( llvm::Align( 1 ) );
|
|
|
|
|
push( 8, val );
|
|
|
|
|
}
|
|
|
|
|
ir_builder->CreateStore( llvm_fptr->getArg( 0 ), stack );
|
|
|
|
|
create_virtual_registers();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -35,11 +30,10 @@ namespace vm
|
|
|
|
|
|
|
|
|
|
void vmp_rtn_t::create_routine( void )
|
|
|
|
|
{
|
|
|
|
|
std::vector< llvm::Type * > arg_types;
|
|
|
|
|
for ( auto idx = 0u; idx < 21; ++idx )
|
|
|
|
|
arg_types.push_back( llvm::PointerType::get( llvm::IntegerType::get( *llvm_ctx, 64 ), 0ull ) );
|
|
|
|
|
|
|
|
|
|
auto func_ty = llvm::FunctionType::get( llvm::Type::getVoidTy( *llvm_ctx ), arg_types, false );
|
|
|
|
|
// function has no arguments and returns void... maybe change this in the future as i learn
|
|
|
|
|
// more and more LLVM...
|
|
|
|
|
auto func_ty = llvm::FunctionType::get( llvm::Type::getVoidTy( *llvm_ctx ),
|
|
|
|
|
{ llvm::PointerType::getInt8PtrTy( *llvm_ctx ) }, false );
|
|
|
|
|
|
|
|
|
|
// convert the rtn_begin address to a hex string and prepend "rtn_" to it...
|
|
|
|
|
std::stringstream rtn_name;
|
|
|
|
@ -47,7 +41,6 @@ namespace vm
|
|
|
|
|
llvm_fptr = llvm::Function::Create( func_ty, llvm::GlobalValue::LinkageTypes::ExternalLinkage,
|
|
|
|
|
rtn_name.str().c_str(), *llvm_module );
|
|
|
|
|
|
|
|
|
|
llvm_fptr->setCallingConv( llvm::CallingConv::X86_FastCall );
|
|
|
|
|
for ( const auto &vmp2_code_block : vmp2_code_blocks )
|
|
|
|
|
{
|
|
|
|
|
// create basic block name... block_xxxxxxxx format...
|
|
|
|
@ -60,53 +53,36 @@ namespace vm
|
|
|
|
|
|
|
|
|
|
void vmp_rtn_t::push( std::uint8_t num_bytes, llvm_value_t *val )
|
|
|
|
|
{
|
|
|
|
|
auto spi = ir_builder->CreateLoad( ir_builder->getInt64Ty(), stack_ptr, false );
|
|
|
|
|
spi->setAlignment( llvm::Align( 1 ) );
|
|
|
|
|
|
|
|
|
|
auto new_spi = ir_builder->CreateSub( spi, llvm::ConstantInt::get( ir_builder->getInt64Ty(), num_bytes ) );
|
|
|
|
|
ir_builder->CreateStore( new_spi, stack_ptr )->setAlignment( llvm::Align( 1 ) );
|
|
|
|
|
|
|
|
|
|
auto *i64_zero = llvm::ConstantInt::get( *llvm_ctx, llvm::APInt( 64, 0 ) );
|
|
|
|
|
llvm_value_t *indices[ 2 ] = { i64_zero, new_spi };
|
|
|
|
|
auto stack_ptr = ir_builder->CreateInBoundsGEP( virtual_stack, llvm::ArrayRef< llvm_value_t * >( indices, 2 ) );
|
|
|
|
|
|
|
|
|
|
if ( num_bytes > 1 )
|
|
|
|
|
{
|
|
|
|
|
auto casted_ptr = ir_builder->CreatePointerCast(
|
|
|
|
|
stack_ptr, llvm::PointerType::get( llvm::IntegerType::get( *llvm_ctx, num_bytes * 8 ), 0 ) );
|
|
|
|
|
|
|
|
|
|
ir_builder->CreateStore( val, casted_ptr )->setAlignment( llvm::Align( 1 ) );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
ir_builder->CreateStore( val, stack_ptr )->setAlignment( llvm::Align( 1 ) );
|
|
|
|
|
// sub rsp, num_bytes
|
|
|
|
|
auto rsp_addr = ir_builder->CreateLoad( stack );
|
|
|
|
|
auto rsp_i64 = ir_builder->CreatePtrToInt( rsp_addr, ir_builder->getInt64Ty() );
|
|
|
|
|
auto sub_rsp_val = ir_builder->CreateSub( rsp_i64, ir_builder->getInt64( num_bytes ) );
|
|
|
|
|
ir_builder->CreateStore(
|
|
|
|
|
ir_builder->CreateIntToPtr( sub_rsp_val, llvm::PointerType::get( ir_builder->getInt8Ty(), 0ull ) ), stack );
|
|
|
|
|
|
|
|
|
|
// mov [rsp], val
|
|
|
|
|
rsp_addr = ir_builder->CreateLoad( stack );
|
|
|
|
|
auto rsp_cast_ptr = ir_builder->CreatePointerCast(
|
|
|
|
|
rsp_addr, llvm::PointerType::get( llvm::IntegerType::get( *llvm_ctx, num_bytes * 8 ), false ) );
|
|
|
|
|
ir_builder->CreateStore( val, rsp_cast_ptr );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
llvm_value_t *vmp_rtn_t::pop( std::uint8_t num_bytes )
|
|
|
|
|
{
|
|
|
|
|
llvm_value_t *output_value = nullptr;
|
|
|
|
|
auto current_spi = ir_builder->CreateLoad( ir_builder->getInt64Ty(), stack_ptr, false );
|
|
|
|
|
current_spi->setAlignment( llvm::Align( 1 ) );
|
|
|
|
|
|
|
|
|
|
llvm_value_t *i64_zero = llvm::ConstantInt::get( *llvm_ctx, llvm::APInt( 64, 0 ) );
|
|
|
|
|
llvm_value_t *indices[ 2 ] = { i64_zero, current_spi };
|
|
|
|
|
auto top_stack = ir_builder->CreateInBoundsGEP( virtual_stack, llvm::ArrayRef< llvm::Value * >( indices, 2 ) );
|
|
|
|
|
|
|
|
|
|
if ( num_bytes > 1 )
|
|
|
|
|
{
|
|
|
|
|
auto casted_ptr = ir_builder->CreatePointerCast(
|
|
|
|
|
top_stack, llvm::PointerType::get( llvm::IntegerType::get( *llvm_ctx, num_bytes * 8 ), 0 ) );
|
|
|
|
|
|
|
|
|
|
output_value = ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, num_bytes * 8 ), casted_ptr );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
output_value = ir_builder->CreateLoad( ir_builder->getInt8Ty(), top_stack );
|
|
|
|
|
|
|
|
|
|
static_cast< llvm::LoadInst * >( output_value )->setAlignment( llvm::Align( 1 ) );
|
|
|
|
|
auto new_spi = ir_builder->CreateAdd(
|
|
|
|
|
current_spi, llvm::ConstantInt::get( llvm::IntegerType::get( *llvm_ctx, 64 ), num_bytes ) );
|
|
|
|
|
|
|
|
|
|
ir_builder->CreateStore( new_spi, stack_ptr )->setAlignment( llvm::Align( 1 ) );
|
|
|
|
|
return output_value;
|
|
|
|
|
// mov rax, [rsp]
|
|
|
|
|
auto rsp_addr = ir_builder->CreateLoad( stack );
|
|
|
|
|
auto rsp_cast_ptr = ir_builder->CreatePointerCast(
|
|
|
|
|
rsp_addr, llvm::PointerType::get( llvm::IntegerType::get( *llvm_ctx, num_bytes * 8 ), false ) );
|
|
|
|
|
auto pop_val = ir_builder->CreateLoad( rsp_cast_ptr );
|
|
|
|
|
|
|
|
|
|
// add rsp, num_bytes
|
|
|
|
|
auto rsp_i64 = ir_builder->CreatePtrToInt( rsp_addr, ir_builder->getInt64Ty() );
|
|
|
|
|
auto sub_rsp_val = ir_builder->CreateAdd( rsp_i64, ir_builder->getInt64( num_bytes ) );
|
|
|
|
|
auto sub_rsp_val_ptr =
|
|
|
|
|
ir_builder->CreateIntToPtr( sub_rsp_val, llvm::PointerType::get( ir_builder->getInt8Ty(), 0ull ) );
|
|
|
|
|
|
|
|
|
|
ir_builder->CreateStore( sub_rsp_val_ptr, stack );
|
|
|
|
|
return pop_val;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
llvm_value_t *vmp_rtn_t::load_value( std::uint8_t byte_size, llvm_global_value_t *var )
|
|
|
|
@ -116,13 +92,9 @@ namespace vm
|
|
|
|
|
auto cast_ptr = ir_builder->CreatePointerCast(
|
|
|
|
|
var, llvm::PointerType::get( llvm::IntegerType::get( *llvm_ctx, byte_size * 8 ), 0 ) );
|
|
|
|
|
|
|
|
|
|
auto result = ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, byte_size * 8 ), cast_ptr );
|
|
|
|
|
result->setAlignment( llvm::Align( 1 ) );
|
|
|
|
|
return result;
|
|
|
|
|
return ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, byte_size * 8 ), cast_ptr );
|
|
|
|
|
}
|
|
|
|
|
auto result = ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, byte_size * 8 ), var );
|
|
|
|
|
result->setAlignment( llvm::Align( 1 ) );
|
|
|
|
|
return result;
|
|
|
|
|
return ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, byte_size * 8 ), var );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
llvm_value_t *vmp_rtn_t::load_value( std::uint8_t byte_size, llvm_alloca_inst_t *var )
|
|
|
|
@ -132,14 +104,9 @@ namespace vm
|
|
|
|
|
auto cast_ptr = ir_builder->CreatePointerCast(
|
|
|
|
|
var, llvm::PointerType::get( llvm::IntegerType::get( *llvm_ctx, byte_size * 8 ), 0 ) );
|
|
|
|
|
|
|
|
|
|
auto result = ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, byte_size * 8 ), cast_ptr );
|
|
|
|
|
result->setAlignment( llvm::Align( 1 ) );
|
|
|
|
|
return result;
|
|
|
|
|
return ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, byte_size * 8 ), cast_ptr );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto result = ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, byte_size * 8 ), var );
|
|
|
|
|
result->setAlignment( llvm::Align( 1 ) );
|
|
|
|
|
return result;
|
|
|
|
|
return ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, byte_size * 8 ), var );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
llvm_function_t *vmp_rtn_t::lift( void )
|
|
|
|
@ -164,18 +131,6 @@ namespace vm
|
|
|
|
|
return llvm_fptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void vmp_rtn_t::create_virtual_stack( void )
|
|
|
|
|
{
|
|
|
|
|
// allocate stack space...
|
|
|
|
|
virtual_stack = ir_builder->CreateAlloca( llvm::ArrayType::get( llvm::IntegerType::get( *llvm_ctx, 8 ), 1024 ),
|
|
|
|
|
nullptr, "stack" );
|
|
|
|
|
|
|
|
|
|
// allocate stack pointer...
|
|
|
|
|
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 ),
|
|
|
|
|
stack_ptr );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
llvm_value_t *vmp_rtn_t::compute_sf( std::uint8_t byte_size, llvm_value_t *val )
|
|
|
|
|
{
|
|
|
|
|
auto op_size = llvm::IntegerType::get( *llvm_ctx, byte_size * 8 );
|
|
|
|
|