cfg_if::cfg_if! {
if #[cfg(target_arch = "x86_64")] {
type Value = u64;
#[inline]
unsafe fn valgrind_request(default: Value, args: &[Value; 6]) -> Value {
let result;
core::arch::asm!(
"rol rdi, 3",
"rol rdi, 13",
"rol rdi, 61",
"rol rdi, 51",
"xchg rbx, rbx",
inout("rdx") default => result,
in("rax") args.as_ptr(),
options(nostack),
);
result
}
} else if #[cfg(target_arch = "x86")] {
type Value = u32;
#[inline]
unsafe fn valgrind_request(default: Value, args: &[Value; 6]) -> Value {
let result;
core::arch::asm!(
"rol edi, 3",
"rol edi, 13",
"rol edi, 29",
"rol edi, 19",
"xchg ebx, ebx",
inout("edx") default => result,
in("eax") args.as_ptr(),
options(nostack),
);
result
}
} else if #[cfg(target_arch = "aarch64")] {
type Value = u64;
#[inline]
unsafe fn valgrind_request(default: Value, args: &[Value; 6]) -> Value {
let result;
core::arch::asm!(
"ror x12, x12, #3",
"ror x12, x12, #13",
"ror x12, x12, #61",
"ror x12, x12, #51",
"orr x10, x10, x10",
inout("x3") default => result,
in("x4") args.as_ptr(),
options(nostack),
);
result
}
} else if #[cfg(target_arch = "arm")] {
type Value = u32;
#[inline]
unsafe fn valgrind_request(default: Value, args: &[Value; 6]) -> Value {
let result;
core::arch::asm!(
"ror r12, r12, #3",
"ror r12, r12, #13",
"ror r12, r12, #29",
"ror r12, r12, #19",
"orr r10, r10, r10",
inout("r3") default => result,
in("r4") args.as_ptr(),
options(nostack),
);
result
}
} else if #[cfg(target_arch = "powerpc64")] {
type Value = u64;
#[inline]
unsafe fn valgrind_request(default: Value, _args: &[Value; 6]) -> Value {
default
}
} else if #[cfg(any(target_arch = "riscv64", target_arch = "riscv32"))] {
type Value = usize;
#[inline]
unsafe fn valgrind_request(default: Value, _args: &[Value; 6]) -> Value {
default
}
} else if #[cfg(target_arch = "loongarch64")] {
type Value = usize;
#[inline]
unsafe fn valgrind_request(default: Value, _args: &[Value; 6]) -> Value {
default
}
} else {
compile_error!("Unsupported target");
}
}
const STACK_REGISTER: Value = 0x1501;
const STACK_DEREGISTER: Value = 0x1502;
#[derive(Debug)]
pub struct ValgrindStackRegistration {
id: Value,
}
impl ValgrindStackRegistration {
#[inline]
pub fn new(addr: *mut u8, len: usize) -> Self {
Self {
id: unsafe {
valgrind_request(
0,
&[
STACK_REGISTER,
addr as Value,
addr as Value + len as Value,
0,
0,
0,
],
)
},
}
}
}
impl Drop for ValgrindStackRegistration {
#[inline]
fn drop(&mut self) {
unsafe {
valgrind_request(0, &[STACK_DEREGISTER, self.id, 0, 0, 0, 0]);
}
}
}