|
|
|
#pragma once
|
|
|
|
#include <vmprofiler.hpp>
|
|
|
|
|
|
|
|
#include "llvm/IR/BasicBlock.h"
|
|
|
|
#include "llvm/IR/Constants.h"
|
|
|
|
#include "llvm/IR/DerivedTypes.h"
|
|
|
|
#include "llvm/IR/Function.h"
|
|
|
|
#include "llvm/IR/IRBuilder.h"
|
|
|
|
#include "llvm/IR/IRPrintingPasses.h"
|
|
|
|
#include "llvm/IR/LLVMContext.h"
|
|
|
|
#include "llvm/IR/Module.h"
|
|
|
|
#include "llvm/IR/PassManager.h"
|
|
|
|
#include "llvm/IR/Type.h"
|
|
|
|
#include "llvm/IR/Verifier.h"
|
|
|
|
#include "llvm/Pass.h"
|
|
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
|
|
|
|
namespace vm
|
|
|
|
{
|
|
|
|
// Obsessive-compulsive disorder is characterized by unreasonable
|
|
|
|
// thoughts and fears (obsessions) that lead to compulsive behaviors.
|
|
|
|
using llvm_type_t = llvm::Type;
|
|
|
|
using llvm_value_t = llvm::Value;
|
|
|
|
using llvm_module_t = llvm::Module;
|
|
|
|
using llvm_context_t = llvm::LLVMContext;
|
|
|
|
using llvm_function_t = llvm::Function;
|
|
|
|
using llvm_irbuilder_t = llvm::IRBuilder<>;
|
|
|
|
using llvm_alloca_inst_t = llvm::AllocaInst;
|
|
|
|
using llvm_basic_block_t = llvm::BasicBlock;
|
|
|
|
using llvm_global_value_t = llvm::GlobalValue;
|
|
|
|
|
|
|
|
class vmp_rtn_t
|
|
|
|
{
|
|
|
|
friend class lifters_t;
|
|
|
|
|
|
|
|
public:
|
|
|
|
explicit vmp_rtn_t( llvm_context_t *llvm_ctx, llvm_module_t *llvm_module, vm::ctx_t *vm_ctx,
|
|
|
|
std::uintptr_t rtn_begin, std::vector< vm::instrs::code_block_t > vmp2_code_blocks );
|
|
|
|
|
|
|
|
llvm_function_t *lift( void );
|
|
|
|
|
|
|
|
private:
|
|
|
|
llvm_context_t *llvm_ctx;
|
|
|
|
llvm_module_t *llvm_module;
|
|
|
|
llvm_function_t *llvm_fptr;
|
|
|
|
llvm_alloca_inst_t *virtual_stack, *stack_ptr, *flags;
|
|
|
|
|
|
|
|
vm::ctx_t *vm_ctx;
|
|
|
|
std::uintptr_t rtn_begin;
|
|
|
|
std::shared_ptr< llvm_irbuilder_t > ir_builder;
|
|
|
|
|
|
|
|
std::map< zydis_register_t, llvm_global_value_t * > native_registers;
|
|
|
|
std::vector< llvm_alloca_inst_t * > virtual_registers;
|
|
|
|
std::vector< std::pair< std::uintptr_t, llvm_basic_block_t * > > llvm_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_global_value_t *global );
|
|
|
|
llvm::Value *load_value( std::uint8_t byte_size, llvm_alloca_inst_t *var );
|
|
|
|
|
|
|
|
llvm_value_t *compute_sf( std::uint8_t byte_size, llvm_value_t *val );
|
|
|
|
llvm_value_t *compute_zf( std::uint8_t byte_size, llvm_value_t *val );
|
|
|
|
llvm_value_t *compute_pf( std::uint8_t byte_size, llvm_value_t *val );
|
|
|
|
llvm_value_t *combine_flags( llvm_value_t *cf, llvm_value_t *pf, llvm_value_t *af, llvm_value_t *zf,
|
|
|
|
llvm_value_t *sf, llvm_value_t *of );
|
|
|
|
void create_native_registers( void );
|
|
|
|
void create_virtual_registers( void );
|
|
|
|
void create_routine( void );
|
|
|
|
void create_virtual_stack( void );
|
|
|
|
void lift_vm_entry( void );
|
|
|
|
};
|
|
|
|
} // namespace vm
|