use std::ffi::c_void;
use std::ptr;
use crate::elf::NT_PRFPREG;
use crate::elf::NT_PRSTATUS;
use crate::CoreError;
use nix::sys::ptrace::Request;
use nix::sys::ptrace::RequestType;
use nix::unistd::Pid;
use zerocopy::FromBytes;
use zerocopy::IntoBytes;
pub fn ptrace_get_reg_set<T: IntoBytes + FromBytes>(
pid: Pid,
set: u32,
) -> Result<Vec<T>, CoreError> {
let mut data = Vec::with_capacity(0x1000 / size_of::<T>());
let vec = libc::iovec {
iov_base: data.as_mut_ptr() as *mut c_void,
iov_len: data.capacity() * size_of::<T>(),
};
let err;
unsafe {
err = libc::ptrace(
Request::PTRACE_GETREGSET as RequestType,
libc::pid_t::from(pid),
set,
&vec as *const _ as *const c_void,
);
data.set_len(vec.iov_len / size_of::<T>());
data.shrink_to_fit();
};
nix::errno::Errno::result(err)?;
Ok(data)
}
pub fn ptrace_interrupt(pid: Pid) -> Result<(), CoreError> {
let ret = unsafe {
nix::errno::Errno::clear();
libc::ptrace(
libc::PTRACE_INTERRUPT as RequestType,
libc::pid_t::from(pid),
ptr::null_mut::<c_void>(),
ptr::null_mut::<c_void>(),
)
};
match nix::errno::Errno::result(ret) {
Ok(..) => Ok(()),
Err(e) => Err(CoreError::NixError(e)),
}
}
pub fn get_gp_reg_set(pid: Pid) -> Result<Vec<u64>, CoreError> {
ptrace_get_reg_set(pid, NT_PRSTATUS)
}
pub fn get_fp_reg_set(pid: Pid) -> Result<Vec<u8>, CoreError> {
ptrace_get_reg_set(pid, NT_PRFPREG)
}