Romain Malmain 43c9100f59
QEMU Synchronous Exit + Syx Snapshot update (#1681)
* Fix: typo in variable name.

* Fix: thread-safe static for emulator initialization.

* Initial support for synchronous exit from QEMU.

* New commands for the sync exit feature.
Supports physical and virtual address requests.
Updated for new SyxSnapshot naming.

* update qemu commit and fix some things

* - Removed lazy_static dependency
- Compiles for usermode
- Format

* Fix warnings

* Fixed sync_exit for missing architectures

---------

Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>
2023-11-23 17:35:32 +01:00

150 lines
4.1 KiB
Rust

// libafl_qemu only supports Linux currently
#![cfg(target_os = "linux")]
// This lint triggers too often on the current GuestAddr type when emulating 64-bit targets because
// u64::from(GuestAddr) is a no-op, but the .into() call is needed when GuestAddr is u32.
#![cfg_attr(
any(cpu_target = "x86_64", cpu_target = "aarch64"),
allow(clippy::useless_conversion)
)]
#![allow(clippy::needless_pass_by_value)]
#![allow(clippy::needless_pass_by_ref_mut)]
#![allow(clippy::transmute_ptr_to_ptr)]
#![allow(clippy::ptr_cast_constness)]
#![allow(clippy::too_many_arguments)]
// Till they fix this buggy lint in clippy
#![allow(clippy::borrow_as_ptr)]
#![allow(clippy::borrow_deref_ref)]
// Allow only ATM, it will be evetually removed
#![allow(clippy::missing_safety_doc)]
// libafl_qemu_sys export types with empty struct markers (e.g. struct {} start_init_save)
// This causes bindgen to generate empty Rust struct that are generally not FFI-safe due to C++ having empty structs with size 1
// As the QEMU codebase is C, it is FFI-safe and we just ignore the warning
#![allow(improper_ctypes)]
use std::env;
pub use libafl_qemu_sys as sys;
pub use strum::IntoEnumIterator;
#[cfg(cpu_target = "aarch64")]
pub mod aarch64;
#[cfg(all(cpu_target = "aarch64", not(feature = "clippy")))]
pub use aarch64::*;
#[cfg(cpu_target = "arm")]
pub mod arm;
#[cfg(all(cpu_target = "arm", not(feature = "clippy")))]
pub use arm::*;
#[cfg(cpu_target = "i386")]
pub mod i386;
#[cfg(all(cpu_target = "i386", not(feature = "clippy")))]
pub use i386::*;
#[cfg(cpu_target = "x86_64")]
pub mod x86_64;
#[cfg(cpu_target = "x86_64")]
pub use x86_64::*;
#[cfg(cpu_target = "mips")]
pub mod mips;
#[cfg(cpu_target = "mips")]
pub use mips::*;
#[cfg(cpu_target = "ppc")]
pub mod ppc;
#[cfg(cpu_target = "ppc")]
pub use ppc::*;
#[cfg(cpu_target = "hexagon")]
pub mod hexagon;
#[cfg(cpu_target = "hexagon")]
pub use hexagon::*;
pub mod elf;
pub mod helper;
pub use helper::*;
pub mod hooks;
pub use hooks::*;
pub mod edges;
pub use edges::QemuEdgeCoverageHelper;
#[cfg(not(any(cpu_target = "mips", cpu_target = "hexagon")))]
pub mod cmplog;
#[cfg(not(any(cpu_target = "mips", cpu_target = "hexagon")))]
pub use cmplog::QemuCmpLogHelper;
#[cfg(all(emulation_mode = "usermode", not(cpu_target = "hexagon")))]
pub mod snapshot;
#[cfg(all(emulation_mode = "usermode", not(cpu_target = "hexagon")))]
pub use snapshot::QemuSnapshotHelper;
#[cfg(all(emulation_mode = "usermode", not(cpu_target = "hexagon")))]
pub mod asan;
#[cfg(all(emulation_mode = "usermode", not(cpu_target = "hexagon")))]
pub use asan::{init_with_asan, QemuAsanHelper};
#[cfg(not(cpu_target = "hexagon"))]
pub mod calls;
#[cfg(not(cpu_target = "hexagon"))]
pub mod drcov;
pub mod executor;
pub use executor::QemuExecutor;
#[cfg(feature = "fork")]
pub use executor::QemuForkExecutor;
pub mod emu;
pub use emu::*;
pub mod sync_backdoor;
#[must_use]
pub fn filter_qemu_args() -> Vec<String> {
let mut args = vec![env::args().next().unwrap()];
let mut args_iter = env::args();
while let Some(arg) = args_iter.next() {
if arg.starts_with("--libafl") {
args.push(arg);
args.push(args_iter.next().unwrap());
} else if arg.starts_with("-libafl") {
args.push("-".to_owned() + &arg);
args.push(args_iter.next().unwrap());
}
}
args
}
#[cfg(feature = "python")]
use pyo3::prelude::*;
#[cfg(feature = "python")]
#[pymodule]
#[pyo3(name = "libafl_qemu")]
#[allow(clippy::items_after_statements, clippy::too_many_lines)]
pub fn python_module(py: Python, m: &PyModule) -> PyResult<()> {
let regsm = PyModule::new(py, "regs")?;
for r in Regs::iter() {
let v: i32 = r.into();
regsm.add(&format!("{r:?}"), v)?;
}
m.add_submodule(regsm)?;
let mmapm = PyModule::new(py, "mmap")?;
for r in emu::MmapPerms::iter() {
let v: i32 = r.into();
mmapm.add(&format!("{r:?}"), v)?;
}
m.add_submodule(mmapm)?;
m.add_class::<emu::MapInfo>()?;
m.add_class::<emu::GuestMaps>()?;
m.add_class::<emu::SyscallHookResult>()?;
m.add_class::<emu::pybind::Emulator>()?;
Ok(())
}