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
4035pub ( 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}
0 commit comments