diff --git a/rust-version b/rust-version index f08a8228d45..1f717dbd6ed 100644 --- a/rust-version +++ b/rust-version @@ -1 +1 @@ -bbe9d27b8ff36da56638aa43d6d0cdfdf89a4e57 +1a4b9a85634c17a60e8802307510c300a35a4b9b diff --git a/src/machine.rs b/src/machine.rs index 9108f4f1666..9e0cb69f28d 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -605,6 +605,7 @@ fn ptr_get_alloc( #[inline(always)] fn memory_read( + _tcx: TyCtxt<'tcx>, machine: &Self, alloc_extra: &AllocExtra, tag: Tag, @@ -627,6 +628,7 @@ fn memory_read( #[inline(always)] fn memory_written( + _tcx: TyCtxt<'tcx>, machine: &mut Self, alloc_extra: &mut AllocExtra, tag: Tag, @@ -649,6 +651,7 @@ fn memory_written( #[inline(always)] fn memory_deallocated( + _tcx: TyCtxt<'tcx>, machine: &mut Self, alloc_extra: &mut AllocExtra, tag: Tag, diff --git a/src/shims/windows/dlsym.rs b/src/shims/windows/dlsym.rs index 325100bdb3a..ac9e085b5d7 100644 --- a/src/shims/windows/dlsym.rs +++ b/src/shims/windows/dlsym.rs @@ -1,10 +1,16 @@ use rustc_middle::mir; +use rustc_target::abi::Size; use rustc_target::spec::abi::Abi; +use log::trace; + +use crate::helpers::check_arg_count; use crate::*; #[derive(Debug, Copy, Clone)] -pub enum Dlsym {} +pub enum Dlsym { + NtWriteFile, +} impl Dlsym { // Returns an error for unsupported symbols, and None if this symbol @@ -12,6 +18,7 @@ impl Dlsym { pub fn from_str(name: &str) -> InterpResult<'static, Option> { Ok(match name { "GetSystemTimePreciseAsFileTime" => None, + "NtWriteFile" => Some(Dlsym::NtWriteFile), _ => throw_unsup_format!("unsupported Windows dlsym: {}", name), }) } @@ -23,15 +30,82 @@ fn call_dlsym( &mut self, dlsym: Dlsym, abi: Abi, - _args: &[OpTy<'tcx, Tag>], + args: &[OpTy<'tcx, Tag>], ret: Option<(&PlaceTy<'tcx, Tag>, mir::BasicBlock)>, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - let (_dest, _ret) = ret.expect("we don't support any diverging dlsym"); + let (dest, ret) = ret.expect("we don't support any diverging dlsym"); assert!(this.tcx.sess.target.os == "windows"); this.check_abi(abi, Abi::System { unwind: false })?; - match dlsym {} + match dlsym { + Dlsym::NtWriteFile => { + if !this.frame_in_std() { + throw_unsup_format!( + "NtWriteFile support is crude and just enough for stdout to work" + ); + } + + let &[ + ref handle, + ref _event, + ref _apc_routine, + ref _apc_context, + ref io_status_block, + ref buf, + ref n, + ref byte_offset, + ref _key, + ] = check_arg_count(args)?; + let handle = this.read_scalar(handle)?.to_machine_isize(this)?; + let buf = this.read_pointer(buf)?; + let n = this.read_scalar(n)?.to_u32()?; + let byte_offset = this.read_scalar(byte_offset)?.to_machine_usize(this)?; // is actually a pointer + let io_status_block = this.deref_operand(io_status_block)?; + + if byte_offset != 0 { + throw_unsup_format!( + "NtWriteFile ByteOffset paremeter is non-null, which is unsupported" + ); + } + + let written = if handle == -11 || handle == -12 { + // stdout/stderr + use std::io::{self, Write}; + + let buf_cont = this.read_bytes_ptr(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 { + throw_unsup_format!( + "on Windows, writing to anything except stdout/stderr is not supported" + ) + }; + // We have to put the result into io_status_block. + if let Some(n) = written { + let io_status_information = + this.mplace_field_named(&io_status_block, "Information")?; + this.write_scalar( + Scalar::from_machine_usize(n.into(), this), + &io_status_information.into(), + )?; + } + // Return whether this was a success. >= 0 is success. + // For the error code we arbitrarily pick 0xC0000185, STATUS_IO_DEVICE_ERROR. + this.write_scalar( + Scalar::from_i32(if written.is_some() { 0 } else { 0xC0000185u32 as i32 }), + dest, + )?; + } + } + + trace!("{:?}", this.dump_place(**dest)); + this.go_to_block(ret); + Ok(()) } } diff --git a/src/shims/windows/foreign_items.rs b/src/shims/windows/foreign_items.rs index 82ac5c5d75c..d7230279431 100644 --- a/src/shims/windows/foreign_items.rs +++ b/src/shims/windows/foreign_items.rs @@ -23,6 +23,7 @@ fn emulate_foreign_item_by_name( // Windows API stubs. // HANDLE = isize + // NTSTATUS = LONH = i32 // DWORD = ULONG = u32 // BOOL = i32 // BOOLEAN = u8 @@ -64,49 +65,6 @@ fn emulate_foreign_item_by_name( this.write_scalar(Scalar::from_i32(result), dest)?; } - // File related shims - "GetStdHandle" => { - let &[ref which] = - this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; - let which = this.read_scalar(which)?.to_i32()?; - // We just make this the identity function, so we know later in `WriteFile` - // which one it is. - this.write_scalar(Scalar::from_machine_isize(which.into(), this), dest)?; - } - "WriteFile" => { - let &[ref handle, ref buf, ref n, ref written_ptr, ref overlapped] = - this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; - this.read_scalar(overlapped)?.to_machine_usize(this)?; // this is a poiner, that we ignore - let handle = this.read_scalar(handle)?.to_machine_isize(this)?; - let buf = this.read_pointer(buf)?; - let n = this.read_scalar(n)?.to_u32()?; - let written_place = this.deref_operand(written_ptr)?; - // 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.read_bytes_ptr(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 { - throw_unsup_format!( - "on Windows, writing to anything except stdout/stderr is not supported" - ) - }; - // 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_i32(if written.is_some() { 1 } else { 0 }), dest)?; - } - // Allocation "HeapAlloc" => { let &[ref handle, ref flags, ref size] = @@ -333,6 +291,15 @@ fn emulate_foreign_item_by_name( // value if this call does result in switching to another thread. this.write_null(dest)?; } + "GetStdHandle" => { + let &[ref which] = + this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; + let which = this.read_scalar(which)?.to_i32()?; + // We just make this the identity function, so we know later in `NtWriteFile` which + // one it is. This is very fake, but libtest needs it so we cannot make it a + // std-only shim. + this.write_scalar(Scalar::from_machine_isize(which.into(), this), dest)?; + } // Better error for attempts to create a thread "CreateThread" => { @@ -350,6 +317,13 @@ fn emulate_foreign_item_by_name( // Just fake a HANDLE this.write_scalar(Scalar::from_machine_isize(1, this), dest)?; } + "GetModuleHandleA" if this.frame_in_std() => { + #[allow(non_snake_case)] + let &[_lpModuleName] = + this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; + // We need to return something non-null here to make `compat_fn!` work. + this.write_scalar(Scalar::from_machine_isize(1, this), dest)?; + } "SetConsoleTextAttribute" if this.frame_in_std() => { #[allow(non_snake_case)] let &[ref _hConsoleOutput, ref _wAttribute] = diff --git a/tests/run-pass/concurrency/simple.rs b/tests/run-pass/concurrency/simple.rs index c659cfbc3fd..40d8802472a 100644 --- a/tests/run-pass/concurrency/simple.rs +++ b/tests/run-pass/concurrency/simple.rs @@ -1,5 +1,5 @@ // ignore-windows: Concurrency on Windows is not supported yet. -// compile-flags: -Zmiri-check-number-validity +// compile-flags: -Zmiri-strict-provenance use std::thread; diff --git a/tests/run-pass/vecdeque.rs b/tests/run-pass/vecdeque.rs index 0cba0165cae..fa6707632dc 100644 --- a/tests/run-pass/vecdeque.rs +++ b/tests/run-pass/vecdeque.rs @@ -26,7 +26,7 @@ fn main() { assert_eq!(**a, 2); } - // Regression test for Debug and Diaplay impl's + // Regression test for Debug impl's println!("{:?} {:?}", dst, dst.iter()); println!("{:?}", VecDeque::::new().iter());