#![allow(clippy::std_instead_of_core)]
use core::ffi::c_void;
#[cfg(target_os = "linux")]
use core::ops::BitAnd;
use num_enum::{IntoPrimitive, TryFromPrimitive};
use strum_macros::EnumIter;
mod bindings;
pub use bindings::*;
#[cfg(feature = "usermode")]
mod usermode;
#[cfg(feature = "usermode")]
pub use usermode::*;
#[macro_export]
macro_rules! extern_c_checked {
() => {};
($visibility:vis fn $c_fn:ident($($param_ident:ident : $param_ty:ty),*) $( -> $ret_ty:ty )?; $($tail:tt)*) => {
paste! {
static [<__ $c_fn:upper __>]: unsafe extern "C" fn($($param_ty),*) $( -> $ret_ty )? = $c_fn;
}
unsafe extern "C" {
$visibility fn $c_fn($($param_ident : $param_ty),*) $( -> $ret_ty )?;
}
extern_c_checked!($($tail)*);
};
($visibility:vis static $c_var:ident : $c_var_ty:ty; $($tail:tt)*) => {
paste! {
#[expect(non_camel_case_types)]
#[expect(unused)]
struct [<__ $c_var:upper _STRUCT__>] { member: *const $c_var_ty }
unsafe impl Sync for [<__ $c_var:upper _STRUCT__>] {}
#[expect(unused_unsafe)]
static [<__ $c_var:upper __>]: [<__ $c_var:upper _STRUCT__>] = unsafe { [<__ $c_var:upper _STRUCT__>] { member: &raw const $c_var } };
}
unsafe extern "C" {
$visibility static $c_var: $c_var_ty;
}
extern_c_checked!($($tail)*);
};
($visibility:vis static mut $c_var:ident : $c_var_ty:ty; $($tail:tt)*) => {
paste! {
#[expect(non_camel_case_types)]
#[expect(unused)]
struct [<__ $c_var:upper _STRUCT__>] { member: *const $c_var_ty }
unsafe impl Sync for [<__ $c_var:upper _STRUCT__>] {}
#[expect(unused_unsafe)]
static mut [<__ $c_var:upper __>]: [<__ $c_var:upper _STRUCT__>] = unsafe { [<__ $c_var:upper _STRUCT__>] { member: &raw const $c_var } };
}
unsafe extern "C" {
$visibility static mut $c_var: $c_var_ty;
}
extern_c_checked!($($tail)*);
};
}
pub type CPUStatePtr = *mut CPUState;
pub type CPUArchStatePtr = *mut CPUArchState;
pub type ExitReasonPtr = *mut libafl_exit_reason;
pub type GuestLong = target_long;
pub type GuestUlong = target_ulong;
pub type GuestUsize = target_ulong;
pub type GuestIsize = target_long;
pub type GuestAddr = vaddr;
pub type GuestPhysAddr = hwaddr;
pub type GuestVirtAddr = vaddr;
pub type GuestHwAddrInfo = qemu_plugin_hwaddr;
#[cfg(feature = "usermode")]
pub type GuestAbiLong = abi_ulong;
#[cfg(feature = "usermode")]
pub type GuestAbiUlong = abi_ulong;
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct FatPtr(pub *const c_void, pub *const c_void);
#[derive(IntoPrimitive, TryFromPrimitive, Debug, Copy, Clone, EnumIter, PartialEq, Eq)]
#[repr(i32)]
pub enum MmapPerms {
None = 0,
Read = libc::PROT_READ,
Write = libc::PROT_WRITE,
Execute = libc::PROT_EXEC,
ReadWrite = libc::PROT_READ | libc::PROT_WRITE,
ReadExecute = libc::PROT_READ | libc::PROT_EXEC,
WriteExecute = libc::PROT_WRITE | libc::PROT_EXEC,
ReadWriteExecute = libc::PROT_READ | libc::PROT_WRITE | libc::PROT_EXEC,
}
#[cfg(target_os = "linux")]
#[must_use]
pub fn memop_size(op: MemOp) -> u32 {
1 << op.bitand(MemOp_MO_SIZE).0
}
#[cfg(target_os = "linux")]
#[must_use]
pub fn memop_big_endian(op: MemOp) -> bool {
op.bitand(MemOp_MO_BSWAP) == MemOp_MO_BE
}
#[cfg(target_os = "linux")]
#[must_use]
pub fn make_plugin_meminfo(oi: MemOpIdx, rw: qemu_plugin_mem_rw) -> qemu_plugin_meminfo_t {
oi | (rw.0 << 16)
}
#[cfg(target_os = "linux")]
pub unsafe fn cpu_env(cpu: *mut CPUState) -> *mut CPUArchState {
unsafe { cpu.add(1) as *mut CPUArchState }
}