1
1
//! Parses ELF auxiliary vectors.
2
2
#![ cfg_attr( not( target_arch = "aarch64" ) , allow( dead_code) ) ]
3
3
4
- extern crate std;
5
- use self :: std:: { prelude:: v1:: * , fs:: File , io:: Read } ;
6
-
7
- use core:: mem;
4
+ #[ cfg( feature = "std_detect_file_io" ) ]
5
+ use :: { fs:: File , io:: Read } ;
8
6
9
7
/// Key to access the CPU Hardware capabilities bitfield.
10
8
pub ( crate ) const AT_HWCAP : usize = 16 ;
@@ -34,8 +32,12 @@ pub(crate) struct AuxVec {
34
32
///
35
33
/// There is no perfect way of reading the auxiliary vector.
36
34
///
37
- /// - If the `getauxval` is dynamically linked to this binary, it will be used.
38
- /// - Otherwise, try to read `/proc/self/auxv`.
35
+ /// - If the `std_detect_dlsym_getauxval` cargo feature is enabled, this will use
36
+ /// `getauxval` if its linked to the binary, and otherwise proceed to a fallback implementation.
37
+ /// When `std_detect_dlsym_getauxval` is disabled, this will assume that `getauxval` is
38
+ /// linked to the binary - if that is not the case the behavior is undefined.
39
+ /// - Otherwise, if the `std_detect_file_io` cargo feature is enabled, it will
40
+ /// try to read `/proc/self/auxv`.
39
41
/// - If that fails, this function returns an error.
40
42
///
41
43
/// Note that run-time feature detection is not invoked for features that can
@@ -49,8 +51,42 @@ pub(crate) struct AuxVec {
49
51
/// [auxvec_h]: https://github.com/torvalds/linux/blob/master/include/uapi/linux/auxvec.h
50
52
/// [auxv_docs]: https://docs.rs/auxv/0.3.3/auxv/
51
53
pub ( crate ) fn auxv ( ) -> Result < AuxVec , ( ) > {
52
- // Try to call a dynamically-linked getauxval function.
53
- if let Ok ( hwcap) = getauxval ( AT_HWCAP ) {
54
+ #[ cfg( feature = "std_detect_dlsym_getauxval" ) ] {
55
+ // Try to call a dynamically-linked getauxval function.
56
+ if let Ok ( hwcap) = getauxval ( AT_HWCAP ) {
57
+ // Targets with only AT_HWCAP:
58
+ #[ cfg( any( target_arch = "aarch64" , target_arch = "mips" ,
59
+ target_arch = "mips64" ) ) ]
60
+ {
61
+ if hwcap != 0 {
62
+ return Ok ( AuxVec { hwcap } ) ;
63
+ }
64
+ }
65
+
66
+ // Targets with AT_HWCAP and AT_HWCAP2:
67
+ #[ cfg( any( target_arch = "arm" , target_arch = "powerpc64" ) ) ]
68
+ {
69
+ if let Ok ( hwcap2) = getauxval ( AT_HWCAP2 ) {
70
+ if hwcap != 0 && hwcap2 != 0 {
71
+ return Ok ( AuxVec { hwcap, hwcap2 } ) ;
72
+ }
73
+ }
74
+ }
75
+ drop ( hwcap) ;
76
+ }
77
+ #[ cfg( feature = "std_detect_file_io" ) ] {
78
+ // If calling getauxval fails, try to read the auxiliary vector from
79
+ // its file:
80
+ auxv_from_file ( "/proc/self/auxv" )
81
+ }
82
+ #[ cfg( not( feature = "std_detect_file_io" ) ) ] {
83
+ Err ( ( ) )
84
+ }
85
+ }
86
+
87
+ #[ cfg( not( feature = "std_detect_dlsym_getauxval" ) ) ] {
88
+ let hwcap = unsafe { ffi_getauxval ( AT_HWCAP ) } ;
89
+
54
90
// Targets with only AT_HWCAP:
55
91
#[ cfg( any( target_arch = "aarch64" , target_arch = "mips" ,
56
92
target_arch = "mips64" ) ) ]
@@ -63,22 +99,18 @@ pub(crate) fn auxv() -> Result<AuxVec, ()> {
63
99
// Targets with AT_HWCAP and AT_HWCAP2:
64
100
#[ cfg( any( target_arch = "arm" , target_arch = "powerpc64" ) ) ]
65
101
{
66
- if let Ok ( hwcap2) = getauxval ( AT_HWCAP2 ) {
67
- if hwcap != 0 && hwcap2 != 0 {
68
- return Ok ( AuxVec { hwcap, hwcap2 } ) ;
69
- }
102
+ let hwcap2 = unsafe { ffi_getauxval ( AT_HWCAP2 ) } ;
103
+ if hwcap != 0 && hwcap2 != 0 {
104
+ return Ok ( AuxVec { hwcap, hwcap2 } ) ;
70
105
}
71
106
}
72
- drop ( hwcap) ;
73
107
}
74
- // If calling getauxval fails, try to read the auxiliary vector from
75
- // its file:
76
- auxv_from_file ( "/proc/self/auxv" )
77
108
}
78
109
79
110
/// Tries to read the `key` from the auxiliary vector by calling the
80
111
/// dynamically-linked `getauxval` function. If the function is not linked,
81
112
/// this function return `Err`.
113
+ #[ cfg( feature = "std_detect_dlsym_getauxval" ) ]
82
114
fn getauxval ( key : usize ) -> Result < usize , ( ) > {
83
115
use libc;
84
116
pub type F = unsafe extern "C" fn ( usize ) -> usize ;
@@ -98,6 +130,7 @@ fn getauxval(key: usize) -> Result<usize, ()> {
98
130
99
131
/// Tries to read the auxiliary vector from the `file`. If this fails, this
100
132
/// function returns `Err`.
133
+ #[ cfg( feature = "std_detect_file_io" ) ]
101
134
fn auxv_from_file ( file : & str ) -> Result < AuxVec , ( ) > {
102
135
let mut file = File :: open ( file) . map_err ( |_| ( ) ) ?;
103
136
@@ -117,6 +150,7 @@ fn auxv_from_file(file: &str) -> Result<AuxVec, ()> {
117
150
118
151
/// Tries to interpret the `buffer` as an auxiliary vector. If that fails, this
119
152
/// function returns `Err`.
153
+ #[ cfg( feature = "std_detect_file_io" ) ]
120
154
fn auxv_from_buf ( buf : & [ usize ; 64 ] ) -> Result < AuxVec , ( ) > {
121
155
// Targets with only AT_HWCAP:
122
156
#[ cfg( any( target_arch = "aarch64" , target_arch = "mips" ,
@@ -157,6 +191,7 @@ mod tests {
157
191
158
192
// Reads the Auxiliary Vector key from /proc/self/auxv
159
193
// using the auxv crate.
194
+ #[ cfg( feature = "std_detect_file_io" ) ]
160
195
fn auxv_crate_getprocfs ( key : usize ) -> Option < usize > {
161
196
use self :: auxv_crate:: AuxvType ;
162
197
use self :: auxv_crate:: procfs:: search_procfs_auxv;
@@ -210,6 +245,7 @@ mod tests {
210
245
}
211
246
}
212
247
248
+ #[ cfg( feature = "std_detect_file_io" ) ]
213
249
cfg_if ! {
214
250
if #[ cfg( target_arch = "arm" ) ] {
215
251
#[ test]
@@ -244,6 +280,7 @@ mod tests {
244
280
}
245
281
246
282
#[ test]
283
+ #[ cfg( feature = "std_detect_file_io" ) ]
247
284
fn auxv_dump_procfs ( ) {
248
285
if let Ok ( auxvec) = auxv_from_file ( "/proc/self/auxv" ) {
249
286
println ! ( "{:?}" , auxvec) ;
0 commit comments