@@ -21,6 +21,8 @@ use core::sync::atomic::AtomicU8;
21
21
use core:: sync:: atomic:: Ordering :: Relaxed ;
22
22
use core:: sync:: atomic:: { AtomicPtr , AtomicUsize } ;
23
23
use linux_raw_sys:: elf:: * ;
24
+ #[ cfg( target_arch = "x86" ) ]
25
+ use linux_raw_sys:: general:: AT_SYSINFO ;
24
26
use linux_raw_sys:: general:: {
25
27
AT_BASE , AT_CLKTCK , AT_EXECFN , AT_HWCAP , AT_HWCAP2 , AT_MINSIGSTKSZ , AT_NULL , AT_PAGESZ ,
26
28
AT_SYSINFO_EHDR ,
@@ -38,8 +40,12 @@ pub(crate) fn page_size() -> usize {
38
40
let mut page_size = PAGE_SIZE . load ( Relaxed ) ;
39
41
40
42
if page_size == 0 {
41
- init_auxv ( ) ;
42
- page_size = PAGE_SIZE . load ( Relaxed ) ;
43
+ #[ cold]
44
+ fn compute_page_size ( ) -> usize {
45
+ init_auxv ( ) ;
46
+ PAGE_SIZE . load ( Relaxed )
47
+ }
48
+ page_size = compute_page_size ( ) ;
43
49
}
44
50
45
51
page_size
@@ -51,8 +57,12 @@ pub(crate) fn clock_ticks_per_second() -> u64 {
51
57
let mut ticks = CLOCK_TICKS_PER_SECOND . load ( Relaxed ) ;
52
58
53
59
if ticks == 0 {
54
- init_auxv ( ) ;
55
- ticks = CLOCK_TICKS_PER_SECOND . load ( Relaxed ) ;
60
+ #[ cold]
61
+ fn compute_clock_ticks_per_second ( ) -> usize {
62
+ init_auxv ( ) ;
63
+ CLOCK_TICKS_PER_SECOND . load ( Relaxed )
64
+ }
65
+ ticks = compute_clock_ticks_per_second ( ) ;
56
66
}
57
67
58
68
ticks as u64
@@ -65,9 +75,12 @@ pub(crate) fn linux_hwcap() -> (usize, usize) {
65
75
let mut hwcap2 = HWCAP2 . load ( Relaxed ) ;
66
76
67
77
if hwcap == 0 || hwcap2 == 0 {
68
- init_auxv ( ) ;
69
- hwcap = HWCAP . load ( Relaxed ) ;
70
- hwcap2 = HWCAP2 . load ( Relaxed ) ;
78
+ #[ cold]
79
+ fn compute_linux_hwcap ( ) -> ( usize , usize ) {
80
+ init_auxv ( ) ;
81
+ ( HWCAP . load ( Relaxed ) , HWCAP2 . load ( Relaxed ) )
82
+ }
83
+ ( hwcap, hwcap2) = compute_linux_hwcap ( ) ;
71
84
}
72
85
73
86
( hwcap, hwcap2)
@@ -92,8 +105,12 @@ pub(crate) fn linux_execfn() -> &'static CStr {
92
105
let mut execfn = EXECFN . load ( Relaxed ) ;
93
106
94
107
if execfn. is_null ( ) {
95
- init_auxv ( ) ;
96
- execfn = EXECFN . load ( Relaxed ) ;
108
+ #[ cold]
109
+ fn compute_linux_execfn ( ) -> * mut c:: c_char {
110
+ init_auxv ( ) ;
111
+ EXECFN . load ( Relaxed )
112
+ }
113
+ execfn = compute_linux_execfn ( ) ;
97
114
}
98
115
99
116
// SAFETY: We assume the `AT_EXECFN` value provided by the kernel is a
@@ -108,8 +125,12 @@ pub(crate) fn linux_secure() -> bool {
108
125
109
126
// 0 means not initialized yet.
110
127
if secure == 0 {
111
- init_auxv ( ) ;
112
- secure = SECURE . load ( Relaxed ) ;
128
+ #[ cold]
129
+ fn compute_linux_secure ( ) -> u8 {
130
+ init_auxv ( ) ;
131
+ SECURE . load ( Relaxed )
132
+ }
133
+ secure = compute_linux_secure ( ) ;
113
134
}
114
135
115
136
// 0 means not present. Libc `getauxval(AT_SECURE)` would return 0.
@@ -125,11 +146,13 @@ pub(crate) fn exe_phdrs() -> (*const c::c_void, usize, usize) {
125
146
let mut phent = PHENT . load ( Relaxed ) ;
126
147
let mut phnum = PHNUM . load ( Relaxed ) ;
127
148
128
- if phdr. is_null ( ) || phnum == 0 {
129
- init_auxv ( ) ;
130
- phdr = PHDR . load ( Relaxed ) ;
131
- phent = PHENT . load ( Relaxed ) ;
132
- phnum = PHNUM . load ( Relaxed ) ;
149
+ if phdr. is_null ( ) || phent == 0 || phnum == 0 {
150
+ #[ cold]
151
+ fn compute_exe_phdrs ( ) -> ( * mut Elf_Phdr , usize , usize ) {
152
+ init_auxv ( ) ;
153
+ ( PHDR . load ( Relaxed ) , PHENT . load ( Relaxed ) , PHNUM . load ( Relaxed ) )
154
+ }
155
+ ( phdr, phent, phnum) = compute_exe_phdrs ( ) ;
133
156
}
134
157
135
158
( phdr. cast ( ) , phent, phnum)
@@ -145,12 +168,16 @@ pub(in super::super) fn sysinfo_ehdr() -> *const Elf_Ehdr {
145
168
let mut ehdr = SYSINFO_EHDR . load ( Relaxed ) ;
146
169
147
170
if ehdr. is_null ( ) {
148
- // Use `maybe_init_auxv` to to read the aux vectors if it can, but do
149
- // nothing if it can't. If it can't, then we'll get a null pointer
150
- // here, which our callers are prepared to deal with.
151
- maybe_init_auxv ( ) ;
171
+ #[ cold]
172
+ fn compute_sysinfo_ehdr ( ) -> * mut Elf_Ehdr {
173
+ // Use `maybe_init_auxv` to to read the aux vectors if it can, but do
174
+ // nothing if it can't. If it can't, then we'll get a null pointer
175
+ // here, which our callers are prepared to deal with.
176
+ maybe_init_auxv ( ) ;
177
+ SYSINFO_EHDR . load ( Relaxed )
178
+ }
152
179
153
- ehdr = SYSINFO_EHDR . load ( Relaxed ) ;
180
+ ehdr = compute_sysinfo_ehdr ( ) ;
154
181
}
155
182
156
183
ehdr
@@ -162,8 +189,12 @@ pub(crate) fn entry() -> usize {
162
189
let mut entry = ENTRY . load ( Relaxed ) ;
163
190
164
191
if entry == 0 {
165
- init_auxv ( ) ;
166
- entry = ENTRY . load ( Relaxed ) ;
192
+ #[ cold]
193
+ fn compute_entry ( ) -> usize {
194
+ init_auxv ( ) ;
195
+ ENTRY . load ( Relaxed )
196
+ }
197
+ entry = compute_entry ( ) ;
167
198
}
168
199
169
200
entry
@@ -175,13 +206,34 @@ pub(crate) fn random() -> *const [u8; 16] {
175
206
let mut random = RANDOM . load ( Relaxed ) ;
176
207
177
208
if random. is_null ( ) {
178
- init_auxv ( ) ;
179
- random = RANDOM . load ( Relaxed ) ;
209
+ #[ cold]
210
+ fn compute_random ( ) -> * mut [ u8 ; 16 ] {
211
+ init_auxv ( ) ;
212
+ RANDOM . load ( Relaxed )
213
+ }
214
+ random = compute_random ( ) ;
180
215
}
181
216
182
217
random
183
218
}
184
219
220
+ #[ cfg( target_arch = "x86" ) ]
221
+ #[ inline]
222
+ pub ( crate ) fn vsyscall ( ) -> * const c:: c_void {
223
+ let mut vsyscall = VSYSCALL . load ( Relaxed ) ;
224
+
225
+ if vsyscall. is_null ( ) {
226
+ #[ cold]
227
+ fn compute_vsyscall ( ) -> * const c:: c_void {
228
+ init_auxv ( ) ;
229
+ VSYSCALL . load ( Relaxed )
230
+ }
231
+ vsyscall = compute_vsyscall ( ) ;
232
+ }
233
+
234
+ vsyscall
235
+ }
236
+
185
237
static PAGE_SIZE : AtomicUsize = AtomicUsize :: new ( 0 ) ;
186
238
static CLOCK_TICKS_PER_SECOND : AtomicUsize = AtomicUsize :: new ( 0 ) ;
187
239
static HWCAP : AtomicUsize = AtomicUsize :: new ( 0 ) ;
@@ -201,6 +253,8 @@ static PHNUM: AtomicUsize = AtomicUsize::new(0);
201
253
static ENTRY : AtomicUsize = AtomicUsize :: new ( 0 ) ;
202
254
#[ cfg( feature = "runtime" ) ]
203
255
static RANDOM : AtomicPtr < [ u8 ; 16 ] > = AtomicPtr :: new ( null_mut ( ) ) ;
256
+ #[ cfg( feature = "x86" ) ]
257
+ static VSYSCALL : AtomicPtr < c:: c_void > = AtomicPtr :: new ( null_mut ( ) ) ;
204
258
205
259
const PR_GET_AUXV : c:: c_int = 0x4155_5856 ;
206
260
@@ -389,6 +443,8 @@ unsafe fn init_from_aux_iter(aux_iter: impl Iterator<Item = Elf_auxv_t>) -> Opti
389
443
let mut egid = None ;
390
444
#[ cfg( feature = "runtime" ) ]
391
445
let mut random = null_mut ( ) ;
446
+ #[ cfg( target_arch = "x86" ) ]
447
+ let mut vsyscall = null_mut ( ) ;
392
448
393
449
for Elf_auxv_t { a_type, a_val } in aux_iter {
394
450
match a_type as _ {
@@ -428,6 +484,8 @@ unsafe fn init_from_aux_iter(aux_iter: impl Iterator<Item = Elf_auxv_t>) -> Opti
428
484
AT_ENTRY => entry = a_val as usize ,
429
485
#[ cfg( feature = "runtime" ) ]
430
486
AT_RANDOM => random = check_raw_pointer :: < [ u8 ; 16 ] > ( a_val as * mut _ ) ?. as_ptr ( ) ,
487
+ #[ cfg( target_arch = "x86" ) ]
488
+ AT_SYSINFO => vsyscall = a_val. cast ( ) ,
431
489
432
490
AT_NULL => break ,
433
491
_ => ( ) ,
@@ -464,6 +522,8 @@ unsafe fn init_from_aux_iter(aux_iter: impl Iterator<Item = Elf_auxv_t>) -> Opti
464
522
ENTRY . store ( entry, Relaxed ) ;
465
523
#[ cfg( feature = "runtime" ) ]
466
524
RANDOM . store ( random, Relaxed ) ;
525
+ #[ cfg( target_arch = "x86" ) ]
526
+ VSYSCALL . store ( vsyscall, Relaxed ) ;
467
527
468
528
Some ( ( ) )
469
529
}
0 commit comments