9
9
allow( dead_code)
10
10
) ]
11
11
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
-
17
12
/// Cache HWCAP bitfields of the ELF Auxiliary Vector.
18
13
///
19
14
/// If an entry cannot be read all the bits in the bitfield are set to zero.
@@ -38,65 +33,34 @@ pub(crate) struct AuxVec {
38
33
///
39
34
/// [elf_common.h]: https://svnweb.freebsd.org/base/release/12.0.0/sys/sys/elf_common.h?revision=341707
40
35
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.
41
+ if hwcap != 0 || hwcap2 != 0 {
42
+ return Ok ( AuxVec { hwcap, hwcap2 } ) ;
47
43
}
48
44
Err ( ( ) )
49
45
}
50
46
51
47
/// 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
-
48
+ fn archauxv ( key : libc:: c_int ) -> usize {
49
+ const OUT_LEN : libc:: c_int = core:: mem:: size_of :: < libc:: c_ulong > ( ) as libc:: c_int ;
50
+ let mut out: libc:: c_ulong = 0 ;
76
51
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 ,
52
+ // elf_aux_info is available on FreeBSD 12.0+ and 11.4+:
53
+ // https://github.com/freebsd/freebsd-src/commit/0b08ae2120cdd08c20a2b806e2fcef4d0a36c470
54
+ // https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/sys/auxv.h
55
+ // FreeBSD 11 support in std has been removed in Rust 1.75 (https://github.com/rust-lang/rust/pull/114521),
56
+ // so we can safely use this function.
57
+ let res = libc:: elf_aux_info (
58
+ key,
59
+ & mut out as * mut libc:: c_ulong as * mut libc:: c_void ,
60
+ OUT_LEN ,
91
61
) ;
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
- }
62
+ // If elf_aux_info fails, `out` will be left at zero (which is the proper default value).
63
+ debug_assert ! ( res == 0 || out == 0 ) ;
100
64
}
101
- return Ok ( 0 ) ;
65
+ out as usize
102
66
}
0 commit comments