Fix broken closure hooks in libafl_qemu (#1839)
* Fix broken crash hook * fix hooks * clippy * pin
This commit is contained in:
parent
9b82af4539
commit
41d24ca375
@ -56,9 +56,11 @@ systemmode = ["libafl_qemu_sys/systemmode"]
|
||||
## Automatically register all `#[derive(SerdeAny)]` types at startup.
|
||||
serdeany_autoreg = ["libafl_bolts/serdeany_autoreg"]
|
||||
|
||||
## Automatically register all `#[derive(SerdeAny)]` types at startup.
|
||||
slirp = [ "systemmode", "libafl_qemu_sys/slirp" ] # build qemu with host libslirp (for user networking)
|
||||
|
||||
# disabled atm, enabled when fixed with dynamic list
|
||||
# shared = [ "libafl_qemu_sys/shared" ]
|
||||
|
||||
[dependencies]
|
||||
libafl = { path = "../libafl", version = "0.11.2", default-features = false, features = ["std", "derive", "regex"] }
|
||||
libafl_bolts = { path = "../libafl_bolts", version = "0.11.2", default-features = false, features = ["std", "derive"] }
|
||||
|
@ -95,6 +95,6 @@ pub fn build() {
|
||||
.status()
|
||||
.expect("make failed")
|
||||
.success());
|
||||
println!("cargo:rerun-if-changed={}/libqasan.so", target_dir.display());
|
||||
// println!("cargo:rerun-if-changed={}/libqasan.so", target_dir.display());
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ categories = [
|
||||
all-features = true
|
||||
|
||||
[features]
|
||||
shared = []
|
||||
slirp = [] # build qemu with host libslirp (for user networking)
|
||||
|
||||
clippy = [] # special feature for clippy, don't use in normal projects§
|
||||
|
@ -10,6 +10,11 @@ const QEMU_URL: &str = "https://github.com/AFLplusplus/qemu-libafl-bridge";
|
||||
const QEMU_DIRNAME: &str = "qemu-libafl-bridge";
|
||||
const QEMU_REVISION: &str = "75d15d54f4417a4766d2dcb493982d9df0e8eac4";
|
||||
|
||||
pub struct BuildResult {
|
||||
pub qemu_path: PathBuf,
|
||||
pub build_dir: PathBuf,
|
||||
}
|
||||
|
||||
fn build_dep_check(tools: &[&str]) {
|
||||
for tool in tools {
|
||||
which(tool).unwrap_or_else(|_| panic!("Build tool {tool} not found"));
|
||||
@ -23,7 +28,7 @@ pub fn build(
|
||||
is_big_endian: bool,
|
||||
is_usermode: bool,
|
||||
jobs: Option<u32>,
|
||||
) -> (PathBuf, PathBuf) {
|
||||
) -> BuildResult {
|
||||
let mut cpu_target = cpu_target.to_string();
|
||||
// qemu-system-arm supports both big and little endian configurations and so
|
||||
// therefore the "be" feature should ignored in this configuration. Also
|
||||
@ -120,13 +125,19 @@ pub fn build(
|
||||
"softmmu".to_string()
|
||||
};
|
||||
|
||||
let output_lib = if is_usermode {
|
||||
build_dir.join(format!("libqemu-{cpu_target}.so"))
|
||||
let (output_lib, output_lib_link) = if is_usermode {
|
||||
(
|
||||
build_dir.join(format!("libqemu-{cpu_target}.so")),
|
||||
format!("qemu-{cpu_target}"),
|
||||
)
|
||||
} else {
|
||||
build_dir.join(format!("libqemu-system-{cpu_target}.so"))
|
||||
(
|
||||
build_dir.join(format!("libqemu-system-{cpu_target}.so")),
|
||||
format!("qemu-system-{cpu_target}"),
|
||||
)
|
||||
};
|
||||
|
||||
println!("cargo:rerun-if-changed={}", output_lib.to_string_lossy());
|
||||
// println!("cargo:rerun-if-changed={}", output_lib.to_string_lossy());
|
||||
|
||||
if !output_lib.is_file() || (custom_qemu_dir.is_some() && !custom_qemu_no_build) {
|
||||
/*drop(
|
||||
@ -337,137 +348,145 @@ pub fn build(
|
||||
}
|
||||
*/
|
||||
|
||||
let compile_commands_string =
|
||||
&fs::read_to_string(build_dir.join("linkinfo.json")).expect("Failed to read linkinfo.json");
|
||||
|
||||
let linkinfo = json::parse(compile_commands_string).expect("Failed to parse linkinfo.json");
|
||||
|
||||
let mut cmd = vec![];
|
||||
for arg in linkinfo["cmd"].members() {
|
||||
cmd.push(
|
||||
arg.as_str()
|
||||
.expect("linkinfo.json `cmd` values must be strings"),
|
||||
if cfg!(feature = "shared") {
|
||||
println!(
|
||||
"cargo:rustc-link-search=native={}",
|
||||
build_dir.to_string_lossy()
|
||||
);
|
||||
}
|
||||
|
||||
assert!(cpp_compiler
|
||||
.to_command()
|
||||
.current_dir(&build_dir)
|
||||
.arg("-o")
|
||||
.arg("libqemu-partially-linked.o")
|
||||
.arg("-r")
|
||||
.args(cmd)
|
||||
.status()
|
||||
.expect("Partial linked failure")
|
||||
.success());
|
||||
|
||||
/* // Old manual linking, kept here for reference and debugging
|
||||
if is_usermode {
|
||||
Command::new("ld")
|
||||
.current_dir(out_dir_path)
|
||||
.arg("-o")
|
||||
.arg("libqemu-partially-linked.o")
|
||||
.arg("-r")
|
||||
.args(objects)
|
||||
.arg("--start-group")
|
||||
.arg("--whole-archive")
|
||||
.arg(format!("{}/libhwcore.fa", build_dir.display()))
|
||||
.arg(format!("{}/libqom.fa", build_dir.display()))
|
||||
.arg(format!("{}/libevent-loop-base.a", build_dir.display()))
|
||||
.arg(format!("{}/gdbstub/libgdb_user.fa", build_dir.display()))
|
||||
.arg("--no-whole-archive")
|
||||
.arg(format!("{}/libqemuutil.a", build_dir.display()))
|
||||
.arg(format!("{}/libhwcore.fa", build_dir.display()))
|
||||
.arg(format!("{}/libqom.fa", build_dir.display()))
|
||||
.arg(format!("{}/gdbstub/libgdb_user.fa", build_dir.display()))
|
||||
.arg(format!(
|
||||
"--dynamic-list={}/plugins/qemu-plugins.symbols",
|
||||
qemu_path.display()
|
||||
))
|
||||
.arg("--end-group")
|
||||
.status()
|
||||
.expect("Partial linked failure");
|
||||
println!("cargo:rustc-link-lib=dylib={output_lib_link}");
|
||||
} else {
|
||||
Command::new("ld")
|
||||
.current_dir(out_dir_path)
|
||||
let compile_commands_string = &fs::read_to_string(build_dir.join("linkinfo.json"))
|
||||
.expect("Failed to read linkinfo.json");
|
||||
|
||||
let linkinfo = json::parse(compile_commands_string).expect("Failed to parse linkinfo.json");
|
||||
|
||||
let mut cmd = vec![];
|
||||
for arg in linkinfo["cmd"].members() {
|
||||
cmd.push(
|
||||
arg.as_str()
|
||||
.expect("linkinfo.json `cmd` values must be strings"),
|
||||
);
|
||||
}
|
||||
|
||||
assert!(cpp_compiler
|
||||
.to_command()
|
||||
.current_dir(&build_dir)
|
||||
.arg("-o")
|
||||
.arg("libqemu-partially-linked.o")
|
||||
.arg("-r")
|
||||
.args(objects)
|
||||
.arg("--start-group")
|
||||
.arg("--whole-archive")
|
||||
.arg(format!("{}/libhwcore.fa", build_dir.display()))
|
||||
.arg(format!("{}/libqom.fa", build_dir.display()))
|
||||
.arg(format!("{}/libevent-loop-base.a", build_dir.display()))
|
||||
.arg(format!("{}/gdbstub/libgdb_softmmu.fa", build_dir.display()))
|
||||
.arg(format!("{}/libio.fa", build_dir.display()))
|
||||
.arg(format!("{}/libcrypto.fa", build_dir.display()))
|
||||
.arg(format!("{}/libauthz.fa", build_dir.display()))
|
||||
.arg(format!("{}/libblockdev.fa", build_dir.display()))
|
||||
.arg(format!("{}/libblock.fa", build_dir.display()))
|
||||
.arg(format!("{}/libchardev.fa", build_dir.display()))
|
||||
.arg(format!("{}/libqmp.fa", build_dir.display()))
|
||||
.arg("--no-whole-archive")
|
||||
.arg(format!("{}/libqemuutil.a", build_dir.display()))
|
||||
.arg(format!(
|
||||
"{}/subprojects/dtc/libfdt/libfdt.a",
|
||||
build_dir.display()
|
||||
))
|
||||
.arg(format!(
|
||||
"{}/subprojects/libvhost-user/libvhost-user-glib.a",
|
||||
build_dir.display()
|
||||
))
|
||||
.arg(format!(
|
||||
"{}/subprojects/libvhost-user/libvhost-user.a",
|
||||
build_dir.display()
|
||||
))
|
||||
.arg(format!(
|
||||
"{}/subprojects/libvduse/libvduse.a",
|
||||
build_dir.display()
|
||||
))
|
||||
.arg(format!("{}/libmigration.fa", build_dir.display()))
|
||||
.arg(format!("{}/libhwcore.fa", build_dir.display()))
|
||||
.arg(format!("{}/libqom.fa", build_dir.display()))
|
||||
.arg(format!("{}/gdbstub/libgdb_softmmu.fa", build_dir.display()))
|
||||
.arg(format!("{}/libio.fa", build_dir.display()))
|
||||
.arg(format!("{}/libcrypto.fa", build_dir.display()))
|
||||
.arg(format!("{}/libauthz.fa", build_dir.display()))
|
||||
.arg(format!("{}/libblockdev.fa", build_dir.display()))
|
||||
.arg(format!("{}/libblock.fa", build_dir.display()))
|
||||
.arg(format!("{}/libchardev.fa", build_dir.display()))
|
||||
.arg(format!("{}/libqmp.fa", build_dir.display()))
|
||||
.arg(format!(
|
||||
"--dynamic-list={}/plugins/qemu-plugins.symbols",
|
||||
qemu_path.display()
|
||||
))
|
||||
.arg("--end-group")
|
||||
.args(cmd)
|
||||
.status()
|
||||
.expect("Partial linked failure");
|
||||
}*/
|
||||
.expect("Partial linked failure")
|
||||
.success());
|
||||
|
||||
Command::new("ar")
|
||||
.current_dir(out_dir_path)
|
||||
.arg("crs")
|
||||
.arg("libqemu-partially-linked.a")
|
||||
.arg(build_dir.join("libqemu-partially-linked.o"))
|
||||
.status()
|
||||
.expect("Ar creation");
|
||||
/* // Old manual linking, kept here for reference and debugging
|
||||
if is_usermode {
|
||||
Command::new("ld")
|
||||
.current_dir(out_dir_path)
|
||||
.arg("-o")
|
||||
.arg("libqemu-partially-linked.o")
|
||||
.arg("-r")
|
||||
.args(objects)
|
||||
.arg("--start-group")
|
||||
.arg("--whole-archive")
|
||||
.arg(format!("{}/libhwcore.fa", build_dir.display()))
|
||||
.arg(format!("{}/libqom.fa", build_dir.display()))
|
||||
.arg(format!("{}/libevent-loop-base.a", build_dir.display()))
|
||||
.arg(format!("{}/gdbstub/libgdb_user.fa", build_dir.display()))
|
||||
.arg("--no-whole-archive")
|
||||
.arg(format!("{}/libqemuutil.a", build_dir.display()))
|
||||
.arg(format!("{}/libhwcore.fa", build_dir.display()))
|
||||
.arg(format!("{}/libqom.fa", build_dir.display()))
|
||||
.arg(format!("{}/gdbstub/libgdb_user.fa", build_dir.display()))
|
||||
.arg(format!(
|
||||
"--dynamic-list={}/plugins/qemu-plugins.symbols",
|
||||
qemu_path.display()
|
||||
))
|
||||
.arg("--end-group")
|
||||
.status()
|
||||
.expect("Partial linked failure");
|
||||
} else {
|
||||
Command::new("ld")
|
||||
.current_dir(out_dir_path)
|
||||
.arg("-o")
|
||||
.arg("libqemu-partially-linked.o")
|
||||
.arg("-r")
|
||||
.args(objects)
|
||||
.arg("--start-group")
|
||||
.arg("--whole-archive")
|
||||
.arg(format!("{}/libhwcore.fa", build_dir.display()))
|
||||
.arg(format!("{}/libqom.fa", build_dir.display()))
|
||||
.arg(format!("{}/libevent-loop-base.a", build_dir.display()))
|
||||
.arg(format!("{}/gdbstub/libgdb_softmmu.fa", build_dir.display()))
|
||||
.arg(format!("{}/libio.fa", build_dir.display()))
|
||||
.arg(format!("{}/libcrypto.fa", build_dir.display()))
|
||||
.arg(format!("{}/libauthz.fa", build_dir.display()))
|
||||
.arg(format!("{}/libblockdev.fa", build_dir.display()))
|
||||
.arg(format!("{}/libblock.fa", build_dir.display()))
|
||||
.arg(format!("{}/libchardev.fa", build_dir.display()))
|
||||
.arg(format!("{}/libqmp.fa", build_dir.display()))
|
||||
.arg("--no-whole-archive")
|
||||
.arg(format!("{}/libqemuutil.a", build_dir.display()))
|
||||
.arg(format!(
|
||||
"{}/subprojects/dtc/libfdt/libfdt.a",
|
||||
build_dir.display()
|
||||
))
|
||||
.arg(format!(
|
||||
"{}/subprojects/libvhost-user/libvhost-user-glib.a",
|
||||
build_dir.display()
|
||||
))
|
||||
.arg(format!(
|
||||
"{}/subprojects/libvhost-user/libvhost-user.a",
|
||||
build_dir.display()
|
||||
))
|
||||
.arg(format!(
|
||||
"{}/subprojects/libvduse/libvduse.a",
|
||||
build_dir.display()
|
||||
))
|
||||
.arg(format!("{}/libmigration.fa", build_dir.display()))
|
||||
.arg(format!("{}/libhwcore.fa", build_dir.display()))
|
||||
.arg(format!("{}/libqom.fa", build_dir.display()))
|
||||
.arg(format!("{}/gdbstub/libgdb_softmmu.fa", build_dir.display()))
|
||||
.arg(format!("{}/libio.fa", build_dir.display()))
|
||||
.arg(format!("{}/libcrypto.fa", build_dir.display()))
|
||||
.arg(format!("{}/libauthz.fa", build_dir.display()))
|
||||
.arg(format!("{}/libblockdev.fa", build_dir.display()))
|
||||
.arg(format!("{}/libblock.fa", build_dir.display()))
|
||||
.arg(format!("{}/libchardev.fa", build_dir.display()))
|
||||
.arg(format!("{}/libqmp.fa", build_dir.display()))
|
||||
.arg(format!(
|
||||
"--dynamic-list={}/plugins/qemu-plugins.symbols",
|
||||
qemu_path.display()
|
||||
))
|
||||
.arg("--end-group")
|
||||
.status()
|
||||
.expect("Partial linked failure");
|
||||
}*/
|
||||
|
||||
println!("cargo:rustc-link-search=native={out_dir}");
|
||||
println!("cargo:rustc-link-lib=static=qemu-partially-linked");
|
||||
Command::new("ar")
|
||||
.current_dir(out_dir_path)
|
||||
.arg("crs")
|
||||
.arg("libqemu-partially-linked.a")
|
||||
.arg(build_dir.join("libqemu-partially-linked.o"))
|
||||
.status()
|
||||
.expect("Ar creation");
|
||||
|
||||
for arg in linkinfo["search"].members() {
|
||||
let val = arg
|
||||
.as_str()
|
||||
.expect("linkinfo.json `search` values must be strings");
|
||||
println!("cargo:rustc-link-search={val}");
|
||||
}
|
||||
println!("cargo:rustc-link-search=native={out_dir}");
|
||||
println!("cargo:rustc-link-lib=static=qemu-partially-linked");
|
||||
|
||||
for arg in linkinfo["libs"].members() {
|
||||
let val = arg
|
||||
.as_str()
|
||||
.expect("linkinfo.json `libs` values must be strings");
|
||||
println!("cargo:rustc-link-lib={val}");
|
||||
for arg in linkinfo["search"].members() {
|
||||
let val = arg
|
||||
.as_str()
|
||||
.expect("linkinfo.json `search` values must be strings");
|
||||
println!("cargo:rustc-link-search={val}");
|
||||
}
|
||||
|
||||
for arg in linkinfo["libs"].members() {
|
||||
let val = arg
|
||||
.as_str()
|
||||
.expect("linkinfo.json `libs` values must be strings");
|
||||
println!("cargo:rustc-link-lib={val}");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -500,5 +519,8 @@ pub fn build(
|
||||
}
|
||||
}
|
||||
|
||||
(qemu_path, build_dir)
|
||||
BuildResult {
|
||||
qemu_path,
|
||||
build_dir,
|
||||
}
|
||||
}
|
||||
|
@ -22,10 +22,16 @@ pub fn build_with_bindings(
|
||||
jobs: Option<u32>,
|
||||
bindings_file: &Path,
|
||||
) {
|
||||
let (qemu_dir, build_dir) = build::build(cpu_target, is_big_endian, is_usermode, jobs);
|
||||
let clang_args = qemu_bindgen_clang_args(&qemu_dir, &build_dir, cpu_target, is_usermode);
|
||||
let build_result = build::build(cpu_target, is_big_endian, is_usermode, jobs);
|
||||
|
||||
let bind = bindings::generate(&build_dir, cpu_target, clang_args)
|
||||
let clang_args = qemu_bindgen_clang_args(
|
||||
&build_result.qemu_path,
|
||||
&build_result.build_dir,
|
||||
cpu_target,
|
||||
is_usermode,
|
||||
);
|
||||
|
||||
let bind = bindings::generate(&build_result.build_dir, cpu_target, clang_args)
|
||||
.expect("Failed to generate the bindings");
|
||||
bind.write_to_file(bindings_file)
|
||||
.expect("Faield to write to the bindings file");
|
||||
|
@ -31,6 +31,7 @@ usermode = []
|
||||
systemmode = []
|
||||
|
||||
slirp = [ "systemmode", "libafl_qemu_build/slirp" ] # build qemu with host libslirp (for user networking)
|
||||
shared = [ "libafl_qemu_build/shared" ]
|
||||
|
||||
clippy = [ "libafl_qemu_build/clippy" ] # special feature for clippy, don't use in normal projects§
|
||||
|
||||
|
@ -6,6 +6,7 @@ use core::{
|
||||
fmt::{self, Debug, Formatter},
|
||||
marker::PhantomData,
|
||||
mem::transmute,
|
||||
pin::Pin,
|
||||
ptr::{self, addr_of, addr_of_mut},
|
||||
};
|
||||
|
||||
@ -25,7 +26,7 @@ use crate::{
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
pub(crate) enum Hook {
|
||||
Function(*const c_void),
|
||||
Closure(Box<FatPtr>),
|
||||
Closure(FatPtr),
|
||||
#[cfg(emulation_mode = "usermode")]
|
||||
Once(Box<FatPtr>),
|
||||
Empty,
|
||||
@ -36,7 +37,7 @@ pub(crate) enum Hook {
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub(crate) enum HookRepr {
|
||||
Function(*const c_void),
|
||||
Closure(Box<FatPtr>),
|
||||
Closure(FatPtr),
|
||||
Empty,
|
||||
}
|
||||
|
||||
@ -77,7 +78,7 @@ macro_rules! hook_to_repr {
|
||||
($h:expr) => {
|
||||
match $h {
|
||||
Hook::Function(f) => HookRepr::Function(f as *const libc::c_void),
|
||||
Hook::Closure(c) => HookRepr::Closure(Box::new(transmute(c))),
|
||||
Hook::Closure(c) => HookRepr::Closure(transmute(c)),
|
||||
Hook::Raw(_) => HookRepr::Empty, // managed by emu
|
||||
Hook::Empty => HookRepr::Empty,
|
||||
}
|
||||
@ -242,13 +243,13 @@ macro_rules! create_exec_wrapper {
|
||||
}
|
||||
}
|
||||
|
||||
static mut GENERIC_HOOKS: Vec<(InstructionHookId, Box<FatPtr>)> = vec![];
|
||||
static mut GENERIC_HOOKS: Vec<Pin<Box<(InstructionHookId, FatPtr)>>> = vec![];
|
||||
create_wrapper!(generic, (pc: GuestAddr));
|
||||
static mut BACKDOOR_HOOKS: Vec<(BackdoorHookId, Box<FatPtr>)> = vec![];
|
||||
static mut BACKDOOR_HOOKS: Vec<Pin<Box<(BackdoorHookId, FatPtr)>>> = vec![];
|
||||
create_wrapper!(backdoor, (pc: GuestAddr));
|
||||
|
||||
#[cfg(emulation_mode = "usermode")]
|
||||
static mut PRE_SYSCALL_HOOKS: Vec<(PreSyscallHookId, Box<FatPtr>)> = vec![];
|
||||
static mut PRE_SYSCALL_HOOKS: Vec<Pin<Box<(PreSyscallHookId, FatPtr)>>> = vec![];
|
||||
#[cfg(emulation_mode = "usermode")]
|
||||
create_wrapper!(pre_syscall, (sys_num: i32,
|
||||
a0: GuestAddr,
|
||||
@ -260,7 +261,7 @@ create_wrapper!(pre_syscall, (sys_num: i32,
|
||||
a6: GuestAddr,
|
||||
a7: GuestAddr), SyscallHookResult);
|
||||
#[cfg(emulation_mode = "usermode")]
|
||||
static mut POST_SYSCALL_HOOKS: Vec<(PostSyscallHookId, Box<FatPtr>)> = vec![];
|
||||
static mut POST_SYSCALL_HOOKS: Vec<Pin<Box<(PostSyscallHookId, FatPtr)>>> = vec![];
|
||||
#[cfg(emulation_mode = "usermode")]
|
||||
create_wrapper!(post_syscall, (res: GuestAddr, sys_num: i32,
|
||||
a0: GuestAddr,
|
||||
@ -272,20 +273,20 @@ create_wrapper!(post_syscall, (res: GuestAddr, sys_num: i32,
|
||||
a6: GuestAddr,
|
||||
a7: GuestAddr), GuestAddr);
|
||||
#[cfg(emulation_mode = "usermode")]
|
||||
static mut NEW_THREAD_HOOKS: Vec<(NewThreadHookId, Box<FatPtr>)> = vec![];
|
||||
static mut NEW_THREAD_HOOKS: Vec<Pin<Box<(NewThreadHookId, FatPtr)>>> = vec![];
|
||||
#[cfg(emulation_mode = "usermode")]
|
||||
create_wrapper!(new_thread, (tid: u32), bool);
|
||||
|
||||
static mut EDGE_HOOKS: Vec<HookState<1, EdgeHookId>> = vec![];
|
||||
static mut EDGE_HOOKS: Vec<Pin<Box<HookState<1, EdgeHookId>>>> = vec![];
|
||||
create_gen_wrapper!(edge, (src: GuestAddr, dest: GuestAddr), u64, 1, EdgeHookId);
|
||||
create_exec_wrapper!(edge, (id: u64), 0, 1, EdgeHookId);
|
||||
|
||||
static mut BLOCK_HOOKS: Vec<HookState<1, BlockHookId>> = vec![];
|
||||
static mut BLOCK_HOOKS: Vec<Pin<Box<HookState<1, BlockHookId>>>> = vec![];
|
||||
create_gen_wrapper!(block, (addr: GuestAddr), u64, 1, BlockHookId);
|
||||
create_post_gen_wrapper!(block, (addr: GuestAddr, len: GuestUsize), 1, BlockHookId);
|
||||
create_exec_wrapper!(block, (id: u64), 0, 1, BlockHookId);
|
||||
|
||||
static mut READ_HOOKS: Vec<HookState<5, ReadHookId>> = vec![];
|
||||
static mut READ_HOOKS: Vec<Pin<Box<HookState<5, ReadHookId>>>> = vec![];
|
||||
create_gen_wrapper!(read, (pc: GuestAddr, info: MemAccessInfo), u64, 5, ReadHookId);
|
||||
create_exec_wrapper!(read, (id: u64, addr: GuestAddr), 0, 5, ReadHookId);
|
||||
create_exec_wrapper!(read, (id: u64, addr: GuestAddr), 1, 5, ReadHookId);
|
||||
@ -293,7 +294,7 @@ create_exec_wrapper!(read, (id: u64, addr: GuestAddr), 2, 5, ReadHookId);
|
||||
create_exec_wrapper!(read, (id: u64, addr: GuestAddr), 3, 5, ReadHookId);
|
||||
create_exec_wrapper!(read, (id: u64, addr: GuestAddr, size: usize), 4, 5, ReadHookId);
|
||||
|
||||
static mut WRITE_HOOKS: Vec<HookState<5, WriteHookId>> = vec![];
|
||||
static mut WRITE_HOOKS: Vec<Pin<Box<HookState<5, WriteHookId>>>> = vec![];
|
||||
create_gen_wrapper!(write, (pc: GuestAddr, info: MemAccessInfo), u64, 5, WriteHookId);
|
||||
create_exec_wrapper!(write, (id: u64, addr: GuestAddr), 0, 5, WriteHookId);
|
||||
create_exec_wrapper!(write, (id: u64, addr: GuestAddr), 1, 5, WriteHookId);
|
||||
@ -301,7 +302,7 @@ create_exec_wrapper!(write, (id: u64, addr: GuestAddr), 2, 5, WriteHookId);
|
||||
create_exec_wrapper!(write, (id: u64, addr: GuestAddr), 3, 5, WriteHookId);
|
||||
create_exec_wrapper!(write, (id: u64, addr: GuestAddr, size: usize), 4, 5, WriteHookId);
|
||||
|
||||
static mut CMP_HOOKS: Vec<HookState<4, CmpHookId>> = vec![];
|
||||
static mut CMP_HOOKS: Vec<Pin<Box<HookState<4, CmpHookId>>>> = vec![];
|
||||
create_gen_wrapper!(cmp, (pc: GuestAddr, size: usize), u64, 4, CmpHookId);
|
||||
create_exec_wrapper!(cmp, (id: u64, v0: u8, v1: u8), 0, 4, CmpHookId);
|
||||
create_exec_wrapper!(cmp, (id: u64, v0: u16, v1: u16), 1, 4, CmpHookId);
|
||||
@ -459,14 +460,25 @@ where
|
||||
invalidate_block: bool,
|
||||
) -> InstructionHookId {
|
||||
unsafe {
|
||||
let mut fat: Box<FatPtr> = Box::new(transmute(hook));
|
||||
let fat: FatPtr = transmute(hook);
|
||||
GENERIC_HOOKS.push(Box::pin((InstructionHookId(0), fat)));
|
||||
let id = self.emulator.set_hook(
|
||||
transmute::<&mut FatPtr, &mut FatPtr>(&mut *fat), //transmute satisfy the lifetime
|
||||
&mut GENERIC_HOOKS
|
||||
.last_mut()
|
||||
.unwrap()
|
||||
.as_mut()
|
||||
.get_unchecked_mut()
|
||||
.1,
|
||||
addr,
|
||||
closure_generic_hook_wrapper::<QT, S>,
|
||||
invalidate_block,
|
||||
);
|
||||
GENERIC_HOOKS.push((id, fat));
|
||||
GENERIC_HOOKS
|
||||
.last_mut()
|
||||
.unwrap()
|
||||
.as_mut()
|
||||
.get_unchecked_mut()
|
||||
.0 = id;
|
||||
id
|
||||
}
|
||||
}
|
||||
@ -506,16 +518,23 @@ where
|
||||
edge_0_exec_hook_wrapper::<QT, S>,
|
||||
extern "C" fn(&mut HookState<1, EdgeHookId>, id: u64)
|
||||
);
|
||||
EDGE_HOOKS.push(HookState {
|
||||
EDGE_HOOKS.push(Box::pin(HookState {
|
||||
id: EdgeHookId(0),
|
||||
gen: hook_to_repr!(generation_hook),
|
||||
post_gen: HookRepr::Empty,
|
||||
execs: [hook_to_repr!(execution_hook)],
|
||||
});
|
||||
let id = self
|
||||
.emulator
|
||||
.add_edge_hooks(EDGE_HOOKS.last_mut().unwrap(), gen, exec);
|
||||
EDGE_HOOKS.last_mut().unwrap().id = id;
|
||||
}));
|
||||
let id = self.emulator.add_edge_hooks(
|
||||
EDGE_HOOKS.last_mut().unwrap().as_mut().get_unchecked_mut(),
|
||||
gen,
|
||||
exec,
|
||||
);
|
||||
EDGE_HOOKS
|
||||
.last_mut()
|
||||
.unwrap()
|
||||
.as_mut()
|
||||
.get_unchecked_mut()
|
||||
.id = id;
|
||||
id
|
||||
}
|
||||
}
|
||||
@ -558,16 +577,24 @@ where
|
||||
block_0_exec_hook_wrapper::<QT, S>,
|
||||
extern "C" fn(&mut HookState<1, BlockHookId>, id: u64)
|
||||
);
|
||||
BLOCK_HOOKS.push(HookState {
|
||||
BLOCK_HOOKS.push(Box::pin(HookState {
|
||||
id: BlockHookId(0),
|
||||
gen: hook_to_repr!(generation_hook),
|
||||
post_gen: hook_to_repr!(post_generation_hook),
|
||||
execs: [hook_to_repr!(execution_hook)],
|
||||
});
|
||||
let id =
|
||||
self.emulator
|
||||
.add_block_hooks(BLOCK_HOOKS.last_mut().unwrap(), gen, postgen, exec);
|
||||
BLOCK_HOOKS.last_mut().unwrap().id = id;
|
||||
}));
|
||||
let id = self.emulator.add_block_hooks(
|
||||
BLOCK_HOOKS.last_mut().unwrap().as_mut().get_unchecked_mut(),
|
||||
gen,
|
||||
postgen,
|
||||
exec,
|
||||
);
|
||||
BLOCK_HOOKS
|
||||
.last_mut()
|
||||
.unwrap()
|
||||
.as_mut()
|
||||
.get_unchecked_mut()
|
||||
.id = id;
|
||||
id
|
||||
}
|
||||
}
|
||||
@ -648,7 +675,7 @@ where
|
||||
read_4_exec_hook_wrapper::<QT, S>,
|
||||
extern "C" fn(&mut HookState<5, ReadHookId>, id: u64, addr: GuestAddr, size: usize)
|
||||
);
|
||||
READ_HOOKS.push(HookState {
|
||||
READ_HOOKS.push(Box::pin(HookState {
|
||||
id: ReadHookId(0),
|
||||
gen: hook_to_repr!(generation_hook),
|
||||
post_gen: HookRepr::Empty,
|
||||
@ -659,9 +686,9 @@ where
|
||||
hook_to_repr!(execution_hook_8),
|
||||
hook_to_repr!(execution_hook_n),
|
||||
],
|
||||
});
|
||||
}));
|
||||
let id = self.emulator.add_read_hooks(
|
||||
READ_HOOKS.last_mut().unwrap(),
|
||||
READ_HOOKS.last_mut().unwrap().as_mut().get_unchecked_mut(),
|
||||
gen,
|
||||
exec1,
|
||||
exec2,
|
||||
@ -669,7 +696,12 @@ where
|
||||
exec8,
|
||||
execn,
|
||||
);
|
||||
READ_HOOKS.last_mut().unwrap().id = id;
|
||||
READ_HOOKS
|
||||
.last_mut()
|
||||
.unwrap()
|
||||
.as_mut()
|
||||
.get_unchecked_mut()
|
||||
.id = id;
|
||||
id
|
||||
}
|
||||
}
|
||||
@ -755,7 +787,7 @@ where
|
||||
size: usize,
|
||||
)
|
||||
);
|
||||
WRITE_HOOKS.push(HookState {
|
||||
WRITE_HOOKS.push(Box::pin(HookState {
|
||||
id: WriteHookId(0),
|
||||
gen: hook_to_repr!(generation_hook),
|
||||
post_gen: HookRepr::Empty,
|
||||
@ -766,9 +798,9 @@ where
|
||||
hook_to_repr!(execution_hook_8),
|
||||
hook_to_repr!(execution_hook_n),
|
||||
],
|
||||
});
|
||||
}));
|
||||
let id = self.emulator.add_write_hooks(
|
||||
WRITE_HOOKS.last_mut().unwrap(),
|
||||
WRITE_HOOKS.last_mut().unwrap().as_mut().get_unchecked_mut(),
|
||||
gen,
|
||||
exec1,
|
||||
exec2,
|
||||
@ -776,7 +808,12 @@ where
|
||||
exec8,
|
||||
execn,
|
||||
);
|
||||
WRITE_HOOKS.last_mut().unwrap().id = id;
|
||||
WRITE_HOOKS
|
||||
.last_mut()
|
||||
.unwrap()
|
||||
.as_mut()
|
||||
.get_unchecked_mut()
|
||||
.id = id;
|
||||
id
|
||||
}
|
||||
}
|
||||
@ -837,7 +874,7 @@ where
|
||||
cmp_3_exec_hook_wrapper::<QT, S>,
|
||||
extern "C" fn(&mut HookState<4, CmpHookId>, id: u64, v0: u64, v1: u64)
|
||||
);
|
||||
CMP_HOOKS.push(HookState {
|
||||
CMP_HOOKS.push(Box::pin(HookState {
|
||||
id: CmpHookId(0),
|
||||
gen: hook_to_repr!(generation_hook),
|
||||
post_gen: HookRepr::Empty,
|
||||
@ -847,16 +884,21 @@ where
|
||||
hook_to_repr!(execution_hook_4),
|
||||
hook_to_repr!(execution_hook_8),
|
||||
],
|
||||
});
|
||||
}));
|
||||
let id = self.emulator.add_cmp_hooks(
|
||||
CMP_HOOKS.last_mut().unwrap(),
|
||||
CMP_HOOKS.last_mut().unwrap().as_mut().get_unchecked_mut(),
|
||||
gen,
|
||||
exec1,
|
||||
exec2,
|
||||
exec4,
|
||||
exec8,
|
||||
);
|
||||
CMP_HOOKS.last_mut().unwrap().id = id;
|
||||
CMP_HOOKS
|
||||
.last_mut()
|
||||
.unwrap()
|
||||
.as_mut()
|
||||
.get_unchecked_mut()
|
||||
.id = id;
|
||||
id
|
||||
}
|
||||
}
|
||||
@ -895,12 +937,23 @@ where
|
||||
hook: Box<dyn for<'a> FnMut(&'a mut Self, Option<&'a mut S>, GuestAddr)>,
|
||||
) -> BackdoorHookId {
|
||||
unsafe {
|
||||
let mut fat: Box<FatPtr> = Box::new(transmute(hook));
|
||||
let fat: FatPtr = transmute(hook);
|
||||
BACKDOOR_HOOKS.push(Box::pin((BackdoorHookId(0), fat)));
|
||||
let id = self.emulator.add_backdoor_hook(
|
||||
transmute::<&mut FatPtr, &mut FatPtr>(&mut *fat), //transmute satisfy the lifetime
|
||||
&mut BACKDOOR_HOOKS
|
||||
.last_mut()
|
||||
.unwrap()
|
||||
.as_mut()
|
||||
.get_unchecked_mut()
|
||||
.1,
|
||||
closure_backdoor_hook_wrapper::<QT, S>,
|
||||
);
|
||||
BACKDOOR_HOOKS.push((id, fat));
|
||||
BACKDOOR_HOOKS
|
||||
.last_mut()
|
||||
.unwrap()
|
||||
.as_mut()
|
||||
.get_unchecked_mut()
|
||||
.0 = id;
|
||||
id
|
||||
}
|
||||
}
|
||||
@ -1008,12 +1061,23 @@ where
|
||||
>,
|
||||
) -> PreSyscallHookId {
|
||||
unsafe {
|
||||
let mut fat: Box<FatPtr> = Box::new(transmute(hook));
|
||||
let fat: FatPtr = transmute(hook);
|
||||
PRE_SYSCALL_HOOKS.push(Box::pin((PreSyscallHookId(0), fat)));
|
||||
let id = self.emulator.add_pre_syscall_hook(
|
||||
transmute::<&mut FatPtr, &mut FatPtr>(&mut *fat), //transmute satisfy the lifetime
|
||||
&mut PRE_SYSCALL_HOOKS
|
||||
.last_mut()
|
||||
.unwrap()
|
||||
.as_mut()
|
||||
.get_unchecked_mut()
|
||||
.1,
|
||||
closure_pre_syscall_hook_wrapper::<QT, S>,
|
||||
);
|
||||
PRE_SYSCALL_HOOKS.push((id, fat));
|
||||
PRE_SYSCALL_HOOKS
|
||||
.last_mut()
|
||||
.unwrap()
|
||||
.as_mut()
|
||||
.get_unchecked_mut()
|
||||
.0 = id;
|
||||
id
|
||||
}
|
||||
}
|
||||
@ -1126,12 +1190,23 @@ where
|
||||
>,
|
||||
) -> PostSyscallHookId {
|
||||
unsafe {
|
||||
let mut fat: Box<FatPtr> = Box::new(transmute(hook));
|
||||
let fat: FatPtr = transmute(hook);
|
||||
POST_SYSCALL_HOOKS.push(Box::pin((PostSyscallHookId(0), fat)));
|
||||
let id = self.emulator.add_post_syscall_hook(
|
||||
transmute::<&mut FatPtr, &mut FatPtr>(&mut *fat), //transmute satisfy the lifetime
|
||||
&mut POST_SYSCALL_HOOKS
|
||||
.last_mut()
|
||||
.unwrap()
|
||||
.as_mut()
|
||||
.get_unchecked_mut()
|
||||
.1,
|
||||
closure_post_syscall_hook_wrapper::<QT, S>,
|
||||
);
|
||||
POST_SYSCALL_HOOKS.push((id, fat));
|
||||
POST_SYSCALL_HOOKS
|
||||
.last_mut()
|
||||
.unwrap()
|
||||
.as_mut()
|
||||
.get_unchecked_mut()
|
||||
.0 = id;
|
||||
id
|
||||
}
|
||||
}
|
||||
@ -1173,12 +1248,23 @@ where
|
||||
hook: Box<dyn for<'a> FnMut(&'a mut Self, Option<&'a mut S>, u32) -> bool>,
|
||||
) -> NewThreadHookId {
|
||||
unsafe {
|
||||
let mut fat: Box<FatPtr> = Box::new(transmute(hook));
|
||||
let fat: FatPtr = transmute(hook);
|
||||
NEW_THREAD_HOOKS.push(Box::pin((NewThreadHookId(0), fat)));
|
||||
let id = self.emulator.add_new_thread_hook(
|
||||
transmute::<&mut FatPtr, &mut FatPtr>(&mut *fat), //transmute satisfy the lifetime
|
||||
&mut NEW_THREAD_HOOKS
|
||||
.last_mut()
|
||||
.unwrap()
|
||||
.as_mut()
|
||||
.get_unchecked_mut()
|
||||
.1,
|
||||
closure_new_thread_hook_wrapper::<QT, S>,
|
||||
);
|
||||
NEW_THREAD_HOOKS.push((id, fat));
|
||||
NEW_THREAD_HOOKS
|
||||
.last_mut()
|
||||
.unwrap()
|
||||
.as_mut()
|
||||
.get_unchecked_mut()
|
||||
.0 = id;
|
||||
id
|
||||
}
|
||||
}
|
||||
@ -1195,7 +1281,7 @@ where
|
||||
pub fn crash_closure(&self, hook: Box<dyn FnMut(&mut Self, i32)>) {
|
||||
unsafe {
|
||||
self.emulator.set_crash_hook(crash_hook_wrapper::<QT, S>);
|
||||
CRASH_HOOKS.push(HookRepr::Closure(Box::new(transmute(hook))));
|
||||
CRASH_HOOKS.push(HookRepr::Closure(transmute(hook)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user