Skip to content

Commit 88ad5da

Browse files
committed
std_detect: Use elf_aux_info on FreeBSD
1 parent b1edbf9 commit 88ad5da

File tree

2 files changed

+28
-60
lines changed

2 files changed

+28
-60
lines changed

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

+23-58
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,6 @@
99
allow(dead_code)
1010
)]
1111

12-
/// Key to access the CPU Hardware capabilities bitfield.
13-
pub(crate) const AT_HWCAP: usize = 25;
14-
/// Key to access the CPU Hardware capabilities 2 bitfield.
15-
pub(crate) const AT_HWCAP2: usize = 26;
16-
1712
/// Cache HWCAP bitfields of the ELF Auxiliary Vector.
1813
///
1914
/// If an entry cannot be read all the bits in the bitfield are set to zero.
@@ -38,65 +33,35 @@ pub(crate) struct AuxVec {
3833
///
3934
/// [elf_common.h]: https://svnweb.freebsd.org/base/release/12.0.0/sys/sys/elf_common.h?revision=341707
4035
pub(crate) fn auxv() -> Result<AuxVec, ()> {
41-
if let Ok(hwcap) = archauxv(AT_HWCAP) {
42-
if let Ok(hwcap2) = archauxv(AT_HWCAP2) {
43-
if hwcap != 0 && hwcap2 != 0 {
44-
return Ok(AuxVec { hwcap, hwcap2 });
45-
}
46-
}
36+
let hwcap = archauxv(libc::AT_HWCAP);
37+
let hwcap2 = archauxv(libc::AT_HWCAP2);
38+
// Zero could indicate that no features were detected, but it's also used to
39+
// indicate an error. In particular, on many platforms AT_HWCAP2 will be
40+
// legitimately zero, since it contains the most recent feature flags. Use the
41+
// fallback only if no features were detected at all.
42+
if hwcap != 0 || hwcap2 != 0 {
43+
return Ok(AuxVec { hwcap, hwcap2 });
4744
}
4845
Err(())
4946
}
5047

5148
/// Tries to read the `key` from the auxiliary vector.
52-
fn archauxv(key: usize) -> Result<usize, ()> {
53-
use core::mem;
54-
55-
#[derive(Copy, Clone)]
56-
#[repr(C)]
57-
pub struct Elf_Auxinfo {
58-
pub a_type: usize,
59-
pub a_un: unnamed,
60-
}
61-
#[derive(Copy, Clone)]
62-
#[repr(C)]
63-
pub union unnamed {
64-
pub a_val: libc::c_long,
65-
pub a_ptr: *mut libc::c_void,
66-
pub a_fcn: Option<unsafe extern "C" fn() -> ()>,
67-
}
68-
69-
let mut auxv: [Elf_Auxinfo; 27] = [Elf_Auxinfo {
70-
a_type: 0,
71-
a_un: unnamed { a_val: 0 },
72-
}; 27];
73-
74-
let mut len: libc::c_uint = mem::size_of_val(&auxv) as libc::c_uint;
75-
49+
fn archauxv(key: libc::c_int) -> usize {
50+
const OUT_LEN: libc::c_int = core::mem::size_of::<libc::c_ulong>() as libc::c_int;
51+
let mut out: libc::c_ulong = 0;
7652
unsafe {
77-
let mut mib = [
78-
libc::CTL_KERN,
79-
libc::KERN_PROC,
80-
libc::KERN_PROC_AUXV,
81-
libc::getpid(),
82-
];
83-
84-
let ret = libc::sysctl(
85-
mib.as_mut_ptr(),
86-
mib.len() as u32,
87-
&mut auxv as *mut _ as *mut _,
88-
&mut len as *mut _ as *mut _,
89-
0 as *mut libc::c_void,
90-
0,
53+
// elf_aux_info is available on FreeBSD 12.0+ and 11.4+:
54+
// https://github.com/freebsd/freebsd-src/commit/0b08ae2120cdd08c20a2b806e2fcef4d0a36c470
55+
// https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/sys/auxv.h
56+
// FreeBSD 11 support in std has been removed in Rust 1.75 (https://github.com/rust-lang/rust/pull/114521),
57+
// so we can safely use this function.
58+
let res = libc::elf_aux_info(
59+
key,
60+
&mut out as *mut libc::c_ulong as *mut libc::c_void,
61+
OUT_LEN,
9162
);
92-
93-
if ret != -1 {
94-
for i in 0..auxv.len() {
95-
if auxv[i].a_type == key {
96-
return Ok(auxv[i].a_un.a_val as usize);
97-
}
98-
}
99-
}
63+
// If elf_aux_info fails, `out` will be left at zero (which is the proper default value).
64+
debug_assert!(res == 0 || out == 0);
10065
}
101-
return Ok(0);
66+
out as usize
10267
}

crates/std_detect/tests/cpu-detection.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -228,8 +228,11 @@ fn powerpc_linux() {
228228
}
229229

230230
#[test]
231-
#[cfg(all(target_arch = "powerpc64", target_os = "linux"))]
232-
fn powerpc64_linux() {
231+
#[cfg(all(
232+
target_arch = "powerpc64",
233+
any(target_os = "linux", target_os = "freebsd"),
234+
))]
235+
fn powerpc64_linux_or_freebsd() {
233236
println!("altivec: {}", is_powerpc64_feature_detected!("altivec"));
234237
println!("vsx: {}", is_powerpc64_feature_detected!("vsx"));
235238
println!("power8: {}", is_powerpc64_feature_detected!("power8"));

0 commit comments

Comments
 (0)