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.
|
## Automatically register all `#[derive(SerdeAny)]` types at startup.
|
||||||
serdeany_autoreg = ["libafl_bolts/serdeany_autoreg"]
|
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)
|
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]
|
[dependencies]
|
||||||
libafl = { path = "../libafl", version = "0.11.2", default-features = false, features = ["std", "derive", "regex"] }
|
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"] }
|
libafl_bolts = { path = "../libafl_bolts", version = "0.11.2", default-features = false, features = ["std", "derive"] }
|
||||||
|
@ -95,6 +95,6 @@ pub fn build() {
|
|||||||
.status()
|
.status()
|
||||||
.expect("make failed")
|
.expect("make failed")
|
||||||
.success());
|
.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
|
all-features = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
shared = []
|
||||||
slirp = [] # build qemu with host libslirp (for user networking)
|
slirp = [] # build qemu with host libslirp (for user networking)
|
||||||
|
|
||||||
clippy = [] # special feature for clippy, don't use in normal projects§
|
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_DIRNAME: &str = "qemu-libafl-bridge";
|
||||||
const QEMU_REVISION: &str = "75d15d54f4417a4766d2dcb493982d9df0e8eac4";
|
const QEMU_REVISION: &str = "75d15d54f4417a4766d2dcb493982d9df0e8eac4";
|
||||||
|
|
||||||
|
pub struct BuildResult {
|
||||||
|
pub qemu_path: PathBuf,
|
||||||
|
pub build_dir: PathBuf,
|
||||||
|
}
|
||||||
|
|
||||||
fn build_dep_check(tools: &[&str]) {
|
fn build_dep_check(tools: &[&str]) {
|
||||||
for tool in tools {
|
for tool in tools {
|
||||||
which(tool).unwrap_or_else(|_| panic!("Build tool {tool} not found"));
|
which(tool).unwrap_or_else(|_| panic!("Build tool {tool} not found"));
|
||||||
@ -23,7 +28,7 @@ pub fn build(
|
|||||||
is_big_endian: bool,
|
is_big_endian: bool,
|
||||||
is_usermode: bool,
|
is_usermode: bool,
|
||||||
jobs: Option<u32>,
|
jobs: Option<u32>,
|
||||||
) -> (PathBuf, PathBuf) {
|
) -> BuildResult {
|
||||||
let mut cpu_target = cpu_target.to_string();
|
let mut cpu_target = cpu_target.to_string();
|
||||||
// qemu-system-arm supports both big and little endian configurations and so
|
// qemu-system-arm supports both big and little endian configurations and so
|
||||||
// therefore the "be" feature should ignored in this configuration. Also
|
// therefore the "be" feature should ignored in this configuration. Also
|
||||||
@ -120,13 +125,19 @@ pub fn build(
|
|||||||
"softmmu".to_string()
|
"softmmu".to_string()
|
||||||
};
|
};
|
||||||
|
|
||||||
let output_lib = if is_usermode {
|
let (output_lib, output_lib_link) = if is_usermode {
|
||||||
build_dir.join(format!("libqemu-{cpu_target}.so"))
|
(
|
||||||
|
build_dir.join(format!("libqemu-{cpu_target}.so")),
|
||||||
|
format!("qemu-{cpu_target}"),
|
||||||
|
)
|
||||||
} else {
|
} 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) {
|
if !output_lib.is_file() || (custom_qemu_dir.is_some() && !custom_qemu_no_build) {
|
||||||
/*drop(
|
/*drop(
|
||||||
@ -337,8 +348,15 @@ pub fn build(
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let compile_commands_string =
|
if cfg!(feature = "shared") {
|
||||||
&fs::read_to_string(build_dir.join("linkinfo.json")).expect("Failed to read linkinfo.json");
|
println!(
|
||||||
|
"cargo:rustc-link-search=native={}",
|
||||||
|
build_dir.to_string_lossy()
|
||||||
|
);
|
||||||
|
println!("cargo:rustc-link-lib=dylib={output_lib_link}");
|
||||||
|
} else {
|
||||||
|
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 linkinfo = json::parse(compile_commands_string).expect("Failed to parse linkinfo.json");
|
||||||
|
|
||||||
@ -469,6 +487,7 @@ pub fn build(
|
|||||||
.expect("linkinfo.json `libs` values must be strings");
|
.expect("linkinfo.json `libs` values must be strings");
|
||||||
println!("cargo:rustc-link-lib={val}");
|
println!("cargo:rustc-link-lib={val}");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
println!("cargo:rustc-link-lib=rt");
|
println!("cargo:rustc-link-lib=rt");
|
||||||
@ -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>,
|
jobs: Option<u32>,
|
||||||
bindings_file: &Path,
|
bindings_file: &Path,
|
||||||
) {
|
) {
|
||||||
let (qemu_dir, build_dir) = build::build(cpu_target, is_big_endian, is_usermode, jobs);
|
let build_result = 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 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");
|
.expect("Failed to generate the bindings");
|
||||||
bind.write_to_file(bindings_file)
|
bind.write_to_file(bindings_file)
|
||||||
.expect("Faield to write to the bindings file");
|
.expect("Faield to write to the bindings file");
|
||||||
|
@ -31,6 +31,7 @@ usermode = []
|
|||||||
systemmode = []
|
systemmode = []
|
||||||
|
|
||||||
slirp = [ "systemmode", "libafl_qemu_build/slirp" ] # build qemu with host libslirp (for user networking)
|
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§
|
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},
|
fmt::{self, Debug, Formatter},
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
mem::transmute,
|
mem::transmute,
|
||||||
|
pin::Pin,
|
||||||
ptr::{self, addr_of, addr_of_mut},
|
ptr::{self, addr_of, addr_of_mut},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -25,7 +26,7 @@ use crate::{
|
|||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||||
pub(crate) enum Hook {
|
pub(crate) enum Hook {
|
||||||
Function(*const c_void),
|
Function(*const c_void),
|
||||||
Closure(Box<FatPtr>),
|
Closure(FatPtr),
|
||||||
#[cfg(emulation_mode = "usermode")]
|
#[cfg(emulation_mode = "usermode")]
|
||||||
Once(Box<FatPtr>),
|
Once(Box<FatPtr>),
|
||||||
Empty,
|
Empty,
|
||||||
@ -36,7 +37,7 @@ pub(crate) enum Hook {
|
|||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
pub(crate) enum HookRepr {
|
pub(crate) enum HookRepr {
|
||||||
Function(*const c_void),
|
Function(*const c_void),
|
||||||
Closure(Box<FatPtr>),
|
Closure(FatPtr),
|
||||||
Empty,
|
Empty,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,7 +78,7 @@ macro_rules! hook_to_repr {
|
|||||||
($h:expr) => {
|
($h:expr) => {
|
||||||
match $h {
|
match $h {
|
||||||
Hook::Function(f) => HookRepr::Function(f as *const libc::c_void),
|
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::Raw(_) => HookRepr::Empty, // managed by emu
|
||||||
Hook::Empty => HookRepr::Empty,
|
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));
|
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));
|
create_wrapper!(backdoor, (pc: GuestAddr));
|
||||||
|
|
||||||
#[cfg(emulation_mode = "usermode")]
|
#[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")]
|
#[cfg(emulation_mode = "usermode")]
|
||||||
create_wrapper!(pre_syscall, (sys_num: i32,
|
create_wrapper!(pre_syscall, (sys_num: i32,
|
||||||
a0: GuestAddr,
|
a0: GuestAddr,
|
||||||
@ -260,7 +261,7 @@ create_wrapper!(pre_syscall, (sys_num: i32,
|
|||||||
a6: GuestAddr,
|
a6: GuestAddr,
|
||||||
a7: GuestAddr), SyscallHookResult);
|
a7: GuestAddr), SyscallHookResult);
|
||||||
#[cfg(emulation_mode = "usermode")]
|
#[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")]
|
#[cfg(emulation_mode = "usermode")]
|
||||||
create_wrapper!(post_syscall, (res: GuestAddr, sys_num: i32,
|
create_wrapper!(post_syscall, (res: GuestAddr, sys_num: i32,
|
||||||
a0: GuestAddr,
|
a0: GuestAddr,
|
||||||
@ -272,20 +273,20 @@ create_wrapper!(post_syscall, (res: GuestAddr, sys_num: i32,
|
|||||||
a6: GuestAddr,
|
a6: GuestAddr,
|
||||||
a7: GuestAddr), GuestAddr);
|
a7: GuestAddr), GuestAddr);
|
||||||
#[cfg(emulation_mode = "usermode")]
|
#[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")]
|
#[cfg(emulation_mode = "usermode")]
|
||||||
create_wrapper!(new_thread, (tid: u32), bool);
|
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_gen_wrapper!(edge, (src: GuestAddr, dest: GuestAddr), u64, 1, EdgeHookId);
|
||||||
create_exec_wrapper!(edge, (id: u64), 0, 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_gen_wrapper!(block, (addr: GuestAddr), u64, 1, BlockHookId);
|
||||||
create_post_gen_wrapper!(block, (addr: GuestAddr, len: GuestUsize), 1, BlockHookId);
|
create_post_gen_wrapper!(block, (addr: GuestAddr, len: GuestUsize), 1, BlockHookId);
|
||||||
create_exec_wrapper!(block, (id: u64), 0, 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_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), 0, 5, ReadHookId);
|
||||||
create_exec_wrapper!(read, (id: u64, addr: GuestAddr), 1, 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), 3, 5, ReadHookId);
|
||||||
create_exec_wrapper!(read, (id: u64, addr: GuestAddr, size: usize), 4, 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_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), 0, 5, WriteHookId);
|
||||||
create_exec_wrapper!(write, (id: u64, addr: GuestAddr), 1, 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), 3, 5, WriteHookId);
|
||||||
create_exec_wrapper!(write, (id: u64, addr: GuestAddr, size: usize), 4, 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_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: u8, v1: u8), 0, 4, CmpHookId);
|
||||||
create_exec_wrapper!(cmp, (id: u64, v0: u16, v1: u16), 1, 4, CmpHookId);
|
create_exec_wrapper!(cmp, (id: u64, v0: u16, v1: u16), 1, 4, CmpHookId);
|
||||||
@ -459,14 +460,25 @@ where
|
|||||||
invalidate_block: bool,
|
invalidate_block: bool,
|
||||||
) -> InstructionHookId {
|
) -> InstructionHookId {
|
||||||
unsafe {
|
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(
|
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,
|
addr,
|
||||||
closure_generic_hook_wrapper::<QT, S>,
|
closure_generic_hook_wrapper::<QT, S>,
|
||||||
invalidate_block,
|
invalidate_block,
|
||||||
);
|
);
|
||||||
GENERIC_HOOKS.push((id, fat));
|
GENERIC_HOOKS
|
||||||
|
.last_mut()
|
||||||
|
.unwrap()
|
||||||
|
.as_mut()
|
||||||
|
.get_unchecked_mut()
|
||||||
|
.0 = id;
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -506,16 +518,23 @@ where
|
|||||||
edge_0_exec_hook_wrapper::<QT, S>,
|
edge_0_exec_hook_wrapper::<QT, S>,
|
||||||
extern "C" fn(&mut HookState<1, EdgeHookId>, id: u64)
|
extern "C" fn(&mut HookState<1, EdgeHookId>, id: u64)
|
||||||
);
|
);
|
||||||
EDGE_HOOKS.push(HookState {
|
EDGE_HOOKS.push(Box::pin(HookState {
|
||||||
id: EdgeHookId(0),
|
id: EdgeHookId(0),
|
||||||
gen: hook_to_repr!(generation_hook),
|
gen: hook_to_repr!(generation_hook),
|
||||||
post_gen: HookRepr::Empty,
|
post_gen: HookRepr::Empty,
|
||||||
execs: [hook_to_repr!(execution_hook)],
|
execs: [hook_to_repr!(execution_hook)],
|
||||||
});
|
}));
|
||||||
let id = self
|
let id = self.emulator.add_edge_hooks(
|
||||||
.emulator
|
EDGE_HOOKS.last_mut().unwrap().as_mut().get_unchecked_mut(),
|
||||||
.add_edge_hooks(EDGE_HOOKS.last_mut().unwrap(), gen, exec);
|
gen,
|
||||||
EDGE_HOOKS.last_mut().unwrap().id = id;
|
exec,
|
||||||
|
);
|
||||||
|
EDGE_HOOKS
|
||||||
|
.last_mut()
|
||||||
|
.unwrap()
|
||||||
|
.as_mut()
|
||||||
|
.get_unchecked_mut()
|
||||||
|
.id = id;
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -558,16 +577,24 @@ where
|
|||||||
block_0_exec_hook_wrapper::<QT, S>,
|
block_0_exec_hook_wrapper::<QT, S>,
|
||||||
extern "C" fn(&mut HookState<1, BlockHookId>, id: u64)
|
extern "C" fn(&mut HookState<1, BlockHookId>, id: u64)
|
||||||
);
|
);
|
||||||
BLOCK_HOOKS.push(HookState {
|
BLOCK_HOOKS.push(Box::pin(HookState {
|
||||||
id: BlockHookId(0),
|
id: BlockHookId(0),
|
||||||
gen: hook_to_repr!(generation_hook),
|
gen: hook_to_repr!(generation_hook),
|
||||||
post_gen: hook_to_repr!(post_generation_hook),
|
post_gen: hook_to_repr!(post_generation_hook),
|
||||||
execs: [hook_to_repr!(execution_hook)],
|
execs: [hook_to_repr!(execution_hook)],
|
||||||
});
|
}));
|
||||||
let id =
|
let id = self.emulator.add_block_hooks(
|
||||||
self.emulator
|
BLOCK_HOOKS.last_mut().unwrap().as_mut().get_unchecked_mut(),
|
||||||
.add_block_hooks(BLOCK_HOOKS.last_mut().unwrap(), gen, postgen, exec);
|
gen,
|
||||||
BLOCK_HOOKS.last_mut().unwrap().id = id;
|
postgen,
|
||||||
|
exec,
|
||||||
|
);
|
||||||
|
BLOCK_HOOKS
|
||||||
|
.last_mut()
|
||||||
|
.unwrap()
|
||||||
|
.as_mut()
|
||||||
|
.get_unchecked_mut()
|
||||||
|
.id = id;
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -648,7 +675,7 @@ where
|
|||||||
read_4_exec_hook_wrapper::<QT, S>,
|
read_4_exec_hook_wrapper::<QT, S>,
|
||||||
extern "C" fn(&mut HookState<5, ReadHookId>, id: u64, addr: GuestAddr, size: usize)
|
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),
|
id: ReadHookId(0),
|
||||||
gen: hook_to_repr!(generation_hook),
|
gen: hook_to_repr!(generation_hook),
|
||||||
post_gen: HookRepr::Empty,
|
post_gen: HookRepr::Empty,
|
||||||
@ -659,9 +686,9 @@ where
|
|||||||
hook_to_repr!(execution_hook_8),
|
hook_to_repr!(execution_hook_8),
|
||||||
hook_to_repr!(execution_hook_n),
|
hook_to_repr!(execution_hook_n),
|
||||||
],
|
],
|
||||||
});
|
}));
|
||||||
let id = self.emulator.add_read_hooks(
|
let id = self.emulator.add_read_hooks(
|
||||||
READ_HOOKS.last_mut().unwrap(),
|
READ_HOOKS.last_mut().unwrap().as_mut().get_unchecked_mut(),
|
||||||
gen,
|
gen,
|
||||||
exec1,
|
exec1,
|
||||||
exec2,
|
exec2,
|
||||||
@ -669,7 +696,12 @@ where
|
|||||||
exec8,
|
exec8,
|
||||||
execn,
|
execn,
|
||||||
);
|
);
|
||||||
READ_HOOKS.last_mut().unwrap().id = id;
|
READ_HOOKS
|
||||||
|
.last_mut()
|
||||||
|
.unwrap()
|
||||||
|
.as_mut()
|
||||||
|
.get_unchecked_mut()
|
||||||
|
.id = id;
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -755,7 +787,7 @@ where
|
|||||||
size: usize,
|
size: usize,
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
WRITE_HOOKS.push(HookState {
|
WRITE_HOOKS.push(Box::pin(HookState {
|
||||||
id: WriteHookId(0),
|
id: WriteHookId(0),
|
||||||
gen: hook_to_repr!(generation_hook),
|
gen: hook_to_repr!(generation_hook),
|
||||||
post_gen: HookRepr::Empty,
|
post_gen: HookRepr::Empty,
|
||||||
@ -766,9 +798,9 @@ where
|
|||||||
hook_to_repr!(execution_hook_8),
|
hook_to_repr!(execution_hook_8),
|
||||||
hook_to_repr!(execution_hook_n),
|
hook_to_repr!(execution_hook_n),
|
||||||
],
|
],
|
||||||
});
|
}));
|
||||||
let id = self.emulator.add_write_hooks(
|
let id = self.emulator.add_write_hooks(
|
||||||
WRITE_HOOKS.last_mut().unwrap(),
|
WRITE_HOOKS.last_mut().unwrap().as_mut().get_unchecked_mut(),
|
||||||
gen,
|
gen,
|
||||||
exec1,
|
exec1,
|
||||||
exec2,
|
exec2,
|
||||||
@ -776,7 +808,12 @@ where
|
|||||||
exec8,
|
exec8,
|
||||||
execn,
|
execn,
|
||||||
);
|
);
|
||||||
WRITE_HOOKS.last_mut().unwrap().id = id;
|
WRITE_HOOKS
|
||||||
|
.last_mut()
|
||||||
|
.unwrap()
|
||||||
|
.as_mut()
|
||||||
|
.get_unchecked_mut()
|
||||||
|
.id = id;
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -837,7 +874,7 @@ where
|
|||||||
cmp_3_exec_hook_wrapper::<QT, S>,
|
cmp_3_exec_hook_wrapper::<QT, S>,
|
||||||
extern "C" fn(&mut HookState<4, CmpHookId>, id: u64, v0: u64, v1: u64)
|
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),
|
id: CmpHookId(0),
|
||||||
gen: hook_to_repr!(generation_hook),
|
gen: hook_to_repr!(generation_hook),
|
||||||
post_gen: HookRepr::Empty,
|
post_gen: HookRepr::Empty,
|
||||||
@ -847,16 +884,21 @@ where
|
|||||||
hook_to_repr!(execution_hook_4),
|
hook_to_repr!(execution_hook_4),
|
||||||
hook_to_repr!(execution_hook_8),
|
hook_to_repr!(execution_hook_8),
|
||||||
],
|
],
|
||||||
});
|
}));
|
||||||
let id = self.emulator.add_cmp_hooks(
|
let id = self.emulator.add_cmp_hooks(
|
||||||
CMP_HOOKS.last_mut().unwrap(),
|
CMP_HOOKS.last_mut().unwrap().as_mut().get_unchecked_mut(),
|
||||||
gen,
|
gen,
|
||||||
exec1,
|
exec1,
|
||||||
exec2,
|
exec2,
|
||||||
exec4,
|
exec4,
|
||||||
exec8,
|
exec8,
|
||||||
);
|
);
|
||||||
CMP_HOOKS.last_mut().unwrap().id = id;
|
CMP_HOOKS
|
||||||
|
.last_mut()
|
||||||
|
.unwrap()
|
||||||
|
.as_mut()
|
||||||
|
.get_unchecked_mut()
|
||||||
|
.id = id;
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -895,12 +937,23 @@ where
|
|||||||
hook: Box<dyn for<'a> FnMut(&'a mut Self, Option<&'a mut S>, GuestAddr)>,
|
hook: Box<dyn for<'a> FnMut(&'a mut Self, Option<&'a mut S>, GuestAddr)>,
|
||||||
) -> BackdoorHookId {
|
) -> BackdoorHookId {
|
||||||
unsafe {
|
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(
|
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>,
|
closure_backdoor_hook_wrapper::<QT, S>,
|
||||||
);
|
);
|
||||||
BACKDOOR_HOOKS.push((id, fat));
|
BACKDOOR_HOOKS
|
||||||
|
.last_mut()
|
||||||
|
.unwrap()
|
||||||
|
.as_mut()
|
||||||
|
.get_unchecked_mut()
|
||||||
|
.0 = id;
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1008,12 +1061,23 @@ where
|
|||||||
>,
|
>,
|
||||||
) -> PreSyscallHookId {
|
) -> PreSyscallHookId {
|
||||||
unsafe {
|
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(
|
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>,
|
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
|
id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1126,12 +1190,23 @@ where
|
|||||||
>,
|
>,
|
||||||
) -> PostSyscallHookId {
|
) -> PostSyscallHookId {
|
||||||
unsafe {
|
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(
|
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>,
|
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
|
id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1173,12 +1248,23 @@ where
|
|||||||
hook: Box<dyn for<'a> FnMut(&'a mut Self, Option<&'a mut S>, u32) -> bool>,
|
hook: Box<dyn for<'a> FnMut(&'a mut Self, Option<&'a mut S>, u32) -> bool>,
|
||||||
) -> NewThreadHookId {
|
) -> NewThreadHookId {
|
||||||
unsafe {
|
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(
|
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>,
|
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
|
id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1195,7 +1281,7 @@ where
|
|||||||
pub fn crash_closure(&self, hook: Box<dyn FnMut(&mut Self, i32)>) {
|
pub fn crash_closure(&self, hook: Box<dyn FnMut(&mut Self, i32)>) {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.emulator.set_crash_hook(crash_hook_wrapper::<QT, S>);
|
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