Rollup merge of #147024 - brad0:std_detect_openbsd_elf_aux_info, r=Mark-Simulacrum
std_detect: Support run-time detection on OpenBSD using elf_aux_info
This commit is contained in:
commit
da171df13c
6 changed files with 107 additions and 5 deletions
|
|
@ -66,10 +66,12 @@ crate from working on applications in which `std` is not available.
|
|||
|
||||
* FreeBSD:
|
||||
* `arm32`, `powerpc64`: `std_detect` supports these on FreeBSD by querying ELF
|
||||
auxiliary vectors using `sysctl`.
|
||||
auxiliary vectors using `elf_aux_info`.
|
||||
* `arm64`: run-time feature detection is implemented by directly querying `mrs`.
|
||||
|
||||
* OpenBSD:
|
||||
* `powerpc64`: `std_detect` supports these on OpenBSD by querying ELF auxiliary
|
||||
vectors using `elf_aux_info`.
|
||||
* `arm64`: run-time feature detection is implemented by querying `sysctl`.
|
||||
|
||||
* Windows:
|
||||
|
|
|
|||
|
|
@ -61,11 +61,12 @@ cfg_select! {
|
|||
#[path = "os/freebsd/mod.rs"]
|
||||
mod os;
|
||||
}
|
||||
all(target_os = "openbsd", target_arch = "aarch64", feature = "libc") => {
|
||||
all(target_os = "openbsd", feature = "libc") => {
|
||||
#[allow(dead_code)] // we don't use code that calls the mrs instruction.
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
#[path = "os/aarch64.rs"]
|
||||
mod aarch64;
|
||||
#[path = "os/openbsd/aarch64.rs"]
|
||||
#[path = "os/openbsd/mod.rs"]
|
||||
mod os;
|
||||
}
|
||||
all(target_os = "windows", any(target_arch = "aarch64", target_arch = "arm64ec")) => {
|
||||
|
|
|
|||
54
library/std_detect/src/detect/os/openbsd/auxvec.rs
Normal file
54
library/std_detect/src/detect/os/openbsd/auxvec.rs
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
//! Parses ELF auxiliary vectors.
|
||||
#![cfg_attr(
|
||||
any(target_arch = "aarch64", target_arch = "powerpc64", target_arch = "riscv64"),
|
||||
allow(dead_code)
|
||||
)]
|
||||
|
||||
/// 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 OpenBSD, they are
|
||||
/// defined in [machine/elf.h][elfh]. 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.h]: https://github.com/openbsd/src/blob/master/sys/arch/arm64/include/elf.h
|
||||
/// [elf.h]: https://github.com/openbsd/src/blob/master/sys/arch/powerpc64/include/elf.h
|
||||
pub(crate) fn auxv() -> Result<AuxVec, ()> {
|
||||
let hwcap = archauxv(libc::AT_HWCAP);
|
||||
let hwcap2 = archauxv(libc::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.
|
||||
if hwcap != 0 || hwcap2 != 0 {
|
||||
return Ok(AuxVec { hwcap, hwcap2 });
|
||||
}
|
||||
Err(())
|
||||
}
|
||||
|
||||
/// Tries to read the `key` from the auxiliary vector.
|
||||
fn archauxv(key: libc::c_int) -> usize {
|
||||
const OUT_LEN: libc::c_int = core::mem::size_of::<libc::c_ulong>() as libc::c_int;
|
||||
let mut out: libc::c_ulong = 0;
|
||||
unsafe {
|
||||
let res =
|
||||
libc::elf_aux_info(key, &mut out as *mut libc::c_ulong as *mut libc::c_void, OUT_LEN);
|
||||
// If elf_aux_info fails, `out` will be left at zero (which is the proper default value).
|
||||
debug_assert!(res == 0 || out == 0);
|
||||
}
|
||||
out as usize
|
||||
}
|
||||
21
library/std_detect/src/detect/os/openbsd/mod.rs
Normal file
21
library/std_detect/src/detect/os/openbsd/mod.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
//! Run-time feature detection on OpenBSD
|
||||
|
||||
mod auxvec;
|
||||
|
||||
cfg_select! {
|
||||
target_arch = "aarch64" => {
|
||||
mod aarch64;
|
||||
pub(crate) use self::aarch64::detect_features;
|
||||
}
|
||||
target_arch = "powerpc64" => {
|
||||
mod powerpc;
|
||||
pub(crate) use self::powerpc::detect_features;
|
||||
}
|
||||
_ => {
|
||||
use crate::detect::cache;
|
||||
/// Performs run-time feature detection.
|
||||
pub(crate) fn detect_features() -> cache::Initializer {
|
||||
cache::Initializer::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
21
library/std_detect/src/detect/os/openbsd/powerpc.rs
Normal file
21
library/std_detect/src/detect/os/openbsd/powerpc.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
//! Run-time feature detection for PowerPC on OpenBSD.
|
||||
|
||||
use super::auxvec;
|
||||
use crate::detect::{Feature, cache};
|
||||
|
||||
pub(crate) fn detect_features() -> cache::Initializer {
|
||||
let mut value = cache::Initializer::default();
|
||||
let enable_feature = |value: &mut cache::Initializer, f, enable| {
|
||||
if enable {
|
||||
value.set(f as u32);
|
||||
}
|
||||
};
|
||||
|
||||
if let Ok(auxv) = auxvec::auxv() {
|
||||
enable_feature(&mut value, Feature::altivec, auxv.hwcap & 0x10000000 != 0);
|
||||
enable_feature(&mut value, Feature::vsx, auxv.hwcap & 0x00000080 != 0);
|
||||
enable_feature(&mut value, Feature::power8, auxv.hwcap2 & 0x80000000 != 0);
|
||||
return value;
|
||||
}
|
||||
value
|
||||
}
|
||||
|
|
@ -319,8 +319,11 @@ fn powerpc_linux() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(all(target_arch = "powerpc64", any(target_os = "linux", target_os = "freebsd"),))]
|
||||
fn powerpc64_linux_or_freebsd() {
|
||||
#[cfg(all(
|
||||
target_arch = "powerpc64",
|
||||
any(target_os = "linux", target_os = "freebsd", target_os = "openbsd"),
|
||||
))]
|
||||
fn powerpc64_linux_or_bsd() {
|
||||
println!("altivec: {}", is_powerpc64_feature_detected!("altivec"));
|
||||
println!("vsx: {}", is_powerpc64_feature_detected!("vsx"));
|
||||
println!("power8: {}", is_powerpc64_feature_detected!("power8"));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue