Auto merge of #2055 - RalfJung:rustup, r=RalfJung
Rustup Fixes https://github.com/rust-lang/miri/issues/1717
This commit is contained in:
commit
be72564a64
@ -1 +1 @@
|
|||||||
bbe9d27b8ff36da56638aa43d6d0cdfdf89a4e57
|
1a4b9a85634c17a60e8802307510c300a35a4b9b
|
||||||
|
@ -605,6 +605,7 @@ fn ptr_get_alloc(
|
|||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn memory_read(
|
fn memory_read(
|
||||||
|
_tcx: TyCtxt<'tcx>,
|
||||||
machine: &Self,
|
machine: &Self,
|
||||||
alloc_extra: &AllocExtra,
|
alloc_extra: &AllocExtra,
|
||||||
tag: Tag,
|
tag: Tag,
|
||||||
@ -627,6 +628,7 @@ fn memory_read(
|
|||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn memory_written(
|
fn memory_written(
|
||||||
|
_tcx: TyCtxt<'tcx>,
|
||||||
machine: &mut Self,
|
machine: &mut Self,
|
||||||
alloc_extra: &mut AllocExtra,
|
alloc_extra: &mut AllocExtra,
|
||||||
tag: Tag,
|
tag: Tag,
|
||||||
@ -649,6 +651,7 @@ fn memory_written(
|
|||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn memory_deallocated(
|
fn memory_deallocated(
|
||||||
|
_tcx: TyCtxt<'tcx>,
|
||||||
machine: &mut Self,
|
machine: &mut Self,
|
||||||
alloc_extra: &mut AllocExtra,
|
alloc_extra: &mut AllocExtra,
|
||||||
tag: Tag,
|
tag: Tag,
|
||||||
|
@ -1,10 +1,16 @@
|
|||||||
use rustc_middle::mir;
|
use rustc_middle::mir;
|
||||||
|
use rustc_target::abi::Size;
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
|
|
||||||
|
use log::trace;
|
||||||
|
|
||||||
|
use crate::helpers::check_arg_count;
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub enum Dlsym {}
|
pub enum Dlsym {
|
||||||
|
NtWriteFile,
|
||||||
|
}
|
||||||
|
|
||||||
impl Dlsym {
|
impl Dlsym {
|
||||||
// Returns an error for unsupported symbols, and None if this symbol
|
// 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<Dlsym>> {
|
pub fn from_str(name: &str) -> InterpResult<'static, Option<Dlsym>> {
|
||||||
Ok(match name {
|
Ok(match name {
|
||||||
"GetSystemTimePreciseAsFileTime" => None,
|
"GetSystemTimePreciseAsFileTime" => None,
|
||||||
|
"NtWriteFile" => Some(Dlsym::NtWriteFile),
|
||||||
_ => throw_unsup_format!("unsupported Windows dlsym: {}", name),
|
_ => throw_unsup_format!("unsupported Windows dlsym: {}", name),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -23,15 +30,82 @@ fn call_dlsym(
|
|||||||
&mut self,
|
&mut self,
|
||||||
dlsym: Dlsym,
|
dlsym: Dlsym,
|
||||||
abi: Abi,
|
abi: Abi,
|
||||||
_args: &[OpTy<'tcx, Tag>],
|
args: &[OpTy<'tcx, Tag>],
|
||||||
ret: Option<(&PlaceTy<'tcx, Tag>, mir::BasicBlock)>,
|
ret: Option<(&PlaceTy<'tcx, Tag>, mir::BasicBlock)>,
|
||||||
) -> InterpResult<'tcx> {
|
) -> InterpResult<'tcx> {
|
||||||
let this = self.eval_context_mut();
|
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");
|
assert!(this.tcx.sess.target.os == "windows");
|
||||||
|
|
||||||
this.check_abi(abi, Abi::System { unwind: false })?;
|
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(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ fn emulate_foreign_item_by_name(
|
|||||||
|
|
||||||
// Windows API stubs.
|
// Windows API stubs.
|
||||||
// HANDLE = isize
|
// HANDLE = isize
|
||||||
|
// NTSTATUS = LONH = i32
|
||||||
// DWORD = ULONG = u32
|
// DWORD = ULONG = u32
|
||||||
// BOOL = i32
|
// BOOL = i32
|
||||||
// BOOLEAN = u8
|
// BOOLEAN = u8
|
||||||
@ -64,49 +65,6 @@ fn emulate_foreign_item_by_name(
|
|||||||
this.write_scalar(Scalar::from_i32(result), dest)?;
|
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
|
// Allocation
|
||||||
"HeapAlloc" => {
|
"HeapAlloc" => {
|
||||||
let &[ref handle, ref flags, ref size] =
|
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.
|
// value if this call does result in switching to another thread.
|
||||||
this.write_null(dest)?;
|
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
|
// Better error for attempts to create a thread
|
||||||
"CreateThread" => {
|
"CreateThread" => {
|
||||||
@ -350,6 +317,13 @@ fn emulate_foreign_item_by_name(
|
|||||||
// Just fake a HANDLE
|
// Just fake a HANDLE
|
||||||
this.write_scalar(Scalar::from_machine_isize(1, this), dest)?;
|
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() => {
|
"SetConsoleTextAttribute" if this.frame_in_std() => {
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
let &[ref _hConsoleOutput, ref _wAttribute] =
|
let &[ref _hConsoleOutput, ref _wAttribute] =
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// ignore-windows: Concurrency on Windows is not supported yet.
|
// ignore-windows: Concurrency on Windows is not supported yet.
|
||||||
// compile-flags: -Zmiri-check-number-validity
|
// compile-flags: -Zmiri-strict-provenance
|
||||||
|
|
||||||
use std::thread;
|
use std::thread;
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ fn main() {
|
|||||||
assert_eq!(**a, 2);
|
assert_eq!(**a, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Regression test for Debug and Diaplay impl's
|
// Regression test for Debug impl's
|
||||||
println!("{:?} {:?}", dst, dst.iter());
|
println!("{:?} {:?}", dst, dst.iter());
|
||||||
println!("{:?}", VecDeque::<u32>::new().iter());
|
println!("{:?}", VecDeque::<u32>::new().iter());
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user