Skip to content

Commit 5cb40db

Browse files
committed
Auto merge of #2055 - RalfJung:rustup, r=RalfJung
Rustup Fixes #1717
2 parents f3a9856 + 3da7c55 commit 5cb40db

File tree

6 files changed

+109
-50
lines changed

6 files changed

+109
-50
lines changed

rust-version

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
bbe9d27b8ff36da56638aa43d6d0cdfdf89a4e57
1+
1a4b9a85634c17a60e8802307510c300a35a4b9b

src/machine.rs

+3
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
605605

606606
#[inline(always)]
607607
fn memory_read(
608+
_tcx: TyCtxt<'tcx>,
608609
machine: &Self,
609610
alloc_extra: &AllocExtra,
610611
tag: Tag,
@@ -627,6 +628,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
627628

628629
#[inline(always)]
629630
fn memory_written(
631+
_tcx: TyCtxt<'tcx>,
630632
machine: &mut Self,
631633
alloc_extra: &mut AllocExtra,
632634
tag: Tag,
@@ -649,6 +651,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
649651

650652
#[inline(always)]
651653
fn memory_deallocated(
654+
_tcx: TyCtxt<'tcx>,
652655
machine: &mut Self,
653656
alloc_extra: &mut AllocExtra,
654657
tag: Tag,

src/shims/windows/dlsym.rs

+78-4
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,24 @@
11
use rustc_middle::mir;
2+
use rustc_target::abi::Size;
23
use rustc_target::spec::abi::Abi;
34

5+
use log::trace;
6+
7+
use crate::helpers::check_arg_count;
48
use crate::*;
59

610
#[derive(Debug, Copy, Clone)]
7-
pub enum Dlsym {}
11+
pub enum Dlsym {
12+
NtWriteFile,
13+
}
814

915
impl Dlsym {
1016
// Returns an error for unsupported symbols, and None if this symbol
1117
// should become a NULL pointer (pretend it does not exist).
1218
pub fn from_str(name: &str) -> InterpResult<'static, Option<Dlsym>> {
1319
Ok(match name {
1420
"GetSystemTimePreciseAsFileTime" => None,
21+
"NtWriteFile" => Some(Dlsym::NtWriteFile),
1522
_ => throw_unsup_format!("unsupported Windows dlsym: {}", name),
1623
})
1724
}
@@ -23,15 +30,82 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
2330
&mut self,
2431
dlsym: Dlsym,
2532
abi: Abi,
26-
_args: &[OpTy<'tcx, Tag>],
33+
args: &[OpTy<'tcx, Tag>],
2734
ret: Option<(&PlaceTy<'tcx, Tag>, mir::BasicBlock)>,
2835
) -> InterpResult<'tcx> {
2936
let this = self.eval_context_mut();
30-
let (_dest, _ret) = ret.expect("we don't support any diverging dlsym");
37+
let (dest, ret) = ret.expect("we don't support any diverging dlsym");
3138
assert!(this.tcx.sess.target.os == "windows");
3239

3340
this.check_abi(abi, Abi::System { unwind: false })?;
3441

35-
match dlsym {}
42+
match dlsym {
43+
Dlsym::NtWriteFile => {
44+
if !this.frame_in_std() {
45+
throw_unsup_format!(
46+
"NtWriteFile support is crude and just enough for stdout to work"
47+
);
48+
}
49+
50+
let &[
51+
ref handle,
52+
ref _event,
53+
ref _apc_routine,
54+
ref _apc_context,
55+
ref io_status_block,
56+
ref buf,
57+
ref n,
58+
ref byte_offset,
59+
ref _key,
60+
] = check_arg_count(args)?;
61+
let handle = this.read_scalar(handle)?.to_machine_isize(this)?;
62+
let buf = this.read_pointer(buf)?;
63+
let n = this.read_scalar(n)?.to_u32()?;
64+
let byte_offset = this.read_scalar(byte_offset)?.to_machine_usize(this)?; // is actually a pointer
65+
let io_status_block = this.deref_operand(io_status_block)?;
66+
67+
if byte_offset != 0 {
68+
throw_unsup_format!(
69+
"NtWriteFile ByteOffset paremeter is non-null, which is unsupported"
70+
);
71+
}
72+
73+
let written = if handle == -11 || handle == -12 {
74+
// stdout/stderr
75+
use std::io::{self, Write};
76+
77+
let buf_cont = this.read_bytes_ptr(buf, Size::from_bytes(u64::from(n)))?;
78+
let res = if handle == -11 {
79+
io::stdout().write(buf_cont)
80+
} else {
81+
io::stderr().write(buf_cont)
82+
};
83+
res.ok().map(|n| n as u32)
84+
} else {
85+
throw_unsup_format!(
86+
"on Windows, writing to anything except stdout/stderr is not supported"
87+
)
88+
};
89+
// We have to put the result into io_status_block.
90+
if let Some(n) = written {
91+
let io_status_information =
92+
this.mplace_field_named(&io_status_block, "Information")?;
93+
this.write_scalar(
94+
Scalar::from_machine_usize(n.into(), this),
95+
&io_status_information.into(),
96+
)?;
97+
}
98+
// Return whether this was a success. >= 0 is success.
99+
// For the error code we arbitrarily pick 0xC0000185, STATUS_IO_DEVICE_ERROR.
100+
this.write_scalar(
101+
Scalar::from_i32(if written.is_some() { 0 } else { 0xC0000185u32 as i32 }),
102+
dest,
103+
)?;
104+
}
105+
}
106+
107+
trace!("{:?}", this.dump_place(**dest));
108+
this.go_to_block(ret);
109+
Ok(())
36110
}
37111
}

src/shims/windows/foreign_items.rs

+25-43
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
2323

2424
// Windows API stubs.
2525
// HANDLE = isize
26+
// NTSTATUS = LONH = i32
2627
// DWORD = ULONG = u32
2728
// BOOL = i32
2829
// BOOLEAN = u8
@@ -64,49 +65,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
6465
this.write_scalar(Scalar::from_i32(result), dest)?;
6566
}
6667

67-
// File related shims
68-
"GetStdHandle" => {
69-
let &[ref which] =
70-
this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
71-
let which = this.read_scalar(which)?.to_i32()?;
72-
// We just make this the identity function, so we know later in `WriteFile`
73-
// which one it is.
74-
this.write_scalar(Scalar::from_machine_isize(which.into(), this), dest)?;
75-
}
76-
"WriteFile" => {
77-
let &[ref handle, ref buf, ref n, ref written_ptr, ref overlapped] =
78-
this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
79-
this.read_scalar(overlapped)?.to_machine_usize(this)?; // this is a poiner, that we ignore
80-
let handle = this.read_scalar(handle)?.to_machine_isize(this)?;
81-
let buf = this.read_pointer(buf)?;
82-
let n = this.read_scalar(n)?.to_u32()?;
83-
let written_place = this.deref_operand(written_ptr)?;
84-
// Spec says to always write `0` first.
85-
this.write_null(&written_place.into())?;
86-
let written = if handle == -11 || handle == -12 {
87-
// stdout/stderr
88-
use std::io::{self, Write};
89-
90-
let buf_cont = this.read_bytes_ptr(buf, Size::from_bytes(u64::from(n)))?;
91-
let res = if handle == -11 {
92-
io::stdout().write(buf_cont)
93-
} else {
94-
io::stderr().write(buf_cont)
95-
};
96-
res.ok().map(|n| n as u32)
97-
} else {
98-
throw_unsup_format!(
99-
"on Windows, writing to anything except stdout/stderr is not supported"
100-
)
101-
};
102-
// If there was no error, write back how much was written.
103-
if let Some(n) = written {
104-
this.write_scalar(Scalar::from_u32(n), &written_place.into())?;
105-
}
106-
// Return whether this was a success.
107-
this.write_scalar(Scalar::from_i32(if written.is_some() { 1 } else { 0 }), dest)?;
108-
}
109-
11068
// Allocation
11169
"HeapAlloc" => {
11270
let &[ref handle, ref flags, ref size] =
@@ -333,6 +291,15 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
333291
// value if this call does result in switching to another thread.
334292
this.write_null(dest)?;
335293
}
294+
"GetStdHandle" => {
295+
let &[ref which] =
296+
this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
297+
let which = this.read_scalar(which)?.to_i32()?;
298+
// We just make this the identity function, so we know later in `NtWriteFile` which
299+
// one it is. This is very fake, but libtest needs it so we cannot make it a
300+
// std-only shim.
301+
this.write_scalar(Scalar::from_machine_isize(which.into(), this), dest)?;
302+
}
336303

337304
// Better error for attempts to create a thread
338305
"CreateThread" => {
@@ -345,11 +312,26 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
345312

346313
// Incomplete shims that we "stub out" just to get pre-main initialization code to work.
347314
// These shims are enabled only when the caller is in the standard library.
315+
"GetStdHandle" if this.frame_in_std() => {
316+
let &[ref which] =
317+
this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
318+
let which = this.read_scalar(which)?.to_i32()?;
319+
// We just make this the identity function, so we know later in `NtWriteFile`
320+
// which one it is.
321+
this.write_scalar(Scalar::from_machine_isize(which.into(), this), dest)?;
322+
}
348323
"GetProcessHeap" if this.frame_in_std() => {
349324
let &[] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
350325
// Just fake a HANDLE
351326
this.write_scalar(Scalar::from_machine_isize(1, this), dest)?;
352327
}
328+
"GetModuleHandleA" if this.frame_in_std() => {
329+
#[allow(non_snake_case)]
330+
let &[_lpModuleName] =
331+
this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
332+
// We need to return something non-null here to make `compat_fn!` work.
333+
this.write_scalar(Scalar::from_machine_isize(1, this), dest)?;
334+
}
353335
"SetConsoleTextAttribute" if this.frame_in_std() => {
354336
#[allow(non_snake_case)]
355337
let &[ref _hConsoleOutput, ref _wAttribute] =

tests/run-pass/concurrency/simple.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// ignore-windows: Concurrency on Windows is not supported yet.
2-
// compile-flags: -Zmiri-check-number-validity
2+
// compile-flags: -Zmiri-strict-provenance
33

44
use std::thread;
55

tests/run-pass/vecdeque.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ fn main() {
2626
assert_eq!(**a, 2);
2727
}
2828

29-
// Regression test for Debug and Diaplay impl's
29+
// Regression test for Debug impl's
3030
println!("{:?} {:?}", dst, dst.iter());
3131
println!("{:?}", VecDeque::<u32>::new().iter());
3232

0 commit comments

Comments
 (0)