1
1
//! Parses ELF auxiliary vectors.
2
2
#![ cfg_attr( not( target_arch = "aarch64" ) , allow( dead_code) ) ]
3
3
4
- #[ cfg( feature = "std_detect_file_io" ) ]
5
- use crate :: { fs:: File , io:: Read } ;
4
+ pub ( crate ) const AT_NULL : usize = 0 ;
6
5
7
6
/// Key to access the CPU Hardware capabilities bitfield.
8
7
pub ( crate ) const AT_HWCAP : usize = 16 ;
9
8
/// Key to access the CPU Hardware capabilities 2 bitfield.
10
- #[ cfg( any( target_arch = "arm" , target_arch = "powerpc64" ) ) ]
9
+ #[ cfg( any(
10
+ target_arch = "arm" ,
11
+ target_arch = "powerpc" ,
12
+ target_arch = "powerpc64"
13
+ ) ) ]
11
14
pub ( crate ) const AT_HWCAP2 : usize = 26 ;
12
15
13
16
/// Cache HWCAP bitfields of the ELF Auxiliary Vector.
@@ -17,7 +20,11 @@ pub(crate) const AT_HWCAP2: usize = 26;
17
20
#[ derive( Debug , Copy , Clone ) ]
18
21
pub ( crate ) struct AuxVec {
19
22
pub hwcap : usize ,
20
- #[ cfg( any( target_arch = "arm" , target_arch = "powerpc64" ) ) ]
23
+ #[ cfg( any(
24
+ target_arch = "arm" ,
25
+ target_arch = "powerpc" ,
26
+ target_arch = "powerpc64"
27
+ ) ) ]
21
28
pub hwcap2 : usize ,
22
29
}
23
30
@@ -64,7 +71,11 @@ pub(crate) fn auxv() -> Result<AuxVec, ()> {
64
71
}
65
72
66
73
// Targets with AT_HWCAP and AT_HWCAP2:
67
- #[ cfg( any( target_arch = "arm" , target_arch = "powerpc64" ) ) ]
74
+ #[ cfg( any(
75
+ target_arch = "arm" ,
76
+ target_arch = "powerpc" ,
77
+ target_arch = "powerpc64"
78
+ ) ) ]
68
79
{
69
80
if let Ok ( hwcap2) = getauxval ( AT_HWCAP2 ) {
70
81
if hwcap != 0 && hwcap2 != 0 {
@@ -74,21 +85,11 @@ pub(crate) fn auxv() -> Result<AuxVec, ()> {
74
85
}
75
86
drop ( hwcap) ;
76
87
}
77
- #[ cfg( feature = "std_detect_file_io" ) ]
78
- {
79
- // If calling getauxval fails, try to read the auxiliary vector from
80
- // its file:
81
- auxv_from_file ( "/proc/self/auxv" )
82
- }
83
- #[ cfg( not( feature = "std_detect_file_io" ) ) ]
84
- {
85
- Err ( ( ) )
86
- }
87
88
}
88
89
89
90
#[ cfg( not( feature = "std_detect_dlsym_getauxval" ) ) ]
90
91
{
91
- let hwcap = unsafe { ffi_getauxval ( AT_HWCAP ) } ;
92
+ let hwcap = unsafe { libc :: getauxval ( AT_HWCAP ) } ;
92
93
93
94
// Targets with only AT_HWCAP:
94
95
#[ cfg( any( target_arch = "aarch64" , target_arch = "mips" , target_arch = "mips64" ) ) ]
@@ -99,14 +100,29 @@ pub(crate) fn auxv() -> Result<AuxVec, ()> {
99
100
}
100
101
101
102
// Targets with AT_HWCAP and AT_HWCAP2:
102
- #[ cfg( any( target_arch = "arm" , target_arch = "powerpc64" ) ) ]
103
+ #[ cfg( any(
104
+ target_arch = "arm" ,
105
+ target_arch = "powerpc" ,
106
+ target_arch = "powerpc64"
107
+ ) ) ]
103
108
{
104
- let hwcap2 = unsafe { ffi_getauxval ( AT_HWCAP2 ) } ;
109
+ let hwcap2 = unsafe { libc :: getauxval ( AT_HWCAP2 ) } ;
105
110
if hwcap != 0 && hwcap2 != 0 {
106
111
return Ok ( AuxVec { hwcap, hwcap2 } ) ;
107
112
}
108
113
}
109
114
}
115
+
116
+ #[ cfg( feature = "std_detect_file_io" ) ]
117
+ {
118
+ // If calling getauxval fails, try to read the auxiliary vector from
119
+ // its file:
120
+ auxv_from_file ( "/proc/self/auxv" )
121
+ }
122
+ #[ cfg( not( feature = "std_detect_file_io" ) ) ]
123
+ {
124
+ Err ( ( ) )
125
+ }
110
126
}
111
127
112
128
/// Tries to read the `key` from the auxiliary vector by calling the
@@ -122,7 +138,7 @@ fn getauxval(key: usize) -> Result<usize, ()> {
122
138
return Err ( ( ) ) ;
123
139
}
124
140
125
- let ffi_getauxval: F = mem:: transmute ( ptr) ;
141
+ let ffi_getauxval: F = core :: mem:: transmute ( ptr) ;
126
142
Ok ( ffi_getauxval ( key) )
127
143
}
128
144
}
@@ -131,18 +147,19 @@ fn getauxval(key: usize) -> Result<usize, ()> {
131
147
/// function returns `Err`.
132
148
#[ cfg( feature = "std_detect_file_io" ) ]
133
149
fn auxv_from_file ( file : & str ) -> Result < AuxVec , ( ) > {
134
- let mut file = File :: open ( file) . map_err ( |_| ( ) ) ?;
150
+ let file = super :: read_file ( file) ?;
135
151
136
152
// See <https://github.com/torvalds/linux/blob/v3.19/include/uapi/linux/auxvec.h>.
137
153
//
138
154
// The auxiliary vector contains at most 32 (key,value) fields: from
139
155
// `AT_EXECFN = 31` to `AT_NULL = 0`. That is, a buffer of
140
156
// 2*32 `usize` elements is enough to read the whole vector.
141
157
let mut buf = [ 0_usize ; 64 ] ;
142
- {
143
- let raw : & mut [ u8 ; 64 * mem :: size_of :: < usize > ( ) ] = unsafe { mem :: transmute ( & mut buf ) } ;
144
- file. read ( raw ) . map_err ( |_| ( ) ) ? ;
158
+ let len = core :: mem :: size_of_val ( & buf ) . max ( file . len ( ) ) ;
159
+ unsafe {
160
+ core :: ptr :: copy_nonoverlapping ( file. as_ptr ( ) , buf . as_mut_ptr ( ) as * mut u8 , len ) ;
145
161
}
162
+
146
163
auxv_from_buf ( & buf)
147
164
}
148
165
@@ -155,18 +172,24 @@ fn auxv_from_buf(buf: &[usize; 64]) -> Result<AuxVec, ()> {
155
172
{
156
173
for el in buf. chunks ( 2 ) {
157
174
match el[ 0 ] {
175
+ AT_NULL => break ,
158
176
AT_HWCAP => return Ok ( AuxVec { hwcap : el[ 1 ] } ) ,
159
177
_ => ( ) ,
160
178
}
161
179
}
162
180
}
163
181
// Targets with AT_HWCAP and AT_HWCAP2:
164
- #[ cfg( any( target_arch = "arm" , target_arch = "powerpc64" ) ) ]
182
+ #[ cfg( any(
183
+ target_arch = "arm" ,
184
+ target_arch = "powerpc" ,
185
+ target_arch = "powerpc64"
186
+ ) ) ]
165
187
{
166
188
let mut hwcap = None ;
167
189
let mut hwcap2 = None ;
168
190
for el in buf. chunks ( 2 ) {
169
191
match el[ 0 ] {
192
+ AT_NULL => break ,
170
193
AT_HWCAP => hwcap = Some ( el[ 1 ] ) ,
171
194
AT_HWCAP2 => hwcap2 = Some ( el[ 1 ] ) ,
172
195
_ => ( ) ,
@@ -214,7 +237,12 @@ mod tests {
214
237
215
238
// FIXME: on mips/mips64 getauxval returns 0, and /proc/self/auxv
216
239
// does not always contain the AT_HWCAP key under qemu.
217
- #[ cfg( not( any( target_arch = "mips" , target_arch = "mips64" , target_arch = "powerpc" ) ) ) ]
240
+ #[ cfg( any(
241
+ target_arch = "aarch64" ,
242
+ target_arch = "arm" ,
243
+ target_arch = "powerpc" ,
244
+ target_arch = "powerpc64"
245
+ ) ) ]
218
246
#[ test]
219
247
fn auxv_crate ( ) {
220
248
let v = auxv ( ) ;
@@ -224,7 +252,11 @@ mod tests {
224
252
}
225
253
226
254
// Targets with AT_HWCAP and AT_HWCAP2:
227
- #[ cfg( any( target_arch = "arm" , target_arch = "powerpc64" ) ) ]
255
+ #[ cfg( any(
256
+ target_arch = "arm" ,
257
+ target_arch = "powerpc" ,
258
+ target_arch = "powerpc64"
259
+ ) ) ]
228
260
{
229
261
if let Some ( hwcap2) = auxv_crate_getauxval ( AT_HWCAP2 ) {
230
262
let rt_hwcap2 = v. expect ( "failed to find hwcap2 key" ) . hwcap2 ;
@@ -243,7 +275,7 @@ mod tests {
243
275
}
244
276
245
277
#[ cfg( feature = "std_detect_file_io" ) ]
246
- cfg_if ! {
278
+ cfg_if:: cfg_if ! {
247
279
if #[ cfg( target_arch = "arm" ) ] {
248
280
#[ test]
249
281
fn linux_rpi3( ) {
@@ -264,6 +296,7 @@ mod tests {
264
296
// want to fall back to /proc/cpuinfo in this case, so
265
297
// reading should fail. assert_eq!(v.hwcap, 126614527);
266
298
// assert_eq!(v.hwcap2, 0);
299
+ let _ = v;
267
300
}
268
301
} else if #[ cfg( target_arch = "aarch64" ) ] {
269
302
#[ test]
@@ -286,15 +319,26 @@ mod tests {
286
319
}
287
320
}
288
321
322
+ #[ cfg( any(
323
+ target_arch = "aarch64" ,
324
+ target_arch = "arm" ,
325
+ target_arch = "powerpc" ,
326
+ target_arch = "powerpc64"
327
+ ) ) ]
289
328
#[ test]
329
+ #[ cfg( feature = "std_detect_file_io" ) ]
290
330
fn auxv_crate_procfs ( ) {
291
331
let v = auxv ( ) ;
292
332
if let Some ( hwcap) = auxv_crate_getprocfs ( AT_HWCAP ) {
293
333
assert_eq ! ( v. unwrap( ) . hwcap, hwcap) ;
294
334
}
295
335
296
336
// Targets with AT_HWCAP and AT_HWCAP2:
297
- #[ cfg( any( target_arch = "arm" , target_arch = "powerpc64" ) ) ]
337
+ #[ cfg( any(
338
+ target_arch = "arm" ,
339
+ target_arch = "powerpc" ,
340
+ target_arch = "powerpc64"
341
+ ) ) ]
298
342
{
299
343
if let Some ( hwcap2) = auxv_crate_getprocfs ( AT_HWCAP2 ) {
300
344
assert_eq ! ( v. unwrap( ) . hwcap2, hwcap2) ;
0 commit comments