diff --git a/ci/build-std-detect.sh b/ci/build-std-detect.sh index e4560b3371..e79a497cc3 100755 --- a/ci/build-std-detect.sh +++ b/ci/build-std-detect.sh @@ -10,6 +10,12 @@ set -ex cd "$(dirname "$0")"/.. targets=( + # Linux + aarch64-unknown-linux-musl + armv5te-unknown-linux-musleabi + aarch64-unknown-linux-ohos + armv7-unknown-linux-ohos + # Android aarch64-linux-android arm-linux-androideabi diff --git a/crates/std_detect/README.md b/crates/std_detect/README.md index b9146d42c9..5191b2f665 100644 --- a/crates/std_detect/README.md +++ b/crates/std_detect/README.md @@ -30,12 +30,15 @@ run-time feature detection. When this feature is disabled, `std_detect` assumes that [`getauxval`] is linked to the binary. If that is not the case the behavior is undefined. - Note: This feature is ignored on `*-linux-gnu*` and `*-android*` targets + Note: This feature is ignored on `*-linux-{gnu,musl,ohos}*` and `*-android*` targets because we can safely assume `getauxval` is linked to the binary. * `*-linux-gnu*` targets ([since Rust 1.64](https://blog.rust-lang.org/2022/08/01/Increasing-glibc-kernel-requirements.html)) - have glibc requirements higher than [glibc 2.16 that added `getauxval`](https://sourceware.org/legacy-ml/libc-announce/2012/msg00000.html). + have glibc requirements higher than [glibc 2.16 that added `getauxval`](https://sourceware.org/legacy-ml/libc-announce/2012/msg00000.html). + * `*-linux-musl*` targets ([at least since Rust 1.15](https://github.com/rust-lang/rust/blob/1.15.0/src/ci/docker/x86_64-musl/build-musl.sh#L15)) + use musl newer than [musl 1.1.0 that added `getauxval`](https://git.musl-libc.org/cgit/musl/tree/WHATSNEW?h=v1.1.0#n1197) + * `*-linux-ohos*` targets use a [fork of musl 1.2](https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/native-lib/musl.md) * `*-android*` targets ([since Rust 1.68](https://blog.rust-lang.org/2023/01/09/android-ndk-update-r25.html)) - have the minimum supported API level higher than [Android 4.3 (API level 18) that added `getauxval`](https://github.com/aosp-mirror/platform_bionic/blob/d3ebc2f7c49a9893b114124d4a6b315f3a328764/libc/include/sys/auxv.h#L49). + have the minimum supported API level higher than [Android 4.3 (API level 18) that added `getauxval`](https://github.com/aosp-mirror/platform_bionic/blob/d3ebc2f7c49a9893b114124d4a6b315f3a328764/libc/include/sys/auxv.h#L49). * `std_detect_file_io` (enabled by default, requires `std`): Enable to perform run-time feature detection using file APIs (e.g. `/proc/cpuinfo`, etc.) if other more performant diff --git a/crates/std_detect/src/detect/os/linux/auxvec.rs b/crates/std_detect/src/detect/os/linux/auxvec.rs index 79720a0dee..e6a9cae18d 100644 --- a/crates/std_detect/src/detect/os/linux/auxvec.rs +++ b/crates/std_detect/src/detect/os/linux/auxvec.rs @@ -58,10 +58,13 @@ pub(crate) struct AuxVec { /// feature detection on some platforms. /// /// Note: The `std_detect_dlsym_getauxval` cargo feature is ignored on -/// `*-linux-gnu*` and `*-android*` targets because we can safely assume `getauxval` +/// `*-linux-{gnu,musl,ohos}*` and `*-android*` targets because we can safely assume `getauxval` /// is linked to the binary. /// - `*-linux-gnu*` targets ([since Rust 1.64](https://blog.rust-lang.org/2022/08/01/Increasing-glibc-kernel-requirements.html)) /// have glibc requirements higher than [glibc 2.16 that added `getauxval`](https://sourceware.org/legacy-ml/libc-announce/2012/msg00000.html). +/// - `*-linux-musl*` targets ([at least since Rust 1.15](https://github.com/rust-lang/rust/blob/1.15.0/src/ci/docker/x86_64-musl/build-musl.sh#L15)) +/// use musl newer than [musl 1.1.0 that added `getauxval`](https://git.musl-libc.org/cgit/musl/tree/WHATSNEW?h=v1.1.0#n1197) +/// - `*-linux-ohos*` targets use a [fork of musl 1.2](https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/native-lib/musl.md) /// - `*-android*` targets ([since Rust 1.68](https://blog.rust-lang.org/2023/01/09/android-ndk-update-r25.html)) /// have the minimum supported API level higher than [Android 4.3 (API level 18) that added `getauxval`](https://github.com/aosp-mirror/platform_bionic/blob/d3ebc2f7c49a9893b114124d4a6b315f3a328764/libc/include/sys/auxv.h#L49). /// @@ -71,62 +74,8 @@ pub(crate) struct AuxVec { /// [auxvec_h]: https://github.com/torvalds/linux/blob/master/include/uapi/linux/auxvec.h /// [auxv_docs]: https://docs.rs/auxv/0.3.3/auxv/ pub(crate) fn auxv() -> Result { - #[cfg(all( - feature = "std_detect_dlsym_getauxval", - not(all(target_os = "linux", target_env = "gnu")), - // TODO: libc crate currently doesn't provide getauxval on 32-bit Android. - not(all(target_os = "android", target_pointer_width = "64")), - ))] - { - // Try to call a dynamically-linked getauxval function. - if let Ok(hwcap) = getauxval(AT_HWCAP) { - // Targets with only AT_HWCAP: - #[cfg(any( - target_arch = "riscv32", - target_arch = "riscv64", - target_arch = "mips", - target_arch = "mips64" - ))] - { - // Zero could indicate that no features were detected, but it's also used to - // indicate an error. In either case, try the fallback. - if hwcap != 0 { - return Ok(AuxVec { hwcap }); - } - } - - // Targets with AT_HWCAP and AT_HWCAP2: - #[cfg(any( - target_arch = "aarch64", - target_arch = "arm", - target_arch = "powerpc", - target_arch = "powerpc64", - target_arch = "s390x", - ))] - { - if let Ok(hwcap2) = getauxval(AT_HWCAP2) { - // Zero could indicate that no features were detected, but it's also used to - // indicate an error. In particular, on many platforms AT_HWCAP2 will be - // legitimately zero, since it contains the most recent feature flags. Use the - // fallback only if no features were detected at all. - if hwcap != 0 || hwcap2 != 0 { - return Ok(AuxVec { hwcap, hwcap2 }); - } - } - } - - // Intentionnaly not used - let _ = hwcap; - } - } - - #[cfg(any( - not(feature = "std_detect_dlsym_getauxval"), - all(target_os = "linux", target_env = "gnu"), - // TODO: libc crate currently doesn't provide getauxval on 32-bit Android. - all(target_os = "android", target_pointer_width = "64"), - ))] - { + // Try to call a getauxval function. + if let Ok(hwcap) = getauxval(AT_HWCAP) { // Targets with only AT_HWCAP: #[cfg(any( target_arch = "riscv32", @@ -136,7 +85,6 @@ pub(crate) fn auxv() -> Result { target_arch = "loongarch64", ))] { - let hwcap = unsafe { libc::getauxval(AT_HWCAP as libc::c_ulong) as usize }; // Zero could indicate that no features were detected, but it's also used to indicate // an error. In either case, try the fallback. if hwcap != 0 { @@ -153,16 +101,19 @@ pub(crate) fn auxv() -> Result { target_arch = "s390x", ))] { - let hwcap = unsafe { libc::getauxval(AT_HWCAP as libc::c_ulong) as usize }; - let hwcap2 = unsafe { libc::getauxval(AT_HWCAP2 as libc::c_ulong) as usize }; - // Zero could indicate that no features were detected, but it's also used to indicate - // an error. In particular, on many platforms AT_HWCAP2 will be legitimately zero, - // since it contains the most recent feature flags. Use the fallback only if no - // features were detected at all. - if hwcap != 0 || hwcap2 != 0 { - return Ok(AuxVec { hwcap, hwcap2 }); + if let Ok(hwcap2) = getauxval(AT_HWCAP2) { + // Zero could indicate that no features were detected, but it's also used to indicate + // an error. In particular, on many platforms AT_HWCAP2 will be legitimately zero, + // since it contains the most recent feature flags. Use the fallback only if no + // features were detected at all. + if hwcap != 0 || hwcap2 != 0 { + return Ok(AuxVec { hwcap, hwcap2 }); + } } } + + // Intentionnaly not used + let _ = hwcap; } #[cfg(feature = "std_detect_file_io")] @@ -178,27 +129,31 @@ pub(crate) fn auxv() -> Result { } /// Tries to read the `key` from the auxiliary vector by calling the -/// dynamically-linked `getauxval` function. If the function is not linked, -/// this function return `Err`. -#[cfg(any( - test, - all( - feature = "std_detect_dlsym_getauxval", - not(all(target_os = "linux", target_env = "gnu")) - ) -))] +/// `getauxval` function. If the function is not linked, this function return `Err`. fn getauxval(key: usize) -> Result { - use libc; - pub type F = unsafe extern "C" fn(usize) -> usize; - unsafe { - let ptr = libc::dlsym(libc::RTLD_DEFAULT, c"getauxval".as_ptr()); - if ptr.is_null() { - return Err(()); + type F = unsafe extern "C" fn(libc::c_ulong) -> libc::c_ulong; + cfg_if::cfg_if! { + if #[cfg(all( + feature = "std_detect_dlsym_getauxval", + not(all( + target_os = "linux", + any(target_env = "gnu", target_env = "musl", target_env = "ohos"), + )), + // TODO: libc crate currently doesn't provide getauxval on 32-bit Android. + not(all(target_os = "android", target_pointer_width = "64")), + ))] { + let ffi_getauxval: F = unsafe { + let ptr = libc::dlsym(libc::RTLD_DEFAULT, c"getauxval".as_ptr()); + if ptr.is_null() { + return Err(()); + } + core::mem::transmute(ptr) + }; + } else { + let ffi_getauxval: F = libc::getauxval; } - - let ffi_getauxval: F = core::mem::transmute(ptr); - Ok(ffi_getauxval(key)) } + Ok(unsafe { ffi_getauxval(key as libc::c_ulong) as usize }) } /// Tries to read the auxiliary vector from the `file`. If this fails, this