@@ -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,40 @@ 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
}
118
+ "posix_fadvise" => {
119
+ // fadvise is only informational, we can ignore it.
120
+ this. write_null ( dest) ?;
121
+ }
132
122
133
- // Other shims
123
+ // Allocation
134
124
"posix_memalign" => {
135
125
let ret = this. deref_operand ( args[ 0 ] ) ?;
136
126
let align = this. read_scalar ( args[ 1 ] ) ?. to_machine_usize ( this) ?;
@@ -159,6 +149,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
159
149
this. write_null ( dest) ?;
160
150
}
161
151
152
+ // Dynamic symbol loading
162
153
"dlsym" => {
163
154
let _handle = this. read_scalar ( args[ 0 ] ) ?;
164
155
let symbol = this. read_scalar ( args[ 1 ] ) ?. not_undef ( ) ?;
@@ -173,7 +164,30 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
173
164
}
174
165
}
175
166
176
- // Hook pthread calls that go to the thread-local storage memory subsystem.
167
+ // Querying system information
168
+ "sysconf" => {
169
+ let name = this. read_scalar ( args[ 0 ] ) ?. to_i32 ( ) ?;
170
+
171
+ let sysconfs = & [
172
+ ( "_SC_PAGESIZE" , Scalar :: from_int ( PAGE_SIZE , dest. layout . size ) ) ,
173
+ ( "_SC_NPROCESSORS_ONLN" , Scalar :: from_int ( NUM_CPUS , dest. layout . size ) ) ,
174
+ ] ;
175
+ let mut result = None ;
176
+ for & ( sysconf_name, value) in sysconfs {
177
+ let sysconf_name = this. eval_libc_i32 ( sysconf_name) ?;
178
+ if sysconf_name == name {
179
+ result = Some ( value) ;
180
+ break ;
181
+ }
182
+ }
183
+ if let Some ( result) = result {
184
+ this. write_scalar ( result, dest) ?;
185
+ } else {
186
+ throw_unsup_format ! ( "unimplemented sysconf name: {}" , name)
187
+ }
188
+ }
189
+
190
+ // Thread-local storage
177
191
"pthread_key_create" => {
178
192
let key_place = this. deref_operand ( args[ 0 ] ) ?;
179
193
@@ -220,36 +234,36 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
220
234
this. write_null ( dest) ?;
221
235
}
222
236
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) ?;
237
+ // Better error for attempts to create a thread
238
+ "pthread_create" => {
239
+ throw_unsup_format ! ( "Miri does not support threading" ) ;
229
240
}
230
- "pthread_attr_getstack" => {
231
- let addr_place = this. deref_operand ( args[ 1 ] ) ?;
232
- let size_place = this. deref_operand ( args[ 2 ] ) ?;
233
-
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
241
243
- // Return success (`0`).
242
+ // Miscellaneous
243
+ "isatty" => {
244
+ let _fd = this. read_scalar ( args[ 0 ] ) ?. to_i32 ( ) ?;
245
+ // "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"
246
+ // FIXME: we just say nothing is a terminal.
247
+ let enotty = this. eval_libc ( "ENOTTY" ) ?;
248
+ this. set_last_error ( enotty) ?;
244
249
this. write_null ( dest) ?;
245
250
}
246
-
247
- // We don't support threading.
248
- "pthread_create" => {
249
- throw_unsup_format ! ( "Miri does not support threading" ) ;
251
+ "pthread_atfork" => {
252
+ let _prepare = this. read_scalar ( args[ 0 ] ) ?. not_undef ( ) ?;
253
+ let _parent = this. read_scalar ( args[ 1 ] ) ?. not_undef ( ) ?;
254
+ let _child = this. read_scalar ( args[ 1 ] ) ?. not_undef ( ) ?;
255
+ // We do not support forking, so there is nothing to do here.
256
+ this. write_null ( dest) ?;
250
257
}
251
258
252
- // Stub out calls for condvar, mutex and rwlock, to just return `0`.
259
+ // Incomplete shims that we "stub out" just to get pre-main initialziation code to work.
260
+ // These shims are enabled only when the caller is in the standard library.
261
+ | "pthread_attr_init"
262
+ | "pthread_attr_destroy"
263
+ | "pthread_self"
264
+ | "pthread_attr_setstacksize" if this. frame ( ) . instance . to_string ( ) . starts_with ( "std::sys::unix::" ) => {
265
+ this. write_null ( dest) ?;
266
+ }
253
267
| "pthread_mutexattr_init"
254
268
| "pthread_mutexattr_settype"
255
269
| "pthread_mutex_init"
@@ -265,68 +279,19 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
265
279
| "pthread_condattr_setclock"
266
280
| "pthread_cond_init"
267
281
| "pthread_condattr_destroy"
268
- | "pthread_cond_destroy"
282
+ | "pthread_cond_destroy" if this . frame ( ) . instance . to_string ( ) . starts_with ( "std::sys::unix::" )
269
283
=> {
270
284
this. write_null ( dest) ?;
271
285
}
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
286
| "signal"
280
287
| "sigaction"
281
288
| "sigaltstack"
289
+ | "mprotect" if this. frame ( ) . instance . to_string ( ) . starts_with ( "std::sys::unix::" )
282
290
=> {
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
291
this. write_null ( dest) ?;
328
292
}
329
293
294
+ // Platform-specific shims
330
295
_ => {
331
296
match this. tcx . sess . target . target . target_os . as_str ( ) {
332
297
"linux" => return linux:: EvalContextExt :: emulate_foreign_item_by_name ( this, link_name, args, dest, ret) ,
0 commit comments