Skip to content

Commit a9bcbf4

Browse files
committed
Add cargo features to disable usage of file I/O and dlsym in std_detect
1 parent 2e2e9d7 commit a9bcbf4

File tree

8 files changed

+125
-40
lines changed

8 files changed

+125
-40
lines changed

ci/run.sh

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,6 @@ cargo_test() {
5858
fi
5959
fi
6060
cmd="$cmd ${subcmd} --target=$TARGET $1"
61-
if [ "$NOSTD" = "1" ]
62-
then
63-
cmd="$cmd -p core_arch"
64-
else
65-
cmd="$cmd -p core_arch -p std_detect -p stdsimd_examples"
66-
fi
6761
cmd="$cmd -- $2"
6862
# Un-commenting this disables the test output and shows only a summary:
6963
#if [ "$NORUN" != "1" ]
@@ -88,8 +82,25 @@ cargo_output() {
8882
}
8983

9084
cargo_setup
91-
cargo_test
92-
cargo_test "--release"
85+
86+
CORE_ARCH="--manifest-path=crates/core_arch/Cargo.toml"
87+
STD_DETECT="--manifest-path=crates/std_detect/Cargo.toml"
88+
STDSIMD_EXAMPLES="--manifest-path=examples/Cargo.toml"
89+
cargo_test "${CORE_ARCH}"
90+
cargo_test "${CORE_ARCH} --release"
91+
if [ "$NOSTD" != "1" ]; then
92+
cargo_test "${STD_DETECT}"
93+
cargo_test "${STD_DETECT} --release"
94+
95+
cargo_test "${STD_DETECT} --no-default-features"
96+
cargo_test "${STD_DETECT} --no-default-features --features=std_detect_file_io"
97+
cargo_test "${STD_DETECT} --no-default-features --features=std_detect_dlsym_getauxval"
98+
cargo_test "${STD_DETECT} --no-default-features --features=std_detect_dlsym_getauxval,std_detect_file_io"
99+
100+
cargo_test "${STDSIMD_EXAMPLES}"
101+
cargo_test "${STDSIMD_EXAMPLES} --release"
102+
fi
103+
93104
cargo_output
94105

95106
# Test targets compiled with extra features.

crates/std_detect/Cargo.toml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,14 @@ is-it-maintained-open-issues = { repository = "rust-lang-nursery/stdsimd" }
2323
maintenance = { status = "experimental" }
2424

2525
[dependencies]
26-
libc = "0.2"
26+
libc = { version = "0.2", optional = true, default-features = false }
2727
cfg-if = "0.1"
2828

2929
[dev-dependencies]
3030
auxv = "0.3.3"
31-
cupid = "0.6.0"
31+
cupid = "0.6.0"
32+
33+
[features]
34+
default = [ "std_detect_dlsym_getauxval", "std_detect_file_io" ]
35+
std_detect_file_io = []
36+
std_detect_dlsym_getauxval = [ "libc" ]

crates/std_detect/README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,22 @@ run-time feature detection support than the one offered by Rust's standard
2424
library. We intend to make `std_detect` more flexible and configurable in this
2525
regard to better serve the needs of `#[no_std]` targets.
2626

27+
# Features
28+
29+
* `std_detect_dlsym_getauxval` (enabled by default, requires `libc`): Enable to
30+
use `libc::dlsym` to query whether [`getauxval`] is linked into the binary. When
31+
this is not the case, this feature allows other fallback methods to perform
32+
run-time feature detection. When this feature is disabled, `std_detect` assumes
33+
that [`getauxval`] is linked to the binary. If that is not the case the behavior
34+
is undefined.
35+
36+
* `std_detect_file_io` (enabled by default, requires `std`): Enable to perform run-time feature
37+
detection using file APIs (e.g. `/proc/cpuinfo`, etc.) if other more performant
38+
methods fail. This feature requires `libstd` as a dependency, preventing the
39+
crate from working on applications in which `std` is not available.
40+
41+
[`getauxval`]: http://man7.org/linux/man-pages/man3/getauxval.3.html
42+
2743
# Platform support
2844

2945
* All `x86`/`x86_64` targets are supported on all platforms by querying the

crates/std_detect/src/detect/cache.rs

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

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

88
#[cfg(target_pointer_width = "64")]
9-
use core::sync::atomic::AtomicU64;
9+
use sync::atomic::AtomicU64;
1010

1111
#[cfg(target_pointer_width = "32")]
12-
use core::sync::atomic::AtomicU32;
12+
use sync::atomic::AtomicU32;
1313

1414
/// Sets the `bit` of `x`.
1515
#[inline]

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

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

4-
extern crate std;
5-
use self::std::{prelude::v1::*, fs::File, io::Read};
6-
7-
use core::mem;
4+
#[cfg(feature = "std_detect_file_io")]
5+
use ::{fs::File, io::Read};
86

97
/// Key to access the CPU Hardware capabilities bitfield.
108
pub(crate) const AT_HWCAP: usize = 16;
@@ -34,8 +32,12 @@ pub(crate) struct AuxVec {
3432
///
3533
/// There is no perfect way of reading the auxiliary vector.
3634
///
37-
/// - If the `getauxval` is dynamically linked to this binary, it will be used.
38-
/// - Otherwise, try to read `/proc/self/auxv`.
35+
/// - If the `std_detect_dlsym_getauxval` cargo feature is enabled, this will use
36+
/// `getauxval` if its linked to the binary, and otherwise proceed to a fallback implementation.
37+
/// When `std_detect_dlsym_getauxval` is disabled, this will assume that `getauxval` is
38+
/// linked to the binary - if that is not the case the behavior is undefined.
39+
/// - Otherwise, if the `std_detect_file_io` cargo feature is enabled, it will
40+
/// try to read `/proc/self/auxv`.
3941
/// - If that fails, this function returns an error.
4042
///
4143
/// Note that run-time feature detection is not invoked for features that can
@@ -49,8 +51,42 @@ pub(crate) struct AuxVec {
4951
/// [auxvec_h]: https://github.com/torvalds/linux/blob/master/include/uapi/linux/auxvec.h
5052
/// [auxv_docs]: https://docs.rs/auxv/0.3.3/auxv/
5153
pub(crate) fn auxv() -> Result<AuxVec, ()> {
52-
// Try to call a dynamically-linked getauxval function.
53-
if let Ok(hwcap) = getauxval(AT_HWCAP) {
54+
#[cfg(feature = "std_detect_dlsym_getauxval")] {
55+
// Try to call a dynamically-linked getauxval function.
56+
if let Ok(hwcap) = getauxval(AT_HWCAP) {
57+
// Targets with only AT_HWCAP:
58+
#[cfg(any(target_arch = "aarch64", target_arch = "mips",
59+
target_arch = "mips64"))]
60+
{
61+
if hwcap != 0 {
62+
return Ok(AuxVec { hwcap });
63+
}
64+
}
65+
66+
// Targets with AT_HWCAP and AT_HWCAP2:
67+
#[cfg(any(target_arch = "arm", target_arch = "powerpc64"))]
68+
{
69+
if let Ok(hwcap2) = getauxval(AT_HWCAP2) {
70+
if hwcap != 0 && hwcap2 != 0 {
71+
return Ok(AuxVec { hwcap, hwcap2 });
72+
}
73+
}
74+
}
75+
drop(hwcap);
76+
}
77+
#[cfg(feature = "std_detect_file_io")] {
78+
// If calling getauxval fails, try to read the auxiliary vector from
79+
// its file:
80+
auxv_from_file("/proc/self/auxv")
81+
}
82+
#[cfg(not(feature = "std_detect_file_io"))] {
83+
Err(())
84+
}
85+
}
86+
87+
#[cfg(not(feature = "std_detect_dlsym_getauxval"))] {
88+
let hwcap = unsafe { ffi_getauxval(AT_HWCAP) };
89+
5490
// Targets with only AT_HWCAP:
5591
#[cfg(any(target_arch = "aarch64", target_arch = "mips",
5692
target_arch = "mips64"))]
@@ -63,22 +99,18 @@ pub(crate) fn auxv() -> Result<AuxVec, ()> {
6399
// Targets with AT_HWCAP and AT_HWCAP2:
64100
#[cfg(any(target_arch = "arm", target_arch = "powerpc64"))]
65101
{
66-
if let Ok(hwcap2) = getauxval(AT_HWCAP2) {
67-
if hwcap != 0 && hwcap2 != 0 {
68-
return Ok(AuxVec { hwcap, hwcap2 });
69-
}
102+
let hwcap2 = unsafe { ffi_getauxval(AT_HWCAP2) };
103+
if hwcap != 0 && hwcap2 != 0 {
104+
return Ok(AuxVec { hwcap, hwcap2 });
70105
}
71106
}
72-
drop(hwcap);
73107
}
74-
// If calling getauxval fails, try to read the auxiliary vector from
75-
// its file:
76-
auxv_from_file("/proc/self/auxv")
77108
}
78109

79110
/// Tries to read the `key` from the auxiliary vector by calling the
80111
/// dynamically-linked `getauxval` function. If the function is not linked,
81112
/// this function return `Err`.
113+
#[cfg(feature = "std_detect_dlsym_getauxval")]
82114
fn getauxval(key: usize) -> Result<usize, ()> {
83115
use libc;
84116
pub type F = unsafe extern "C" fn(usize) -> usize;
@@ -98,6 +130,7 @@ fn getauxval(key: usize) -> Result<usize, ()> {
98130

99131
/// Tries to read the auxiliary vector from the `file`. If this fails, this
100132
/// function returns `Err`.
133+
#[cfg(feature = "std_detect_file_io")]
101134
fn auxv_from_file(file: &str) -> Result<AuxVec, ()> {
102135
let mut file = File::open(file).map_err(|_| ())?;
103136

@@ -117,6 +150,7 @@ fn auxv_from_file(file: &str) -> Result<AuxVec, ()> {
117150

118151
/// Tries to interpret the `buffer` as an auxiliary vector. If that fails, this
119152
/// function returns `Err`.
153+
#[cfg(feature = "std_detect_file_io")]
120154
fn auxv_from_buf(buf: &[usize; 64]) -> Result<AuxVec, ()> {
121155
// Targets with only AT_HWCAP:
122156
#[cfg(any(target_arch = "aarch64", target_arch = "mips",
@@ -157,6 +191,7 @@ mod tests {
157191

158192
// Reads the Auxiliary Vector key from /proc/self/auxv
159193
// using the auxv crate.
194+
#[cfg(feature = "std_detect_file_io")]
160195
fn auxv_crate_getprocfs(key: usize) -> Option<usize> {
161196
use self::auxv_crate::AuxvType;
162197
use self::auxv_crate::procfs::search_procfs_auxv;
@@ -210,6 +245,7 @@ mod tests {
210245
}
211246
}
212247

248+
#[cfg(feature = "std_detect_file_io")]
213249
cfg_if! {
214250
if #[cfg(target_arch = "arm")] {
215251
#[test]
@@ -244,6 +280,7 @@ mod tests {
244280
}
245281

246282
#[test]
283+
#[cfg(feature = "std_detect_file_io")]
247284
fn auxv_dump_procfs() {
248285
if let Ok(auxvec) = auxv_from_file("/proc/self/auxv") {
249286
println!("{:?}", auxvec);

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
//! Run-time feature detection on Linux
22
33
mod auxvec;
4+
5+
#[cfg(feature = "std_detect_file_io")]
46
mod cpuinfo;
57

68
cfg_if! {

crates/std_detect/src/detect/os/x86.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
//! x86 run-time feature detection is OS independent.
22
3-
use core::{prelude::v1::*, mem};
43
#[cfg(target_arch = "x86")]
5-
use core::arch::x86::*;
4+
use arch::x86::*;
65
#[cfg(target_arch = "x86_64")]
7-
use core::arch::x86_64::*;
6+
use arch::x86_64::*;
7+
8+
use mem;
89

910
use crate::detect::{Feature, cache, bit};
1011

crates/std_detect/src/lib.rs

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@
1212
//! * `powerpc64`: [`is_powerpc64_feature_detected`]
1313
1414
#![unstable(feature = "stdsimd", issue = "27731")]
15-
#![feature(const_fn, integer_atomics, staged_api, stdsimd)]
16-
#![feature(doc_cfg, allow_internal_unstable)]
15+
#![feature(const_fn, staged_api, stdsimd, doc_cfg, allow_internal_unstable)]
1716
#![cfg_attr(feature = "cargo-clippy", allow(clippy::shadow_reuse))]
1817
#![cfg_attr(
1918
feature = "cargo-clippy",
@@ -23,15 +22,29 @@
2322
#![cfg_attr(all(target_os = "freebsd", target_arch = "aarch64"), feature(asm))]
2423
#![no_std]
2524

26-
#[cfg(test)]
27-
#[macro_use(println)]
28-
extern crate std;
29-
30-
extern crate libc;
31-
3225
#[macro_use]
3326
extern crate cfg_if;
3427

28+
cfg_if! {
29+
if #[cfg(feature = "std_detect_file_io")] {
30+
#[cfg_attr(test, macro_use(println))]
31+
extern crate std;
32+
33+
#[allow(unused_imports)]
34+
use std::{arch, fs, io, mem, sync};
35+
} else {
36+
#[cfg(test)]
37+
#[macro_use(println)]
38+
extern crate std;
39+
40+
#[allow(unused_imports)]
41+
use core::{arch, mem, sync};
42+
}
43+
}
44+
45+
#[cfg(feature = "std_detect_dlsym_getauxval")]
46+
extern crate libc;
47+
3548
#[doc(hidden)]
3649
#[unstable(feature = "stdsimd", issue = "27731")]
3750
pub mod detect;

0 commit comments

Comments
 (0)