Skip to content

Commit

Permalink
Auto merge of rust-lang#103721 - RalfJung:miri, r=RalfJung
Browse files Browse the repository at this point in the history
  • Loading branch information
bors committed Oct 30, 2022
2 parents b776a79 + 6bbf016 commit fbe501e
Show file tree
Hide file tree
Showing 25 changed files with 346 additions and 74 deletions.
12 changes: 4 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ on:
branches:
- 'master'
schedule:
- cron: '5 15 * * *' # At 15:05 UTC every day.
- cron: '6 6 * * *' # At 6:06 UTC every day.

env:
CARGO_UNSTABLE_SPARSE_REGISTRY: 'true'
Expand All @@ -24,16 +24,12 @@ jobs:
strategy:
fail-fast: false
matrix:
build: [linux64, macos, win32]
include:
- build: linux64
os: ubuntu-latest
- os: ubuntu-latest
host_target: x86_64-unknown-linux-gnu
- build: macos
os: macos-latest
- os: macos-latest
host_target: x86_64-apple-darwin
- build: win32
os: windows-latest
- os: windows-latest
host_target: i686-pc-windows-msvc
steps:
- uses: actions/checkout@v3
Expand Down
1 change: 1 addition & 0 deletions ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ case $HOST_TARGET in
;;
i686-pc-windows-msvc)
MIRI_TEST_TARGET=x86_64-unknown-linux-gnu run_tests
MIRI_TEST_TARGET=x86_64-pc-windows-gnu run_tests
;;
*)
echo "FATAL: unknown OS"
Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@ pub use crate::eval::{
pub use crate::helpers::{CurrentSpan, EvalContextExt as _};
pub use crate::intptrcast::ProvenanceMode;
pub use crate::machine::{
AllocExtra, FrameData, MiriInterpCx, MiriInterpCxExt, MiriMachine, MiriMemoryKind, Provenance,
ProvenanceExtra, PAGE_SIZE, STACK_ADDR, STACK_SIZE,
AllocExtra, FrameData, MiriInterpCx, MiriInterpCxExt, MiriMachine, MiriMemoryKind,
PrimitiveLayouts, Provenance, ProvenanceExtra, PAGE_SIZE, STACK_ADDR, STACK_SIZE,
};
pub use crate::mono_hash_map::MonoHashMap;
pub use crate::operator::EvalContextExt as _;
Expand Down
30 changes: 30 additions & 0 deletions src/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,10 +276,14 @@ pub struct PrimitiveLayouts<'tcx> {
pub i8: TyAndLayout<'tcx>,
pub i16: TyAndLayout<'tcx>,
pub i32: TyAndLayout<'tcx>,
pub i64: TyAndLayout<'tcx>,
pub i128: TyAndLayout<'tcx>,
pub isize: TyAndLayout<'tcx>,
pub u8: TyAndLayout<'tcx>,
pub u16: TyAndLayout<'tcx>,
pub u32: TyAndLayout<'tcx>,
pub u64: TyAndLayout<'tcx>,
pub u128: TyAndLayout<'tcx>,
pub usize: TyAndLayout<'tcx>,
pub bool: TyAndLayout<'tcx>,
pub mut_raw_ptr: TyAndLayout<'tcx>, // *mut ()
Expand All @@ -296,16 +300,42 @@ impl<'mir, 'tcx: 'mir> PrimitiveLayouts<'tcx> {
i8: layout_cx.layout_of(tcx.types.i8)?,
i16: layout_cx.layout_of(tcx.types.i16)?,
i32: layout_cx.layout_of(tcx.types.i32)?,
i64: layout_cx.layout_of(tcx.types.i64)?,
i128: layout_cx.layout_of(tcx.types.i128)?,
isize: layout_cx.layout_of(tcx.types.isize)?,
u8: layout_cx.layout_of(tcx.types.u8)?,
u16: layout_cx.layout_of(tcx.types.u16)?,
u32: layout_cx.layout_of(tcx.types.u32)?,
u64: layout_cx.layout_of(tcx.types.u64)?,
u128: layout_cx.layout_of(tcx.types.u128)?,
usize: layout_cx.layout_of(tcx.types.usize)?,
bool: layout_cx.layout_of(tcx.types.bool)?,
mut_raw_ptr: layout_cx.layout_of(mut_raw_ptr)?,
const_raw_ptr: layout_cx.layout_of(const_raw_ptr)?,
})
}

pub fn uint(&self, size: Size) -> Option<TyAndLayout<'tcx>> {
match size.bits() {
8 => Some(self.u8),
16 => Some(self.u16),
32 => Some(self.u32),
64 => Some(self.u64),
128 => Some(self.u128),
_ => None,
}
}

pub fn int(&self, size: Size) -> Option<TyAndLayout<'tcx>> {
match size.bits() {
8 => Some(self.i8),
16 => Some(self.i16),
32 => Some(self.i32),
64 => Some(self.i64),
128 => Some(self.i128),
_ => None,
}
}
}

/// The machine itself.
Expand Down
13 changes: 12 additions & 1 deletion src/shims/intrinsics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use rustc_middle::{
mir,
ty::{self, FloatTy, Ty},
};
use rustc_target::abi::Integer;
use rustc_target::abi::{Integer, Size};

use crate::*;
use atomic::EvalContextExt as _;
Expand Down Expand Up @@ -120,6 +120,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
this.write_bytes_ptr(ptr, iter::repeat(val_byte).take(byte_count.bytes_usize()))?;
}

"ptr_mask" => {
let [ptr, mask] = check_arg_count(args)?;

let ptr = this.read_pointer(ptr)?;
let mask = this.read_scalar(mask)?.to_machine_usize(this)?;

let masked_addr = Size::from_bytes(ptr.addr().bytes() & mask);

this.write_pointer(Pointer::new(ptr.provenance, masked_addr), dest)?;
}

// Floating-point operations
"fabsf32" => {
let [f] = check_arg_count(args)?;
Expand Down
40 changes: 13 additions & 27 deletions src/shims/unix/linux/sync.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::time::SystemTime;

use crate::concurrency::thread::{MachineCallback, Time};
use crate::*;
use rustc_target::abi::{Align, Size};
use std::time::SystemTime;

/// Implementation of the SYS_futex syscall.
/// `args` is the arguments *after* the syscall number.
Expand All @@ -28,13 +28,14 @@ pub fn futex<'tcx>(
// The first three arguments (after the syscall number itself) are the same to all futex operations:
// (int *addr, int op, int val).
// We checked above that these definitely exist.
let addr = this.read_immediate(&args[0])?;
let addr = this.read_pointer(&args[0])?;
let op = this.read_scalar(&args[1])?.to_i32()?;
let val = this.read_scalar(&args[2])?.to_i32()?;

let thread = this.get_active_thread();
let addr_scalar = addr.to_scalar();
let addr_usize = addr_scalar.to_machine_usize(this)?;
// This is a vararg function so we have to bring our own type for this pointer.
let addr = MPlaceTy::from_aligned_ptr(addr, this.machine.layouts.i32);
let addr_usize = addr.ptr.addr().bytes();

let futex_private = this.eval_libc_i32("FUTEX_PRIVATE_FLAG")?;
let futex_wait = this.eval_libc_i32("FUTEX_WAIT")?;
Expand Down Expand Up @@ -89,9 +90,11 @@ pub fn futex<'tcx>(
let timeout_time = if this.ptr_is_null(timeout.ptr)? {
None
} else {
this.check_no_isolation(
"`futex` syscall with `op=FUTEX_WAIT` and non-null timeout",
)?;
if op & futex_realtime != 0 {
this.check_no_isolation(
"`futex` syscall with `op=FUTEX_WAIT` and non-null timeout with `FUTEX_CLOCK_REALTIME`",
)?;
}
let duration = match this.read_timespec(&timeout)? {
Some(duration) => duration,
None => {
Expand All @@ -117,15 +120,6 @@ pub fn futex<'tcx>(
}
})
};
// Check the pointer for alignment and validity.
// The API requires `addr` to be a 4-byte aligned pointer, and will
// use the 4 bytes at the given address as an (atomic) i32.
this.check_ptr_access_align(
addr_scalar.to_pointer(this)?,
Size::from_bytes(4),
Align::from_bytes(4).unwrap(),
CheckInAllocMsg::MemoryAccessTest,
)?;
// There may be a concurrent thread changing the value of addr
// and then invoking the FUTEX_WAKE syscall. It is critical that the
// effects of this and the other thread are correctly observed,
Expand Down Expand Up @@ -172,14 +166,7 @@ pub fn futex<'tcx>(
this.atomic_fence(AtomicFenceOrd::SeqCst)?;
// Read an `i32` through the pointer, regardless of any wrapper types.
// It's not uncommon for `addr` to be passed as another type than `*mut i32`, such as `*const AtomicI32`.
let futex_val = this
.read_scalar_at_offset_atomic(
&addr.into(),
0,
this.machine.layouts.i32,
AtomicReadOrd::Relaxed,
)?
.to_i32()?;
let futex_val = this.read_scalar_atomic(&addr, AtomicReadOrd::Relaxed)?.to_i32()?;
if val == futex_val {
// The value still matches, so we block the thread make it wait for FUTEX_WAKE.
this.block_thread(thread);
Expand Down Expand Up @@ -214,11 +201,10 @@ pub fn futex<'tcx>(
}
}

let dest = dest.clone();
this.register_timeout_callback(
thread,
timeout_time,
Box::new(Callback { thread, addr_usize, dest }),
Box::new(Callback { thread, addr_usize, dest: dest.clone() }),
);
}
} else {
Expand Down
5 changes: 4 additions & 1 deletion src/shims/unix/macos/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,11 +177,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let [name] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let thread = this.pthread_self()?;
let max_len = this.eval_libc("MAXTHREADNAMESIZE")?.to_machine_usize(this)?;
this.pthread_setname_np(
let res = this.pthread_setname_np(
thread,
this.read_scalar(name)?,
max_len.try_into().unwrap(),
)?;
// Contrary to the manpage, `pthread_setname_np` on macOS still
// returns an integer indicating success.
this.write_scalar(res, dest)?;
}
"pthread_getname_np" => {
let [thread, name, len] =
Expand Down
3 changes: 1 addition & 2 deletions src/shims/unix/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -743,8 +743,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
) -> InterpResult<'tcx> {
let this = self.eval_context_mut();

this.check_no_isolation("`pthread_cond_timedwait`")?;

let id = this.condvar_get_or_create_id(cond_op, CONDVAR_ID_OFFSET)?;
let mutex_id = this.mutex_get_or_create_id(mutex_op, MUTEX_ID_OFFSET)?;
let active_thread = this.get_active_thread();
Expand All @@ -761,6 +759,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
};

let timeout_time = if clock_id == this.eval_libc_i32("CLOCK_REALTIME")? {
this.check_no_isolation("`pthread_cond_timedwait` with `CLOCK_REALTIME`")?;
Time::RealTime(SystemTime::UNIX_EPOCH.checked_add(duration).unwrap())
} else if clock_id == this.eval_libc_i32("CLOCK_MONOTONIC")? {
Time::Monotonic(this.machine.clock.anchor().checked_add(duration).unwrap())
Expand Down
15 changes: 15 additions & 0 deletions src/shims/windows/dlsym.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@ use log::trace;

use crate::helpers::check_arg_count;
use crate::shims::windows::handle::{EvalContextExt as _, Handle, PseudoHandle};
use crate::shims::windows::sync::EvalContextExt as _;
use crate::*;

#[derive(Debug, Copy, Clone)]
pub enum Dlsym {
NtWriteFile,
SetThreadDescription,
WaitOnAddress,
WakeByAddressSingle,
}

impl Dlsym {
Expand All @@ -22,6 +25,8 @@ impl Dlsym {
"GetSystemTimePreciseAsFileTime" => None,
"NtWriteFile" => Some(Dlsym::NtWriteFile),
"SetThreadDescription" => Some(Dlsym::SetThreadDescription),
"WaitOnAddress" => Some(Dlsym::WaitOnAddress),
"WakeByAddressSingle" => Some(Dlsym::WakeByAddressSingle),
_ => throw_unsup_format!("unsupported Windows dlsym: {}", name),
})
}
Expand Down Expand Up @@ -127,6 +132,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {

this.write_null(dest)?;
}
Dlsym::WaitOnAddress => {
let [ptr_op, compare_op, size_op, timeout_op] = check_arg_count(args)?;

this.WaitOnAddress(ptr_op, compare_op, size_op, timeout_op, dest)?;
}
Dlsym::WakeByAddressSingle => {
let [ptr_op] = check_arg_count(args)?;

this.WakeByAddressSingle(ptr_op)?;
}
}

trace!("{:?}", this.dump_place(**dest));
Expand Down
Loading

0 comments on commit fbe501e

Please sign in to comment.