Apple aarch64 fixes (#660)
* Apple aarch64 fixes * added shmem provider testcase * added method to not ignore cores, removed deprecated core_affinity api * cleaned up set_affinity tests * fixes * fixes * more aarch * apple needs serial tests * disable testcase for now
This commit is contained in:
parent
e7e82af52c
commit
2e746bf439
@ -16,7 +16,7 @@
|
||||
//! let handles = core_ids.into_iter().map(|id| {
|
||||
//! thread::spawn(move || {
|
||||
//! // Pin this thread to a single CPU core.
|
||||
//! core_affinity::set_for_current(id);
|
||||
//! id.set_affinity();
|
||||
//! // Do more work after this.
|
||||
//! })
|
||||
//! }).collect::<Vec<_>>();
|
||||
@ -43,16 +43,6 @@ pub fn get_core_ids() -> Result<Vec<CoreId>, Error> {
|
||||
get_core_ids_helper()
|
||||
}
|
||||
|
||||
/// This function tries to pin the current
|
||||
/// thread to the specified core.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `core_id` - `ID` of the core to pin
|
||||
pub fn set_for_current(core_id: CoreId) -> Result<(), Error> {
|
||||
set_for_current_helper(core_id)
|
||||
}
|
||||
|
||||
/// This represents a CPU core.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct CoreId {
|
||||
@ -62,8 +52,21 @@ pub struct CoreId {
|
||||
|
||||
impl CoreId {
|
||||
/// Set the affinity of the current process to this [`CoreId`]
|
||||
///
|
||||
/// Note: This will *_not_* fail if the target platform does not support core affinity.
|
||||
/// (only on error cases for supported platforms)
|
||||
/// If you really need to fail for unsupported platforms (like `aarch64` on `macOS`), use [`CoreId::set_affinity_forced`] instead.
|
||||
///
|
||||
pub fn set_affinity(&self) -> Result<(), Error> {
|
||||
set_for_current(*self)
|
||||
match set_for_current_helper(*self) {
|
||||
Ok(_) | Err(Error::Unsupported(_, _)) => Ok(()),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the affinity of the current process to this [`CoreId`]
|
||||
pub fn set_affinity_forced(&self) -> Result<(), Error> {
|
||||
set_for_current_helper(*self)
|
||||
}
|
||||
}
|
||||
|
||||
@ -274,8 +277,6 @@ mod linux {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use num_cpus;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
@ -283,19 +284,13 @@ mod linux {
|
||||
get_affinity_mask().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_linux_get_core_ids() {
|
||||
let set = get_core_ids().unwrap();
|
||||
assert_eq!(set.len(), num_cpus::get());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_linux_set_for_current() {
|
||||
let ids = get_core_ids().unwrap();
|
||||
|
||||
assert!(!ids.is_empty());
|
||||
|
||||
set_for_current(ids[0]).unwrap();
|
||||
ids[0].set_affinity().unwrap();
|
||||
|
||||
// Ensure that the system pinned the current thread
|
||||
// to the specified core.
|
||||
@ -542,28 +537,6 @@ mod windows {
|
||||
|
||||
Some(n_logical_procs)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use num_cpus;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_apple_get_core_ids() {
|
||||
let set = get_core_ids().unwrap();
|
||||
assert_eq!(set.len(), num_cpus::get());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_apple_set_for_current() {
|
||||
let ids = get_core_ids().unwrap();
|
||||
|
||||
assert!(!ids.is_empty());
|
||||
|
||||
set_for_current(ids[0]).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apple Section
|
||||
@ -590,8 +563,8 @@ mod apple {
|
||||
use alloc::vec::Vec;
|
||||
use libc::{
|
||||
integer_t, kern_return_t, mach_msg_type_number_t, pthread_mach_thread_np, pthread_self,
|
||||
thread_policy_flavor_t, thread_policy_t, thread_t, THREAD_AFFINITY_POLICY,
|
||||
THREAD_AFFINITY_POLICY_COUNT,
|
||||
thread_policy_flavor_t, thread_policy_t, thread_t, KERN_NOT_SUPPORTED, KERN_SUCCESS,
|
||||
THREAD_AFFINITY_POLICY, THREAD_AFFINITY_POLICY_COUNT,
|
||||
};
|
||||
use num_cpus;
|
||||
|
||||
@ -632,9 +605,18 @@ mod apple {
|
||||
);
|
||||
|
||||
// 0 == KERN_SUCCESS
|
||||
|
||||
if result == 0 {
|
||||
if result == KERN_SUCCESS {
|
||||
Ok(())
|
||||
} else if result == KERN_NOT_SUPPORTED {
|
||||
// 46 == KERN_NOT_SUPPORTED
|
||||
// Seting a core affinity is not supported on aarch64 apple...
|
||||
// We won't report this as an error to the user, a there's nothing they could do about it.
|
||||
// Error codes, see <https://opensource.apple.com/source/xnu/xnu-792/osfmk/mach/kern_return.h>
|
||||
//|| (cfg!(all(target_vendor = "apple", target_arch = "aarch64"))
|
||||
// && result == KERN_NOT_SUPPORTED)
|
||||
Err(Error::unsupported(
|
||||
"Setting a core affinity is not supported on this platform (KERN_NOT_SUPPORTED)",
|
||||
))
|
||||
} else {
|
||||
Err(Error::unknown(format!(
|
||||
"Failed to set_for_current {:?}",
|
||||
@ -643,28 +625,6 @@ mod apple {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use num_cpus;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_windows_get_core_ids() {
|
||||
let set = get_core_ids().unwrap();
|
||||
assert_eq!(set.len(), num_cpus::get());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_windows_set_for_current() {
|
||||
let ids = get_core_ids().unwrap();
|
||||
|
||||
assert!(!ids.is_empty());
|
||||
|
||||
set_for_current(ids[0]).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -684,11 +644,11 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_set_for_current() {
|
||||
fn test_set_affinity() {
|
||||
let ids = get_core_ids().unwrap();
|
||||
|
||||
assert!(!ids.is_empty());
|
||||
|
||||
set_for_current(ids[0]).unwrap();
|
||||
ids[0].set_affinity().unwrap();
|
||||
}
|
||||
}
|
||||
|
@ -2745,7 +2745,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
pub fn llmp_connection() {
|
||||
pub fn test_llmp_connection() {
|
||||
#[allow(unused_variables)]
|
||||
let shmem_provider = StdShMemProvider::new().unwrap();
|
||||
let mut broker = match LlmpConnection::on_port(shmem_provider.clone(), 1337).unwrap() {
|
||||
|
@ -103,7 +103,7 @@ pub fn dump_registers<W: Write>(
|
||||
writer: &mut BufWriter<W>,
|
||||
ucontext: &ucontext_t,
|
||||
) -> Result<(), std::io::Error> {
|
||||
let mcontext = unsafe { *ucontext.uc_mcontext };
|
||||
let mcontext = unsafe { &*ucontext.uc_mcontext };
|
||||
for reg in 0..29_u8 {
|
||||
writeln!(
|
||||
writer,
|
||||
@ -225,7 +225,7 @@ fn write_crash<W: Write>(
|
||||
signal: Signal,
|
||||
ucontext: &ucontext_t,
|
||||
) -> Result<(), std::io::Error> {
|
||||
let mcontext = unsafe { *ucontext.uc_mcontext };
|
||||
let mcontext = unsafe { &*ucontext.uc_mcontext };
|
||||
writeln!(
|
||||
writer,
|
||||
"Received signal {} at 0x{:016x}, fault address: 0x{:016x}",
|
||||
|
@ -190,6 +190,7 @@ where
|
||||
res.id = id;
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
fn new_shmem(&mut self, map_size: usize) -> Result<Self::ShMem, Error> {
|
||||
let (server_fd, client_fd) = self.send_receive(ServedShMemRequest::NewMap(map_size))?;
|
||||
|
||||
@ -718,3 +719,25 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
TODO: Fix test
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use serial_test::serial;
|
||||
|
||||
use crate::bolts::{
|
||||
os::unix_shmem_server::ServedShMemProvider,
|
||||
shmem::{ShMem, ShMemProvider, UnixShMemProvider},
|
||||
};
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_shmem_server_connection() {
|
||||
let mut sp = ServedShMemProvider::<UnixShMemProvider>::new().unwrap();
|
||||
let map = sp.new_shmem(2 << 14).unwrap();
|
||||
assert!(map.is_empty());
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
@ -67,8 +67,8 @@ pub struct mcontext_t {
|
||||
pub fault_address: c_ulong,
|
||||
}
|
||||
|
||||
/// User Context Struct
|
||||
#[cfg(target_arch = "arm")]
|
||||
/// User Context Struct on `arm` `linux`
|
||||
#[cfg(all(target_os = "linux", target_arch = "arm"))]
|
||||
#[derive(Debug)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[repr(C)]
|
||||
@ -85,9 +85,165 @@ pub struct ucontext_t {
|
||||
pub uc_sigmask: libc::sigset_t,
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "arm"))]
|
||||
/// # Internal representation
|
||||
///
|
||||
/// ```c
|
||||
/// _STRUCT_ARM_EXCEPTION_STATE64
|
||||
/// {
|
||||
/// __uint64_t far; /* Virtual Fault Address */
|
||||
/// __uint32_t esr; /* Exception syndrome */
|
||||
/// __uint32_t exception; /* number of arm exception taken */
|
||||
/// };
|
||||
/// ```
|
||||
#[cfg(all(target_vendor = "apple", target_arch = "aarch64"))]
|
||||
#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
pub struct arm_exception_state64 {
|
||||
/// Virtual Fault Address
|
||||
pub __far: u64,
|
||||
/// Exception syndrome
|
||||
pub __esr: u32,
|
||||
/// number of arm exception taken
|
||||
pub __exception: u32,
|
||||
}
|
||||
|
||||
/// ```c
|
||||
/// _STRUCT_ARM_THREAD_STATE64
|
||||
/// {
|
||||
/// __uint64_t __x[29]; /* General purpose registers x0-x28 */
|
||||
/// __uint64_t __fp; /* Frame pointer x29 */
|
||||
/// __uint64_t __lr; /* Link register x30 */
|
||||
/// __uint64_t __sp; /* Stack pointer x31 */
|
||||
/// __uint64_t __pc; /* Program counter */
|
||||
/// __uint32_t __cpsr; /* Current program status register */
|
||||
/// __uint32_t __pad; /* Same size for 32-bit or 64-bit clients */
|
||||
/// };
|
||||
/// ```
|
||||
#[cfg(all(target_vendor = "apple", target_arch = "aarch64"))]
|
||||
#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
pub struct arm_thread_state64 {
|
||||
/// General purpose registers x0-x28
|
||||
pub __x: [u64; 29],
|
||||
/// Frame pointer x29
|
||||
pub __fp: u64,
|
||||
/// Link register x30
|
||||
pub __lr: u64,
|
||||
/// Stack pointer x31
|
||||
pub __sp: u64,
|
||||
/// Program counter
|
||||
pub __pc: u64,
|
||||
/// Current program status register
|
||||
pub __cpsr: u32,
|
||||
/// Same size for 32-bit or 64-bit clients
|
||||
pub __pad: u32,
|
||||
}
|
||||
|
||||
/// ```c
|
||||
/// _STRUCT_ARM_NEON_STATE64
|
||||
/// {
|
||||
/// char opaque[(32 * 16) + (2 * sizeof(__uint32_t))];
|
||||
/// } __attribute__((aligned(16)));
|
||||
/// ````
|
||||
#[cfg(all(target_vendor = "apple", target_arch = "aarch64"))]
|
||||
#[derive(Debug)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[repr(C, align(16))]
|
||||
//#[repr(align(16))]
|
||||
pub struct arm_neon_state64 {
|
||||
/// opaque
|
||||
pub opaque: [u8; (32 * 16) + (2 * mem::size_of::<u32>())],
|
||||
}
|
||||
|
||||
/// ```c
|
||||
/// _STRUCT_MCONTEXT64
|
||||
/// {
|
||||
/// _STRUCT_ARM_EXCEPTION_STATE64 es;
|
||||
/// _STRUCT_ARM_THREAD_STATE64 ss;
|
||||
/// _STRUCT_ARM_NEON_STATE64 ns;
|
||||
///};
|
||||
/// ```
|
||||
#[cfg(all(target_vendor = "apple", target_arch = "aarch64"))]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
pub struct mcontext64 {
|
||||
/// _STRUCT_ARM_EXCEPTION_STATE64
|
||||
pub __es: arm_exception_state64,
|
||||
/// _STRUCT_ARM_THREAD_STATE64
|
||||
pub __ss: arm_thread_state64,
|
||||
/// _STRUCT_ARM_NEON_STATE64
|
||||
pub __ns: arm_neon_state64,
|
||||
}
|
||||
|
||||
/// ```c
|
||||
/// _STRUCT_SIGALTSTACK
|
||||
/// {
|
||||
/// void *ss_sp; /* signal stack base */
|
||||
/// __darwin_size_t ss_size; /* signal stack length */
|
||||
/// int ss_flags; /* SA_DISABLE and/or SA_ONSTACK */
|
||||
/// };
|
||||
/// ````
|
||||
#[cfg(all(target_vendor = "apple", target_arch = "aarch64"))]
|
||||
#[derive(Debug)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[repr(C)]
|
||||
pub struct sigaltstack {
|
||||
/// signal stack base
|
||||
pub ss_sp: *mut c_void,
|
||||
/// signal stack length
|
||||
pub ss_size: libc::size_t,
|
||||
/// SA_DISABLE and/or SA_ONSTACK
|
||||
pub ss_flags: c_int,
|
||||
}
|
||||
|
||||
/// User Context Struct on apple `aarch64`
|
||||
///
|
||||
/// ```c
|
||||
/// _STRUCT_UCONTEXT
|
||||
/// {
|
||||
/// int uc_onstack;
|
||||
/// __darwin_sigset_t uc_sigmask; /* signal mask used by this context */
|
||||
/// _STRUCT_SIGALTSTACK uc_stack; /* stack used by this context */
|
||||
/// _STRUCT_UCONTEXT *uc_link; /* pointer to resuming context */
|
||||
/// __darwin_size_t uc_mcsize; /* size of the machine context passed in */
|
||||
/// _STRUCT_MCONTEXT *uc_mcontext; /* pointer to machine specific context */
|
||||
/// #ifdef _XOPEN_SOURCE
|
||||
/// _STRUCT_MCONTEXT __mcontext_data;
|
||||
/// #endif /* _XOPEN_SOURCE */
|
||||
/// };
|
||||
/// ```
|
||||
#[cfg(all(target_vendor = "apple", target_arch = "aarch64"))]
|
||||
#[derive(Debug)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[repr(C)]
|
||||
pub struct ucontext_t {
|
||||
/// onstack
|
||||
pub uc_onstack: c_int,
|
||||
/// signal mask used by this context
|
||||
pub uc_sigmask: u32,
|
||||
/// stack used by this context
|
||||
pub uc_stack: sigaltstack,
|
||||
/// pointer to resuming context
|
||||
pub uc_link: *mut c_void,
|
||||
/// size of the machine context passed in
|
||||
pub uc_mcsize: ssize_t,
|
||||
/// pointer to machine specific context
|
||||
pub uc_mcontext: *mut mcontext64,
|
||||
/// The mcontext data in multiple steps.
|
||||
pub mcontext_data: mcontext64,
|
||||
}
|
||||
|
||||
pub use libc::{c_void, siginfo_t};
|
||||
|
||||
#[cfg(not(any(
|
||||
all(target_os = "linux", target_arch = "arm"),
|
||||
all(target_vendor = "apple", target_arch = "aarch64")
|
||||
)))]
|
||||
pub use libc::ucontext_t;
|
||||
|
||||
#[cfg(all(target_vendor = "apple", target_arch = "aarch64"))]
|
||||
use libc::ssize_t;
|
||||
use libc::{
|
||||
c_int, malloc, sigaction, sigaddset, sigaltstack, sigemptyset, stack_t, SA_NODEFER, SA_ONSTACK,
|
||||
SA_SIGINFO, SIGABRT, SIGALRM, SIGBUS, SIGFPE, SIGHUP, SIGILL, SIGINT, SIGKILL, SIGPIPE,
|
||||
@ -97,17 +253,10 @@ use num_enum::{IntoPrimitive, TryFromPrimitive};
|
||||
|
||||
use crate::Error;
|
||||
|
||||
pub use libc::{c_void, siginfo_t};
|
||||
|
||||
extern "C" {
|
||||
/// The `libc` `getcontext`
|
||||
/// For some reason, it's not available on MacOS.
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// Somehow, `MacOS` on `aarch64` claims this type uses a 128 bit `int`
|
||||
/// (@`rustc` 1.59.0)
|
||||
/// Not much we can about it, for now.
|
||||
#[allow(improper_ctypes)]
|
||||
fn getcontext(ucp: *mut ucontext_t) -> c_int;
|
||||
}
|
||||
|
||||
|
@ -12,10 +12,7 @@ use crate::bolts::{
|
||||
llmp::{LLMP_FLAG_COMPRESSED, LLMP_FLAG_INITIALIZED},
|
||||
};
|
||||
#[cfg(feature = "std")]
|
||||
use crate::bolts::{
|
||||
core_affinity::set_for_current, llmp::LlmpConnection, shmem::StdShMemProvider,
|
||||
staterestore::StateRestorer,
|
||||
};
|
||||
use crate::bolts::{llmp::LlmpConnection, shmem::StdShMemProvider, staterestore::StateRestorer};
|
||||
use crate::{
|
||||
bolts::{
|
||||
llmp::{self, Flags, LlmpClient, LlmpClientDescription, Tag},
|
||||
@ -825,8 +822,9 @@ where
|
||||
};
|
||||
|
||||
if let Some(core_id) = core_id {
|
||||
let core_id: CoreId = core_id;
|
||||
println!("Setting core affinity to {:?}", core_id);
|
||||
set_for_current(core_id)?;
|
||||
core_id.set_affinity()?;
|
||||
}
|
||||
|
||||
// We are the fuzzer respawner in a llmp client
|
||||
@ -894,7 +892,8 @@ where
|
||||
};
|
||||
|
||||
if let Some(core_id) = core_id {
|
||||
set_for_current(core_id)?;
|
||||
let core_id: CoreId = core_id;
|
||||
core_id.set_affinity()?;
|
||||
}
|
||||
|
||||
// If we're restarting, deserialize the old state.
|
||||
|
@ -41,8 +41,8 @@ use super::HasObservers;
|
||||
/// `StdIn`: The traget reads from stdin
|
||||
/// `File`: The target reads from the specified [`InputFile`]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
enum InputLocation {
|
||||
/// Mutate a commandline argument to deliver an input
|
||||
pub enum InputLocation {
|
||||
/// Mutate a command line argument to deliver an input
|
||||
Arg {
|
||||
/// The offset of the argument to mutate
|
||||
argnum: usize,
|
||||
|
@ -1624,6 +1624,7 @@ pub mod child_signal_handlers {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use core::marker::PhantomData;
|
||||
use serial_test::serial;
|
||||
|
||||
#[cfg(all(feature = "std", feature = "fork", unix))]
|
||||
use crate::{
|
||||
@ -1653,6 +1654,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
#[cfg(all(feature = "std", feature = "fork", unix))]
|
||||
fn test_inprocessfork_exec() {
|
||||
use crate::executors::inprocess::InChildProcessHandlers;
|
||||
|
@ -161,6 +161,8 @@ pub enum Error {
|
||||
IllegalState(String, ErrorBacktrace),
|
||||
/// The argument passed to this method or function is not valid
|
||||
IllegalArgument(String, ErrorBacktrace),
|
||||
/// The performed action is not supported on the current platform
|
||||
Unsupported(String, ErrorBacktrace),
|
||||
/// Shutting down, not really an error.
|
||||
ShuttingDown,
|
||||
/// Something else happened
|
||||
@ -249,6 +251,14 @@ impl Error {
|
||||
pub fn shutting_down() -> Self {
|
||||
Error::ShuttingDown
|
||||
}
|
||||
/// This operation is not supported on the current architecture or platform
|
||||
#[must_use]
|
||||
pub fn unsupported<S>(arg: S) -> Self
|
||||
where
|
||||
S: Into<String>,
|
||||
{
|
||||
Error::Unsupported(arg.into(), ErrorBacktrace::new())
|
||||
}
|
||||
/// Something else happened
|
||||
#[must_use]
|
||||
pub fn unknown<S>(arg: S) -> Self
|
||||
@ -304,6 +314,14 @@ impl fmt::Display for Error {
|
||||
write!(f, "Illegal argument: {0}", &s)?;
|
||||
display_error_backtrace(f, b)
|
||||
}
|
||||
Self::Unsupported(s, b) => {
|
||||
write!(
|
||||
f,
|
||||
"The operation is not supported on the current platform: {0}",
|
||||
&s
|
||||
)?;
|
||||
display_error_backtrace(f, b)
|
||||
}
|
||||
Self::ShuttingDown => write!(f, "Shutting down!"),
|
||||
Self::Unknown(s, b) => {
|
||||
write!(f, "Unknown error: {0}", &s)?;
|
||||
|
Loading…
x
Reference in New Issue
Block a user