libmwemu 0.24.3

x86 32/64bits and system internals emulator, for securely emulating malware and other stuff.
Documentation
use iced_x86::{Decoder, DecoderOptions};

use crate::debug::console::Console;
use crate::err::MwemuError;
use crate::windows::constants;

use super::Emu;

impl Emu {
    pub(crate) fn fill_code_block(
        &mut self,
        pc: u64,
        block: &mut Vec<u8>,
    ) -> Result<(), MwemuError> {
        let code = match self.maps.get_mem_by_addr(pc) {
            Some(code) => code,
            None => {
                log::trace!("code flow to unmapped address 0x{:x}", pc);
                Console::spawn_console(self);
                return Err(MwemuError::new("cannot read program counter"));
            }
        };

        let block_slice = code.read_bytes(pc, constants::BLOCK_LEN);
        if block_slice.len() != block.len() {
            block.resize(block_slice.len(), 0);
        }
        block.clone_from_slice(block_slice);

        Ok(())
    }

    pub(crate) fn ensure_instruction_cache_populated(
        &mut self,
        pc: u64,
        block: &[u8],
        arch_bits: u32,
        is_aarch64: bool,
    ) -> Result<(), MwemuError> {
        let cache_hit = match &mut self.arch_state {
            super::ArchState::X86 {
                instruction_cache, ..
            } => instruction_cache.lookup_entry(pc, 0),
            super::ArchState::AArch64 {
                instruction_cache, ..
            } => instruction_cache.lookup_entry(pc, 0),
        };

        if cache_hit {
            return Ok(());
        }

        if !is_aarch64 {
            let zeros = block.iter().take_while(|&&b| b == 0).count();
            if !self.cfg.allow_empty_code_blocks && zeros > 100 {
                if self.cfg.verbose > 0 {
                    log::trace!("{} empty code block at 0x{:x}", self.pos, pc);
                }
                return Err(MwemuError::new("empty code block"));
            }
        }

        if block.is_empty() {
            return Err(MwemuError::new("cannot read code block, weird address."));
        }

        match &mut self.arch_state {
            super::ArchState::X86 {
                instruction_cache, ..
            } => {
                let mut decoder = Decoder::with_ip(arch_bits, block, pc, DecoderOptions::NONE);
                self.rep = None;
                let addition = block.len().min(16);
                instruction_cache.insert_from_decoder(&mut decoder, addition, pc);
            }
            super::ArchState::AArch64 {
                instruction_cache, ..
            } => {
                instruction_cache.insert_from_block(block, pc);
            }
        }

        Ok(())
    }

    pub(crate) fn instruction_cache_can_decode(&self) -> bool {
        match &self.arch_state {
            super::ArchState::X86 {
                instruction_cache, ..
            } => instruction_cache.can_decode(),
            super::ArchState::AArch64 {
                instruction_cache, ..
            } => instruction_cache.can_decode(),
        }
    }
}