Skip to content

Commit

Permalink
Merge pull request #578 from RalfJung/misc
Browse files Browse the repository at this point in the history
Test cargo-miri on Windows
  • Loading branch information
RalfJung authored Dec 19, 2018
2 parents d8956f0 + 750cd44 commit 8359898
Show file tree
Hide file tree
Showing 9 changed files with 141 additions and 34 deletions.
8 changes: 6 additions & 2 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,17 @@ build: false
test_script:
- set RUST_TEST_NOCAPTURE=1
- set RUST_BACKTRACE=1
# Build miri
# Build and install miri
- cargo build --release --all-features --all-targets
- cargo install --all-features --force --path .
# Get ourselves a MIR-full libstd, and use it henceforth
- cargo run --release --all-features --bin cargo-miri -- miri setup
- cargo miri setup
- set MIRI_SYSROOT=%USERPROFILE%\AppData\Local\miri\miri\cache\HOST
# Test miri
- cargo test --release --all-features
# Test cargo integration
- cd test-cargo-miri
- python3 run-test.py

notifications:
- provider: Email
Expand Down
92 changes: 82 additions & 10 deletions src/fn_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -562,27 +562,50 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a,
},

// Windows API stubs
"SetLastError" => {
let err = this.read_scalar(args[0])?.to_u32()?;
this.machine.last_error = err;
}
"GetLastError" => {
this.write_scalar(Scalar::from_uint(this.machine.last_error, Size::from_bits(32)), dest)?;
}

"AddVectoredExceptionHandler" => {
// any non zero value works for the stdlib. This is just used for stackoverflows anyway
this.write_scalar(Scalar::from_int(1, dest.layout.size), dest)?;
},
"InitializeCriticalSection" |
"EnterCriticalSection" |
"LeaveCriticalSection" |
"DeleteCriticalSection" |
"SetLastError" => {
// Function does not return anything, nothing to do
"DeleteCriticalSection" => {
// Nothing to do, not even a return value
},
"GetModuleHandleW" |
"GetProcAddress" |
"TryEnterCriticalSection" => {
"TryEnterCriticalSection" |
"GetConsoleScreenBufferInfo" |
"SetConsoleTextAttribute" => {
// pretend these do not exist/nothing happened, by returning zero
this.write_null(dest)?;
},
"GetLastError" => {
// this is c::ERROR_CALL_NOT_IMPLEMENTED
this.write_scalar(Scalar::from_int(120, dest.layout.size), dest)?;
},
"GetSystemInfo" => {
let system_info = this.deref_operand(args[0])?;
let system_info_ptr = system_info.ptr.to_ptr()?;
// initialize with 0
this.memory_mut().get_mut(system_info_ptr.alloc_id)?
.write_repeat(tcx, system_info_ptr, 0, system_info.layout.size)?;
// set number of processors to 1
let dword_size = Size::from_bytes(4);
let offset = 2*dword_size + 3*tcx.pointer_size();
this.memory_mut().get_mut(system_info_ptr.alloc_id)?
.write_scalar(
tcx,
system_info_ptr.offset(offset, tcx)?,
Scalar::from_int(1, dword_size).into(),
dword_size,
)?;
}

"TlsAlloc" => {
// This just creates a key; Windows does not natively support TLS dtors.

Expand All @@ -596,18 +619,67 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a,
this.write_scalar(Scalar::from_uint(key, dest.layout.size), dest)?;
}
"TlsGetValue" => {
let key = this.read_scalar(args[0])?.to_bits(args[0].layout.size)?;
let key = this.read_scalar(args[0])?.to_u32()? as u128;
let ptr = this.machine.tls.load_tls(key)?;
this.write_scalar(ptr, dest)?;
}
"TlsSetValue" => {
let key = this.read_scalar(args[0])?.to_bits(args[0].layout.size)?;
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, 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_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])?;
this.write_null(written_place.into())?; // spec says we always write 0 first
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);
Some(n) // pretend it all went well
};
// If there was no error, write back how much was written
if let Some(n) = written {
this.write_scalar(Scalar::from_uint(n, Size::from_bits(32)), 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" => {
// This is not the env var you are looking for
this.machine.last_error = 203; // ERROR_ENVVAR_NOT_FOUND
this.write_null(dest)?;
}
"GetCommandLineW" => {
this.write_scalar(Scalar::Ptr(this.machine.cmd_line.unwrap()), dest)?;
}

// We can't execute anything else
_ => {
Expand Down
67 changes: 52 additions & 15 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use std::borrow::Cow;
use std::env;

use rustc::ty::{self, TyCtxt, query::TyCtxtAt};
use rustc::ty::layout::{TyLayout, LayoutOf, Size};
use rustc::ty::layout::{TyLayout, LayoutOf, Size, Align};
use rustc::hir::{self, def_id::DefId};
use rustc::mir;

Expand Down Expand Up @@ -123,24 +123,54 @@ pub fn create_ecx<'a, 'mir: 'a, 'tcx: 'mir>(
let dest = ecx.eval_place(&mir::Place::Local(args.next().unwrap()))?;
let argc = Scalar::from_int(1, dest.layout.size);
ecx.write_scalar(argc, dest)?;
let argc_place = ecx.allocate(dest.layout, MiriMemoryKind::Env.into())?;
ecx.write_scalar(argc, argc_place.into())?;
ecx.machine.argc = Some(argc_place.ptr.to_ptr()?);
// Store argc for macOS _NSGetArgc
{
let argc_place = ecx.allocate(dest.layout, MiriMemoryKind::Env.into())?;
ecx.write_scalar(argc, argc_place.into())?;
ecx.machine.argc = Some(argc_place.ptr.to_ptr()?);
}

// FIXME: extract main source file path
// Third argument (argv): &[b"foo"]
const CMD: &str = "running-in-miri\0";
let dest = ecx.eval_place(&mir::Place::Local(args.next().unwrap()))?;
let foo = ecx.memory_mut().allocate_static_bytes(b"foo\0").with_default_tag();
let foo_ty = ecx.tcx.mk_imm_ptr(ecx.tcx.types.u8);
let foo_layout = ecx.layout_of(foo_ty)?;
let foo_place = ecx.allocate(foo_layout, MiriMemoryKind::Env.into())?;
ecx.write_scalar(Scalar::Ptr(foo), foo_place.into())?;
ecx.memory_mut().mark_immutable(foo_place.to_ptr()?.alloc_id)?;
let argv = foo_place.ptr;
ecx.write_scalar(argv, dest)?;
let argv_place = ecx.allocate(dest.layout, MiriMemoryKind::Env.into())?;
ecx.write_scalar(argv, argv_place.into())?;
ecx.machine.argv = Some(argv_place.ptr.to_ptr()?);
let cmd = ecx.memory_mut().allocate_static_bytes(CMD.as_bytes()).with_default_tag();
let raw_str_layout = ecx.layout_of(ecx.tcx.mk_imm_ptr(ecx.tcx.types.u8))?;
let cmd_place = ecx.allocate(raw_str_layout, MiriMemoryKind::Env.into())?;
ecx.write_scalar(Scalar::Ptr(cmd), cmd_place.into())?;
ecx.memory_mut().mark_immutable(cmd_place.to_ptr()?.alloc_id)?;
// Store argv for macOS _NSGetArgv
{
let argv = cmd_place.ptr;
ecx.write_scalar(argv, dest)?;
let argv_place = ecx.allocate(dest.layout, MiriMemoryKind::Env.into())?;
ecx.write_scalar(argv, argv_place.into())?;
ecx.machine.argv = Some(argv_place.ptr.to_ptr()?);
}
// Store cmdline as UTF-16 for Windows GetCommandLineW
{
let tcx = &{ecx.tcx.tcx};
let cmd_utf16: Vec<u16> = CMD.encode_utf16().collect();
let cmd_ptr = ecx.memory_mut().allocate(
Size::from_bytes(cmd_utf16.len() as u64 * 2),
Align::from_bytes(2).unwrap(),
MiriMemoryKind::Env.into(),
)?.with_default_tag();
ecx.machine.cmd_line = Some(cmd_ptr);
// store the UTF-16 string
let char_size = Size::from_bytes(2);
let cmd_alloc = ecx.memory_mut().get_mut(cmd_ptr.alloc_id)?;
let mut cur_ptr = cmd_ptr;
for &c in cmd_utf16.iter() {
cmd_alloc.write_scalar(
tcx,
cur_ptr,
Scalar::from_uint(c, char_size).into(),
char_size,
)?;
cur_ptr = cur_ptr.offset(char_size, tcx)?;
}
}

assert!(args.next().is_none(), "start lang item has more arguments than expected");

Expand Down Expand Up @@ -263,8 +293,13 @@ pub struct Evaluator<'tcx> {

/// Program arguments (`Option` because we can only initialize them after creating the ecx).
/// These are *pointers* to argc/argv because macOS.
/// We also need the full cmdline as one string because Window.
pub(crate) argc: Option<Pointer<Borrow>>,
pub(crate) argv: Option<Pointer<Borrow>>,
pub(crate) cmd_line: Option<Pointer<Borrow>>,

/// Last OS error
pub(crate) last_error: u32,

/// TLS state
pub(crate) tls: TlsData<'tcx>,
Expand All @@ -282,6 +317,8 @@ impl<'tcx> Evaluator<'tcx> {
env_vars: HashMap::default(),
argc: None,
argv: None,
cmd_line: None,
last_error: 0,
tls: TlsData::default(),
validate,
stacked_borrows: stacked_borrows::State::default(),
Expand Down
2 changes: 0 additions & 2 deletions tests/run-pass/box-pair-to-vec.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
//ignore-msvc: Stdout not implemented on Windows

#[repr(C)]
#[derive(Debug)]
struct PairFoo {
Expand Down
1 change: 0 additions & 1 deletion tests/run-pass/catch.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
//ignore-msvc: Stdout not implemented on Windows
use std::panic::{catch_unwind, AssertUnwindSafe};

fn main() {
Expand Down
1 change: 0 additions & 1 deletion tests/run-pass/format.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
//ignore-msvc: Stdout not implemented on Windows
fn main() {
println!("Hello {}", 13);
}
1 change: 0 additions & 1 deletion tests/run-pass/hello.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
//ignore-msvc: Stdout not implemented on Windows
fn main() {
println!("Hello, world!");
}
2 changes: 1 addition & 1 deletion tests/run-pass/issue-17877.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
// except according to those terms.

//ignore-windows: Causes a stack overflow?!? Likely a rustc bug: https://github.com/rust-lang/rust/issues/53820
//Once that bug is fixed, increase the size to 16*1024 and enable on all platforms.
//FIXME: Once that bug is fixed, increase the size to 16*1024 and enable on all platforms.

#![feature(slice_patterns)]

Expand Down
1 change: 0 additions & 1 deletion tests/run-pass/issue-3794.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//ignore-msvc: Stdout not implemented on Windows
#![feature(box_syntax)]

trait T {
Expand Down

0 comments on commit 8359898

Please sign in to comment.