parent
d1f566c441
commit
7680ea1346
@ -171,7 +171,7 @@ pub fn fuzz() {
|
|||||||
|
|
||||||
// If the execution stops at any point other than the designated breakpoint (e.g. a breakpoint on a panic method) we consider it a crash
|
// If the execution stops at any point other than the designated breakpoint (e.g. a breakpoint on a panic method) we consider it a crash
|
||||||
let mut pcs = (0..qemu.num_cpus())
|
let mut pcs = (0..qemu.num_cpus())
|
||||||
.map(|i| qemu.cpu_from_index(i))
|
.map(|i| qemu.cpu_from_index(i).unwrap())
|
||||||
.map(|cpu| -> Result<u32, QemuRWError> { cpu.read_reg(Regs::Pc) });
|
.map(|cpu| -> Result<u32, QemuRWError> { cpu.read_reg(Regs::Pc) });
|
||||||
let ret = match pcs
|
let ret = match pcs
|
||||||
.find(|pc| (breakpoint..breakpoint + 5).contains(pc.as_ref().unwrap_or(&0)))
|
.find(|pc| (breakpoint..breakpoint + 5).contains(pc.as_ref().unwrap_or(&0)))
|
||||||
|
@ -22,8 +22,11 @@ impl<C, CM, ED, ET, I, S, SM> Emulator<C, CM, ED, ET, I, S, SM> {
|
|||||||
self.qemu.h2g(addr)
|
self.qemu.h2g(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks whether the access at address @addr of size @size is valid.
|
||||||
|
/// The acess is done relatively to the CPU as described by [`Qemu::access_ok`].
|
||||||
|
/// If no CPU is found, returns None.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn access_ok(&self, kind: VerifyAccess, addr: GuestAddr, size: usize) -> bool {
|
pub fn access_ok(&self, kind: VerifyAccess, addr: GuestAddr, size: usize) -> Option<bool> {
|
||||||
self.qemu.access_ok(kind, addr, size)
|
self.qemu.access_ok(kind, addr, size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,7 +154,7 @@ pub struct MemAccessInfo {
|
|||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct CPU {
|
pub struct CPU {
|
||||||
ptr: CPUStatePtr,
|
cpu_ptr: CPUStatePtr,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
@ -305,12 +305,12 @@ impl CPU {
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
#[expect(clippy::cast_sign_loss)]
|
#[expect(clippy::cast_sign_loss)]
|
||||||
pub fn index(&self) -> usize {
|
pub fn index(&self) -> usize {
|
||||||
unsafe { libafl_qemu_cpu_index(self.ptr) as usize }
|
unsafe { libafl_qemu_cpu_index(self.cpu_ptr) as usize }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trigger_breakpoint(&self) {
|
pub fn trigger_breakpoint(&self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
libafl_qemu_trigger_breakpoint(self.ptr);
|
libafl_qemu_trigger_breakpoint(self.cpu_ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,7 +318,7 @@ impl CPU {
|
|||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn num_regs(&self) -> i32 {
|
pub fn num_regs(&self) -> i32 {
|
||||||
unsafe { libafl_qemu_num_regs(self.ptr) }
|
unsafe { libafl_qemu_num_regs(self.cpu_ptr) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_reg<R>(&self, reg: R) -> Result<GuestReg, QemuRWError>
|
pub fn read_reg<R>(&self, reg: R) -> Result<GuestReg, QemuRWError>
|
||||||
@ -328,12 +328,12 @@ impl CPU {
|
|||||||
unsafe {
|
unsafe {
|
||||||
let reg_id = reg.clone().into();
|
let reg_id = reg.clone().into();
|
||||||
let mut val = MaybeUninit::uninit();
|
let mut val = MaybeUninit::uninit();
|
||||||
let success = libafl_qemu_read_reg(self.ptr, reg_id, val.as_mut_ptr() as *mut u8);
|
let success = libafl_qemu_read_reg(self.cpu_ptr, reg_id, val.as_mut_ptr() as *mut u8);
|
||||||
if success == 0 {
|
if success == 0 {
|
||||||
Err(QemuRWError::wrong_reg(
|
Err(QemuRWError::wrong_reg(
|
||||||
QemuRWErrorKind::Write,
|
QemuRWErrorKind::Write,
|
||||||
reg,
|
reg,
|
||||||
Some(self.ptr),
|
Some(self.cpu_ptr),
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
#[cfg(feature = "be")]
|
#[cfg(feature = "be")]
|
||||||
@ -357,12 +357,13 @@ impl CPU {
|
|||||||
#[cfg(not(feature = "be"))]
|
#[cfg(not(feature = "be"))]
|
||||||
let val = GuestReg::to_le(val.into());
|
let val = GuestReg::to_le(val.into());
|
||||||
|
|
||||||
let success = unsafe { libafl_qemu_write_reg(self.ptr, reg_id, &raw const val as *mut u8) };
|
let success =
|
||||||
|
unsafe { libafl_qemu_write_reg(self.cpu_ptr, reg_id, &raw const val as *mut u8) };
|
||||||
if success == 0 {
|
if success == 0 {
|
||||||
Err(QemuRWError::wrong_reg(
|
Err(QemuRWError::wrong_reg(
|
||||||
QemuRWErrorKind::Write,
|
QemuRWErrorKind::Write,
|
||||||
reg,
|
reg,
|
||||||
Some(self.ptr),
|
Some(self.cpu_ptr),
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -374,7 +375,7 @@ impl CPU {
|
|||||||
// TODO use gdbstub's target_cpu_memory_rw_debug
|
// TODO use gdbstub's target_cpu_memory_rw_debug
|
||||||
let ret = unsafe {
|
let ret = unsafe {
|
||||||
libafl_qemu_sys::cpu_memory_rw_debug(
|
libafl_qemu_sys::cpu_memory_rw_debug(
|
||||||
self.ptr,
|
self.cpu_ptr,
|
||||||
addr as GuestVirtAddr,
|
addr as GuestVirtAddr,
|
||||||
buf.as_mut_ptr() as *mut _,
|
buf.as_mut_ptr() as *mut _,
|
||||||
buf.len(),
|
buf.len(),
|
||||||
@ -385,7 +386,7 @@ impl CPU {
|
|||||||
if ret != 0 {
|
if ret != 0 {
|
||||||
Err(QemuRWError::wrong_mem_location(
|
Err(QemuRWError::wrong_mem_location(
|
||||||
QemuRWErrorKind::Read,
|
QemuRWErrorKind::Read,
|
||||||
self.ptr,
|
self.cpu_ptr,
|
||||||
addr,
|
addr,
|
||||||
buf.len(),
|
buf.len(),
|
||||||
))
|
))
|
||||||
@ -411,7 +412,7 @@ impl CPU {
|
|||||||
// TODO use gdbstub's target_cpu_memory_rw_debug
|
// TODO use gdbstub's target_cpu_memory_rw_debug
|
||||||
let ret = unsafe {
|
let ret = unsafe {
|
||||||
libafl_qemu_sys::cpu_memory_rw_debug(
|
libafl_qemu_sys::cpu_memory_rw_debug(
|
||||||
self.ptr,
|
self.cpu_ptr,
|
||||||
addr as GuestVirtAddr,
|
addr as GuestVirtAddr,
|
||||||
buf.as_ptr() as *mut _,
|
buf.as_ptr() as *mut _,
|
||||||
buf.len(),
|
buf.len(),
|
||||||
@ -422,7 +423,7 @@ impl CPU {
|
|||||||
if ret != 0 {
|
if ret != 0 {
|
||||||
Err(QemuRWError::wrong_mem_location(
|
Err(QemuRWError::wrong_mem_location(
|
||||||
QemuRWErrorKind::Write,
|
QemuRWErrorKind::Write,
|
||||||
self.ptr,
|
self.cpu_ptr,
|
||||||
addr,
|
addr,
|
||||||
buf.len(),
|
buf.len(),
|
||||||
))
|
))
|
||||||
@ -432,7 +433,7 @@ impl CPU {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset(&self) {
|
pub fn reset(&self) {
|
||||||
unsafe { libafl_qemu_sys::cpu_reset(self.ptr) };
|
unsafe { libafl_qemu_sys::cpu_reset(self.cpu_ptr) };
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
@ -440,7 +441,7 @@ impl CPU {
|
|||||||
unsafe {
|
unsafe {
|
||||||
let mut saved = MaybeUninit::<CPUArchState>::uninit();
|
let mut saved = MaybeUninit::<CPUArchState>::uninit();
|
||||||
copy_nonoverlapping(
|
copy_nonoverlapping(
|
||||||
libafl_qemu_sys::cpu_env(self.ptr.as_mut().unwrap()),
|
libafl_qemu_sys::cpu_env(self.cpu_ptr.as_mut().unwrap()),
|
||||||
saved.as_mut_ptr(),
|
saved.as_mut_ptr(),
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
@ -452,7 +453,7 @@ impl CPU {
|
|||||||
unsafe {
|
unsafe {
|
||||||
copy_nonoverlapping(
|
copy_nonoverlapping(
|
||||||
saved,
|
saved,
|
||||||
libafl_qemu_sys::cpu_env(self.ptr.as_mut().unwrap()),
|
libafl_qemu_sys::cpu_env(self.cpu_ptr.as_mut().unwrap()),
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -460,7 +461,7 @@ impl CPU {
|
|||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn raw_ptr(&self) -> CPUStatePtr {
|
pub fn raw_ptr(&self) -> CPUStatePtr {
|
||||||
self.ptr
|
self.cpu_ptr
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
@ -737,43 +738,62 @@ impl Qemu {
|
|||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(CPU { ptr })
|
Some(CPU { cpu_ptr: ptr })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[expect(clippy::cast_possible_wrap)]
|
#[expect(clippy::cast_possible_wrap)]
|
||||||
pub fn cpu_from_index(&self, index: usize) -> CPU {
|
pub fn cpu_from_index(&self, index: usize) -> Option<CPU> {
|
||||||
unsafe {
|
let cpu_ptr = unsafe { libafl_qemu_get_cpu(index as i32) };
|
||||||
CPU {
|
|
||||||
ptr: libafl_qemu_get_cpu(index as i32),
|
if cpu_ptr.is_null() {
|
||||||
}
|
None
|
||||||
|
} else {
|
||||||
|
Some(CPU { cpu_ptr })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// CPU will be incorrect if CPU index does not exist
|
||||||
|
#[must_use]
|
||||||
|
#[expect(clippy::cast_possible_wrap)]
|
||||||
|
pub unsafe fn cpu_from_index_unchecked(&self, index: usize) -> CPU {
|
||||||
|
let cpu_ptr = unsafe { libafl_qemu_get_cpu(index as i32) };
|
||||||
|
|
||||||
|
CPU { cpu_ptr }
|
||||||
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn page_from_addr(&self, addr: GuestAddr) -> GuestAddr {
|
pub fn page_from_addr(&self, addr: GuestAddr) -> GuestAddr {
|
||||||
unsafe { libafl_page_from_addr(addr) }
|
unsafe { libafl_page_from_addr(addr) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read a value from a guest address, taking into account the potential indirections with the current CPU.
|
/// Read a value from a guest address, taking into account the potential indirections with the current CPU.
|
||||||
|
/// Uses the 0th CPU if no CPU is currently running.
|
||||||
pub fn read_mem(&self, addr: GuestAddr, buf: &mut [u8]) -> Result<(), QemuRWError> {
|
pub fn read_mem(&self, addr: GuestAddr, buf: &mut [u8]) -> Result<(), QemuRWError> {
|
||||||
self.current_cpu()
|
self.current_cpu()
|
||||||
.unwrap_or_else(|| self.cpu_from_index(0))
|
.or_else(|| self.cpu_from_index(0))
|
||||||
|
.ok_or(QemuRWError::current_cpu_not_found(QemuRWErrorKind::Read))?
|
||||||
.read_mem(addr, buf)
|
.read_mem(addr, buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read a value from a guest address, taking into account the potential indirections with the current CPU.
|
/// Read a value from a guest address, taking into account the potential indirections with the current CPU.
|
||||||
|
/// Uses the 0th CPU if no CPU is currently running.
|
||||||
pub fn read_mem_vec(&self, addr: GuestAddr, len: usize) -> Result<Vec<u8>, QemuRWError> {
|
pub fn read_mem_vec(&self, addr: GuestAddr, len: usize) -> Result<Vec<u8>, QemuRWError> {
|
||||||
self.current_cpu()
|
self.current_cpu()
|
||||||
.unwrap_or_else(|| self.cpu_from_index(0))
|
.or_else(|| self.cpu_from_index(0))
|
||||||
|
.ok_or(QemuRWError::current_cpu_not_found(QemuRWErrorKind::Read))?
|
||||||
.read_mem_vec(addr, len)
|
.read_mem_vec(addr, len)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write a value to a guest address, taking into account the potential indirections with the current CPU.
|
/// Write a value to a guest address, taking into account the potential indirections with the current CPU.
|
||||||
|
/// Uses the 0th CPU if no CPU is currently running.
|
||||||
pub fn write_mem(&self, addr: GuestAddr, buf: &[u8]) -> Result<(), QemuRWError> {
|
pub fn write_mem(&self, addr: GuestAddr, buf: &[u8]) -> Result<(), QemuRWError> {
|
||||||
self.current_cpu()
|
self.current_cpu()
|
||||||
.unwrap_or_else(|| self.cpu_from_index(0))
|
.or_else(|| self.cpu_from_index(0))
|
||||||
|
.ok_or(QemuRWError::current_cpu_not_found(QemuRWErrorKind::Write))?
|
||||||
.write_mem(addr, buf)
|
.write_mem(addr, buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -816,12 +836,12 @@ impl Qemu {
|
|||||||
/// This may only be safely used for valid guest addresses.
|
/// This may only be safely used for valid guest addresses.
|
||||||
///
|
///
|
||||||
/// In any case, no check will be performed on the correctness of the operation.
|
/// In any case, no check will be performed on the correctness of the operation.
|
||||||
///
|
/// Also, the there must be a current CPU (or a CPU at index 0).
|
||||||
/// Please refer to [`CPU::read_mem`] for more details.
|
/// Please refer to [`CPU::read_mem`] for more details.
|
||||||
pub unsafe fn read_mem_unchecked(&self, addr: GuestAddr, buf: &mut [u8]) {
|
pub unsafe fn read_mem_unchecked(&self, addr: GuestAddr, buf: &mut [u8]) {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.current_cpu()
|
self.current_cpu()
|
||||||
.unwrap_or_else(|| self.cpu_from_index(0))
|
.unwrap_or_else(|| self.cpu_from_index_unchecked(0))
|
||||||
.read_mem_unchecked(addr, buf);
|
.read_mem_unchecked(addr, buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -834,11 +854,12 @@ impl Qemu {
|
|||||||
/// In any case, no check will be performed on the correctness of the operation.
|
/// In any case, no check will be performed on the correctness of the operation.
|
||||||
///
|
///
|
||||||
/// This may only be safely used for valid guest addresses.
|
/// This may only be safely used for valid guest addresses.
|
||||||
|
/// Also, the there must be a current CPU (or a CPU at index 0).
|
||||||
/// Please refer to [`CPU::write_mem`] for more details.
|
/// Please refer to [`CPU::write_mem`] for more details.
|
||||||
pub unsafe fn write_mem_unchecked(&self, addr: GuestAddr, buf: &[u8]) {
|
pub unsafe fn write_mem_unchecked(&self, addr: GuestAddr, buf: &[u8]) {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.current_cpu()
|
self.current_cpu()
|
||||||
.unwrap_or_else(|| self.cpu_from_index(0))
|
.unwrap_or_else(|| self.cpu_from_index_unchecked(0))
|
||||||
.write_mem_unchecked(addr, buf);
|
.write_mem_unchecked(addr, buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,7 @@ impl CPU {
|
|||||||
let page = libafl_page_from_addr(vaddr as GuestUsize) as GuestVirtAddr;
|
let page = libafl_page_from_addr(vaddr as GuestUsize) as GuestVirtAddr;
|
||||||
let mut attrs = MaybeUninit::<libafl_qemu_sys::MemTxAttrs>::uninit();
|
let mut attrs = MaybeUninit::<libafl_qemu_sys::MemTxAttrs>::uninit();
|
||||||
let paddr = libafl_qemu_sys::cpu_get_phys_page_attrs_debug(
|
let paddr = libafl_qemu_sys::cpu_get_phys_page_attrs_debug(
|
||||||
self.ptr,
|
self.cpu_ptr,
|
||||||
page as GuestVirtAddr,
|
page as GuestVirtAddr,
|
||||||
attrs.as_mut_ptr(),
|
attrs.as_mut_ptr(),
|
||||||
);
|
);
|
||||||
@ -134,7 +134,7 @@ impl CPU {
|
|||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn current_paging_id(&self) -> Option<GuestPhysAddr> {
|
pub fn current_paging_id(&self) -> Option<GuestPhysAddr> {
|
||||||
let paging_id = unsafe { libafl_qemu_current_paging_id(self.ptr) };
|
let paging_id = unsafe { libafl_qemu_current_paging_id(self.cpu_ptr) };
|
||||||
|
|
||||||
if paging_id == 0 {
|
if paging_id == 0 {
|
||||||
None
|
None
|
||||||
@ -149,10 +149,10 @@ impl CPU {
|
|||||||
/// no check is done on the correctness of the operation.
|
/// no check is done on the correctness of the operation.
|
||||||
/// if a problem occurred during the operation, there will be no feedback
|
/// if a problem occurred during the operation, there will be no feedback
|
||||||
pub unsafe fn read_mem_unchecked(&self, addr: GuestAddr, buf: &mut [u8]) {
|
pub unsafe fn read_mem_unchecked(&self, addr: GuestAddr, buf: &mut [u8]) {
|
||||||
// TODO use gdbstub's target_cpu_memory_rw_debug
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
// TODO use gdbstub's target_cpu_memory_rw_debug
|
||||||
libafl_qemu_sys::cpu_memory_rw_debug(
|
libafl_qemu_sys::cpu_memory_rw_debug(
|
||||||
self.ptr,
|
self.cpu_ptr,
|
||||||
addr as GuestVirtAddr,
|
addr as GuestVirtAddr,
|
||||||
buf.as_mut_ptr() as *mut _,
|
buf.as_mut_ptr() as *mut _,
|
||||||
buf.len(),
|
buf.len(),
|
||||||
@ -167,10 +167,10 @@ impl CPU {
|
|||||||
/// no check is done on the correctness of the operation.
|
/// no check is done on the correctness of the operation.
|
||||||
/// if a problem occurred during the operation, there will be no feedback
|
/// if a problem occurred during the operation, there will be no feedback
|
||||||
pub unsafe fn write_mem_unchecked(&self, addr: GuestAddr, buf: &[u8]) {
|
pub unsafe fn write_mem_unchecked(&self, addr: GuestAddr, buf: &[u8]) {
|
||||||
// TODO use gdbstub's target_cpu_memory_rw_debug
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
// TODO use gdbstub's target_cpu_memory_rw_debug
|
||||||
libafl_qemu_sys::cpu_memory_rw_debug(
|
libafl_qemu_sys::cpu_memory_rw_debug(
|
||||||
self.ptr,
|
self.cpu_ptr,
|
||||||
addr as GuestVirtAddr,
|
addr as GuestVirtAddr,
|
||||||
buf.as_ptr() as *mut _,
|
buf.as_ptr() as *mut _,
|
||||||
buf.len(),
|
buf.len(),
|
||||||
@ -376,7 +376,7 @@ impl<'a> Iterator for HostMemoryIter<'a> {
|
|||||||
} else {
|
} else {
|
||||||
// Host memory allocation is always host-page aligned, so we can freely go from host page to host page.
|
// Host memory allocation is always host-page aligned, so we can freely go from host page to host page.
|
||||||
let start_host_addr: *const u8 =
|
let start_host_addr: *const u8 =
|
||||||
unsafe { libafl_qemu_sys::libafl_paddr2host(self.cpu.ptr, self.addr, false) };
|
unsafe { libafl_qemu_sys::libafl_paddr2host(self.cpu.cpu_ptr, self.addr, false) };
|
||||||
let host_page_size = Qemu::get().unwrap().host_page_size();
|
let host_page_size = Qemu::get().unwrap().host_page_size();
|
||||||
let mut size_taken: usize = std::cmp::min(
|
let mut size_taken: usize = std::cmp::min(
|
||||||
(start_host_addr as usize).next_multiple_of(host_page_size),
|
(start_host_addr as usize).next_multiple_of(host_page_size),
|
||||||
@ -388,8 +388,9 @@ impl<'a> Iterator for HostMemoryIter<'a> {
|
|||||||
|
|
||||||
// Now self.addr is host-page aligned
|
// Now self.addr is host-page aligned
|
||||||
while self.remaining_len > 0 {
|
while self.remaining_len > 0 {
|
||||||
let next_page_host_addr: *const u8 =
|
let next_page_host_addr: *const u8 = unsafe {
|
||||||
unsafe { libafl_qemu_sys::libafl_paddr2host(self.cpu.ptr, self.addr, false) };
|
libafl_qemu_sys::libafl_paddr2host(self.cpu.cpu_ptr, self.addr, false)
|
||||||
|
};
|
||||||
|
|
||||||
// Non-contiguous, we stop here for the slice
|
// Non-contiguous, we stop here for the slice
|
||||||
if next_page_host_addr != start_host_addr {
|
if next_page_host_addr != start_host_addr {
|
||||||
|
@ -264,11 +264,17 @@ impl Qemu {
|
|||||||
unsafe { (addr as usize - guest_base) as GuestAddr }
|
unsafe { (addr as usize - guest_base) as GuestAddr }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Tells whether access to target address @addr of size @size is valid or not.
|
||||||
|
/// The access is checked relatively to `current_cpu` if available, or the CPU at index 0
|
||||||
|
/// otherwise.
|
||||||
|
/// The function returns None if no CPU could be found.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn access_ok(&self, kind: VerifyAccess, addr: GuestAddr, size: usize) -> bool {
|
pub fn access_ok(&self, kind: VerifyAccess, addr: GuestAddr, size: usize) -> Option<bool> {
|
||||||
self.current_cpu()
|
Some(
|
||||||
.unwrap_or_else(|| self.cpu_from_index(0))
|
self.current_cpu()
|
||||||
.access_ok(kind, addr, size)
|
.or_else(|| self.cpu_from_index(0))?
|
||||||
|
.access_ok(kind, addr, size),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn force_dfl(&self) {
|
pub fn force_dfl(&self) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user