11//! Parses ELF auxiliary vectors.
22#![ cfg_attr( not( target_arch = "aarch64" ) , allow( dead_code) ) ]
33
4- #[ cfg( feature = "std_detect_file_io" ) ]
5- use crate :: { fs:: File , io:: Read } ;
4+ pub ( crate ) const AT_NULL : usize = 0 ;
65
76/// Key to access the CPU Hardware capabilities bitfield.
87pub ( crate ) const AT_HWCAP : usize = 16 ;
98/// 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+ ) ) ]
1114pub ( crate ) const AT_HWCAP2 : usize = 26 ;
1215
1316/// Cache HWCAP bitfields of the ELF Auxiliary Vector.
@@ -17,7 +20,11 @@ pub(crate) const AT_HWCAP2: usize = 26;
1720#[ derive( Debug , Copy , Clone ) ]
1821pub ( crate ) struct AuxVec {
1922 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+ ) ) ]
2128 pub hwcap2 : usize ,
2229}
2330
@@ -64,7 +71,11 @@ pub(crate) fn auxv() -> Result<AuxVec, ()> {
6471 }
6572
6673 // 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+ ) ) ]
6879 {
6980 if let Ok ( hwcap2) = getauxval ( AT_HWCAP2 ) {
7081 if hwcap != 0 && hwcap2 != 0 {
@@ -74,21 +85,11 @@ pub(crate) fn auxv() -> Result<AuxVec, ()> {
7485 }
7586 drop ( hwcap) ;
7687 }
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- }
8788 }
8889
8990 #[ cfg( not( feature = "std_detect_dlsym_getauxval" ) ) ]
9091 {
91- let hwcap = unsafe { ffi_getauxval ( AT_HWCAP ) } ;
92+ let hwcap = unsafe { libc :: getauxval ( AT_HWCAP ) } ;
9293
9394 // Targets with only AT_HWCAP:
9495 #[ cfg( any( target_arch = "aarch64" , target_arch = "mips" , target_arch = "mips64" ) ) ]
@@ -99,14 +100,29 @@ pub(crate) fn auxv() -> Result<AuxVec, ()> {
99100 }
100101
101102 // 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+ ) ) ]
103108 {
104- let hwcap2 = unsafe { ffi_getauxval ( AT_HWCAP2 ) } ;
109+ let hwcap2 = unsafe { libc :: getauxval ( AT_HWCAP2 ) } ;
105110 if hwcap != 0 && hwcap2 != 0 {
106111 return Ok ( AuxVec { hwcap, hwcap2 } ) ;
107112 }
108113 }
109114 }
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+ }
110126}
111127
112128/// Tries to read the `key` from the auxiliary vector by calling the
@@ -122,7 +138,7 @@ fn getauxval(key: usize) -> Result<usize, ()> {
122138 return Err ( ( ) ) ;
123139 }
124140
125- let ffi_getauxval: F = mem:: transmute ( ptr) ;
141+ let ffi_getauxval: F = core :: mem:: transmute ( ptr) ;
126142 Ok ( ffi_getauxval ( key) )
127143 }
128144}
@@ -131,18 +147,19 @@ fn getauxval(key: usize) -> Result<usize, ()> {
131147/// function returns `Err`.
132148#[ cfg( feature = "std_detect_file_io" ) ]
133149fn auxv_from_file ( file : & str ) -> Result < AuxVec , ( ) > {
134- let mut file = File :: open ( file) . map_err ( |_| ( ) ) ?;
150+ let file = super :: read_file ( file) ?;
135151
136152 // See <https://github.com/torvalds/linux/blob/v3.19/include/uapi/linux/auxvec.h>.
137153 //
138154 // The auxiliary vector contains at most 32 (key,value) fields: from
139155 // `AT_EXECFN = 31` to `AT_NULL = 0`. That is, a buffer of
140156 // 2*32 `usize` elements is enough to read the whole vector.
141157 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 ) ;
145161 }
162+
146163 auxv_from_buf ( & buf)
147164}
148165
@@ -155,18 +172,24 @@ fn auxv_from_buf(buf: &[usize; 64]) -> Result<AuxVec, ()> {
155172 {
156173 for el in buf. chunks ( 2 ) {
157174 match el[ 0 ] {
175+ AT_NULL => break ,
158176 AT_HWCAP => return Ok ( AuxVec { hwcap : el[ 1 ] } ) ,
159177 _ => ( ) ,
160178 }
161179 }
162180 }
163181 // 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+ ) ) ]
165187 {
166188 let mut hwcap = None ;
167189 let mut hwcap2 = None ;
168190 for el in buf. chunks ( 2 ) {
169191 match el[ 0 ] {
192+ AT_NULL => break ,
170193 AT_HWCAP => hwcap = Some ( el[ 1 ] ) ,
171194 AT_HWCAP2 => hwcap2 = Some ( el[ 1 ] ) ,
172195 _ => ( ) ,
@@ -214,7 +237,12 @@ mod tests {
214237
215238 // FIXME: on mips/mips64 getauxval returns 0, and /proc/self/auxv
216239 // 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+ ) ) ]
218246 #[ test]
219247 fn auxv_crate ( ) {
220248 let v = auxv ( ) ;
@@ -224,7 +252,11 @@ mod tests {
224252 }
225253
226254 // 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+ ) ) ]
228260 {
229261 if let Some ( hwcap2) = auxv_crate_getauxval ( AT_HWCAP2 ) {
230262 let rt_hwcap2 = v. expect ( "failed to find hwcap2 key" ) . hwcap2 ;
@@ -243,7 +275,7 @@ mod tests {
243275 }
244276
245277 #[ cfg( feature = "std_detect_file_io" ) ]
246- cfg_if ! {
278+ cfg_if:: cfg_if ! {
247279 if #[ cfg( target_arch = "arm" ) ] {
248280 #[ test]
249281 fn linux_rpi3( ) {
@@ -264,6 +296,7 @@ mod tests {
264296 // want to fall back to /proc/cpuinfo in this case, so
265297 // reading should fail. assert_eq!(v.hwcap, 126614527);
266298 // assert_eq!(v.hwcap2, 0);
299+ let _ = v;
267300 }
268301 } else if #[ cfg( target_arch = "aarch64" ) ] {
269302 #[ test]
@@ -286,15 +319,26 @@ mod tests {
286319 }
287320 }
288321
322+ #[ cfg( any(
323+ target_arch = "aarch64" ,
324+ target_arch = "arm" ,
325+ target_arch = "powerpc" ,
326+ target_arch = "powerpc64"
327+ ) ) ]
289328 #[ test]
329+ #[ cfg( feature = "std_detect_file_io" ) ]
290330 fn auxv_crate_procfs ( ) {
291331 let v = auxv ( ) ;
292332 if let Some ( hwcap) = auxv_crate_getprocfs ( AT_HWCAP ) {
293333 assert_eq ! ( v. unwrap( ) . hwcap, hwcap) ;
294334 }
295335
296336 // 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+ ) ) ]
298342 {
299343 if let Some ( hwcap2) = auxv_crate_getprocfs ( AT_HWCAP2 ) {
300344 assert_eq ! ( v. unwrap( ) . hwcap2, hwcap2) ;
0 commit comments