hypervisor: emulator: Format instructions on error paths

Formatting instructions might be costly, so we only want to do that on
the emulation error paths.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
This commit is contained in:
Samuel Ortiz 2020-12-01 00:00:53 +01:00
parent 3fa6e17cc4
commit 15f0451c34
4 changed files with 28 additions and 4 deletions

View File

@ -28,7 +28,7 @@ features = ["elf", "bzimage"]
[dependencies.iced-x86]
version = "1.9.1"
default-features = false
features = ["std", "decoder", "op_code_info", "instr_info"]
features = ["std", "decoder", "op_code_info", "instr_info", "fast_fmt"]
[dev-dependencies]
env_logger = "0.8.2"

View File

@ -76,6 +76,9 @@ pub enum EmulationError<T: Debug> {
#[error("Platform emulation error: {0}")]
PlatformEmulationError(PlatformError),
#[error(transparent)]
EmulationError(#[from] anyhow::Error),
}
/// The PlatformEmulator trait emulates a guest platform.

View File

@ -114,3 +114,16 @@ macro_rules! insn_add {
$insn_map.add_insn(Code::$code, Box::new($mnemonic::$code {}));
};
}
macro_rules! insn_format {
($insn:ident) => {{
let mut output = String::new();
let mut formatter = FastFormatter::new();
formatter
.options_mut()
.set_space_after_operand_separator(true);
formatter.format(&$insn, &mut output);
output
}};
}

View File

@ -12,6 +12,7 @@ use crate::arch::x86::regs::*;
use crate::arch::x86::*;
use crate::arch::x86::{Exception, SegmentRegisterOps};
use crate::x86_64::{SegmentRegister, SpecialRegisters, StandardRegisters};
use anyhow::Context;
use iced_x86::*;
#[macro_use]
@ -551,7 +552,8 @@ impl<'a, T: CpuStateManager> Emulator<'a, T> {
decoder.decode_out(&mut insn);
if decoder.last_error() != DecoderError::None {
return Err(EmulationError::InstructionFetchingError(anyhow!(
"{:#x?}", insn
"{:#x?}",
insn_format!(insn)
)));
}
@ -563,9 +565,15 @@ impl<'a, T: CpuStateManager> Emulator<'a, T> {
.instructions
.get(&insn.code())
.ok_or_else(|| {
EmulationError::UnsupportedInstruction(anyhow!("{:?}", insn.mnemonic()))
EmulationError::UnsupportedInstruction(anyhow!(
"{:#x?} {:?} {:?}",
insn_format!(insn),
insn.mnemonic(),
insn.code()
))
})?
.emulate(&insn, &mut state, self.platform)?;
.emulate(&insn, &mut state, self.platform)
.context(anyhow!("Failed to emulate {:#x?}", insn_format!(insn)))?;
last_decoded_ip = decoder.ip();
num_insn_emulated += 1;