@@ -24,22 +24,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
2424 let result = this. getenv ( args[ 0 ] ) ?;
2525 this. write_scalar ( result, dest) ?;
2626 }
27-
2827 "unsetenv" => {
2928 let result = this. unsetenv ( args[ 0 ] ) ?;
3029 this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
3130 }
32-
3331 "setenv" => {
3432 let result = this. setenv ( args[ 0 ] , args[ 1 ] ) ?;
3533 this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
3634 }
37-
3835 "getcwd" => {
3936 let result = this. getcwd ( args[ 0 ] , args[ 1 ] ) ?;
4037 this. write_scalar ( result, dest) ?;
4138 }
42-
4339 "chdir" => {
4440 let result = this. chdir ( args[ 0 ] ) ?;
4541 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
5046 let result = this. open ( args[ 0 ] , args[ 1 ] ) ?;
5147 this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
5248 }
53-
5449 "fcntl" => {
5550 let result = this. fcntl ( args[ 0 ] , args[ 1 ] , args. get ( 2 ) . cloned ( ) ) ?;
5651 this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
5752 }
58-
5953 "read" => {
6054 let result = this. read ( args[ 0 ] , args[ 1 ] , args[ 2 ] ) ?;
6155 this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
6256 }
63-
6457 "write" => {
6558 let fd = this. read_scalar ( args[ 0 ] ) ?. to_i32 ( ) ?;
6659 let buf = this. read_scalar ( args[ 1 ] ) ?. not_undef ( ) ?;
@@ -94,43 +87,40 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
9487 // Now, `result` is the value we return back to the program.
9588 this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
9689 }
97-
9890 "unlink" => {
9991 let result = this. unlink ( args[ 0 ] ) ?;
10092 this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
10193 }
102-
10394 "symlink" => {
10495 let result = this. symlink ( args[ 0 ] , args[ 1 ] ) ?;
10596 this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
10697 }
107-
10898 "rename" => {
10999 let result = this. rename ( args[ 0 ] , args[ 1 ] ) ?;
110100 this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
111101 }
112-
113102 "mkdir" => {
114103 let result = this. mkdir ( args[ 0 ] , args[ 1 ] ) ?;
115104 this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
116105 }
117-
118106 "rmdir" => {
119107 let result = this. rmdir ( args[ 0 ] ) ?;
120108 this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
121109 }
122-
123110 "closedir" => {
124111 let result = this. closedir ( args[ 0 ] ) ?;
125112 this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
126113 }
127-
128114 "lseek" | "lseek64" => {
129115 let result = this. lseek64 ( args[ 0 ] , args[ 1 ] , args[ 2 ] ) ?;
130116 this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
131117 }
118+ "posix_fadvise" => {
119+ // fadvise is only informational, we can ignore it.
120+ this. write_null ( dest) ?;
121+ }
132122
133- // Other shims
123+ // Allocation
134124 "posix_memalign" => {
135125 let ret = this. deref_operand ( args[ 0 ] ) ?;
136126 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
159149 this. write_null ( dest) ?;
160150 }
161151
152+ // Dynamic symbol loading
162153 "dlsym" => {
163154 let _handle = this. read_scalar ( args[ 0 ] ) ?;
164155 let symbol = this. read_scalar ( args[ 1 ] ) ?. not_undef ( ) ?;
@@ -173,7 +164,30 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
173164 }
174165 }
175166
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
177191 "pthread_key_create" => {
178192 let key_place = this. deref_operand ( args[ 0 ] ) ?;
179193
@@ -220,36 +234,36 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
220234 this. write_null ( dest) ?;
221235 }
222236
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" ) ;
229240 }
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- ) ?;
242241
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) ?;
244249 this. write_null ( dest) ?;
245250 }
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) ?;
250257 }
251258
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+ }
253267 | "pthread_mutexattr_init"
254268 | "pthread_mutexattr_settype"
255269 | "pthread_mutex_init"
@@ -265,68 +279,19 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
265279 | "pthread_condattr_setclock"
266280 | "pthread_cond_init"
267281 | "pthread_condattr_destroy"
268- | "pthread_cond_destroy"
282+ | "pthread_cond_destroy" if this . frame ( ) . instance . to_string ( ) . starts_with ( "std::sys::unix::" )
269283 => {
270284 this. write_null ( dest) ?;
271285 }
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.
279286 | "signal"
280287 | "sigaction"
281288 | "sigaltstack"
289+ | "mprotect" if this. frame ( ) . instance . to_string ( ) . starts_with ( "std::sys::unix::" )
282290 => {
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" => {
327291 this. write_null ( dest) ?;
328292 }
329293
294+ // Platform-specific shims
330295 _ => {
331296 match this. tcx . sess . target . target . target_os . as_str ( ) {
332297 "linux" => return linux:: EvalContextExt :: emulate_foreign_item_by_name ( this, link_name, args, dest, ret) ,
0 commit comments