diff --git a/src/shims/foreign_items.rs b/src/shims/foreign_items.rs index d3a8ac1b065..f8a61a7c5a1 100644 --- a/src/shims/foreign_items.rs +++ b/src/shims/foreign_items.rs @@ -702,163 +702,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx 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)?; - } - "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)?; - } - "GetConsoleMode" => { - // Everything is a pipe. - this.write_null(dest)?; - } - "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)?; - } - _ => match this.tcx.sess.target.target.target_os.to_lowercase().as_str() { "linux" | "macos" => posix::EvalContextExt::emulate_foreign_item_by_name(this, link_name, args, dest)?, "windows" => windows::EvalContextExt::emulate_foreign_item_by_name(this, link_name, args, dest)?, diff --git a/src/shims/foreign_items/posix/linux.rs b/src/shims/foreign_items/posix/linux.rs index bc61aea18c7..31a0a815891 100644 --- a/src/shims/foreign_items/posix/linux.rs +++ b/src/shims/foreign_items/posix/linux.rs @@ -38,6 +38,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?; } + "pthread_getattr_np" => { + this.write_null(dest)?; + } _ => throw_unsup_format!("can't call foreign function: {}", link_name), }; diff --git a/src/shims/foreign_items/posix/macos.rs b/src/shims/foreign_items/posix/macos.rs index e0ac92868a2..8ed793b6c03 100644 --- a/src/shims/foreign_items/posix/macos.rs +++ b/src/shims/foreign_items/posix/macos.rs @@ -53,6 +53,35 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?; } + // macOS API stubs. + "pthread_attr_get_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)?; + } + + _ => throw_unsup_format!("can't call foreign function: {}", link_name), }; diff --git a/src/shims/foreign_items/windows.rs b/src/shims/foreign_items/windows.rs index 23aa8ae7deb..e16a89a126f 100644 --- a/src/shims/foreign_items/windows.rs +++ b/src/shims/foreign_items/windows.rs @@ -1,5 +1,6 @@ use crate::*; use rustc::ty::layout::Size; +use std::iter; impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> { @@ -10,6 +11,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx dest: PlaceTy<'tcx, Tag>, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); + let tcx = &{ this.tcx.tcx }; match link_name { // Environment related shims @@ -66,6 +68,132 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx 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)?; + } + "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)?; + } + "GetConsoleMode" => { + // Everything is a pipe. + this.write_null(dest)?; + } + "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)?; + } _ => throw_unsup_format!("can't call foreign function: {}", link_name), }