Skip to content

Commit

Permalink
Rollup merge of #108500 - RalfJung:miri, r=RalfJung
Browse files Browse the repository at this point in the history
update Miri

r? `@ghost`
  • Loading branch information
matthiaskrgr committed Feb 26, 2023
2 parents e237c9d + 3f88f4c commit 80f2908
Show file tree
Hide file tree
Showing 28 changed files with 274 additions and 55 deletions.
10 changes: 2 additions & 8 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ dependencies = [
"directories",
"rustc-build-sysroot",
"rustc-workspace-hack",
"rustc_tools_util 0.2.1",
"rustc_tools_util",
"rustc_version",
"serde",
"serde_json",
Expand Down Expand Up @@ -738,7 +738,7 @@ dependencies = [
"regex",
"rustc-semver",
"rustc-workspace-hack",
"rustc_tools_util 0.3.0",
"rustc_tools_util",
"semver",
"serde",
"syn",
Expand Down Expand Up @@ -4727,12 +4727,6 @@ dependencies = [
"tracing",
]

[[package]]
name = "rustc_tools_util"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "598f48ce2a421542b3e64828aa742b687cc1b91d2f96591cfdb7ac5988cd6366"

[[package]]
name = "rustc_tools_util"
version = "0.3.0"
Expand Down
7 changes: 7 additions & 0 deletions src/tools/miri/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,13 @@ josh-proxy --local=$HOME/.cache/josh --remote=https://github.com --no-background

This uses a directory `$HOME/.cache/josh` as a cache, to speed up repeated pulling/pushing.

To make josh push via ssh instead of https, you can add the following to your `.gitconfig`:

```toml
[url "git@github.com:"]
pushInsteadOf = https://github.com/
```

### Importing changes from the rustc repo

Josh needs to be running, as described above.
Expand Down
6 changes: 4 additions & 2 deletions src/tools/miri/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,9 @@ degree documented below):
- The best-supported target is `x86_64-unknown-linux-gnu`. Miri releases are
blocked on things working with this target. Most other Linux targets should
also work well; we do run the test suite on `i686-unknown-linux-gnu` as a
32bit target and `mips64-unknown-linux-gnuabi64` as a big-endian target.
32bit target and `mips64-unknown-linux-gnuabi64` as a big-endian target, as
well as the ARM targets `aarch64-unknown-linux-gnu` and
`arm-unknown-linux-gnueabi`.
- `x86_64-apple-darwin` should work basically as well as Linux. We also test
`aarch64-apple-darwin`. However, we might ship Miri with a nightly even when
some features on these targets regress.
Expand Down Expand Up @@ -590,7 +592,7 @@ extern "Rust" {
/// `out` must point to at least `out_size` many bytes, and the result will be stored there
/// with a null terminator.
/// Returns 0 if the `out` buffer was large enough, and the required size otherwise.
fn miri_host_to_target_path(path: *const i8, out: *mut i8, out_size: usize) -> usize;
fn miri_host_to_target_path(path: *const std::ffi::c_char, out: *mut std::ffi::c_char, out_size: usize) -> usize;
}
```

Expand Down
4 changes: 2 additions & 2 deletions src/tools/miri/cargo-miri/Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -193,9 +193,9 @@ checksum = "fc71d2faa173b74b232dedc235e3ee1696581bb132fc116fa3626d6151a1a8fb"

[[package]]
name = "rustc_tools_util"
version = "0.2.1"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "598f48ce2a421542b3e64828aa742b687cc1b91d2f96591cfdb7ac5988cd6366"
checksum = "8ba09476327c4b70ccefb6180f046ef588c26a24cf5d269a9feba316eb4f029f"

[[package]]
name = "rustc_version"
Expand Down
2 changes: 1 addition & 1 deletion src/tools/miri/cargo-miri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@ rustc-workspace-hack = "1.0.0"
serde = { version = "*", features = ["derive"] }

[build-dependencies]
rustc_tools_util = "0.2"
rustc_tools_util = "0.3"
9 changes: 1 addition & 8 deletions src/tools/miri/cargo-miri/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,5 @@ fn main() {
// Don't rebuild miri when nothing changed.
println!("cargo:rerun-if-changed=build.rs");
// gather version info
println!(
"cargo:rustc-env=GIT_HASH={}",
rustc_tools_util::get_commit_hash().unwrap_or_default()
);
println!(
"cargo:rustc-env=COMMIT_DATE={}",
rustc_tools_util::get_commit_date().unwrap_or_default()
);
rustc_tools_util::setup_version_info!();
}
2 changes: 2 additions & 0 deletions src/tools/miri/ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ run_tests
case $HOST_TARGET in
x86_64-unknown-linux-gnu)
MIRI_TEST_TARGET=i686-unknown-linux-gnu run_tests
MIRI_TEST_TARGET=aarch64-unknown-linux-gnu run_tests
MIRI_TEST_TARGET=aarch64-apple-darwin run_tests
MIRI_TEST_TARGET=i686-pc-windows-msvc run_tests
MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple atomic data_race env/var
Expand All @@ -118,6 +119,7 @@ case $HOST_TARGET in
MIRI_TEST_TARGET=x86_64-pc-windows-msvc run_tests
;;
i686-pc-windows-msvc)
MIRI_TEST_TARGET=arm-unknown-linux-gnueabi run_tests
MIRI_TEST_TARGET=x86_64-unknown-linux-gnu run_tests
MIRI_TEST_TARGET=x86_64-pc-windows-gnu run_tests
;;
Expand Down
2 changes: 1 addition & 1 deletion src/tools/miri/rust-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
c54c8cbac882e149e04a9e1f2d146fd548ae30ae
c4e0cd966062ca67daed20775f4e8a60c28e57df
3 changes: 1 addition & 2 deletions src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,7 @@ impl NewPermission {
NewPermission::Uniform {
perm: Permission::Unique,
access: Some(AccessKind::Write),
protector: (kind == RetagKind::FnEntry)
.then_some(ProtectorKind::WeakProtector),
protector: (kind == RetagKind::FnEntry).then_some(ProtectorKind::WeakProtector),
}
} else {
// `!Unpin` boxes do not get `noalias` nor `dereferenceable`.
Expand Down
3 changes: 2 additions & 1 deletion src/tools/miri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#![allow(
clippy::collapsible_else_if,
clippy::collapsible_if,
clippy::if_same_then_else,
clippy::comparison_chain,
clippy::enum_variant_names,
clippy::field_reassign_with_default,
Expand All @@ -21,7 +22,7 @@
clippy::single_match,
clippy::useless_format,
clippy::derive_partial_eq_without_eq,
clippy::derive_hash_xor_eq,
clippy::derived_hash_with_manual_eq,
clippy::too_many_arguments,
clippy::type_complexity,
clippy::single_element_loop,
Expand Down
19 changes: 12 additions & 7 deletions src/tools/miri/src/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,8 @@ pub struct MiriMachine<'mir, 'tcx> {

impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
pub(crate) fn new(config: &MiriConfig, layout_cx: LayoutCx<'tcx, TyCtxt<'tcx>>) -> Self {
let local_crates = helpers::get_local_crates(layout_cx.tcx);
let tcx = layout_cx.tcx;
let local_crates = helpers::get_local_crates(tcx);
let layouts =
PrimitiveLayouts::new(layout_cx).expect("Couldn't get layouts of primitive types");
let profiler = config.measureme_out.as_ref().map(|out| {
Expand All @@ -486,10 +487,13 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
let rng = StdRng::seed_from_u64(config.seed.unwrap_or(0));
let borrow_tracker = config.borrow_tracker.map(|bt| bt.instanciate_global_state(config));
let data_race = config.data_race_detector.then(|| data_race::GlobalState::new(config));
// Determinine page size, stack address, and stack size.
// These values are mostly meaningless, but the stack address is also where we start
// allocating physical integer addresses for all allocations.
let page_size = if let Some(page_size) = config.page_size {
page_size
} else {
let target = &layout_cx.tcx.sess.target;
let target = &tcx.sess.target;
match target.arch.as_ref() {
"wasm32" | "wasm64" => 64 * 1024, // https://webassembly.github.io/spec/core/exec/runtime.html#memory-instances
"aarch64" =>
Expand All @@ -504,10 +508,12 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
_ => 4 * 1024,
}
};
let stack_addr = page_size * 32;
let stack_size = page_size * 16;
// On 16bit targets, 32 pages is more than the entire address space!
let stack_addr = if tcx.pointer_size().bits() < 32 { page_size } else { page_size * 32 };
let stack_size =
if tcx.pointer_size().bits() < 32 { page_size * 4 } else { page_size * 16 };
MiriMachine {
tcx: layout_cx.tcx,
tcx,
borrow_tracker,
data_race,
intptrcast: RefCell::new(intptrcast::GlobalStateInner::new(config, stack_addr)),
Expand Down Expand Up @@ -902,8 +908,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
};
let (shim_size, shim_align, _kind) = ecx.get_alloc_info(alloc_id);
let def_ty = ecx.tcx.type_of(def_id).subst_identity();
let extern_decl_layout =
ecx.tcx.layout_of(ty::ParamEnv::empty().and(def_ty)).unwrap();
let extern_decl_layout = ecx.tcx.layout_of(ty::ParamEnv::empty().and(def_ty)).unwrap();
if extern_decl_layout.size != shim_size || extern_decl_layout.align.abi != shim_align {
throw_unsup_format!(
"`extern` static `{name}` from crate `{krate}` has been declared \
Expand Down
13 changes: 13 additions & 0 deletions src/tools/miri/src/shims/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -885,6 +885,19 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
}
}
}
"llvm.arm.hint" if this.tcx.sess.target.arch == "arm" => {
let [arg] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?;
let arg = this.read_scalar(arg)?.to_i32()?;
match arg {
// YIELD
1 => {
this.yield_active_thread();
}
_ => {
throw_unsup_format!("unsupported llvm.arm.hint argument {}", arg);
}
}
}

// Platform-specific shims
_ =>
Expand Down
58 changes: 57 additions & 1 deletion src/tools/miri/src/shims/unix/linux/fd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ use socketpair::SocketPair;

use shims::unix::fs::EvalContextExt as _;

use std::cell::Cell;

pub mod epoll;
pub mod event;
pub mod socketpair;
Expand Down Expand Up @@ -101,6 +103,60 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
}
}

/// The `epoll_wait()` system call waits for events on the `Epoll`
/// instance referred to by the file descriptor `epfd`. The buffer
/// pointed to by `events` is used to return information from the ready
/// list about file descriptors in the interest list that have some
/// events available. Up to `maxevents` are returned by `epoll_wait()`.
/// The `maxevents` argument must be greater than zero.

/// The `timeout` argument specifies the number of milliseconds that
/// `epoll_wait()` will block. Time is measured against the
/// CLOCK_MONOTONIC clock.

/// A call to `epoll_wait()` will block until either:
/// • a file descriptor delivers an event;
/// • the call is interrupted by a signal handler; or
/// • the timeout expires.

/// Note that the timeout interval will be rounded up to the system
/// clock granularity, and kernel scheduling delays mean that the
/// blocking interval may overrun by a small amount. Specifying a
/// timeout of -1 causes `epoll_wait()` to block indefinitely, while
/// specifying a timeout equal to zero cause `epoll_wait()` to return
/// immediately, even if no events are available.
///
/// On success, `epoll_wait()` returns the number of file descriptors
/// ready for the requested I/O, or zero if no file descriptor became
/// ready during the requested timeout milliseconds. On failure,
/// `epoll_wait()` returns -1 and errno is set to indicate the error.
///
/// <https://man7.org/linux/man-pages/man2/epoll_wait.2.html>
fn epoll_wait(
&mut self,
epfd: &OpTy<'tcx, Provenance>,
events: &OpTy<'tcx, Provenance>,
maxevents: &OpTy<'tcx, Provenance>,
timeout: &OpTy<'tcx, Provenance>,
) -> InterpResult<'tcx, Scalar<Provenance>> {
let this = self.eval_context_mut();

let epfd = this.read_scalar(epfd)?.to_i32()?;
let _events = this.read_scalar(events)?.to_pointer(this)?;
let _maxevents = this.read_scalar(maxevents)?.to_i32()?;
let _timeout = this.read_scalar(timeout)?.to_i32()?;

let numevents = 0;
if let Some(epfd) = this.machine.file_handler.handles.get_mut(&epfd) {
let _epfd = epfd.as_epoll_handle()?;

// FIXME return number of events ready when scheme for marking events ready exists
Ok(Scalar::from_i32(numevents))
} else {
Ok(Scalar::from_i32(this.handle_not_found()?))
}
}

/// This function creates an `Event` that is used as an event wait/notify mechanism by
/// user-space applications, and by the kernel to notify user-space applications of events.
/// The `Event` contains an `u64` counter maintained by the kernel. The counter is initialized
Expand Down Expand Up @@ -142,7 +198,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
}

let fh = &mut this.machine.file_handler;
let fd = fh.insert_fd(Box::new(Event { val }));
let fd = fh.insert_fd(Box::new(Event { val: Cell::new(val.into()) }));
Ok(Scalar::from_i32(fd))
}

Expand Down
35 changes: 33 additions & 2 deletions src/tools/miri/src/shims/unix/linux/fd/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::shims::unix::fs::FileDescriptor;

use rustc_const_eval::interpret::InterpResult;

use std::cell::Cell;
use std::io;

/// A kind of file descriptor created by `eventfd`.
Expand All @@ -13,7 +14,9 @@ use std::io;
/// <https://man.netbsd.org/eventfd.2>
#[derive(Debug)]
pub struct Event {
pub val: u32,
/// The object contains an unsigned 64-bit integer (uint64_t) counter that is maintained by the
/// kernel. This counter is initialized with the value specified in the argument initval.
pub val: Cell<u64>,
}

impl FileDescriptor for Event {
Expand All @@ -22,7 +25,7 @@ impl FileDescriptor for Event {
}

fn dup(&mut self) -> io::Result<Box<dyn FileDescriptor>> {
Ok(Box::new(Event { val: self.val }))
Ok(Box::new(Event { val: self.val.clone() }))
}

fn is_tty(&self) -> bool {
Expand All @@ -35,4 +38,32 @@ impl FileDescriptor for Event {
) -> InterpResult<'tcx, io::Result<i32>> {
Ok(Ok(0))
}

/// A write call adds the 8-byte integer value supplied in
/// its buffer to the counter. The maximum value that may be
/// stored in the counter is the largest unsigned 64-bit value
/// minus 1 (i.e., 0xfffffffffffffffe). If the addition would
/// cause the counter's value to exceed the maximum, then the
/// write either blocks until a read is performed on the
/// file descriptor, or fails with the error EAGAIN if the
/// file descriptor has been made nonblocking.

/// A write fails with the error EINVAL if the size of the
/// supplied buffer is less than 8 bytes, or if an attempt is
/// made to write the value 0xffffffffffffffff.
///
/// FIXME: use endianness
fn write<'tcx>(
&self,
_communicate_allowed: bool,
bytes: &[u8],
) -> InterpResult<'tcx, io::Result<usize>> {
let v1 = self.val.get();
// FIXME handle blocking when addition results in exceeding the max u64 value
// or fail with EAGAIN if the file descriptor is nonblocking.
let v2 = v1.checked_add(u64::from_be_bytes(bytes.try_into().unwrap())).unwrap();
self.val.set(v2);
assert_eq!(8, bytes.len());
Ok(Ok(8))
}
}
6 changes: 6 additions & 0 deletions src/tools/miri/src/shims/unix/linux/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let result = this.epoll_ctl(epfd, op, fd, event)?;
this.write_scalar(result, dest)?;
}
"epoll_wait" => {
let [epfd, events, maxevents, timeout] =
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let result = this.epoll_wait(epfd, events, maxevents, timeout)?;
this.write_scalar(result, dest)?;
}
"eventfd" => {
let [val, flag] =
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
Expand Down
6 changes: 3 additions & 3 deletions src/tools/miri/test-cargo-miri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,16 @@ fn main() {
// (We rely on the test runner to always disable isolation when passing no arguments.)
if std::env::args().len() <= 1 {
fn host_to_target_path(path: String) -> PathBuf {
use std::ffi::{CStr, CString};
use std::ffi::{c_char, CStr, CString};

let path = CString::new(path).unwrap();
let mut out = Vec::with_capacity(1024);

unsafe {
extern "Rust" {
fn miri_host_to_target_path(
path: *const i8,
out: *mut i8,
path: *const c_char,
out: *mut c_char,
out_size: usize,
) -> usize;
}
Expand Down
Loading

0 comments on commit 80f2908

Please sign in to comment.