From 0fac868685020a78b056facee7fa321a02457d5f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 29 Jun 2019 13:33:47 +0200 Subject: [PATCH 1/3] support num_cpus and test that --- src/fn_call.rs | 19 ++++++++++++------- src/intptrcast.rs | 6 ++---- src/lib.rs | 5 +++++ test-cargo-miri/Cargo.lock | 10 ++++++++++ test-cargo-miri/Cargo.toml | 1 + test-cargo-miri/run-test.py | 6 +++--- test-cargo-miri/src/main.rs | 3 +++ test-cargo-miri/test.stdout.ref | 8 +++++--- test-cargo-miri/test.stdout.ref2 | 4 ++-- test-cargo-miri/tests/test.rs | 26 +++++++++++++++++++------- 10 files changed, 62 insertions(+), 26 deletions(-) diff --git a/src/fn_call.rs b/src/fn_call.rs index e2a4daa6f38..559524b2fe0 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -622,11 +622,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx let name = this.read_scalar(args[0])?.to_i32()?; trace!("sysconf() called with name {}", name); - // Cache the sysconf integers via Miri's global cache. + // TODO: Cache the sysconf integers via Miri's global cache. let paths = &[ - (&["libc", "_SC_PAGESIZE"], Scalar::from_int(4096, dest.layout.size)), + (&["libc", "_SC_PAGESIZE"], Scalar::from_int(PAGE_SIZE, dest.layout.size)), (&["libc", "_SC_GETPW_R_SIZE_MAX"], Scalar::from_int(-1, dest.layout.size)), - (&["libc", "_SC_NPROCESSORS_ONLN"], Scalar::from_int(1, dest.layout.size)), + (&["libc", "_SC_NPROCESSORS_ONLN"], Scalar::from_int(NUM_CPUS, dest.layout.size)), ]; let mut result = None; for &(path, path_value) in paths { @@ -648,6 +648,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx } } + "sched_getaffinity" => { + // Return an error; `num_cpus` then falls back to `sysconf`. + this.write_scalar(Scalar::from_int(-1, dest.layout.size), dest)?; + } + "isatty" => { this.write_null(dest)?; } @@ -722,14 +727,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // Second argument is where we are supposed to write the stack size. let ptr = this.deref_operand(args[1])?; // Just any address. - let stack_addr = Scalar::from_int(0x80000, args[1].layout.size); + let stack_addr = Scalar::from_uint(STACK_ADDR, args[1].layout.size); this.write_scalar(stack_addr, ptr.into())?; // Return success (`0`). this.write_null(dest)?; } "pthread_get_stackaddr_np" => { // Just any address. - let stack_addr = Scalar::from_int(0x80000, dest.layout.size); + let stack_addr = Scalar::from_uint(STACK_ADDR, dest.layout.size); this.write_scalar(stack_addr, dest)?; } @@ -838,14 +843,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // 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`. + // Set number of processors. 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(), + Scalar::from_int(NUM_CPUS, dword_size).into(), dword_size, )?; } diff --git a/src/intptrcast.rs b/src/intptrcast.rs index 176e1bc591c..83e500ea32d 100644 --- a/src/intptrcast.rs +++ b/src/intptrcast.rs @@ -4,8 +4,7 @@ use rustc::mir::interpret::{AllocId, Pointer, InterpResult}; use rustc_mir::interpret::Memory; use rustc_target::abi::Size; -use crate::stacked_borrows::Tag; -use crate::Evaluator; +use crate::{Evaluator, Tag, STACK_ADDR}; pub type MemoryExtra = RefCell; @@ -25,11 +24,10 @@ pub struct GlobalState { } impl Default for GlobalState { - // FIXME: Query the page size in the future fn default() -> Self { GlobalState { int_to_ptr_map: Vec::default(), - next_base_addr: 2u64.pow(16) + next_base_addr: STACK_ADDR, } } } diff --git a/src/lib.rs b/src/lib.rs index ab9e9854c34..567fdae53b4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -40,6 +40,11 @@ pub use crate::stacked_borrows::{EvalContextExt as StackedBorEvalContextExt, Tag pub use crate::machine::{MemoryExtra, AllocExtra, MiriMemoryKind, Evaluator, MiriEvalContext, MiriEvalContextExt}; pub use crate::eval::{eval_main, create_ecx, MiriConfig}; +// Some global facts about the emulated machine. +pub const PAGE_SIZE: u64 = 4*1024; +pub const STACK_ADDR: u64 = 16*PAGE_SIZE; +pub const NUM_CPUS: u64 = 1; + /// Insert rustc arguments at the beginning of the argument list that Miri wants to be /// set per default, for maximal validation power. pub fn miri_default_args() -> &'static [&'static str] { diff --git a/test-cargo-miri/Cargo.lock b/test-cargo-miri/Cargo.lock index d404872f9db..8343832886a 100644 --- a/test-cargo-miri/Cargo.lock +++ b/test-cargo-miri/Cargo.lock @@ -29,6 +29,7 @@ name = "cargo-miri-test" version = "0.1.0" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -66,6 +67,14 @@ name = "libc" version = "0.2.58" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "num_cpus" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ppv-lite86" version = "0.2.5" @@ -148,6 +157,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum getrandom 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8d1dffef07351aafe6ef177e4dd2b8dcf503e6bc765dea3b0de9ed149a3db1ec" "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" "checksum libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "6281b86796ba5e4366000be6e9e18bf35580adf9e63fbe2294aadb587613a319" +"checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" "checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" "checksum rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d47eab0e83d9693d40f825f86948aa16eff6750ead4bdffc4ab95b8b3a7f052c" "checksum rand_chacha 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e193067942ef6f485a349a113329140d0ab9e2168ce92274499bb0e9a4190d9d" diff --git a/test-cargo-miri/Cargo.toml b/test-cargo-miri/Cargo.toml index c7fc62b79e8..3abb437049f 100644 --- a/test-cargo-miri/Cargo.toml +++ b/test-cargo-miri/Cargo.toml @@ -9,3 +9,4 @@ byteorder = "1.0" [dev-dependencies] rand = { version = "0.7", features = ["small_rng"] } +num_cpus = "1.10.1" diff --git a/test-cargo-miri/run-test.py b/test-cargo-miri/run-test.py index 33664737709..73515c74e40 100755 --- a/test-cargo-miri/run-test.py +++ b/test-cargo-miri/run-test.py @@ -8,7 +8,7 @@ and the working directory to contain the cargo-miri-test project. import sys, subprocess, os def fail(msg): - print("TEST FAIL: {}".format(msg)) + print("\nTEST FAIL: {}".format(msg)) sys.exit(1) def cargo_miri(cmd): @@ -57,7 +57,7 @@ def test_cargo_miri_test(): "test.stdout.ref", "test.stderr.ref" ) test("cargo miri test (with filter)", - cargo_miri("test") + ["--", "--", "impl"], + cargo_miri("test") + ["--", "--", "le1"], "test.stdout.ref2", "test.stderr.ref" ) @@ -66,5 +66,5 @@ os.chdir(os.path.dirname(os.path.realpath(__file__))) test_cargo_miri_run() test_cargo_miri_test() -print("TEST SUCCESSFUL!") +print("\nTEST SUCCESSFUL!") sys.exit(0) diff --git a/test-cargo-miri/src/main.rs b/test-cargo-miri/src/main.rs index c21547c29ff..d3663ec849d 100644 --- a/test-cargo-miri/src/main.rs +++ b/test-cargo-miri/src/main.rs @@ -1,10 +1,13 @@ use byteorder::{BigEndian, ByteOrder}; fn main() { + // Exercise external crate, printing to stdout. let buf = &[1,2,3,4]; let n = ::read_u32(buf); assert_eq!(n, 0x01020304); println!("{:#010x}", n); + + // Access program arguments, printing to stderr. for arg in std::env::args() { eprintln!("{}", arg); } diff --git a/test-cargo-miri/test.stdout.ref b/test-cargo-miri/test.stdout.ref index 58b9b4794b9..c2257e68e25 100644 --- a/test-cargo-miri/test.stdout.ref +++ b/test-cargo-miri/test.stdout.ref @@ -5,9 +5,11 @@ test test::rng ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out -running 2 tests +running 4 tests test entropy_rng ... ok -test simple ... ok +test num_cpus ... ok +test simple1 ... ok +test simple2 ... ok -test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out +test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out diff --git a/test-cargo-miri/test.stdout.ref2 b/test-cargo-miri/test.stdout.ref2 index ce3506709d5..a6f6e915e0e 100644 --- a/test-cargo-miri/test.stdout.ref2 +++ b/test-cargo-miri/test.stdout.ref2 @@ -5,7 +5,7 @@ test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 1 filtered out running 1 test -test simple ... ok +test simple1 ... ok -test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 1 filtered out +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 3 filtered out diff --git a/test-cargo-miri/tests/test.rs b/test-cargo-miri/tests/test.rs index ac0db2778ca..cfbe3f6d7fb 100644 --- a/test-cargo-miri/tests/test.rs +++ b/test-cargo-miri/tests/test.rs @@ -3,13 +3,28 @@ use rand::{SeedableRng, Rng, rngs::SmallRng}; // Having more than 1 test does seem to make a difference // (i.e., this calls ptr::swap which having just one test does not). #[test] -fn simple() { +fn simple1() { assert_eq!(4, 4); } +#[test] +fn simple2() { + assert_ne!(42, 24); +} + +// A test that won't work on miri (tests disabling tests) +#[cfg(not(miri))] +#[test] +fn does_not_work_on_miri() { + let x = 0u8; + assert!(&x as *const _ as usize % 4 < 4); +} + +// We also use this to test some external crates, that we cannot depend on in the compiletest suite. + #[test] fn entropy_rng() { - // Use this opportunity to test querying the RNG (needs an external crate, hence tested here and not in the compiletest suite) + // Try seeding with "real" entropy. let mut rng = SmallRng::from_entropy(); let _val = rng.gen::(); let _val = rng.gen::(); @@ -22,10 +37,7 @@ fn entropy_rng() { let _val = rng.gen::(); } -// A test that won't work on miri -#[cfg(not(miri))] #[test] -fn does_not_work_on_miri() { - let x = 0u8; - assert!(&x as *const _ as usize % 4 < 4); +fn num_cpus() { + assert_eq!(num_cpus::get(), 1); } From c7bf9064f7028a9e43feaf699e23f1443704e448 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 29 Jun 2019 13:37:38 +0200 Subject: [PATCH 2/3] comment on STACK_ADDR --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 567fdae53b4..66b6afde331 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,7 +42,7 @@ pub use crate::eval::{eval_main, create_ecx, MiriConfig}; // Some global facts about the emulated machine. pub const PAGE_SIZE: u64 = 4*1024; -pub const STACK_ADDR: u64 = 16*PAGE_SIZE; +pub const STACK_ADDR: u64 = 16*PAGE_SIZE; // not really about the "stack", but where we start assigning integer addresses to allocations pub const NUM_CPUS: u64 = 1; /// Insert rustc arguments at the beginning of the argument list that Miri wants to be From 019ad4bab456bf107cba54dc8c396fbdd6d2bae0 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 29 Jun 2019 14:37:41 +0200 Subject: [PATCH 3/3] move constants to machine.rs --- src/lib.rs | 10 ++++------ src/machine.rs | 5 +++++ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 66b6afde331..0e4a9c4ccc3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -37,14 +37,12 @@ pub use crate::range_map::RangeMap; pub use crate::helpers::{EvalContextExt as HelpersEvalContextExt}; pub use crate::mono_hash_map::MonoHashMap; pub use crate::stacked_borrows::{EvalContextExt as StackedBorEvalContextExt, Tag, Permission, Stack, Stacks, Item}; -pub use crate::machine::{MemoryExtra, AllocExtra, MiriMemoryKind, Evaluator, MiriEvalContext, MiriEvalContextExt}; +pub use crate::machine::{ + PAGE_SIZE, STACK_ADDR, NUM_CPUS, + MemoryExtra, AllocExtra, MiriMemoryKind, Evaluator, MiriEvalContext, MiriEvalContextExt, +}; pub use crate::eval::{eval_main, create_ecx, MiriConfig}; -// Some global facts about the emulated machine. -pub const PAGE_SIZE: u64 = 4*1024; -pub const STACK_ADDR: u64 = 16*PAGE_SIZE; // not really about the "stack", but where we start assigning integer addresses to allocations -pub const NUM_CPUS: u64 = 1; - /// Insert rustc arguments at the beginning of the argument list that Miri wants to be /// set per default, for maximal validation power. pub fn miri_default_args() -> &'static [&'static str] { diff --git a/src/machine.rs b/src/machine.rs index eb177fa2a18..383b6aac631 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -12,6 +12,11 @@ use rustc::mir; use crate::*; +// Some global facts about the emulated machine. +pub const PAGE_SIZE: u64 = 4*1024; // FIXME: adjust to target architecture +pub const STACK_ADDR: u64 = 16*PAGE_SIZE; // not really about the "stack", but where we start assigning integer addresses to allocations +pub const NUM_CPUS: u64 = 1; + /// Extra memory kinds #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum MiriMemoryKind {