use std::cell::RefCell;
use crate::emu::Emu;
thread_local! {
static CURRENT_EMU: RefCell<Option<*const Emu>> = RefCell::new(None);
}
pub fn with_current_emu<F, R>(f: F) -> Option<R>
where
F: FnOnce(&Emu) -> R,
{
CURRENT_EMU.with(|current| {
current
.borrow()
.and_then(|ptr| unsafe { ptr.as_ref().map(|emu| f(emu)) })
})
}
pub fn with_current_emu_mut<F, R>(f: F) -> Option<R>
where
F: FnOnce(&mut Emu) -> R,
{
CURRENT_EMU.with(|current| {
current
.borrow()
.and_then(|ptr| unsafe { (ptr as *mut Emu).as_mut().map(|emu| f(emu)) })
})
}
pub fn set_current_emu(emu: &Emu) {
CURRENT_EMU.with(|current| {
*current.borrow_mut() = Some(emu as *const _);
});
}
pub fn clear_current_emu() {
CURRENT_EMU.with(|current| {
*current.borrow_mut() = None;
});
}
pub fn is_emu_set() -> bool {
CURRENT_EMU.with(|current| current.borrow().is_some())
}
pub fn log_emu_state(emu: &mut Emu) {
log::error!("=== EMULATOR STATE ===");
log::error!("Current position: {}", emu.pos);
let color = "\x1b[0;31m";
if let Some(decoded) = emu.last_decoded {
let out = emu.format_instruction(&decoded);
log::trace!(
"{}{} 0x{:x}: {}{}",
color,
emu.pos,
emu.last_decoded_addr,
out,
emu.colors.nc
);
}
log::error!("Registers:");
if emu.cfg.arch.is_aarch64() {
let regs = emu.regs_aarch64();
for i in 0..31 {
if i % 2 == 0 && i + 1 < 31 {
log::error!(" X{:<2}: 0x{:016x} X{:<2}: 0x{:016x}", i, regs.x[i], i + 1, regs.x[i + 1]);
} else if i % 2 == 0 {
log::error!(" X{:<2}: 0x{:016x}", i, regs.x[i]);
}
}
log::error!(" SP: 0x{:016x}", regs.sp);
log::error!(" PC: 0x{:016x}", regs.pc);
log::error!(" NZCV: N={} Z={} C={} V={}", regs.nzcv.n, regs.nzcv.z, regs.nzcv.c, regs.nzcv.v);
} else {
log::error!(
" RAX: 0x{:016x} RBX: 0x{:016x}",
emu.regs().rax,
emu.regs().rbx
);
log::error!(
" RCX: 0x{:016x} RDX: 0x{:016x}",
emu.regs().rcx,
emu.regs().rdx
);
log::error!(
" RSI: 0x{:016x} RDI: 0x{:016x}",
emu.regs().rsi,
emu.regs().rdi
);
log::error!(
" RBP: 0x{:016x} RSP: 0x{:016x}",
emu.regs().rbp,
emu.regs().rsp
);
log::error!(
" R8: 0x{:016x} R9: 0x{:016x}",
emu.regs().r8,
emu.regs().r9
);
log::error!(
" R10: 0x{:016x} R11: 0x{:016x}",
emu.regs().r10,
emu.regs().r11
);
log::error!(
" R12: 0x{:016x} R13: 0x{:016x}",
emu.regs().r12,
emu.regs().r13
);
log::error!(
" R14: 0x{:016x} R15: 0x{:016x}",
emu.regs().r14,
emu.regs().r15
);
log::error!(" RIP: 0x{:016x}", emu.regs().rip);
log::error!("EFLAGS: 0x{:08x}", emu.flags().dump());
}
if let Some(decoded) = emu.last_decoded {
let out = emu.format_instruction(&decoded);
log::error!("Last instruction: {}", out);
log::error!("Instruction size: {}", emu.last_instruction_size);
}
if !emu.cfg.arch.is_aarch64() && !emu.call_stack().is_empty() {
log::error!(
"Call stack (last {} entries):",
emu.call_stack().len().min(10)
);
for (i, entry) in emu.call_stack().iter().rev().take(10).enumerate() {
log::error!(" {}: {:x}:call:{:x}", i, entry.0, entry.1);
}
}
log::error!("Tick count: {}", emu.tick);
log::error!("Base address: 0x{:x}", emu.base);
log::error!("Filename: {}", emu.filename);
log::error!("==============================");
}