@@ -24,22 +24,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
24
24
let result = this. getenv ( args[ 0 ] ) ?;
25
25
this. write_scalar ( result, dest) ?;
26
26
}
27
-
28
27
"unsetenv" => {
29
28
let result = this. unsetenv ( args[ 0 ] ) ?;
30
29
this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
31
30
}
32
-
33
31
"setenv" => {
34
32
let result = this. setenv ( args[ 0 ] , args[ 1 ] ) ?;
35
33
this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
36
34
}
37
-
38
35
"getcwd" => {
39
36
let result = this. getcwd ( args[ 0 ] , args[ 1 ] ) ?;
40
37
this. write_scalar ( result, dest) ?;
41
38
}
42
-
43
39
"chdir" => {
44
40
let result = this. chdir ( args[ 0 ] ) ?;
45
41
this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
@@ -50,17 +46,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
50
46
let result = this. open ( args[ 0 ] , args[ 1 ] ) ?;
51
47
this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
52
48
}
53
-
54
49
"fcntl" => {
55
50
let result = this. fcntl ( args[ 0 ] , args[ 1 ] , args. get ( 2 ) . cloned ( ) ) ?;
56
51
this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
57
52
}
58
-
59
53
"read" => {
60
54
let result = this. read ( args[ 0 ] , args[ 1 ] , args[ 2 ] ) ?;
61
55
this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
62
56
}
63
-
64
57
"write" => {
65
58
let fd = this. read_scalar ( args[ 0 ] ) ?. to_i32 ( ) ?;
66
59
let buf = this. read_scalar ( args[ 1 ] ) ?. not_undef ( ) ?;
@@ -94,43 +87,36 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
94
87
// Now, `result` is the value we return back to the program.
95
88
this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
96
89
}
97
-
98
90
"unlink" => {
99
91
let result = this. unlink ( args[ 0 ] ) ?;
100
92
this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
101
93
}
102
-
103
94
"symlink" => {
104
95
let result = this. symlink ( args[ 0 ] , args[ 1 ] ) ?;
105
96
this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
106
97
}
107
-
108
98
"rename" => {
109
99
let result = this. rename ( args[ 0 ] , args[ 1 ] ) ?;
110
100
this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
111
101
}
112
-
113
102
"mkdir" => {
114
103
let result = this. mkdir ( args[ 0 ] , args[ 1 ] ) ?;
115
104
this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
116
105
}
117
-
118
106
"rmdir" => {
119
107
let result = this. rmdir ( args[ 0 ] ) ?;
120
108
this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
121
109
}
122
-
123
110
"closedir" => {
124
111
let result = this. closedir ( args[ 0 ] ) ?;
125
112
this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
126
113
}
127
-
128
114
"lseek" | "lseek64" => {
129
115
let result = this. lseek64 ( args[ 0 ] , args[ 1 ] , args[ 2 ] ) ?;
130
116
this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
131
117
}
132
118
133
- // Other shims
119
+ // Allocation
134
120
"posix_memalign" => {
135
121
let ret = this. deref_operand ( args[ 0 ] ) ?;
136
122
let align = this. read_scalar ( args[ 1 ] ) ?. to_machine_usize ( this) ?;
@@ -159,6 +145,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
159
145
this. write_null ( dest) ?;
160
146
}
161
147
148
+ // Dynamic symbol loading
162
149
"dlsym" => {
163
150
let _handle = this. read_scalar ( args[ 0 ] ) ?;
164
151
let symbol = this. read_scalar ( args[ 1 ] ) ?. not_undef ( ) ?;
@@ -173,7 +160,30 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
173
160
}
174
161
}
175
162
176
- // Hook pthread calls that go to the thread-local storage memory subsystem.
163
+ // Querying system information
164
+ "sysconf" => {
165
+ let name = this. read_scalar ( args[ 0 ] ) ?. to_i32 ( ) ?;
166
+
167
+ let sysconfs = & [
168
+ ( "_SC_PAGESIZE" , Scalar :: from_int ( PAGE_SIZE , dest. layout . size ) ) ,
169
+ ( "_SC_NPROCESSORS_ONLN" , Scalar :: from_int ( NUM_CPUS , dest. layout . size ) ) ,
170
+ ] ;
171
+ let mut result = None ;
172
+ for & ( sysconf_name, value) in sysconfs {
173
+ let sysconf_name = this. eval_libc_i32 ( sysconf_name) ?;
174
+ if sysconf_name == name {
175
+ result = Some ( value) ;
176
+ break ;
177
+ }
178
+ }
179
+ if let Some ( result) = result {
180
+ this. write_scalar ( result, dest) ?;
181
+ } else {
182
+ throw_unsup_format ! ( "unimplemented sysconf name: {}" , name)
183
+ }
184
+ }
185
+
186
+ // Thread-local storage
177
187
"pthread_key_create" => {
178
188
let key_place = this. deref_operand ( args[ 0 ] ) ?;
179
189
@@ -220,36 +230,36 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
220
230
this. write_null ( dest) ?;
221
231
}
222
232
223
- // Stack size/address stuff.
224
- | "pthread_attr_init"
225
- | "pthread_attr_destroy"
226
- | "pthread_self"
227
- | "pthread_attr_setstacksize" => {
228
- this. write_null ( dest) ?;
233
+ // Better error for attempts to create a thread
234
+ "pthread_create" => {
235
+ throw_unsup_format ! ( "Miri does not support threading" ) ;
229
236
}
230
- "pthread_attr_getstack" => {
231
- let addr_place = this. deref_operand ( args[ 1 ] ) ?;
232
- let size_place = this. deref_operand ( args[ 2 ] ) ?;
233
237
234
- this. write_scalar (
235
- Scalar :: from_uint ( STACK_ADDR , addr_place. layout . size ) ,
236
- addr_place. into ( ) ,
237
- ) ?;
238
- this. write_scalar (
239
- Scalar :: from_uint ( STACK_SIZE , size_place. layout . size ) ,
240
- size_place. into ( ) ,
241
- ) ?;
242
-
243
- // Return success (`0`).
238
+ // Miscellaneous
239
+ "isatty" => {
240
+ let _fd = this. read_scalar ( args[ 0 ] ) ?. to_i32 ( ) ?;
241
+ // "returns 1 if fd is an open file descriptor referring to a terminal; otherwise 0 is returned, and errno is set to indicate the error"
242
+ // FIXME: we just say nothing is a terminal.
243
+ let enotty = this. eval_libc ( "ENOTTY" ) ?;
244
+ this. set_last_error ( enotty) ?;
244
245
this. write_null ( dest) ?;
245
246
}
246
-
247
- // We don't support threading.
248
- "pthread_create" => {
249
- throw_unsup_format ! ( "Miri does not support threading" ) ;
247
+ "pthread_atfork" => {
248
+ let _prepare = this. read_scalar ( args[ 0 ] ) ?. not_undef ( ) ?;
249
+ let _parent = this. read_scalar ( args[ 1 ] ) ?. not_undef ( ) ?;
250
+ let _child = this. read_scalar ( args[ 1 ] ) ?. not_undef ( ) ?;
251
+ // We do not support forking, so there is nothing to do here.
252
+ this. write_null ( dest) ?;
250
253
}
251
254
252
- // Stub out calls for condvar, mutex and rwlock, to just return `0`.
255
+ // Incomplete shims that we "stub out" just to get pre-main initialziation code to work.
256
+ // These shims are enabled only when the caller is in the standard library.
257
+ | "pthread_attr_init"
258
+ | "pthread_attr_destroy"
259
+ | "pthread_self"
260
+ | "pthread_attr_setstacksize" if this. frame ( ) . instance . to_string ( ) . starts_with ( "std::sys::unix::" ) => {
261
+ this. write_null ( dest) ?;
262
+ }
253
263
| "pthread_mutexattr_init"
254
264
| "pthread_mutexattr_settype"
255
265
| "pthread_mutex_init"
@@ -265,68 +275,19 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
265
275
| "pthread_condattr_setclock"
266
276
| "pthread_cond_init"
267
277
| "pthread_condattr_destroy"
268
- | "pthread_cond_destroy"
278
+ | "pthread_cond_destroy" if this . frame ( ) . instance . to_string ( ) . starts_with ( "std::sys::unix::" )
269
279
=> {
270
280
this. write_null ( dest) ?;
271
281
}
272
-
273
- // We don't support fork so we don't have to do anything for atfork.
274
- "pthread_atfork" => {
275
- this. write_null ( dest) ?;
276
- }
277
-
278
- // Some things needed for `sys::thread` initialization to go through.
279
282
| "signal"
280
283
| "sigaction"
281
284
| "sigaltstack"
285
+ | "mprotect" if this. frame ( ) . instance . to_string ( ) . starts_with ( "std::sys::unix::" )
282
286
=> {
283
- this. write_scalar ( Scalar :: from_int ( 0 , dest. layout . size ) , dest) ?;
284
- }
285
-
286
- "sysconf" => {
287
- let name = this. read_scalar ( args[ 0 ] ) ?. to_i32 ( ) ?;
288
-
289
- trace ! ( "sysconf() called with name {}" , name) ;
290
- // TODO: Cache the sysconf integers via Miri's global cache.
291
- let sysconfs = & [
292
- ( "_SC_PAGESIZE" , Scalar :: from_int ( PAGE_SIZE , dest. layout . size ) ) ,
293
- ( "_SC_GETPW_R_SIZE_MAX" , Scalar :: from_int ( -1 , dest. layout . size ) ) ,
294
- ( "_SC_NPROCESSORS_ONLN" , Scalar :: from_int ( NUM_CPUS , dest. layout . size ) ) ,
295
- ] ;
296
- let mut result = None ;
297
- for & ( sysconf_name, value) in sysconfs {
298
- let sysconf_name = this. eval_libc_i32 ( sysconf_name) ?;
299
- if sysconf_name == name {
300
- result = Some ( value) ;
301
- break ;
302
- }
303
- }
304
- if let Some ( result) = result {
305
- this. write_scalar ( result, dest) ?;
306
- } else {
307
- throw_unsup_format ! ( "unimplemented sysconf name: {}" , name)
308
- }
309
- }
310
-
311
- "isatty" => {
312
- this. write_null ( dest) ?;
313
- }
314
-
315
- "posix_fadvise" => {
316
- // fadvise is only informational, we can ignore it.
317
- this. write_null ( dest) ?;
318
- }
319
-
320
- "mmap" => {
321
- // This is a horrible hack, but since the guard page mechanism calls mmap and expects a particular return value, we just give it that value.
322
- let addr = this. read_scalar ( args[ 0 ] ) ?. not_undef ( ) ?;
323
- this. write_scalar ( addr, dest) ?;
324
- }
325
-
326
- "mprotect" => {
327
287
this. write_null ( dest) ?;
328
288
}
329
289
290
+ // Platform-specific shims
330
291
_ => {
331
292
match this. tcx . sess . target . target . target_os . as_str ( ) {
332
293
"linux" => return linux:: EvalContextExt :: emulate_foreign_item_by_name ( this, link_name, args, dest, ret) ,
0 commit comments