@@ -25,22 +25,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
2525 let result = this. getenv ( args[ 0 ] ) ?;
2626 this. write_scalar ( result, dest) ?;
2727 }
28-
2928 "unsetenv" => {
3029 let result = this. unsetenv ( args[ 0 ] ) ?;
3130 this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
3231 }
33-
3432 "setenv" => {
3533 let result = this. setenv ( args[ 0 ] , args[ 1 ] ) ?;
3634 this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
3735 }
38-
3936 "getcwd" => {
4037 let result = this. getcwd ( args[ 0 ] , args[ 1 ] ) ?;
4138 this. write_scalar ( result, dest) ?;
4239 }
43-
4440 "chdir" => {
4541 let result = this. chdir ( args[ 0 ] ) ?;
4642 this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
@@ -51,17 +47,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
5147 let result = this. open ( args[ 0 ] , args[ 1 ] ) ?;
5248 this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
5349 }
54-
5550 "fcntl" => {
5651 let result = this. fcntl ( args[ 0 ] , args[ 1 ] , args. get ( 2 ) . cloned ( ) ) ?;
5752 this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
5853 }
59-
6054 "read" => {
6155 let result = this. read ( args[ 0 ] , args[ 1 ] , args[ 2 ] ) ?;
6256 this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
6357 }
64-
6558 "write" => {
6659 let fd = this. read_scalar ( args[ 0 ] ) ?. to_i32 ( ) ?;
6760 let buf = this. read_scalar ( args[ 1 ] ) ?. not_undef ( ) ?;
@@ -95,43 +88,40 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
9588 // Now, `result` is the value we return back to the program.
9689 this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
9790 }
98-
9991 "unlink" => {
10092 let result = this. unlink ( args[ 0 ] ) ?;
10193 this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
10294 }
103-
10495 "symlink" => {
10596 let result = this. symlink ( args[ 0 ] , args[ 1 ] ) ?;
10697 this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
10798 }
108-
10999 "rename" => {
110100 let result = this. rename ( args[ 0 ] , args[ 1 ] ) ?;
111101 this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
112102 }
113-
114103 "mkdir" => {
115104 let result = this. mkdir ( args[ 0 ] , args[ 1 ] ) ?;
116105 this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
117106 }
118-
119107 "rmdir" => {
120108 let result = this. rmdir ( args[ 0 ] ) ?;
121109 this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
122110 }
123-
124111 "closedir" => {
125112 let result = this. closedir ( args[ 0 ] ) ?;
126113 this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
127114 }
128-
129115 "lseek" | "lseek64" => {
130116 let result = this. lseek64 ( args[ 0 ] , args[ 1 ] , args[ 2 ] ) ?;
131117 this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
132118 }
119+ "posix_fadvise" => {
120+ // fadvise is only informational, we can ignore it.
121+ this. write_null ( dest) ?;
122+ }
133123
134- // Other shims
124+ // Allocation
135125 "posix_memalign" => {
136126 let ret = this. deref_operand ( args[ 0 ] ) ?;
137127 let align = this. read_scalar ( args[ 1 ] ) ?. to_machine_usize ( this) ?;
@@ -160,6 +150,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
160150 this. write_null ( dest) ?;
161151 }
162152
153+ // Dynamic symbol loading
163154 "dlsym" => {
164155 let _handle = this. read_scalar ( args[ 0 ] ) ?;
165156 let symbol = this. read_scalar ( args[ 1 ] ) ?. not_undef ( ) ?;
@@ -174,7 +165,30 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
174165 }
175166 }
176167
177- // Hook pthread calls that go to the thread-local storage memory subsystem.
168+ // Querying system information
169+ "sysconf" => {
170+ let name = this. read_scalar ( args[ 0 ] ) ?. to_i32 ( ) ?;
171+
172+ let sysconfs = & [
173+ ( "_SC_PAGESIZE" , Scalar :: from_int ( PAGE_SIZE , dest. layout . size ) ) ,
174+ ( "_SC_NPROCESSORS_ONLN" , Scalar :: from_int ( NUM_CPUS , dest. layout . size ) ) ,
175+ ] ;
176+ let mut result = None ;
177+ for & ( sysconf_name, value) in sysconfs {
178+ let sysconf_name = this. eval_libc_i32 ( sysconf_name) ?;
179+ if sysconf_name == name {
180+ result = Some ( value) ;
181+ break ;
182+ }
183+ }
184+ if let Some ( result) = result {
185+ this. write_scalar ( result, dest) ?;
186+ } else {
187+ throw_unsup_format ! ( "unimplemented sysconf name: {}" , name)
188+ }
189+ }
190+
191+ // Thread-local storage
178192 "pthread_key_create" => {
179193 let key_place = this. deref_operand ( args[ 0 ] ) ?;
180194
@@ -221,36 +235,36 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
221235 this. write_null ( dest) ?;
222236 }
223237
224- // Stack size/address stuff.
225- | "pthread_attr_init"
226- | "pthread_attr_destroy"
227- | "pthread_self"
228- | "pthread_attr_setstacksize" => {
229- this. write_null ( dest) ?;
238+ // Better error for attempts to create a thread
239+ "pthread_create" => {
240+ throw_unsup_format ! ( "Miri does not support threading" ) ;
230241 }
231- "pthread_attr_getstack" => {
232- let addr_place = this. deref_operand ( args[ 1 ] ) ?;
233- let size_place = this. deref_operand ( args[ 2 ] ) ?;
234-
235- this. write_scalar (
236- Scalar :: from_uint ( STACK_ADDR , addr_place. layout . size ) ,
237- addr_place. into ( ) ,
238- ) ?;
239- this. write_scalar (
240- Scalar :: from_uint ( STACK_SIZE , size_place. layout . size ) ,
241- size_place. into ( ) ,
242- ) ?;
243242
244- // Return success (`0`).
243+ // Miscellaneous
244+ "isatty" => {
245+ let _fd = this. read_scalar ( args[ 0 ] ) ?. to_i32 ( ) ?;
246+ // "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"
247+ // FIXME: we just say nothing is a terminal.
248+ let enotty = this. eval_libc ( "ENOTTY" ) ?;
249+ this. set_last_error ( enotty) ?;
245250 this. write_null ( dest) ?;
246251 }
247-
248- // We don't support threading.
249- "pthread_create" => {
250- throw_unsup_format ! ( "Miri does not support threading" ) ;
252+ "pthread_atfork" => {
253+ let _prepare = this. read_scalar ( args[ 0 ] ) ?. not_undef ( ) ?;
254+ let _parent = this. read_scalar ( args[ 1 ] ) ?. not_undef ( ) ?;
255+ let _child = this. read_scalar ( args[ 1 ] ) ?. not_undef ( ) ?;
256+ // We do not support forking, so there is nothing to do here.
257+ this. write_null ( dest) ?;
251258 }
252259
253- // Stub out calls for condvar, mutex and rwlock, to just return `0`.
260+ // Incomplete shims that we "stub out" just to get pre-main initialziation code to work.
261+ // These shims are enabled only when the caller is in the standard library.
262+ | "pthread_attr_init"
263+ | "pthread_attr_destroy"
264+ | "pthread_self"
265+ | "pthread_attr_setstacksize" if this. frame ( ) . instance . to_string ( ) . starts_with ( "std::sys::unix::" ) => {
266+ this. write_null ( dest) ?;
267+ }
254268 | "pthread_mutexattr_init"
255269 | "pthread_mutexattr_settype"
256270 | "pthread_mutex_init"
@@ -266,68 +280,19 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
266280 | "pthread_condattr_setclock"
267281 | "pthread_cond_init"
268282 | "pthread_condattr_destroy"
269- | "pthread_cond_destroy"
283+ | "pthread_cond_destroy" if this . frame ( ) . instance . to_string ( ) . starts_with ( "std::sys::unix::" )
270284 => {
271285 this. write_null ( dest) ?;
272286 }
273-
274- // We don't support fork so we don't have to do anything for atfork.
275- "pthread_atfork" => {
276- this. write_null ( dest) ?;
277- }
278-
279- // Some things needed for `sys::thread` initialization to go through.
280287 | "signal"
281288 | "sigaction"
282289 | "sigaltstack"
290+ | "mprotect" if this. frame ( ) . instance . to_string ( ) . starts_with ( "std::sys::unix::" )
283291 => {
284- this. write_scalar ( Scalar :: from_int ( 0 , dest. layout . size ) , dest) ?;
285- }
286-
287- "sysconf" => {
288- let name = this. read_scalar ( args[ 0 ] ) ?. to_i32 ( ) ?;
289-
290- trace ! ( "sysconf() called with name {}" , name) ;
291- // TODO: Cache the sysconf integers via Miri's global cache.
292- let sysconfs = & [
293- ( "_SC_PAGESIZE" , Scalar :: from_int ( PAGE_SIZE , dest. layout . size ) ) ,
294- ( "_SC_GETPW_R_SIZE_MAX" , Scalar :: from_int ( -1 , dest. layout . size ) ) ,
295- ( "_SC_NPROCESSORS_ONLN" , Scalar :: from_int ( NUM_CPUS , dest. layout . size ) ) ,
296- ] ;
297- let mut result = None ;
298- for & ( sysconf_name, value) in sysconfs {
299- let sysconf_name = this. eval_libc_i32 ( sysconf_name) ?;
300- if sysconf_name == name {
301- result = Some ( value) ;
302- break ;
303- }
304- }
305- if let Some ( result) = result {
306- this. write_scalar ( result, dest) ?;
307- } else {
308- throw_unsup_format ! ( "unimplemented sysconf name: {}" , name)
309- }
310- }
311-
312- "isatty" => {
313- this. write_null ( dest) ?;
314- }
315-
316- "posix_fadvise" => {
317- // fadvise is only informational, we can ignore it.
318- this. write_null ( dest) ?;
319- }
320-
321- "mmap" => {
322- // 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.
323- let addr = this. read_scalar ( args[ 0 ] ) ?. not_undef ( ) ?;
324- this. write_scalar ( addr, dest) ?;
325- }
326-
327- "mprotect" => {
328292 this. write_null ( dest) ?;
329293 }
330294
295+ // Platform-specific shims
331296 _ => {
332297 match this. tcx . sess . target . target . target_os . as_str ( ) {
333298 "linux" => return linux:: EvalContextExt :: emulate_foreign_item_by_name ( this, link_name, args, dest, ret) ,
0 commit comments