diff options
Diffstat (limited to 'library/stdarch/crates/std_detect/src/detect')
11 files changed, 159 insertions, 71 deletions
diff --git a/library/stdarch/crates/std_detect/src/detect/cache.rs b/library/stdarch/crates/std_detect/src/detect/cache.rs index e79c96dafaf..d01a5ea244d 100644 --- a/library/stdarch/crates/std_detect/src/detect/cache.rs +++ b/library/stdarch/crates/std_detect/src/detect/cache.rs @@ -3,9 +3,9 @@ #![allow(dead_code)] // not used on all platforms -use crate::sync::atomic::Ordering; +use core::sync::atomic::Ordering; -use crate::sync::atomic::AtomicUsize; +use core::sync::atomic::AtomicUsize; /// Sets the `bit` of `x`. #[inline] @@ -125,9 +125,16 @@ cfg_if::cfg_if! { if #[cfg(feature = "std_detect_env_override")] { #[inline] fn initialize(mut value: Initializer) -> Initializer { - if let Ok(disable) = crate::env::var("RUST_STD_DETECT_UNSTABLE") { - for v in disable.split(" ") { - let _ = super::Feature::from_str(v).map(|v| value.unset(v as u32)); + let env = unsafe { + libc::getenv(b"RUST_STD_DETECT_UNSTABLE\0".as_ptr() as *const libc::c_char) + }; + if !env.is_null() { + let len = unsafe { libc::strlen(env) }; + let env = unsafe { core::slice::from_raw_parts(env as *const u8, len) }; + if let Ok(disable) = core::str::from_utf8(env) { + for v in disable.split(" ") { + let _ = super::Feature::from_str(v).map(|v| value.unset(v as u32)); + } } } do_initialize(value); diff --git a/library/stdarch/crates/std_detect/src/detect/mod.rs b/library/stdarch/crates/std_detect/src/detect/mod.rs index 7aedef47d66..1b7768ae8f0 100644 --- a/library/stdarch/crates/std_detect/src/detect/mod.rs +++ b/library/stdarch/crates/std_detect/src/detect/mod.rs @@ -98,10 +98,10 @@ cfg_if! { // On x86/x86_64 no OS specific functionality is required. #[path = "os/x86.rs"] mod os; - } else if #[cfg(all(target_os = "linux", feature = "use_std"))] { + } else if #[cfg(all(target_os = "linux", feature = "libc"))] { #[path = "os/linux/mod.rs"] mod os; - } else if #[cfg(all(target_os = "freebsd", feature = "use_std"))] { + } else if #[cfg(all(target_os = "freebsd", feature = "libc"))] { #[cfg(target_arch = "aarch64")] #[path = "os/aarch64.rs"] mod aarch64; @@ -140,7 +140,7 @@ pub fn features() -> impl Iterator<Item = (&'static str, bool)> { target_arch = "mips64", ))] { (0_u8..Feature::_last as u8).map(|discriminant: u8| { - let f: Feature = unsafe { crate::mem::transmute(discriminant) }; + let f: Feature = unsafe { core::mem::transmute(discriminant) }; let name: &'static str = f.to_str(); let enabled: bool = check_for(f); (name, enabled) diff --git a/library/stdarch/crates/std_detect/src/detect/os/freebsd/auxvec.rs b/library/stdarch/crates/std_detect/src/detect/os/freebsd/auxvec.rs index c595ec459b5..832ce2252ed 100644 --- a/library/stdarch/crates/std_detect/src/detect/os/freebsd/auxvec.rs +++ b/library/stdarch/crates/std_detect/src/detect/os/freebsd/auxvec.rs @@ -42,7 +42,7 @@ pub(crate) fn auxv() -> Result<AuxVec, ()> { /// Tries to read the `key` from the auxiliary vector. fn archauxv(key: usize) -> Result<usize, ()> { - use crate::mem; + use core::mem; #[derive(Copy, Clone)] #[repr(C)] diff --git a/library/stdarch/crates/std_detect/src/detect/os/freebsd/mod.rs b/library/stdarch/crates/std_detect/src/detect/os/freebsd/mod.rs index 4321bce74dd..ade7fb6269d 100644 --- a/library/stdarch/crates/std_detect/src/detect/os/freebsd/mod.rs +++ b/library/stdarch/crates/std_detect/src/detect/os/freebsd/mod.rs @@ -5,18 +5,18 @@ mod auxvec; cfg_if::cfg_if! { if #[cfg(target_arch = "aarch64")] { mod aarch64; - pub use self::aarch64::check_for; + pub(crate) use self::aarch64::detect_features; } else if #[cfg(target_arch = "arm")] { mod arm; - pub use self::arm::check_for; + pub(crate) use self::arm::detect_features; } else if #[cfg(target_arch = "powerpc64")] { mod powerpc; - pub use self::powerpc::check_for; + pub(crate) use self::powerpc::detect_features; } else { - use crate::arch::detect::Feature; + use crate::detect::cache; /// Performs run-time feature detection. - pub fn check_for(_x: Feature) -> bool { - false + pub(crate) fn detect_features() -> cache::Initializer { + cache::Initializer::default() } } } diff --git a/library/stdarch/crates/std_detect/src/detect/os/linux/aarch64.rs b/library/stdarch/crates/std_detect/src/detect/os/linux/aarch64.rs index b1b68f763e5..80c36e9b997 100644 --- a/library/stdarch/crates/std_detect/src/detect/os/linux/aarch64.rs +++ b/library/stdarch/crates/std_detect/src/detect/os/linux/aarch64.rs @@ -1,6 +1,6 @@ //! Run-time feature detection for Aarch64 on Linux. -use super::{auxvec, cpuinfo}; +use super::auxvec; use crate::detect::{bit, cache, Feature}; /// Try to read the features from the auxiliary vector, and if that fails, try @@ -10,7 +10,8 @@ pub(crate) fn detect_features() -> cache::Initializer { let hwcap: AtHwcap = auxv.into(); return hwcap.cache(); } - if let Ok(c) = cpuinfo::CpuInfo::new() { + #[cfg(feature = "std_detect_file_io")] + if let Ok(c) = super::cpuinfo::CpuInfo::new() { let hwcap: AtHwcap = c.into(); return hwcap.cache(); } @@ -77,9 +78,10 @@ impl From<auxvec::AuxVec> for AtHwcap { } } -impl From<cpuinfo::CpuInfo> for AtHwcap { +#[cfg(feature = "std_detect_file_io")] +impl From<super::cpuinfo::CpuInfo> for AtHwcap { /// Reads AtHwcap from /proc/cpuinfo . - fn from(c: cpuinfo::CpuInfo) -> Self { + fn from(c: super::cpuinfo::CpuInfo) -> Self { let f = &c.field("Features"); AtHwcap { // 64-bit names. FIXME: In 32-bit compatibility mode /proc/cpuinfo will diff --git a/library/stdarch/crates/std_detect/src/detect/os/linux/arm.rs b/library/stdarch/crates/std_detect/src/detect/os/linux/arm.rs index 4b0cb586bba..66cfd05e806 100644 --- a/library/stdarch/crates/std_detect/src/detect/os/linux/arm.rs +++ b/library/stdarch/crates/std_detect/src/detect/os/linux/arm.rs @@ -1,6 +1,6 @@ //! Run-time feature detection for ARM on Linux. -use super::{auxvec, cpuinfo}; +use super::auxvec; use crate::detect::{bit, cache, Feature}; /// Try to read the features from the auxiliary vector, and if that fails, try @@ -31,7 +31,8 @@ pub(crate) fn detect_features() -> cache::Initializer { return value; } - if let Ok(c) = cpuinfo::CpuInfo::new() { + #[cfg(feature = "std_detect_file_io")] + if let Ok(c) = super::cpuinfo::CpuInfo::new() { enable_feature( &mut value, Feature::neon, @@ -55,7 +56,8 @@ pub(crate) fn detect_features() -> cache::Initializer { /// Is the CPU known to have a broken NEON unit? /// /// See https://crbug.com/341598. -fn has_broken_neon(cpuinfo: &cpuinfo::CpuInfo) -> bool { +#[cfg(feature = "std_detect_file_io")] +fn has_broken_neon(cpuinfo: &super::cpuinfo::CpuInfo) -> bool { cpuinfo.field("CPU implementer") == "0x51" && cpuinfo.field("CPU architecture") == "7" && cpuinfo.field("CPU variant") == "0x1" diff --git a/library/stdarch/crates/std_detect/src/detect/os/linux/auxvec.rs b/library/stdarch/crates/std_detect/src/detect/os/linux/auxvec.rs index 6ebae67fbf8..d556b23b1de 100644 --- a/library/stdarch/crates/std_detect/src/detect/os/linux/auxvec.rs +++ b/library/stdarch/crates/std_detect/src/detect/os/linux/auxvec.rs @@ -1,13 +1,16 @@ //! Parses ELF auxiliary vectors. #![cfg_attr(not(target_arch = "aarch64"), allow(dead_code))] -#[cfg(feature = "std_detect_file_io")] -use crate::{fs::File, io::Read}; +pub(crate) const AT_NULL: usize = 0; /// Key to access the CPU Hardware capabilities bitfield. pub(crate) const AT_HWCAP: usize = 16; /// Key to access the CPU Hardware capabilities 2 bitfield. -#[cfg(any(target_arch = "arm", target_arch = "powerpc64"))] +#[cfg(any( + target_arch = "arm", + target_arch = "powerpc", + target_arch = "powerpc64" +))] pub(crate) const AT_HWCAP2: usize = 26; /// Cache HWCAP bitfields of the ELF Auxiliary Vector. @@ -17,7 +20,11 @@ pub(crate) const AT_HWCAP2: usize = 26; #[derive(Debug, Copy, Clone)] pub(crate) struct AuxVec { pub hwcap: usize, - #[cfg(any(target_arch = "arm", target_arch = "powerpc64"))] + #[cfg(any( + target_arch = "arm", + target_arch = "powerpc", + target_arch = "powerpc64" + ))] pub hwcap2: usize, } @@ -64,7 +71,11 @@ pub(crate) fn auxv() -> Result<AuxVec, ()> { } // Targets with AT_HWCAP and AT_HWCAP2: - #[cfg(any(target_arch = "arm", target_arch = "powerpc64"))] + #[cfg(any( + target_arch = "arm", + target_arch = "powerpc", + target_arch = "powerpc64" + ))] { if let Ok(hwcap2) = getauxval(AT_HWCAP2) { if hwcap != 0 && hwcap2 != 0 { @@ -74,21 +85,11 @@ pub(crate) fn auxv() -> Result<AuxVec, ()> { } drop(hwcap); } - #[cfg(feature = "std_detect_file_io")] - { - // If calling getauxval fails, try to read the auxiliary vector from - // its file: - auxv_from_file("/proc/self/auxv") - } - #[cfg(not(feature = "std_detect_file_io"))] - { - Err(()) - } } #[cfg(not(feature = "std_detect_dlsym_getauxval"))] { - let hwcap = unsafe { ffi_getauxval(AT_HWCAP) }; + let hwcap = unsafe { libc::getauxval(AT_HWCAP) }; // Targets with only AT_HWCAP: #[cfg(any(target_arch = "aarch64", target_arch = "mips", target_arch = "mips64"))] @@ -99,14 +100,29 @@ pub(crate) fn auxv() -> Result<AuxVec, ()> { } // Targets with AT_HWCAP and AT_HWCAP2: - #[cfg(any(target_arch = "arm", target_arch = "powerpc64"))] + #[cfg(any( + target_arch = "arm", + target_arch = "powerpc", + target_arch = "powerpc64" + ))] { - let hwcap2 = unsafe { ffi_getauxval(AT_HWCAP2) }; + let hwcap2 = unsafe { libc::getauxval(AT_HWCAP2) }; if hwcap != 0 && hwcap2 != 0 { return Ok(AuxVec { hwcap, hwcap2 }); } } } + + #[cfg(feature = "std_detect_file_io")] + { + // If calling getauxval fails, try to read the auxiliary vector from + // its file: + auxv_from_file("/proc/self/auxv") + } + #[cfg(not(feature = "std_detect_file_io"))] + { + Err(()) + } } /// Tries to read the `key` from the auxiliary vector by calling the @@ -122,7 +138,7 @@ fn getauxval(key: usize) -> Result<usize, ()> { return Err(()); } - let ffi_getauxval: F = mem::transmute(ptr); + let ffi_getauxval: F = core::mem::transmute(ptr); Ok(ffi_getauxval(key)) } } @@ -131,7 +147,7 @@ fn getauxval(key: usize) -> Result<usize, ()> { /// function returns `Err`. #[cfg(feature = "std_detect_file_io")] fn auxv_from_file(file: &str) -> Result<AuxVec, ()> { - let mut file = File::open(file).map_err(|_| ())?; + let file = super::read_file(file)?; // See <https://github.com/torvalds/linux/blob/v3.19/include/uapi/linux/auxvec.h>. // @@ -139,10 +155,11 @@ fn auxv_from_file(file: &str) -> Result<AuxVec, ()> { // `AT_EXECFN = 31` to `AT_NULL = 0`. That is, a buffer of // 2*32 `usize` elements is enough to read the whole vector. let mut buf = [0_usize; 64]; - { - let raw: &mut [u8; 64 * mem::size_of::<usize>()] = unsafe { mem::transmute(&mut buf) }; - file.read(raw).map_err(|_| ())?; + let len = core::mem::size_of_val(&buf).max(file.len()); + unsafe { + core::ptr::copy_nonoverlapping(file.as_ptr(), buf.as_mut_ptr() as *mut u8, len); } + auxv_from_buf(&buf) } @@ -155,18 +172,24 @@ fn auxv_from_buf(buf: &[usize; 64]) -> Result<AuxVec, ()> { { for el in buf.chunks(2) { match el[0] { + AT_NULL => break, AT_HWCAP => return Ok(AuxVec { hwcap: el[1] }), _ => (), } } } // Targets with AT_HWCAP and AT_HWCAP2: - #[cfg(any(target_arch = "arm", target_arch = "powerpc64"))] + #[cfg(any( + target_arch = "arm", + target_arch = "powerpc", + target_arch = "powerpc64" + ))] { let mut hwcap = None; let mut hwcap2 = None; for el in buf.chunks(2) { match el[0] { + AT_NULL => break, AT_HWCAP => hwcap = Some(el[1]), AT_HWCAP2 => hwcap2 = Some(el[1]), _ => (), @@ -214,7 +237,12 @@ mod tests { // FIXME: on mips/mips64 getauxval returns 0, and /proc/self/auxv // does not always contain the AT_HWCAP key under qemu. - #[cfg(not(any(target_arch = "mips", target_arch = "mips64", target_arch = "powerpc")))] + #[cfg(any( + target_arch = "aarch64", + target_arch = "arm", + target_arch = "powerpc", + target_arch = "powerpc64" + ))] #[test] fn auxv_crate() { let v = auxv(); @@ -224,7 +252,11 @@ mod tests { } // Targets with AT_HWCAP and AT_HWCAP2: - #[cfg(any(target_arch = "arm", target_arch = "powerpc64"))] + #[cfg(any( + target_arch = "arm", + target_arch = "powerpc", + target_arch = "powerpc64" + ))] { if let Some(hwcap2) = auxv_crate_getauxval(AT_HWCAP2) { let rt_hwcap2 = v.expect("failed to find hwcap2 key").hwcap2; @@ -243,7 +275,7 @@ mod tests { } #[cfg(feature = "std_detect_file_io")] - cfg_if! { + cfg_if::cfg_if! { if #[cfg(target_arch = "arm")] { #[test] fn linux_rpi3() { @@ -264,6 +296,7 @@ mod tests { // want to fall back to /proc/cpuinfo in this case, so // reading should fail. assert_eq!(v.hwcap, 126614527); // assert_eq!(v.hwcap2, 0); + let _ = v; } } else if #[cfg(target_arch = "aarch64")] { #[test] @@ -286,7 +319,14 @@ mod tests { } } + #[cfg(any( + target_arch = "aarch64", + target_arch = "arm", + target_arch = "powerpc", + target_arch = "powerpc64" + ))] #[test] + #[cfg(feature = "std_detect_file_io")] fn auxv_crate_procfs() { let v = auxv(); if let Some(hwcap) = auxv_crate_getprocfs(AT_HWCAP) { @@ -294,7 +334,11 @@ mod tests { } // Targets with AT_HWCAP and AT_HWCAP2: - #[cfg(any(target_arch = "arm", target_arch = "powerpc64"))] + #[cfg(any( + target_arch = "arm", + target_arch = "powerpc", + target_arch = "powerpc64" + ))] { if let Some(hwcap2) = auxv_crate_getprocfs(AT_HWCAP2) { assert_eq!(v.unwrap().hwcap2, hwcap2); diff --git a/library/stdarch/crates/std_detect/src/detect/os/linux/cpuinfo.rs b/library/stdarch/crates/std_detect/src/detect/os/linux/cpuinfo.rs index f76c48a4b16..1f403df01fc 100644 --- a/library/stdarch/crates/std_detect/src/detect/os/linux/cpuinfo.rs +++ b/library/stdarch/crates/std_detect/src/detect/os/linux/cpuinfo.rs @@ -1,8 +1,7 @@ //! Parses /proc/cpuinfo #![cfg_attr(not(target_arch = "arm"), allow(dead_code))] -extern crate std; -use self::std::{fs::File, io, io::Read, prelude::v1::*}; +use alloc::string::String; /// cpuinfo pub(crate) struct CpuInfo { @@ -11,11 +10,11 @@ pub(crate) struct CpuInfo { impl CpuInfo { /// Reads /proc/cpuinfo into CpuInfo. - pub(crate) fn new() -> Result<Self, io::Error> { - let mut file = File::open("/proc/cpuinfo")?; - let mut cpui = Self { raw: String::new() }; - file.read_to_string(&mut cpui.raw)?; - Ok(cpui) + pub(crate) fn new() -> Result<Self, ()> { + let raw = super::read_file("/proc/cpuinfo")?; + Ok(Self { + raw: String::from_utf8(raw).map_err(|_| ())?, + }) } /// Returns the value of the cpuinfo `field`. pub(crate) fn field(&self, field: &str) -> CpuInfoField { @@ -34,7 +33,7 @@ impl CpuInfo { } #[cfg(test)] - fn from_str(other: &str) -> Result<Self, ::std::io::Error> { + fn from_str(other: &str) -> Result<Self, ()> { Ok(Self { raw: String::from(other), }) diff --git a/library/stdarch/crates/std_detect/src/detect/os/linux/mod.rs b/library/stdarch/crates/std_detect/src/detect/os/linux/mod.rs index e02d5e6dcda..4b6776e982a 100644 --- a/library/stdarch/crates/std_detect/src/detect/os/linux/mod.rs +++ b/library/stdarch/crates/std_detect/src/detect/os/linux/mod.rs @@ -1,28 +1,61 @@ //! Run-time feature detection on Linux +//! +#[cfg(feature = "std_detect_file_io")] +use alloc::vec::Vec; mod auxvec; #[cfg(feature = "std_detect_file_io")] mod cpuinfo; -cfg_if! { +#[cfg(feature = "std_detect_file_io")] +fn read_file(path: &str) -> Result<Vec<u8>, ()> { + let mut path = Vec::from(path.as_bytes()); + path.push(0); + + unsafe { + let file = libc::open(path.as_ptr() as *const libc::c_char, libc::O_RDONLY); + if file == -1 { + return Err(()); + } + + let mut data = Vec::new(); + loop { + data.reserve(4096); + let spare = data.spare_capacity_mut(); + match libc::read(file, spare.as_mut_ptr() as *mut _, spare.len()) { + -1 => { + libc::close(file); + return Err(()); + } + 0 => break, + n => data.set_len(data.len() + n as usize), + } + } + + libc::close(file); + Ok(data) + } +} + +cfg_if::cfg_if! { if #[cfg(target_arch = "aarch64")] { mod aarch64; - pub use self::aarch64::check_for; + pub(crate) use self::aarch64::detect_features; } else if #[cfg(target_arch = "arm")] { mod arm; - pub use self::arm::check_for; + pub(crate) use self::arm::detect_features; } else if #[cfg(any(target_arch = "mips", target_arch = "mips64"))] { mod mips; - pub use self::mips::check_for; + pub(crate) use self::mips::detect_features; } else if #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))] { mod powerpc; - pub use self::powerpc::check_for; + pub(crate) use self::powerpc::detect_features; } else { - use crate::detect::Feature; + use crate::detect::cache; /// Performs run-time feature detection. - pub fn check_for(_x: Feature) -> bool { - false + pub(crate) fn detect_features() -> cache::Initializer { + cache::Initializer::default() } } } diff --git a/library/stdarch/crates/std_detect/src/detect/os/linux/powerpc.rs b/library/stdarch/crates/std_detect/src/detect/os/linux/powerpc.rs index 97afe49fe50..c3308e81582 100644 --- a/library/stdarch/crates/std_detect/src/detect/os/linux/powerpc.rs +++ b/library/stdarch/crates/std_detect/src/detect/os/linux/powerpc.rs @@ -1,6 +1,6 @@ //! Run-time feature detection for PowerPC on Linux. -use super::{auxvec, cpuinfo}; +use super::auxvec; use crate::detect::{cache, Feature}; /// Try to read the features from the auxiliary vector, and if that fails, try @@ -27,7 +27,8 @@ pub(crate) fn detect_features() -> cache::Initializer { // PowerPC's /proc/cpuinfo lacks a proper Feature field, // but `altivec` support is indicated in the `cpu` field. - if let Ok(c) = cpuinfo::CpuInfo::new() { + #[cfg(feature = "std_detect_file_io")] + if let Ok(c) = super::cpuinfo::CpuInfo::new() { enable_feature(&mut value, Feature::altivec, c.field("cpu").has("altivec")); return value; } diff --git a/library/stdarch/crates/std_detect/src/detect/os/x86.rs b/library/stdarch/crates/std_detect/src/detect/os/x86.rs index 436fb00f061..388af2e3043 100644 --- a/library/stdarch/crates/std_detect/src/detect/os/x86.rs +++ b/library/stdarch/crates/std_detect/src/detect/os/x86.rs @@ -1,11 +1,11 @@ //! x86 run-time feature detection is OS independent. #[cfg(target_arch = "x86")] -use crate::arch::x86::*; +use core::arch::x86::*; #[cfg(target_arch = "x86_64")] -use crate::arch::x86_64::*; +use core::arch::x86_64::*; -use crate::mem; +use core::mem; use crate::detect::{bit, cache, Feature}; |
