use anyhow::Result;
use log::debug;
use crate::module::{Arch, Module};
pub fn get_disassembler(module: &Module) -> Result<zydis::Decoder> {
let mut decoder = match module.arch {
Arch::X64 => zydis::Decoder::new(zydis::MachineMode::LONG_64, zydis::AddressWidth::_64)?,
Arch::X32 => zydis::Decoder::new(zydis::MachineMode::LEGACY_32, zydis::AddressWidth::_32)?,
};
decoder.enable_mode(zydis::DecoderMode::MINIMAL, false)?;
decoder.enable_mode(zydis::DecoderMode::KNC, false)?;
decoder.enable_mode(zydis::DecoderMode::MPX, false)?;
decoder.enable_mode(zydis::DecoderMode::CET, false)?;
decoder.enable_mode(zydis::DecoderMode::LZCNT, false)?;
decoder.enable_mode(zydis::DecoderMode::TZCNT, false)?;
decoder.enable_mode(zydis::DecoderMode::WBNOINVD, false)?;
decoder.enable_mode(zydis::DecoderMode::CLDEMOTE, false)?;
Ok(decoder)
}
pub fn linear_disassemble<'a>(
decoder: &'a zydis::Decoder,
buf: &'a [u8],
) -> Box<dyn Iterator<Item = (usize, zydis::Result<Option<zydis::DecodedInstruction>>)> + 'a> {
let mut offset = 0usize;
let mut insn_count = 0usize;
let iter = std::iter::from_fn(move || {
if offset >= buf.len() {
debug!("decoded {} instructions", insn_count);
return None;
}
let insn_offset = offset;
let insn_buf = &buf[insn_offset..];
let insn = decoder.decode(insn_buf);
if let Ok(Some(insn)) = &insn {
offset += insn.length as usize;
insn_count += 1;
} else {
offset += 1;
}
Some((insn_offset, insn))
});
Box::new(iter)
}