1
+ mod windows;
2
+ mod posix;
3
+
1
4
use std:: { convert:: TryInto , iter} ;
2
5
3
6
use rustc_hir:: def_id:: DefId ;
@@ -167,6 +170,30 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
167
170
} ;
168
171
169
172
// Next: functions that return.
173
+ match link_name {
174
+ "__rust_maybe_catch_panic" => {
175
+ this. handle_catch_panic ( args, dest, ret) ?;
176
+ return Ok ( None ) ;
177
+ }
178
+
179
+ _ => this. emulate_foreign_item_by_name ( link_name, args, dest) ?,
180
+ } ;
181
+
182
+ this. dump_place ( * dest) ;
183
+ this. go_to_block ( ret) ;
184
+
185
+ Ok ( None )
186
+ }
187
+
188
+ fn emulate_foreign_item_by_name (
189
+ & mut self ,
190
+ link_name : & str ,
191
+ args : & [ OpTy < ' tcx , Tag > ] ,
192
+ dest : PlaceTy < ' tcx , Tag > ,
193
+ ) -> InterpResult < ' tcx > {
194
+ let this = self . eval_context_mut ( ) ;
195
+ let tcx = & { this. tcx . tcx } ;
196
+
170
197
match link_name {
171
198
"malloc" => {
172
199
let size = this. read_scalar ( args[ 0 ] ) ?. to_machine_usize ( this) ?;
@@ -339,11 +366,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
339
366
}
340
367
}
341
368
342
- "__rust_maybe_catch_panic" => {
343
- this. handle_catch_panic ( args, dest, ret) ?;
344
- return Ok ( None ) ;
345
- }
346
-
347
369
"memcmp" => {
348
370
let left = this. read_scalar ( args[ 0 ] ) ?. not_undef ( ) ?;
349
371
let right = this. read_scalar ( args[ 1 ] ) ?. not_undef ( ) ?;
@@ -399,143 +421,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
399
421
}
400
422
}
401
423
402
- | "__errno_location"
403
- | "__error"
404
- => {
405
- let errno_place = this. machine . last_error . unwrap ( ) ;
406
- this. write_scalar ( errno_place. to_ref ( ) . to_scalar ( ) ?, dest) ?;
407
- }
408
-
409
- "getenv" => {
410
- let result = this. getenv ( args[ 0 ] ) ?;
411
- this. write_scalar ( result, dest) ?;
412
- }
413
-
414
- "unsetenv" => {
415
- let result = this. unsetenv ( args[ 0 ] ) ?;
416
- this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
417
- }
418
-
419
- "setenv" => {
420
- let result = this. setenv ( args[ 0 ] , args[ 1 ] ) ?;
421
- this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
422
- }
423
-
424
- "getcwd" => {
425
- let result = this. getcwd ( args[ 0 ] , args[ 1 ] ) ?;
426
- this. write_scalar ( result, dest) ?;
427
- }
428
-
429
- "chdir" => {
430
- let result = this. chdir ( args[ 0 ] ) ?;
431
- this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
432
- }
433
-
434
- | "open"
435
- | "open64"
436
- => {
437
- let result = this. open ( args[ 0 ] , args[ 1 ] ) ?;
438
- this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
439
- }
440
-
441
- "fcntl" => {
442
- let result = this. fcntl ( args[ 0 ] , args[ 1 ] , args. get ( 2 ) . cloned ( ) ) ?;
443
- this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
444
- }
445
-
446
- | "close"
447
- | "close$NOCANCEL"
448
- => {
449
- let result = this. close ( args[ 0 ] ) ?;
450
- this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
451
- }
452
-
453
- "read" => {
454
- let result = this. read ( args[ 0 ] , args[ 1 ] , args[ 2 ] ) ?;
455
- this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
456
- }
457
-
458
- "write" => {
459
- let fd = this. read_scalar ( args[ 0 ] ) ?. to_i32 ( ) ?;
460
- let buf = this. read_scalar ( args[ 1 ] ) ?. not_undef ( ) ?;
461
- let n = this. read_scalar ( args[ 2 ] ) ?. to_machine_usize ( tcx) ?;
462
- trace ! ( "Called write({:?}, {:?}, {:?})" , fd, buf, n) ;
463
- let result = if fd == 1 || fd == 2 {
464
- // stdout/stderr
465
- use std:: io:: { self , Write } ;
466
-
467
- let buf_cont = this. memory . read_bytes ( buf, Size :: from_bytes ( n) ) ?;
468
- // We need to flush to make sure this actually appears on the screen
469
- let res = if fd == 1 {
470
- // Stdout is buffered, flush to make sure it appears on the screen.
471
- // This is the write() syscall of the interpreted program, we want it
472
- // to correspond to a write() syscall on the host -- there is no good
473
- // in adding extra buffering here.
474
- let res = io:: stdout ( ) . write ( buf_cont) ;
475
- io:: stdout ( ) . flush ( ) . unwrap ( ) ;
476
- res
477
- } else {
478
- // No need to flush, stderr is not buffered.
479
- io:: stderr ( ) . write ( buf_cont)
480
- } ;
481
- match res {
482
- Ok ( n) => n as i64 ,
483
- Err ( _) => -1 ,
484
- }
485
- } else {
486
- this. write ( args[ 0 ] , args[ 1 ] , args[ 2 ] ) ?
487
- } ;
488
- // Now, `result` is the value we return back to the program.
489
- this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
490
- }
491
-
492
- | "lseek64"
493
- | "lseek"
494
- => {
495
- let result = this. lseek64 ( args[ 0 ] , args[ 1 ] , args[ 2 ] ) ?;
496
- this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
497
- }
498
-
499
- "unlink" => {
500
- let result = this. unlink ( args[ 0 ] ) ?;
501
- this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
502
- }
503
-
504
- "symlink" => {
505
- let result = this. symlink ( args[ 0 ] , args[ 1 ] ) ?;
506
- this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
507
- }
508
-
509
- "stat$INODE64" => {
510
- let result = this. stat ( args[ 0 ] , args[ 1 ] ) ?;
511
- this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
512
- }
513
-
514
- "lstat$INODE64" => {
515
- let result = this. lstat ( args[ 0 ] , args[ 1 ] ) ?;
516
- this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
517
- }
518
-
519
- "fstat$INODE64" => {
520
- let result = this. fstat ( args[ 0 ] , args[ 1 ] ) ?;
521
- this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
522
- }
523
424
524
425
"rename" => {
525
426
let result = this. rename ( args[ 0 ] , args[ 1 ] ) ?;
526
427
this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
527
428
}
528
429
529
- "clock_gettime" => {
530
- let result = this. clock_gettime ( args[ 0 ] , args[ 1 ] ) ?;
531
- this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
532
- }
533
-
534
- "gettimeofday" => {
535
- let result = this. gettimeofday ( args[ 0 ] , args[ 1 ] ) ?;
536
- this. write_scalar ( Scalar :: from_int ( result, dest. layout . size ) , dest) ?;
537
- }
538
-
539
430
"strlen" => {
540
431
let ptr = this. read_scalar ( args[ 0 ] ) ?. not_undef ( ) ?;
541
432
let n = this. memory . read_c_str ( ptr) ?. len ( ) ;
@@ -950,60 +841,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
950
841
// which one it is.
951
842
this. write_scalar ( Scalar :: from_int ( which, this. pointer_size ( ) ) , dest) ?;
952
843
}
953
- "WriteFile" => {
954
- let handle = this. read_scalar ( args[ 0 ] ) ?. to_machine_isize ( this) ?;
955
- let buf = this. read_scalar ( args[ 1 ] ) ?. not_undef ( ) ?;
956
- let n = this. read_scalar ( args[ 2 ] ) ?. to_u32 ( ) ?;
957
- let written_place = this. deref_operand ( args[ 3 ] ) ?;
958
- // Spec says to always write `0` first.
959
- this. write_null ( written_place. into ( ) ) ?;
960
- let written = if handle == -11 || handle == -12 {
961
- // stdout/stderr
962
- use std:: io:: { self , Write } ;
963
-
964
- let buf_cont = this. memory . read_bytes ( buf, Size :: from_bytes ( u64:: from ( n) ) ) ?;
965
- let res = if handle == -11 {
966
- io:: stdout ( ) . write ( buf_cont)
967
- } else {
968
- io:: stderr ( ) . write ( buf_cont)
969
- } ;
970
- res. ok ( ) . map ( |n| n as u32 )
971
- } else {
972
- eprintln ! ( "Miri: Ignored output to handle {}" , handle) ;
973
- // Pretend it all went well.
974
- Some ( n)
975
- } ;
976
- // If there was no error, write back how much was written.
977
- if let Some ( n) = written {
978
- this. write_scalar ( Scalar :: from_u32 ( n) , written_place. into ( ) ) ?;
979
- }
980
- // Return whether this was a success.
981
- this. write_scalar (
982
- Scalar :: from_int ( if written. is_some ( ) { 1 } else { 0 } , dest. layout . size ) ,
983
- dest,
984
- ) ?;
985
- }
986
844
"GetConsoleMode" => {
987
845
// Everything is a pipe.
988
846
this. write_null ( dest) ?;
989
847
}
990
- "GetEnvironmentVariableW" => {
991
- // args[0] : LPCWSTR lpName (32-bit ptr to a const string of 16-bit Unicode chars)
992
- // args[1] : LPWSTR lpBuffer (32-bit pointer to a string of 16-bit Unicode chars)
993
- // lpBuffer : ptr to buffer that receives contents of the env_var as a null-terminated string.
994
- // Return `# of chars` stored in the buffer pointed to by lpBuffer, excluding null-terminator.
995
- // Return 0 upon failure.
996
-
997
- // This is not the env var you are looking for.
998
- this. set_last_error ( Scalar :: from_u32 ( 203 ) ) ?; // ERROR_ENVVAR_NOT_FOUND
999
- this. write_null ( dest) ?;
1000
- }
1001
- "SetEnvironmentVariableW" => {
1002
- // args[0] : LPCWSTR lpName (32-bit ptr to a const string of 16-bit Unicode chars)
1003
- // args[1] : LPCWSTR lpValue (32-bit ptr to a const string of 16-bit Unicode chars)
1004
- // Return nonzero if success, else return 0.
1005
- throw_unsup_format ! ( "can't set environment variable on Windows" ) ;
1006
- }
1007
848
"GetCommandLineW" => {
1008
849
this. write_scalar (
1009
850
this. machine . cmd_line . expect ( "machine must be initialized" ) ,
@@ -1018,13 +859,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
1018
859
this. write_scalar ( Scalar :: from_bool ( true ) , dest) ?;
1019
860
}
1020
861
1021
- // We can't execute anything else.
1022
- _ => throw_unsup_format ! ( "can't call foreign function: {}" , link_name) ,
1023
- }
862
+ _ => match this. tcx . sess . target . target . target_os . to_lowercase ( ) . as_str ( ) {
863
+ "linux" | "macos" => posix:: EvalContextExt :: emulate_foreign_item_by_name ( this, link_name, args, dest) ?,
864
+ "windows" => windows:: EvalContextExt :: emulate_foreign_item_by_name ( this, link_name, args, dest) ?,
865
+ target => throw_unsup_format ! ( "The {} target platform is not supported" , target) ,
866
+ }
867
+ } ;
1024
868
1025
- this. dump_place ( * dest) ;
1026
- this. go_to_block ( ret) ;
1027
- Ok ( None )
869
+ Ok ( ( ) )
1028
870
}
1029
871
1030
872
/// Evaluates the scalar at the specified path. Returns Some(val)
0 commit comments