]> git.lizzy.rs Git - rust.git/blobdiff - src/shims/foreign_items.rs
avoid using unchecked casts or arithmetic
[rust.git] / src / shims / foreign_items.rs
index ff5ffb0e3ac6ac7daa6f81e3dba39221e2cbe1ab..deabbdd6081933a22d5daad07a3a86f228f4634c 100644 (file)
@@ -1,12 +1,15 @@
-use std::{convert::TryInto, iter};
+mod windows;
+mod posix;
+
+use std::{convert::{TryInto, TryFrom}, iter};
 
 use rustc_hir::def_id::DefId;
 use rustc::mir;
 use rustc::ty;
-use rustc::ty::layout::{Align, LayoutOf, Size};
+use rustc::ty::layout::{Align, Size};
 use rustc_apfloat::Float;
 use rustc_span::symbol::sym;
-use syntax::attr;
+use rustc_ast::attr;
 
 use crate::*;
 
@@ -124,13 +127,36 @@ fn emulate_foreign_item(
         let tcx = &{ this.tcx.tcx };
 
         // First: functions that diverge.
-        let (dest, ret) = match link_name {
-            // Note that this matches calls to the *foreign* item `__rust_start_panic* -
-            // that is, calls to `extern "Rust" { fn __rust_start_panic(...) }`.
+        let (dest, ret) = match ret {
+            None => match link_name {
+                // This matches calls to the foreign item `panic_impl`.
+                // The implementation is provided by the function with the `#[panic_handler]` attribute.
+                "panic_impl" => {
+                    let panic_impl_id = this.tcx.lang_items().panic_impl().unwrap();
+                    let panic_impl_instance = ty::Instance::mono(*this.tcx, panic_impl_id);
+                    return Ok(Some(&*this.load_mir(panic_impl_instance.def, None)?));
+                }
+                | "exit"
+                | "ExitProcess"
+                => {
+                    // it's really u32 for ExitProcess, but we have to put it into the `Exit` variant anyway
+                    let code = this.read_scalar(args[0])?.to_i32()?;
+                    throw_machine_stop!(TerminationInfo::Exit(code.into()));
+                }
+                _ => throw_unsup_format!("can't call (diverging) foreign function: {}", link_name),
+            },
+            Some(p) => p,
+        };
+
+        // Second: some functions that we forward to MIR implementations.
+        match link_name {
+            // This matches calls to the foreign item `__rust_start_panic`, that is,
+            // calls to `extern "Rust" { fn __rust_start_panic(...) }`
+            // (and `__rust_panic_cleanup`, respectively).
             // We forward this to the underlying *implementation* in the panic runtime crate.
             // Normally, this will be either `libpanic_unwind` or `libpanic_abort`, but it could
             // also be a custom user-provided implementation via `#![feature(panic_runtime)]`
-            "__rust_start_panic" => {
+            "__rust_start_panic" | "__rust_panic_cleanup"=> {
                 // FIXME we might want to cache this... but it's not really performance-critical.
                 let panic_runtime = tcx
                     .crates()
@@ -139,34 +165,35 @@ fn emulate_foreign_item(
                     .expect("No panic runtime found!");
                 let panic_runtime = tcx.crate_name(*panic_runtime);
                 let start_panic_instance =
-                    this.resolve_path(&[&*panic_runtime.as_str(), "__rust_start_panic"])?;
+                    this.resolve_path(&[&*panic_runtime.as_str(), link_name])?;
                 return Ok(Some(&*this.load_mir(start_panic_instance.def, None)?));
             }
-            // Similarly, we forward calls to the `panic_impl` foreign item to its implementation.
-            // The implementation is provided by the function with the `#[panic_handler]` attribute.
-            "panic_impl" => {
-                let panic_impl_id = this.tcx.lang_items().panic_impl().unwrap();
-                let panic_impl_instance = ty::Instance::mono(*this.tcx, panic_impl_id);
-                return Ok(Some(&*this.load_mir(panic_impl_instance.def, None)?));
-            }
+            _ => {}
+        }
 
-            | "exit"
-            | "ExitProcess"
-            => {
-                // it's really u32 for ExitProcess, but we have to put it into the `Exit` variant anyway
-                let code = this.read_scalar(args[0])?.to_i32()?;
-                throw_machine_stop!(TerminationInfo::Exit(code.into()));
-            }
-            _ => {
-                if let Some(p) = ret {
-                    p
-                } else {
-                    throw_unsup_format!("can't call (diverging) foreign function: {}", link_name);
-                }
-            }
-        };
+        // Third: functions that return.
+        if this.emulate_foreign_item_by_name(link_name, args, dest, ret)? {
+            this.dump_place(*dest);
+            this.go_to_block(ret);
+        }
 
-        // Next: functions that return.
+        Ok(None)
+    }
+
+    /// Emulates calling a foreign item using its name, failing if the item is not supported.
+    /// Returns `true` if the caller is expected to jump to the return block, and `false` if
+    /// jumping has already been taken care of.
+    fn emulate_foreign_item_by_name(
+        &mut self,
+        link_name: &str,
+        args: &[OpTy<'tcx, Tag>],
+        dest: PlaceTy<'tcx, Tag>,
+        ret: mir::BasicBlock,
+    ) -> InterpResult<'tcx, bool> {
+        let this = self.eval_context_mut();
+
+        // Here we dispatch all the shims for foreign functions. If you have a platform specific
+        // shim, add it to the corresponding submodule.
         match link_name {
             "malloc" => {
                 let size = this.read_scalar(args[0])?.to_machine_usize(this)?;
@@ -181,33 +208,6 @@ fn emulate_foreign_item(
                 let res = this.malloc(size, /*zero_init:*/ true, MiriMemoryKind::C);
                 this.write_scalar(res, dest)?;
             }
-            "posix_memalign" => {
-                let ret = this.deref_operand(args[0])?;
-                let align = this.read_scalar(args[1])?.to_machine_usize(this)?;
-                let size = this.read_scalar(args[2])?.to_machine_usize(this)?;
-                // Align must be power of 2, and also at least ptr-sized (POSIX rules).
-                if !align.is_power_of_two() {
-                    throw_unsup!(HeapAllocNonPowerOfTwoAlignment(align));
-                }
-                if align < this.pointer_size().bytes() {
-                    throw_ub_format!(
-                        "posix_memalign: alignment must be at least the size of a pointer, but is {}",
-                        align,
-                    );
-                }
-
-                if size == 0 {
-                    this.write_null(ret.into())?;
-                } else {
-                    let ptr = this.memory.allocate(
-                        Size::from_bytes(size),
-                        Align::from_bytes(align).unwrap(),
-                        MiriMemoryKind::C.into(),
-                    );
-                    this.write_scalar(ptr, ret.into())?;
-                }
-                this.write_null(dest)?;
-            }
             "free" => {
                 let ptr = this.read_scalar(args[0])?.not_undef()?;
                 this.free(ptr, MiriMemoryKind::C)?;
@@ -250,7 +250,7 @@ fn emulate_foreign_item(
                     MiriMemoryKind::Rust.into(),
                 );
                 // We just allocated this, the access is definitely in-bounds.
-                this.memory.write_bytes(ptr.into(), iter::repeat(0u8).take(size as usize)).unwrap();
+                this.memory.write_bytes(ptr.into(), iter::repeat(0u8).take(usize::try_from(size).unwrap())).unwrap();
                 this.write_scalar(ptr, dest)?;
             }
             "__rust_dealloc" => {
@@ -292,58 +292,6 @@ fn emulate_foreign_item(
                 this.write_scalar(new_ptr, dest)?;
             }
 
-            "syscall" => {
-                let sys_getrandom = this
-                    .eval_path_scalar(&["libc", "SYS_getrandom"])?
-                    .expect("Failed to get libc::SYS_getrandom")
-                    .to_machine_usize(this)?;
-
-                let sys_statx = this
-                    .eval_path_scalar(&["libc", "SYS_statx"])?
-                    .expect("Failed to get libc::SYS_statx")
-                    .to_machine_usize(this)?;
-
-                match this.read_scalar(args[0])?.to_machine_usize(this)? {
-                    // `libc::syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), GRND_NONBLOCK)`
-                    // is called if a `HashMap` is created the regular way (e.g. HashMap<K, V>).
-                    id if id == sys_getrandom => {
-                        // The first argument is the syscall id,
-                        // so skip over it.
-                        linux_getrandom(this, &args[1..], dest)?;
-                    }
-                    id if id == sys_statx => {
-                        // The first argument is the syscall id,
-                        // so skip over it.
-                        let result = this.statx(args[1], args[2], args[3], args[4], args[5])?;
-                        this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?;
-                    }
-                    id => throw_unsup_format!("miri does not support syscall ID {}", id),
-                }
-            }
-
-            "getrandom" => {
-                linux_getrandom(this, args, dest)?;
-            }
-
-            "dlsym" => {
-                let _handle = this.read_scalar(args[0])?;
-                let symbol = this.read_scalar(args[1])?.not_undef()?;
-                let symbol_name = this.memory.read_c_str(symbol)?;
-                let err = format!("bad c unicode symbol: {:?}", symbol_name);
-                let symbol_name = ::std::str::from_utf8(symbol_name).unwrap_or(&err);
-                if let Some(dlsym) = Dlsym::from_str(symbol_name)? {
-                    let ptr = this.memory.create_fn_alloc(FnVal::Other(dlsym));
-                    this.write_scalar(Scalar::from(ptr), dest)?;
-                } else {
-                    this.write_null(dest)?;
-                }
-            }
-
-            "__rust_maybe_catch_panic" => {
-                this.handle_catch_panic(args, dest, ret)?;
-                return Ok(None);
-            }
-
             "memcmp" => {
                 let left = this.read_scalar(args[0])?.not_undef()?;
                 let right = this.read_scalar(args[1])?.not_undef()?;
@@ -399,147 +347,10 @@ fn emulate_foreign_item(
                 }
             }
 
-            | "__errno_location"
-            | "__error"
-            => {
-                let errno_place = this.machine.last_error.unwrap();
-                this.write_scalar(errno_place.to_ref().to_scalar()?, dest)?;
-            }
-
-            "getenv" => {
-                let result = this.getenv(args[0])?;
-                this.write_scalar(result, dest)?;
-            }
-
-            "unsetenv" => {
-                let result = this.unsetenv(args[0])?;
-                this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?;
-            }
-
-            "setenv" => {
-                let result = this.setenv(args[0], args[1])?;
-                this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?;
-            }
-
-            "getcwd" => {
-                let result = this.getcwd(args[0], args[1])?;
-                this.write_scalar(result, dest)?;
-            }
-
-            "chdir" => {
-                let result = this.chdir(args[0])?;
-                this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?;
-            }
-
-            | "open"
-            | "open64"
-            => {
-                let result = this.open(args[0], args[1])?;
-                this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?;
-            }
-
-            "fcntl" => {
-                let result = this.fcntl(args[0], args[1], args.get(2).cloned())?;
-                this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?;
-            }
-
-            | "close"
-            | "close$NOCANCEL"
-            => {
-                let result = this.close(args[0])?;
-                this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?;
-            }
-
-            "read" => {
-                let result = this.read(args[0], args[1], args[2])?;
-                this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?;
-            }
-
-            "write" => {
-                let fd = this.read_scalar(args[0])?.to_i32()?;
-                let buf = this.read_scalar(args[1])?.not_undef()?;
-                let n = this.read_scalar(args[2])?.to_machine_usize(tcx)?;
-                trace!("Called write({:?}, {:?}, {:?})", fd, buf, n);
-                let result = if fd == 1 || fd == 2 {
-                    // stdout/stderr
-                    use std::io::{self, Write};
-
-                    let buf_cont = this.memory.read_bytes(buf, Size::from_bytes(n))?;
-                    // We need to flush to make sure this actually appears on the screen
-                    let res = if fd == 1 {
-                        // Stdout is buffered, flush to make sure it appears on the screen.
-                        // This is the write() syscall of the interpreted program, we want it
-                        // to correspond to a write() syscall on the host -- there is no good
-                        // in adding extra buffering here.
-                        let res = io::stdout().write(buf_cont);
-                        io::stdout().flush().unwrap();
-                        res
-                    } else {
-                        // No need to flush, stderr is not buffered.
-                        io::stderr().write(buf_cont)
-                    };
-                    match res {
-                        Ok(n) => n as i64,
-                        Err(_) => -1,
-                    }
-                } else {
-                    this.write(args[0], args[1], args[2])?
-                };
-                // Now, `result` is the value we return back to the program.
-                this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?;
-            }
-
-            | "lseek64"
-            | "lseek"
-            => {
-                let result = this.lseek64(args[0], args[1], args[2])?;
-                this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?;
-            }
-
-            "unlink" => {
-                let result = this.unlink(args[0])?;
-                this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?;
-            }
-
-            "symlink" => {
-                let result = this.symlink(args[0], args[1])?;
-                this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?;
-            }
-
-            "stat$INODE64" => {
-                let result = this.stat(args[0], args[1])?;
-                this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?;
-            }
-
-            "lstat$INODE64" => {
-                let result = this.lstat(args[0], args[1])?;
-                this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?;
-            }
-
-            "fstat$INODE64" => {
-                let result = this.fstat(args[0], args[1])?;
-                this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?;
-            }
-
-            "rename" => {
-                let result = this.rename(args[0], args[1])?;
-                this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?;
-            }
-
-            "clock_gettime" => {
-                let result = this.clock_gettime(args[0], args[1])?;
-                this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?;
-            }
-
-            "gettimeofday" => {
-                let result = this.gettimeofday(args[0], args[1])?;
-                this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?;
-            }
-
             "strlen" => {
                 let ptr = this.read_scalar(args[0])?.not_undef()?;
                 let n = this.memory.read_c_str(ptr)?.len();
-                this.write_scalar(Scalar::from_uint(n as u64, dest.layout.size), dest)?;
+                this.write_scalar(Scalar::from_uint(u64::try_from(n).unwrap(), dest.layout.size), dest)?;
             }
 
             // math functions
@@ -629,10 +440,10 @@ fn emulate_foreign_item(
 
                 // Saturating cast to i16. Even those are outside the valid exponent range to
                 // `scalbn` below will do its over/underflow handling.
-                let exp = if exp > i16::max_value() as i32 {
-                    i16::max_value()
-                } else if exp < i16::min_value() as i32 {
-                    i16::min_value()
+                let exp = if exp > i32::from(i16::MAX) {
+                    i16::MAX
+                } else if exp < i32::from(i16::MIN) {
+                    i16::MIN
                 } else {
                     exp.try_into().unwrap()
                 };
@@ -641,390 +452,14 @@ fn emulate_foreign_item(
                 this.write_scalar(Scalar::from_f64(res), dest)?;
             }
 
-            // Some things needed for `sys::thread` initialization to go through.
-            | "signal"
-            | "sigaction"
-            | "sigaltstack"
-            => {
-                this.write_scalar(Scalar::from_int(0, dest.layout.size), dest)?;
-            }
-
-            "sysconf" => {
-                let name = this.read_scalar(args[0])?.to_i32()?;
-
-                trace!("sysconf() called with name {}", name);
-                // TODO: Cache the sysconf integers via Miri's global cache.
-                let paths = &[
-                    (&["libc", "_SC_PAGESIZE"], Scalar::from_int(PAGE_SIZE, dest.layout.size)),
-                    (&["libc", "_SC_GETPW_R_SIZE_MAX"], Scalar::from_int(-1, dest.layout.size)),
-                    (
-                        &["libc", "_SC_NPROCESSORS_ONLN"],
-                        Scalar::from_int(NUM_CPUS, dest.layout.size),
-                    ),
-                ];
-                let mut result = None;
-                for &(path, path_value) in paths {
-                    if let Some(val) = this.eval_path_scalar(path)? {
-                        let val = val.to_i32()?;
-                        if val == name {
-                            result = Some(path_value);
-                            break;
-                        }
-                    }
-                }
-                if let Some(result) = result {
-                    this.write_scalar(result, dest)?;
-                } else {
-                    throw_unsup_format!("Unimplemented sysconf name: {}", name)
-                }
-            }
-
-            "sched_getaffinity" => {
-                // Return an error; `num_cpus` then falls back to `sysconf`.
-                this.write_scalar(Scalar::from_int(-1, dest.layout.size), dest)?;
-            }
-
-            "isatty" => {
-                this.write_null(dest)?;
-            }
-
-            // Hook pthread calls that go to the thread-local storage memory subsystem.
-            "pthread_key_create" => {
-                let key_place = this.deref_operand(args[0])?;
-
-                // Extract the function type out of the signature (that seems easier than constructing it ourselves).
-                let dtor = match this.test_null(this.read_scalar(args[1])?.not_undef()?)? {
-                    Some(dtor_ptr) => Some(this.memory.get_fn(dtor_ptr)?.as_instance()?),
-                    None => None,
-                };
-
-                // Figure out how large a pthread TLS key actually is.
-                // This is `libc::pthread_key_t`.
-                let key_type = args[0].layout.ty
-                    .builtin_deref(true)
-                    .ok_or_else(|| err_ub_format!(
-                        "wrong signature used for `pthread_key_create`: first argument must be a raw pointer."
-                    ))?
-                    .ty;
-                let key_layout = this.layout_of(key_type)?;
-
-                // Create key and write it into the memory where `key_ptr` wants it.
-                let key = this.machine.tls.create_tls_key(dtor) as u128;
-                if key_layout.size.bits() < 128 && key >= (1u128 << key_layout.size.bits() as u128)
-                {
-                    throw_unsup!(OutOfTls);
-                }
-
-                this.write_scalar(Scalar::from_uint(key, key_layout.size), key_place.into())?;
-
-                // Return success (`0`).
-                this.write_null(dest)?;
-            }
-            "pthread_key_delete" => {
-                let key = this.read_scalar(args[0])?.to_bits(args[0].layout.size)?;
-                this.machine.tls.delete_tls_key(key)?;
-                // Return success (0)
-                this.write_null(dest)?;
-            }
-            "pthread_getspecific" => {
-                let key = this.read_scalar(args[0])?.to_bits(args[0].layout.size)?;
-                let ptr = this.machine.tls.load_tls(key, tcx)?;
-                this.write_scalar(ptr, dest)?;
-            }
-            "pthread_setspecific" => {
-                let key = this.read_scalar(args[0])?.to_bits(args[0].layout.size)?;
-                let new_ptr = this.read_scalar(args[1])?.not_undef()?;
-                this.machine.tls.store_tls(key, this.test_null(new_ptr)?)?;
-
-                // Return success (`0`).
-                this.write_null(dest)?;
-            }
-
-            // Stack size/address stuff.
-            | "pthread_attr_init"
-            | "pthread_attr_destroy"
-            | "pthread_self"
-            | "pthread_attr_setstacksize" => {
-                this.write_null(dest)?;
-            }
-            "pthread_attr_getstack" => {
-                let addr_place = this.deref_operand(args[1])?;
-                let size_place = this.deref_operand(args[2])?;
-
-                this.write_scalar(
-                    Scalar::from_uint(STACK_ADDR, addr_place.layout.size),
-                    addr_place.into(),
-                )?;
-                this.write_scalar(
-                    Scalar::from_uint(STACK_SIZE, size_place.layout.size),
-                    size_place.into(),
-                )?;
-
-                // Return success (`0`).
-                this.write_null(dest)?;
-            }
-
-            // We don't support threading. (Also for Windows.)
-            | "pthread_create"
-            | "CreateThread"
-            => {
-                throw_unsup_format!("Miri does not support threading");
-            }
-
-            // Stub out calls for condvar, mutex and rwlock, to just return `0`.
-            | "pthread_mutexattr_init"
-            | "pthread_mutexattr_settype"
-            | "pthread_mutex_init"
-            | "pthread_mutexattr_destroy"
-            | "pthread_mutex_lock"
-            | "pthread_mutex_unlock"
-            | "pthread_mutex_destroy"
-            | "pthread_rwlock_rdlock"
-            | "pthread_rwlock_unlock"
-            | "pthread_rwlock_wrlock"
-            | "pthread_rwlock_destroy"
-            | "pthread_condattr_init"
-            | "pthread_condattr_setclock"
-            | "pthread_cond_init"
-            | "pthread_condattr_destroy"
-            | "pthread_cond_destroy"
-            => {
-                this.write_null(dest)?;
-            }
-
-            // We don't support fork so we don't have to do anything for atfork.
-            "pthread_atfork" => {
-                this.write_null(dest)?;
-            }
-
-            "posix_fadvise" => {
-                // fadvise is only informational, we can ignore it.
-                this.write_null(dest)?;
-            }
-
-            "mmap" => {
-                // 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.
-                let addr = this.read_scalar(args[0])?.not_undef()?;
-                this.write_scalar(addr, dest)?;
-            }
-            "mprotect" => {
-                this.write_null(dest)?;
-            }
-
-            // macOS API stubs.
-            | "pthread_attr_get_np"
-            | "pthread_getattr_np"
-            => {
-                this.write_null(dest)?;
-            }
-            "pthread_get_stackaddr_np" => {
-                let stack_addr = Scalar::from_uint(STACK_ADDR, dest.layout.size);
-                this.write_scalar(stack_addr, dest)?;
-            }
-            "pthread_get_stacksize_np" => {
-                let stack_size = Scalar::from_uint(STACK_SIZE, dest.layout.size);
-                this.write_scalar(stack_size, dest)?;
-            }
-            "_tlv_atexit" => {
-                // FIXME: register the destructor.
-            }
-            "_NSGetArgc" => {
-                this.write_scalar(this.machine.argc.expect("machine must be initialized"), dest)?;
-            }
-            "_NSGetArgv" => {
-                this.write_scalar(this.machine.argv.expect("machine must be initialized"), dest)?;
-            }
-            "SecRandomCopyBytes" => {
-                let len = this.read_scalar(args[1])?.to_machine_usize(this)?;
-                let ptr = this.read_scalar(args[2])?.not_undef()?;
-                this.gen_random(ptr, len as usize)?;
-                this.write_null(dest)?;
-            }
-
-            // Windows API stubs.
-            // HANDLE = isize
-            // DWORD = ULONG = u32
-            // BOOL = i32
-            "GetProcessHeap" => {
-                // Just fake a HANDLE
-                this.write_scalar(Scalar::from_int(1, this.pointer_size()), dest)?;
+            _ => match this.tcx.sess.target.target.target_os.as_str() {
+                "linux" | "macos" => return posix::EvalContextExt::emulate_foreign_item_by_name(this, link_name, args, dest, ret),
+                "windows" => return windows::EvalContextExt::emulate_foreign_item_by_name(this, link_name, args, dest, ret),
+                target => throw_unsup_format!("The {} target platform is not supported", target),
             }
-            "HeapAlloc" => {
-                let _handle = this.read_scalar(args[0])?.to_machine_isize(this)?;
-                let flags = this.read_scalar(args[1])?.to_u32()?;
-                let size = this.read_scalar(args[2])?.to_machine_usize(this)?;
-                let zero_init = (flags & 0x00000008) != 0; // HEAP_ZERO_MEMORY
-                let res = this.malloc(size, zero_init, MiriMemoryKind::WinHeap);
-                this.write_scalar(res, dest)?;
-            }
-            "HeapFree" => {
-                let _handle = this.read_scalar(args[0])?.to_machine_isize(this)?;
-                let _flags = this.read_scalar(args[1])?.to_u32()?;
-                let ptr = this.read_scalar(args[2])?.not_undef()?;
-                this.free(ptr, MiriMemoryKind::WinHeap)?;
-                this.write_scalar(Scalar::from_int(1, Size::from_bytes(4)), dest)?;
-            }
-            "HeapReAlloc" => {
-                let _handle = this.read_scalar(args[0])?.to_machine_isize(this)?;
-                let _flags = this.read_scalar(args[1])?.to_u32()?;
-                let ptr = this.read_scalar(args[2])?.not_undef()?;
-                let size = this.read_scalar(args[3])?.to_machine_usize(this)?;
-                let res = this.realloc(ptr, size, MiriMemoryKind::WinHeap)?;
-                this.write_scalar(res, dest)?;
-            }
-
-            "SetLastError" => {
-                this.set_last_error(this.read_scalar(args[0])?.not_undef()?)?;
-            }
-            "GetLastError" => {
-                let last_error = this.get_last_error()?;
-                this.write_scalar(last_error, dest)?;
-            }
-
-            "AddVectoredExceptionHandler" => {
-                // Any non zero value works for the stdlib. This is just used for stack overflows anyway.
-                this.write_scalar(Scalar::from_int(1, dest.layout.size), dest)?;
-            }
-
-            | "InitializeCriticalSection"
-            | "EnterCriticalSection"
-            | "LeaveCriticalSection"
-            | "DeleteCriticalSection"
-            => {
-                // Nothing to do, not even a return value.
-            }
-
-            | "GetModuleHandleW"
-            | "GetProcAddress"
-            | "TryEnterCriticalSection"
-            | "GetConsoleScreenBufferInfo"
-            | "SetConsoleTextAttribute"
-            => {
-                // Pretend these do not exist / nothing happened, by returning zero.
-                this.write_null(dest)?;
-            }
-
-            "GetSystemInfo" => {
-                let system_info = this.deref_operand(args[0])?;
-                // Initialize with `0`.
-                this.memory.write_bytes(
-                    system_info.ptr,
-                    iter::repeat(0u8).take(system_info.layout.size.bytes() as usize),
-                )?;
-                // Set number of processors.
-                let dword_size = Size::from_bytes(4);
-                let num_cpus = this.mplace_field(system_info, 6)?;
-                this.write_scalar(Scalar::from_int(NUM_CPUS, dword_size), num_cpus.into())?;
-            }
-
-            "TlsAlloc" => {
-                // This just creates a key; Windows does not natively support TLS destructors.
-
-                // Create key and return it.
-                let key = this.machine.tls.create_tls_key(None) as u128;
-
-                // Figure out how large a TLS key actually is. This is `c::DWORD`.
-                if dest.layout.size.bits() < 128
-                    && key >= (1u128 << dest.layout.size.bits() as u128)
-                {
-                    throw_unsup!(OutOfTls);
-                }
-                this.write_scalar(Scalar::from_uint(key, dest.layout.size), dest)?;
-            }
-            "TlsGetValue" => {
-                let key = this.read_scalar(args[0])?.to_u32()? as u128;
-                let ptr = this.machine.tls.load_tls(key, tcx)?;
-                this.write_scalar(ptr, dest)?;
-            }
-            "TlsSetValue" => {
-                let key = this.read_scalar(args[0])?.to_u32()? as u128;
-                let new_ptr = this.read_scalar(args[1])?.not_undef()?;
-                this.machine.tls.store_tls(key, this.test_null(new_ptr)?)?;
-
-                // Return success (`1`).
-                this.write_scalar(Scalar::from_int(1, dest.layout.size), dest)?;
-            }
-            "GetStdHandle" => {
-                let which = this.read_scalar(args[0])?.to_i32()?;
-                // We just make this the identity function, so we know later in `WriteFile`
-                // which one it is.
-                this.write_scalar(Scalar::from_int(which, this.pointer_size()), dest)?;
-            }
-            "WriteFile" => {
-                let handle = this.read_scalar(args[0])?.to_machine_isize(this)?;
-                let buf = this.read_scalar(args[1])?.not_undef()?;
-                let n = this.read_scalar(args[2])?.to_u32()?;
-                let written_place = this.deref_operand(args[3])?;
-                // Spec says to always write `0` first.
-                this.write_null(written_place.into())?;
-                let written = if handle == -11 || handle == -12 {
-                    // stdout/stderr
-                    use std::io::{self, Write};
-
-                    let buf_cont = this.memory.read_bytes(buf, Size::from_bytes(u64::from(n)))?;
-                    let res = if handle == -11 {
-                        io::stdout().write(buf_cont)
-                    } else {
-                        io::stderr().write(buf_cont)
-                    };
-                    res.ok().map(|n| n as u32)
-                } else {
-                    eprintln!("Miri: Ignored output to handle {}", handle);
-                    // Pretend it all went well.
-                    Some(n)
-                };
-                // If there was no error, write back how much was written.
-                if let Some(n) = written {
-                    this.write_scalar(Scalar::from_u32(n), written_place.into())?;
-                }
-                // Return whether this was a success.
-                this.write_scalar(
-                    Scalar::from_int(if written.is_some() { 1 } else { 0 }, dest.layout.size),
-                    dest,
-                )?;
-            }
-            "GetConsoleMode" => {
-                // Everything is a pipe.
-                this.write_null(dest)?;
-            }
-            "GetEnvironmentVariableW" => {
-                // args[0] : LPCWSTR lpName (32-bit ptr to a const string of 16-bit Unicode chars)
-                // args[1] : LPWSTR lpBuffer (32-bit pointer to a string of 16-bit Unicode chars)
-                // lpBuffer : ptr to buffer that receives contents of the env_var as a null-terminated string.
-                // Return `# of chars` stored in the buffer pointed to by lpBuffer, excluding null-terminator.
-                // Return 0 upon failure.
-
-                // This is not the env var you are looking for.
-                this.set_last_error(Scalar::from_u32(203))?; // ERROR_ENVVAR_NOT_FOUND
-                this.write_null(dest)?;
-            }
-            "SetEnvironmentVariableW" => {
-                // args[0] : LPCWSTR lpName (32-bit ptr to a const string of 16-bit Unicode chars)
-                // args[1] : LPCWSTR lpValue (32-bit ptr to a const string of 16-bit Unicode chars)
-                // Return nonzero if success, else return 0.
-                throw_unsup_format!("can't set environment variable on Windows");
-            }
-            "GetCommandLineW" => {
-                this.write_scalar(
-                    this.machine.cmd_line.expect("machine must be initialized"),
-                    dest,
-                )?;
-            }
-            // The actual name of 'RtlGenRandom'
-            "SystemFunction036" => {
-                let ptr = this.read_scalar(args[0])?.not_undef()?;
-                let len = this.read_scalar(args[1])?.to_u32()?;
-                this.gen_random(ptr, len as usize)?;
-                this.write_scalar(Scalar::from_bool(true), dest)?;
-            }
-
-            // We can't execute anything else.
-            _ => throw_unsup_format!("can't call foreign function: {}", link_name),
-        }
+        };
 
-        this.dump_place(*dest);
-        this.go_to_block(ret);
-        Ok(None)
+        Ok(true)
     }
 
     /// Evaluates the scalar at the specified path. Returns Some(val)
@@ -1043,21 +478,3 @@ fn eval_path_scalar(
         return Ok(None);
     }
 }
-
-// Shims the linux 'getrandom()' syscall.
-fn linux_getrandom<'tcx>(
-    this: &mut MiriEvalContext<'_, 'tcx>,
-    args: &[OpTy<'tcx, Tag>],
-    dest: PlaceTy<'tcx, Tag>,
-) -> InterpResult<'tcx> {
-    let ptr = this.read_scalar(args[0])?.not_undef()?;
-    let len = this.read_scalar(args[1])?.to_machine_usize(this)?;
-
-    // The only supported flags are GRND_RANDOM and GRND_NONBLOCK,
-    // neither of which have any effect on our current PRNG.
-    let _flags = this.read_scalar(args[2])?.to_i32()?;
-
-    this.gen_random(ptr, len as usize)?;
-    this.write_scalar(Scalar::from_uint(len, dest.layout.size), dest)?;
-    Ok(())
-}