diff --git a/CMakeLists.txt b/CMakeLists.txt index fd8c7af..ddd557c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,6 +54,7 @@ list(APPEND vmdevirt_SOURCES "src/lifters/popvsp.cpp" "src/lifters/pushvsp.cpp" "src/lifters/read.cpp" + "src/lifters/readcr8.cpp" "src/lifters/sflags.cpp" "src/lifters/shl.cpp" "src/lifters/shr.cpp" diff --git a/include/vm_lifters.hpp b/include/vm_lifters.hpp index 241fb08..9b81957 100644 --- a/include/vm_lifters.hpp +++ b/include/vm_lifters.hpp @@ -34,17 +34,18 @@ namespace vm static lifter_callback_t addq, adddw, addw; static lifter_callback_t sregq, sregdw, sregb; static lifter_callback_t lregq, lregdw; - static lifter_callback_t imulq; static lifter_callback_t pushvsp; static lifter_callback_t popvsp; static lifter_callback_t writeq, writedw; - static lifter_callback_t readq, readdw, readb; + static lifter_callback_t readq, readdw, readw, readb; static lifter_callback_t nandq, nanddw, nandb; - static lifter_callback_t shrq; + static lifter_callback_t shrq, shrdw; + static lifter_callback_t shlq; static lifter_callback_t jmp; static lifter_callback_t lflagsq; static lifter_callback_t vmexit; + static lifter_callback_t readcr8; std::map< vm::handler::mnemonic_t, lifter_callback_t * > lifters = { { vm::handler::LCONSTQ, &lconstq }, { vm::handler::LCONSTDW, &lconstdw }, @@ -58,9 +59,11 @@ namespace vm { vm::handler::ADDDW, &adddw }, { vm::handler::ADDW, &addw }, { vm::handler::SHRQ, &shrq }, + { vm::handler::SHRDW, &shrdw }, + { vm::handler::SHLQ, &shlq }, { vm::handler::IMULQ, &imulq }, - { vm::handler::PUSHVSP, &pushvsp }, - { vm::handler::POPVSP, &popvsp }, + { vm::handler::PUSHVSPQ, &pushvsp }, + { vm::handler::POPVSPQ, &popvsp }, { vm::handler::SREGQ, &sregq }, { vm::handler::SREGDW, &sregdw }, { vm::handler::SREGB, &sregb }, @@ -68,6 +71,7 @@ namespace vm { vm::handler::LREGDW, &lregdw }, { vm::handler::READQ, &readq }, { vm::handler::READDW, &readdw }, + { vm::handler::READW, &readw }, { vm::handler::READB, &readb }, { vm::handler::WRITEQ, &writeq }, { vm::handler::WRITEDW, &writedw }, @@ -75,6 +79,7 @@ namespace vm { vm::handler::NANDDW, &nanddw }, { vm::handler::NANDB, &nandb }, { vm::handler::LFLAGSQ, &lflagsq }, + { vm::handler::READCR8, &readcr8 }, { vm::handler::JMP, &jmp }, { vm::handler::VMEXIT, &vmexit } }; diff --git a/src/lifters/read.cpp b/src/lifters/read.cpp index 7dbea1e..6bf602a 100644 --- a/src/lifters/read.cpp +++ b/src/lifters/read.cpp @@ -20,6 +20,15 @@ namespace vm rtn->push( 4, t3 ); }; + lifters_t::lifter_callback_t lifters_t::readw = + [ & ]( vm::devirt_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 = ir_builder->CreateIntToPtr( t1, llvm::PointerType::get( ir_builder->getInt16Ty(), 0ull ) ); + auto t3 = ir_builder->CreateLoad( ir_builder->getInt16Ty(), t2 ); + rtn->push( 2, t3 ); + }; + lifters_t::lifter_callback_t lifters_t::readb = [ & ]( vm::devirt_t *rtn, const vm::instrs::code_block_t &vm_code_block, const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) { diff --git a/src/lifters/readcr8.cpp b/src/lifters/readcr8.cpp new file mode 100644 index 0000000..a69063b --- /dev/null +++ b/src/lifters/readcr8.cpp @@ -0,0 +1,26 @@ +#include + +namespace vm +{ + lifters_t::lifter_callback_t lifters_t::readcr8 = + [ & ]( vm::devirt_t *rtn, const vm::instrs::code_block_t &vm_code_block, const vm::instrs::virt_instr_t &vinstr, + llvm::IRBuilder<> *ir_builder ) { + llvm::Function *readcr8_intrin = nullptr; + if ( !( readcr8_intrin = rtn->llvm_module->getFunction( "readcr8" ) ) ) + { + readcr8_intrin = llvm::Function::Create( llvm::FunctionType::get( ir_builder->getInt64Ty(), false ), + llvm::GlobalValue::LinkageTypes::ExternalLinkage ); + + auto entry_block = llvm::BasicBlock::Create( ir_builder->getContext(), "", readcr8_intrin ); + auto ib = ir_builder->GetInsertBlock(); + ir_builder->SetInsertPoint( entry_block ); + auto intrin = llvm::InlineAsm::get( llvm::FunctionType::get( ir_builder->getVoidTy(), false ), + "mov rax, cr8; ret", "", false, false, llvm::InlineAsm::AD_Intel ); + ir_builder->CreateCall( intrin ); + ir_builder->CreateRetVoid(); // TODO: dont return VOID here... + ir_builder->SetInsertPoint( ib ); + } + auto t1 = ir_builder->CreateCall( readcr8_intrin ); + rtn->push( 8, t1 ); + }; +} \ No newline at end of file diff --git a/src/lifters/shl.cpp b/src/lifters/shl.cpp index e69de29..60ce8f5 100644 --- a/src/lifters/shl.cpp +++ b/src/lifters/shl.cpp @@ -0,0 +1,19 @@ +#include + +namespace vm +{ + lifters_t::lifter_callback_t lifters_t::shlq = + [ & ]( vm::devirt_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( 2 ); + auto t3 = ir_builder->CreateIntCast( t2, llvm::IntegerType::get( *rtn->llvm_ctx, 64 ), false ); + auto t4 = ir_builder->CreateShl( t1, t3 ); + + auto &vmp_rtn = rtn->vmp_rtns.back(); + // TODO: update rflags... + + rtn->push( 8, t4 ); + rtn->push( 8, rtn->load_value( 8, vmp_rtn->flags ) ); + }; +} \ No newline at end of file diff --git a/src/lifters/shr.cpp b/src/lifters/shr.cpp index 03a74f6..32800ff 100644 --- a/src/lifters/shr.cpp +++ b/src/lifters/shr.cpp @@ -2,7 +2,6 @@ namespace vm { - // our undefined behavior is that we don't model cases where the shift count is zero... llvm::Value *lifters_t::shr_flags( vm::devirt_t *rtn, std::uint8_t byte_size, llvm::Value *lhs, llvm::Value *rhs, llvm::Value *result ) { @@ -10,19 +9,18 @@ namespace vm auto msb = rtn->ir_builder->CreateLShr( lhs, ( byte_size * 8 ) - 1 ); auto cf = rtn->ir_builder->CreateZExt( msb, llvm::IntegerType::get( *rtn->llvm_ctx, 64 ) ); - auto of = - rtn->sf( byte_size, lhs ); // we reuse the compute_sf helper since the flag expression is the same + auto of = rtn->sf( byte_size, lhs ); auto sf = rtn->sf( byte_size, result ); auto zf = rtn->zf( byte_size, result ); auto pf = llvm::ConstantInt::get( llvm::IntegerType::get( *rtn->llvm_ctx, 64 ), 0 ); - return rtn->flags( cf, pf, llvm::ConstantInt::get( llvm::IntegerType::get( *rtn->llvm_ctx, 64 ), 0 ), - zf, sf, of ); + return rtn->flags( cf, pf, llvm::ConstantInt::get( llvm::IntegerType::get( *rtn->llvm_ctx, 64 ), 0 ), zf, sf, + of ); } lifters_t::lifter_callback_t lifters_t::shrq = - [ & ]( vm::devirt_t *rtn, const vm::instrs::code_block_t &vm_code_block, - const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) { + [ & ]( vm::devirt_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( 2 ); auto t3 = ir_builder->CreateIntCast( t2, llvm::IntegerType::get( *rtn->llvm_ctx, 64 ), false ); @@ -34,4 +32,19 @@ namespace vm rtn->push( 8, t4 ); rtn->push( 8, rtn->load_value( 8, vmp_rtn->flags ) ); }; + + lifters_t::lifter_callback_t lifters_t::shrdw = + [ & ]( vm::devirt_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( 4 ); + auto t2 = rtn->pop( 2 ); + auto t3 = ir_builder->CreateIntCast( t2, llvm::IntegerType::get( *rtn->llvm_ctx, 32 ), false ); + auto t4 = ir_builder->CreateLShr( t1, t3 ); + + auto &vmp_rtn = rtn->vmp_rtns.back(); + auto flags = lifters_t::shr_flags( rtn, 4, t1, t3, t4 ); + ir_builder->CreateStore( flags, vmp_rtn->flags ); + rtn->push( 4, t4 ); + rtn->push( 8, rtn->load_value( 8, vmp_rtn->flags ) ); + }; } // namespace vm \ No newline at end of file