//! Parses ELF auxiliary vectors. #![cfg_attr( any( target_arch = "aarch64", target_arch = "arm", target_arch = "powerpc64", target_arch = "riscv64" ), allow(dead_code) )] /// Key to access the CPU Hardware capabilities bitfield. pub(crate) const AT_HWCAP: usize = 25; /// Key to access the CPU Hardware capabilities 2 bitfield. pub(crate) const AT_HWCAP2: usize = 26; /// Cache HWCAP bitfields of the ELF Auxiliary Vector. /// /// If an entry cannot be read all the bits in the bitfield are set to zero. /// This should be interpreted as all the features being disabled. #[derive(Debug, Copy, Clone)] pub(crate) struct AuxVec { pub hwcap: usize, pub hwcap2: usize, } /// ELF Auxiliary Vector /// /// The auxiliary vector is a memory region in a running ELF program's stack /// composed of (key: usize, value: usize) pairs. /// /// The keys used in the aux vector are platform dependent. For FreeBSD, they are /// defined in [sys/elf_common.h][elf_common_h]. The hardware capabilities of a given /// CPU can be queried with the `AT_HWCAP` and `AT_HWCAP2` keys. /// /// Note that run-time feature detection is not invoked for features that can /// be detected at compile-time. /// /// [elf_common.h]: https://svnweb.freebsd.org/base/release/12.0.0/sys/sys/elf_common.h?revision=341707 pub(crate) fn auxv() -> Result { if let Ok(hwcap) = archauxv(AT_HWCAP) { if let Ok(hwcap2) = archauxv(AT_HWCAP2) { if hwcap != 0 && hwcap2 != 0 { return Ok(AuxVec { hwcap, hwcap2 }); } } } Err(()) } /// Tries to read the `key` from the auxiliary vector. fn archauxv(key: usize) -> Result { use core::mem; #[derive(Copy, Clone)] #[repr(C)] pub struct Elf_Auxinfo { pub a_type: usize, pub a_un: unnamed, } #[derive(Copy, Clone)] #[repr(C)] pub union unnamed { pub a_val: libc::c_long, pub a_ptr: *mut libc::c_void, pub a_fcn: Option ()>, } let mut auxv: [Elf_Auxinfo; 27] = [Elf_Auxinfo { a_type: 0, a_un: unnamed { a_val: 0 }, }; 27]; let mut len: libc::c_uint = mem::size_of_val(&auxv) as libc::c_uint; unsafe { let mut mib = [ libc::CTL_KERN, libc::KERN_PROC, libc::KERN_PROC_AUXV, libc::getpid(), ]; let ret = libc::sysctl( mib.as_mut_ptr(), mib.len() as u32, &mut auxv as *mut _ as *mut _, &mut len as *mut _ as *mut _, 0 as *mut libc::c_void, 0, ); if ret != -1 { for i in 0..auxv.len() { if auxv[i].a_type == key { return Ok(auxv[i].a_un.a_val as usize); } } } } return Ok(0); }