Skip to content

Commit 2d6375a

Browse files
authored
Turn std_detect into a no_std crate (#1005)
1 parent 8f63131 commit 2d6375a

File tree

13 files changed

+165
-95
lines changed

13 files changed

+165
-95
lines changed

crates/std_detect/src/detect/cache.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
44
#![allow(dead_code)] // not used on all platforms
55

6-
use crate::sync::atomic::Ordering;
6+
use core::sync::atomic::Ordering;
77

8-
use crate::sync::atomic::AtomicUsize;
8+
use core::sync::atomic::AtomicUsize;
99

1010
/// Sets the `bit` of `x`.
1111
#[inline]
@@ -125,9 +125,16 @@ cfg_if::cfg_if! {
125125
if #[cfg(feature = "std_detect_env_override")] {
126126
#[inline]
127127
fn initialize(mut value: Initializer) -> Initializer {
128-
if let Ok(disable) = crate::env::var("RUST_STD_DETECT_UNSTABLE") {
129-
for v in disable.split(" ") {
130-
let _ = super::Feature::from_str(v).map(|v| value.unset(v as u32));
128+
let env = unsafe {
129+
libc::getenv(b"RUST_STD_DETECT_UNSTABLE\0".as_ptr() as *const libc::c_char)
130+
};
131+
if !env.is_null() {
132+
let len = unsafe { libc::strlen(env) };
133+
let env = unsafe { core::slice::from_raw_parts(env as *const u8, len) };
134+
if let Ok(disable) = core::str::from_utf8(env) {
135+
for v in disable.split(" ") {
136+
let _ = super::Feature::from_str(v).map(|v| value.unset(v as u32));
137+
}
131138
}
132139
}
133140
do_initialize(value);

crates/std_detect/src/detect/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,10 @@ cfg_if! {
9898
// On x86/x86_64 no OS specific functionality is required.
9999
#[path = "os/x86.rs"]
100100
mod os;
101-
} else if #[cfg(all(target_os = "linux", feature = "use_std"))] {
101+
} else if #[cfg(all(target_os = "linux", feature = "libc"))] {
102102
#[path = "os/linux/mod.rs"]
103103
mod os;
104-
} else if #[cfg(all(target_os = "freebsd", feature = "use_std"))] {
104+
} else if #[cfg(all(target_os = "freebsd", feature = "libc"))] {
105105
#[cfg(target_arch = "aarch64")]
106106
#[path = "os/aarch64.rs"]
107107
mod aarch64;
@@ -140,7 +140,7 @@ pub fn features() -> impl Iterator<Item = (&'static str, bool)> {
140140
target_arch = "mips64",
141141
))] {
142142
(0_u8..Feature::_last as u8).map(|discriminant: u8| {
143-
let f: Feature = unsafe { crate::mem::transmute(discriminant) };
143+
let f: Feature = unsafe { core::mem::transmute(discriminant) };
144144
let name: &'static str = f.to_str();
145145
let enabled: bool = check_for(f);
146146
(name, enabled)

crates/std_detect/src/detect/os/freebsd/auxvec.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ pub(crate) fn auxv() -> Result<AuxVec, ()> {
4242

4343
/// Tries to read the `key` from the auxiliary vector.
4444
fn archauxv(key: usize) -> Result<usize, ()> {
45-
use crate::mem;
45+
use core::mem;
4646

4747
#[derive(Copy, Clone)]
4848
#[repr(C)]

crates/std_detect/src/detect/os/freebsd/mod.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,18 @@ mod auxvec;
55
cfg_if::cfg_if! {
66
if #[cfg(target_arch = "aarch64")] {
77
mod aarch64;
8-
pub use self::aarch64::check_for;
8+
pub(crate) use self::aarch64::detect_features;
99
} else if #[cfg(target_arch = "arm")] {
1010
mod arm;
11-
pub use self::arm::check_for;
11+
pub(crate) use self::arm::detect_features;
1212
} else if #[cfg(target_arch = "powerpc64")] {
1313
mod powerpc;
14-
pub use self::powerpc::check_for;
14+
pub(crate) use self::powerpc::detect_features;
1515
} else {
16-
use crate::arch::detect::Feature;
16+
use crate::detect::cache;
1717
/// Performs run-time feature detection.
18-
pub fn check_for(_x: Feature) -> bool {
19-
false
18+
pub(crate) fn detect_features() -> cache::Initializer {
19+
cache::Initializer::default()
2020
}
2121
}
2222
}

crates/std_detect/src/detect/os/linux/aarch64.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Run-time feature detection for Aarch64 on Linux.
22
3-
use super::{auxvec, cpuinfo};
3+
use super::auxvec;
44
use crate::detect::{bit, cache, Feature};
55

66
/// 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 {
1010
let hwcap: AtHwcap = auxv.into();
1111
return hwcap.cache();
1212
}
13-
if let Ok(c) = cpuinfo::CpuInfo::new() {
13+
#[cfg(feature = "std_detect_file_io")]
14+
if let Ok(c) = super::cpuinfo::CpuInfo::new() {
1415
let hwcap: AtHwcap = c.into();
1516
return hwcap.cache();
1617
}
@@ -77,9 +78,10 @@ impl From<auxvec::AuxVec> for AtHwcap {
7778
}
7879
}
7980

80-
impl From<cpuinfo::CpuInfo> for AtHwcap {
81+
#[cfg(feature = "std_detect_file_io")]
82+
impl From<super::cpuinfo::CpuInfo> for AtHwcap {
8183
/// Reads AtHwcap from /proc/cpuinfo .
82-
fn from(c: cpuinfo::CpuInfo) -> Self {
84+
fn from(c: super::cpuinfo::CpuInfo) -> Self {
8385
let f = &c.field("Features");
8486
AtHwcap {
8587
// 64-bit names. FIXME: In 32-bit compatibility mode /proc/cpuinfo will

crates/std_detect/src/detect/os/linux/arm.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Run-time feature detection for ARM on Linux.
22
3-
use super::{auxvec, cpuinfo};
3+
use super::auxvec;
44
use crate::detect::{bit, cache, Feature};
55

66
/// 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 {
3131
return value;
3232
}
3333

34-
if let Ok(c) = cpuinfo::CpuInfo::new() {
34+
#[cfg(feature = "std_detect_file_io")]
35+
if let Ok(c) = super::cpuinfo::CpuInfo::new() {
3536
enable_feature(
3637
&mut value,
3738
Feature::neon,
@@ -55,7 +56,8 @@ pub(crate) fn detect_features() -> cache::Initializer {
5556
/// Is the CPU known to have a broken NEON unit?
5657
///
5758
/// See https://crbug.com/341598.
58-
fn has_broken_neon(cpuinfo: &cpuinfo::CpuInfo) -> bool {
59+
#[cfg(feature = "std_detect_file_io")]
60+
fn has_broken_neon(cpuinfo: &super::cpuinfo::CpuInfo) -> bool {
5961
cpuinfo.field("CPU implementer") == "0x51"
6062
&& cpuinfo.field("CPU architecture") == "7"
6163
&& cpuinfo.field("CPU variant") == "0x1"

crates/std_detect/src/detect/os/linux/auxvec.rs

Lines changed: 72 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
//! Parses ELF auxiliary vectors.
22
#![cfg_attr(not(target_arch = "aarch64"), allow(dead_code))]
33

4-
#[cfg(feature = "std_detect_file_io")]
5-
use crate::{fs::File, io::Read};
4+
pub(crate) const AT_NULL: usize = 0;
65

76
/// Key to access the CPU Hardware capabilities bitfield.
87
pub(crate) const AT_HWCAP: usize = 16;
98
/// Key to access the CPU Hardware capabilities 2 bitfield.
10-
#[cfg(any(target_arch = "arm", target_arch = "powerpc64"))]
9+
#[cfg(any(
10+
target_arch = "arm",
11+
target_arch = "powerpc",
12+
target_arch = "powerpc64"
13+
))]
1114
pub(crate) const AT_HWCAP2: usize = 26;
1215

1316
/// Cache HWCAP bitfields of the ELF Auxiliary Vector.
@@ -17,7 +20,11 @@ pub(crate) const AT_HWCAP2: usize = 26;
1720
#[derive(Debug, Copy, Clone)]
1821
pub(crate) struct AuxVec {
1922
pub hwcap: usize,
20-
#[cfg(any(target_arch = "arm", target_arch = "powerpc64"))]
23+
#[cfg(any(
24+
target_arch = "arm",
25+
target_arch = "powerpc",
26+
target_arch = "powerpc64"
27+
))]
2128
pub hwcap2: usize,
2229
}
2330

@@ -64,7 +71,11 @@ pub(crate) fn auxv() -> Result<AuxVec, ()> {
6471
}
6572

6673
// Targets with AT_HWCAP and AT_HWCAP2:
67-
#[cfg(any(target_arch = "arm", target_arch = "powerpc64"))]
74+
#[cfg(any(
75+
target_arch = "arm",
76+
target_arch = "powerpc",
77+
target_arch = "powerpc64"
78+
))]
6879
{
6980
if let Ok(hwcap2) = getauxval(AT_HWCAP2) {
7081
if hwcap != 0 && hwcap2 != 0 {
@@ -74,21 +85,11 @@ pub(crate) fn auxv() -> Result<AuxVec, ()> {
7485
}
7586
drop(hwcap);
7687
}
77-
#[cfg(feature = "std_detect_file_io")]
78-
{
79-
// If calling getauxval fails, try to read the auxiliary vector from
80-
// its file:
81-
auxv_from_file("/proc/self/auxv")
82-
}
83-
#[cfg(not(feature = "std_detect_file_io"))]
84-
{
85-
Err(())
86-
}
8788
}
8889

8990
#[cfg(not(feature = "std_detect_dlsym_getauxval"))]
9091
{
91-
let hwcap = unsafe { ffi_getauxval(AT_HWCAP) };
92+
let hwcap = unsafe { libc::getauxval(AT_HWCAP) };
9293

9394
// Targets with only AT_HWCAP:
9495
#[cfg(any(target_arch = "aarch64", target_arch = "mips", target_arch = "mips64"))]
@@ -99,14 +100,29 @@ pub(crate) fn auxv() -> Result<AuxVec, ()> {
99100
}
100101

101102
// Targets with AT_HWCAP and AT_HWCAP2:
102-
#[cfg(any(target_arch = "arm", target_arch = "powerpc64"))]
103+
#[cfg(any(
104+
target_arch = "arm",
105+
target_arch = "powerpc",
106+
target_arch = "powerpc64"
107+
))]
103108
{
104-
let hwcap2 = unsafe { ffi_getauxval(AT_HWCAP2) };
109+
let hwcap2 = unsafe { libc::getauxval(AT_HWCAP2) };
105110
if hwcap != 0 && hwcap2 != 0 {
106111
return Ok(AuxVec { hwcap, hwcap2 });
107112
}
108113
}
109114
}
115+
116+
#[cfg(feature = "std_detect_file_io")]
117+
{
118+
// If calling getauxval fails, try to read the auxiliary vector from
119+
// its file:
120+
auxv_from_file("/proc/self/auxv")
121+
}
122+
#[cfg(not(feature = "std_detect_file_io"))]
123+
{
124+
Err(())
125+
}
110126
}
111127

112128
/// Tries to read the `key` from the auxiliary vector by calling the
@@ -122,7 +138,7 @@ fn getauxval(key: usize) -> Result<usize, ()> {
122138
return Err(());
123139
}
124140

125-
let ffi_getauxval: F = mem::transmute(ptr);
141+
let ffi_getauxval: F = core::mem::transmute(ptr);
126142
Ok(ffi_getauxval(key))
127143
}
128144
}
@@ -131,18 +147,19 @@ fn getauxval(key: usize) -> Result<usize, ()> {
131147
/// function returns `Err`.
132148
#[cfg(feature = "std_detect_file_io")]
133149
fn auxv_from_file(file: &str) -> Result<AuxVec, ()> {
134-
let mut file = File::open(file).map_err(|_| ())?;
150+
let file = super::read_file(file)?;
135151

136152
// See <https://github.com/torvalds/linux/blob/v3.19/include/uapi/linux/auxvec.h>.
137153
//
138154
// The auxiliary vector contains at most 32 (key,value) fields: from
139155
// `AT_EXECFN = 31` to `AT_NULL = 0`. That is, a buffer of
140156
// 2*32 `usize` elements is enough to read the whole vector.
141157
let mut buf = [0_usize; 64];
142-
{
143-
let raw: &mut [u8; 64 * mem::size_of::<usize>()] = unsafe { mem::transmute(&mut buf) };
144-
file.read(raw).map_err(|_| ())?;
158+
let len = core::mem::size_of_val(&buf).max(file.len());
159+
unsafe {
160+
core::ptr::copy_nonoverlapping(file.as_ptr(), buf.as_mut_ptr() as *mut u8, len);
145161
}
162+
146163
auxv_from_buf(&buf)
147164
}
148165

@@ -155,18 +172,24 @@ fn auxv_from_buf(buf: &[usize; 64]) -> Result<AuxVec, ()> {
155172
{
156173
for el in buf.chunks(2) {
157174
match el[0] {
175+
AT_NULL => break,
158176
AT_HWCAP => return Ok(AuxVec { hwcap: el[1] }),
159177
_ => (),
160178
}
161179
}
162180
}
163181
// Targets with AT_HWCAP and AT_HWCAP2:
164-
#[cfg(any(target_arch = "arm", target_arch = "powerpc64"))]
182+
#[cfg(any(
183+
target_arch = "arm",
184+
target_arch = "powerpc",
185+
target_arch = "powerpc64"
186+
))]
165187
{
166188
let mut hwcap = None;
167189
let mut hwcap2 = None;
168190
for el in buf.chunks(2) {
169191
match el[0] {
192+
AT_NULL => break,
170193
AT_HWCAP => hwcap = Some(el[1]),
171194
AT_HWCAP2 => hwcap2 = Some(el[1]),
172195
_ => (),
@@ -214,7 +237,12 @@ mod tests {
214237

215238
// FIXME: on mips/mips64 getauxval returns 0, and /proc/self/auxv
216239
// does not always contain the AT_HWCAP key under qemu.
217-
#[cfg(not(any(target_arch = "mips", target_arch = "mips64", target_arch = "powerpc")))]
240+
#[cfg(any(
241+
target_arch = "aarch64",
242+
target_arch = "arm",
243+
target_arch = "powerpc",
244+
target_arch = "powerpc64"
245+
))]
218246
#[test]
219247
fn auxv_crate() {
220248
let v = auxv();
@@ -224,7 +252,11 @@ mod tests {
224252
}
225253

226254
// Targets with AT_HWCAP and AT_HWCAP2:
227-
#[cfg(any(target_arch = "arm", target_arch = "powerpc64"))]
255+
#[cfg(any(
256+
target_arch = "arm",
257+
target_arch = "powerpc",
258+
target_arch = "powerpc64"
259+
))]
228260
{
229261
if let Some(hwcap2) = auxv_crate_getauxval(AT_HWCAP2) {
230262
let rt_hwcap2 = v.expect("failed to find hwcap2 key").hwcap2;
@@ -243,7 +275,7 @@ mod tests {
243275
}
244276

245277
#[cfg(feature = "std_detect_file_io")]
246-
cfg_if! {
278+
cfg_if::cfg_if! {
247279
if #[cfg(target_arch = "arm")] {
248280
#[test]
249281
fn linux_rpi3() {
@@ -264,6 +296,7 @@ mod tests {
264296
// want to fall back to /proc/cpuinfo in this case, so
265297
// reading should fail. assert_eq!(v.hwcap, 126614527);
266298
// assert_eq!(v.hwcap2, 0);
299+
let _ = v;
267300
}
268301
} else if #[cfg(target_arch = "aarch64")] {
269302
#[test]
@@ -286,15 +319,26 @@ mod tests {
286319
}
287320
}
288321

322+
#[cfg(any(
323+
target_arch = "aarch64",
324+
target_arch = "arm",
325+
target_arch = "powerpc",
326+
target_arch = "powerpc64"
327+
))]
289328
#[test]
329+
#[cfg(feature = "std_detect_file_io")]
290330
fn auxv_crate_procfs() {
291331
let v = auxv();
292332
if let Some(hwcap) = auxv_crate_getprocfs(AT_HWCAP) {
293333
assert_eq!(v.unwrap().hwcap, hwcap);
294334
}
295335

296336
// Targets with AT_HWCAP and AT_HWCAP2:
297-
#[cfg(any(target_arch = "arm", target_arch = "powerpc64"))]
337+
#[cfg(any(
338+
target_arch = "arm",
339+
target_arch = "powerpc",
340+
target_arch = "powerpc64"
341+
))]
298342
{
299343
if let Some(hwcap2) = auxv_crate_getprocfs(AT_HWCAP2) {
300344
assert_eq!(v.unwrap().hwcap2, hwcap2);

0 commit comments

Comments
 (0)