Auto merge of #2661 - DrMeepster:deref_operand_as, r=oli-obk
Dereference pointers in shims as correct types Currently, shims will dereference pointers as the type written by the user. This can cause false positives, incorrect behavior such as #2136, and even ICEs if a field is not present. This PR fixes this by having shims dereference pointers with types from `std` or `libc` that we can rely on the layout and field names of instead of with whatever the user passed in. Fixes #1123
This commit is contained in:
commit
b4b7cd63d7
14 changed files with 233 additions and 125 deletions
|
|
@ -2,6 +2,7 @@ use std::collections::VecDeque;
|
|||
use std::num::NonZeroU32;
|
||||
|
||||
use rustc_index::Idx;
|
||||
use rustc_middle::ty::layout::TyAndLayout;
|
||||
|
||||
use super::sync::EvalContextExtPriv as _;
|
||||
use super::thread::MachineCallback;
|
||||
|
|
@ -94,10 +95,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
fn init_once_get_or_create_id(
|
||||
&mut self,
|
||||
lock_op: &OpTy<'tcx, Provenance>,
|
||||
lock_layout: TyAndLayout<'tcx>,
|
||||
offset: u64,
|
||||
) -> InterpResult<'tcx, InitOnceId> {
|
||||
let this = self.eval_context_mut();
|
||||
this.init_once_get_or_create(|ecx, next_id| ecx.get_or_create_id(next_id, lock_op, offset))
|
||||
this.init_once_get_or_create(|ecx, next_id| {
|
||||
ecx.get_or_create_id(next_id, lock_op, lock_layout, offset)
|
||||
})
|
||||
}
|
||||
|
||||
/// Provides the closure with the next InitOnceId. Creates that InitOnce if the closure returns None,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ use log::trace;
|
|||
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_index::{Idx, IndexVec};
|
||||
use rustc_middle::ty::layout::TyAndLayout;
|
||||
|
||||
use super::init_once::InitOnce;
|
||||
use super::vector_clock::VClock;
|
||||
|
|
@ -200,11 +201,12 @@ pub(super) trait EvalContextExtPriv<'mir, 'tcx: 'mir>:
|
|||
&mut self,
|
||||
next_id: Id,
|
||||
lock_op: &OpTy<'tcx, Provenance>,
|
||||
lock_layout: TyAndLayout<'tcx>,
|
||||
offset: u64,
|
||||
) -> InterpResult<'tcx, Option<Id>> {
|
||||
let this = self.eval_context_mut();
|
||||
let value_place =
|
||||
this.deref_operand_and_offset(lock_op, offset, this.machine.layouts.u32)?;
|
||||
this.deref_operand_and_offset(lock_op, offset, lock_layout, this.machine.layouts.u32)?;
|
||||
|
||||
// Since we are lazy, this update has to be atomic.
|
||||
let (old, success) = this
|
||||
|
|
@ -278,28 +280,37 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
fn mutex_get_or_create_id(
|
||||
&mut self,
|
||||
lock_op: &OpTy<'tcx, Provenance>,
|
||||
lock_layout: TyAndLayout<'tcx>,
|
||||
offset: u64,
|
||||
) -> InterpResult<'tcx, MutexId> {
|
||||
let this = self.eval_context_mut();
|
||||
this.mutex_get_or_create(|ecx, next_id| ecx.get_or_create_id(next_id, lock_op, offset))
|
||||
this.mutex_get_or_create(|ecx, next_id| {
|
||||
ecx.get_or_create_id(next_id, lock_op, lock_layout, offset)
|
||||
})
|
||||
}
|
||||
|
||||
fn rwlock_get_or_create_id(
|
||||
&mut self,
|
||||
lock_op: &OpTy<'tcx, Provenance>,
|
||||
lock_layout: TyAndLayout<'tcx>,
|
||||
offset: u64,
|
||||
) -> InterpResult<'tcx, RwLockId> {
|
||||
let this = self.eval_context_mut();
|
||||
this.rwlock_get_or_create(|ecx, next_id| ecx.get_or_create_id(next_id, lock_op, offset))
|
||||
this.rwlock_get_or_create(|ecx, next_id| {
|
||||
ecx.get_or_create_id(next_id, lock_op, lock_layout, offset)
|
||||
})
|
||||
}
|
||||
|
||||
fn condvar_get_or_create_id(
|
||||
&mut self,
|
||||
lock_op: &OpTy<'tcx, Provenance>,
|
||||
lock_layout: TyAndLayout<'tcx>,
|
||||
offset: u64,
|
||||
) -> InterpResult<'tcx, CondvarId> {
|
||||
let this = self.eval_context_mut();
|
||||
this.condvar_get_or_create(|ecx, next_id| ecx.get_or_create_id(next_id, lock_op, offset))
|
||||
this.condvar_get_or_create(|ecx, next_id| {
|
||||
ecx.get_or_create_id(next_id, lock_op, lock_layout, offset)
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
|||
|
|
@ -730,20 +730,51 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Dereference a pointer operand to a place using `layout` instead of the pointer's declared type
|
||||
fn deref_operand_as(
|
||||
&self,
|
||||
op: &OpTy<'tcx, Provenance>,
|
||||
layout: TyAndLayout<'tcx>,
|
||||
) -> InterpResult<'tcx, MPlaceTy<'tcx, Provenance>> {
|
||||
let this = self.eval_context_ref();
|
||||
let ptr = this.read_pointer(op)?;
|
||||
|
||||
let mplace = MPlaceTy::from_aligned_ptr(ptr, layout);
|
||||
|
||||
this.check_mplace(mplace)?;
|
||||
|
||||
Ok(mplace)
|
||||
}
|
||||
|
||||
fn deref_pointer_as(
|
||||
&self,
|
||||
val: &ImmTy<'tcx, Provenance>,
|
||||
layout: TyAndLayout<'tcx>,
|
||||
) -> InterpResult<'tcx, MPlaceTy<'tcx, Provenance>> {
|
||||
let this = self.eval_context_ref();
|
||||
let mut mplace = this.ref_to_mplace(val)?;
|
||||
|
||||
mplace.layout = layout;
|
||||
mplace.align = layout.align.abi;
|
||||
|
||||
Ok(mplace)
|
||||
}
|
||||
|
||||
/// Calculates the MPlaceTy given the offset and layout of an access on an operand
|
||||
fn deref_operand_and_offset(
|
||||
&self,
|
||||
op: &OpTy<'tcx, Provenance>,
|
||||
offset: u64,
|
||||
layout: TyAndLayout<'tcx>,
|
||||
base_layout: TyAndLayout<'tcx>,
|
||||
value_layout: TyAndLayout<'tcx>,
|
||||
) -> InterpResult<'tcx, MPlaceTy<'tcx, Provenance>> {
|
||||
let this = self.eval_context_ref();
|
||||
let op_place = this.deref_operand(op)?; // FIXME: we still deref with the original type!
|
||||
let op_place = this.deref_operand_as(op, base_layout)?;
|
||||
let offset = Size::from_bytes(offset);
|
||||
|
||||
// Ensure that the access is within bounds.
|
||||
assert!(op_place.layout.size >= offset + layout.size);
|
||||
let value_place = op_place.offset(offset, layout, this)?;
|
||||
assert!(base_layout.size >= offset + value_layout.size);
|
||||
let value_place = op_place.offset(offset, value_layout, this)?;
|
||||
Ok(value_place)
|
||||
}
|
||||
|
||||
|
|
@ -751,10 +782,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
&self,
|
||||
op: &OpTy<'tcx, Provenance>,
|
||||
offset: u64,
|
||||
layout: TyAndLayout<'tcx>,
|
||||
base_layout: TyAndLayout<'tcx>,
|
||||
value_layout: TyAndLayout<'tcx>,
|
||||
) -> InterpResult<'tcx, Scalar<Provenance>> {
|
||||
let this = self.eval_context_ref();
|
||||
let value_place = this.deref_operand_and_offset(op, offset, layout)?;
|
||||
let value_place = this.deref_operand_and_offset(op, offset, base_layout, value_layout)?;
|
||||
this.read_scalar(&value_place.into())
|
||||
}
|
||||
|
||||
|
|
@ -763,10 +795,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
op: &OpTy<'tcx, Provenance>,
|
||||
offset: u64,
|
||||
value: impl Into<Scalar<Provenance>>,
|
||||
layout: TyAndLayout<'tcx>,
|
||||
base_layout: TyAndLayout<'tcx>,
|
||||
value_layout: TyAndLayout<'tcx>,
|
||||
) -> InterpResult<'tcx, ()> {
|
||||
let this = self.eval_context_mut();
|
||||
let value_place = this.deref_operand_and_offset(op, offset, layout)?;
|
||||
let value_place = this.deref_operand_and_offset(op, offset, base_layout, value_layout)?;
|
||||
this.write_scalar(value, &value_place.into())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -409,14 +409,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
// &mut self,
|
||||
// arg1: &OpTy<'tcx, Provenance>,
|
||||
// arg2: &OpTy<'tcx, Provenance>,
|
||||
// arg3: &OpTy<'tcx, Provenance>)
|
||||
// arg3: &OpTy<'tcx, Provenance>,
|
||||
// arg4: &OpTy<'tcx, Provenance>)
|
||||
// -> InterpResult<'tcx, Scalar<Provenance>> {
|
||||
// let this = self.eval_context_mut();
|
||||
//
|
||||
// // First thing: load all the arguments. Details depend on the shim.
|
||||
// let arg1 = this.read_scalar(arg1)?.to_u32()?;
|
||||
// let arg2 = this.read_pointer(arg2)?; // when you need to work with the pointer directly
|
||||
// let arg3 = this.deref_operand(arg3)?; // when you want to load/store through the pointer at its declared type
|
||||
// let arg3 = this.deref_operand(arg3)?; // when you want to load/store through the pointer
|
||||
// let arg4 = this.deref_operand_as(arg4, this.libc_ty_layout("some_libc_struct")?)
|
||||
//
|
||||
// // ...
|
||||
//
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
this.assert_target_os_is_unix("clock_gettime");
|
||||
|
||||
let clk_id = this.read_scalar(clk_id_op)?.to_i32()?;
|
||||
let tp = this.deref_operand_as(tp_op, this.libc_ty_layout("timespec"))?;
|
||||
|
||||
let absolute_clocks;
|
||||
let mut relative_clocks;
|
||||
|
|
@ -76,7 +77,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
let tv_sec = duration.as_secs();
|
||||
let tv_nsec = duration.subsec_nanos();
|
||||
|
||||
this.write_int_fields(&[tv_sec.into(), tv_nsec.into()], &this.deref_operand(tp_op)?)?;
|
||||
this.write_int_fields(&[tv_sec.into(), tv_nsec.into()], &tp)?;
|
||||
|
||||
Ok(Scalar::from_i32(0))
|
||||
}
|
||||
|
|
@ -91,6 +92,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
this.assert_target_os_is_unix("gettimeofday");
|
||||
this.check_no_isolation("`gettimeofday`")?;
|
||||
|
||||
let tv = this.deref_operand_as(tv_op, this.libc_ty_layout("timeval"))?;
|
||||
|
||||
// Using tz is obsolete and should always be null
|
||||
let tz = this.read_pointer(tz_op)?;
|
||||
if !this.ptr_is_null(tz)? {
|
||||
|
|
@ -103,7 +106,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
let tv_sec = duration.as_secs();
|
||||
let tv_usec = duration.subsec_micros();
|
||||
|
||||
this.write_int_fields(&[tv_sec.into(), tv_usec.into()], &this.deref_operand(tv_op)?)?;
|
||||
this.write_int_fields(&[tv_sec.into(), tv_usec.into()], &tv)?;
|
||||
|
||||
Ok(0)
|
||||
}
|
||||
|
|
@ -118,6 +121,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
this.assert_target_os("windows", "GetSystemTimeAsFileTime");
|
||||
this.check_no_isolation("`GetSystemTimeAsFileTime`")?;
|
||||
|
||||
let filetime = this.deref_operand_as(LPFILETIME_op, this.windows_ty_layout("FILETIME"))?;
|
||||
|
||||
let NANOS_PER_SEC = this.eval_windows_u64("time", "NANOS_PER_SEC");
|
||||
let INTERVALS_PER_SEC = this.eval_windows_u64("time", "INTERVALS_PER_SEC");
|
||||
let INTERVALS_TO_UNIX_EPOCH = this.eval_windows_u64("time", "INTERVALS_TO_UNIX_EPOCH");
|
||||
|
|
@ -131,10 +136,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
|
||||
let dwLowDateTime = u32::try_from(duration_ticks & 0x00000000FFFFFFFF).unwrap();
|
||||
let dwHighDateTime = u32::try_from((duration_ticks & 0xFFFFFFFF00000000) >> 32).unwrap();
|
||||
this.write_int_fields(
|
||||
&[dwLowDateTime.into(), dwHighDateTime.into()],
|
||||
&this.deref_operand(LPFILETIME_op)?,
|
||||
)?;
|
||||
this.write_int_fields(&[dwLowDateTime.into(), dwHighDateTime.into()], &filetime)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -177,7 +179,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
// and thus 10^9 counts per second.
|
||||
this.write_scalar(
|
||||
Scalar::from_i64(1_000_000_000),
|
||||
&this.deref_operand(lpFrequency_op)?.into(),
|
||||
&this.deref_operand_as(lpFrequency_op, this.machine.layouts.u64)?.into(),
|
||||
)?;
|
||||
Ok(Scalar::from_i32(-1)) // Return non-zero on success
|
||||
}
|
||||
|
|
@ -204,7 +206,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
|
||||
this.assert_target_os("macos", "mach_timebase_info");
|
||||
|
||||
let info = this.deref_operand(info_op)?;
|
||||
let info = this.deref_operand_as(info_op, this.libc_ty_layout("mach_timebase_info"))?;
|
||||
|
||||
// Since our emulated ticks in `mach_absolute_time` *are* nanoseconds,
|
||||
// no scaling needs to happen.
|
||||
|
|
@ -223,7 +225,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
|
||||
this.assert_target_os_is_unix("nanosleep");
|
||||
|
||||
let duration = match this.read_timespec(&this.deref_operand(req_op)?)? {
|
||||
let req = this.deref_operand_as(req_op, this.libc_ty_layout("timespec"))?;
|
||||
|
||||
let duration = match this.read_timespec(&req)? {
|
||||
Some(duration) => duration,
|
||||
None => {
|
||||
let einval = this.eval_libc("EINVAL");
|
||||
|
|
|
|||
|
|
@ -259,7 +259,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
// Thread-local storage
|
||||
"pthread_key_create" => {
|
||||
let [key, dtor] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
|
||||
let key_place = this.deref_operand(key)?;
|
||||
let key_place = this.deref_operand_as(key, this.libc_ty_layout("pthread_key_t"))?;
|
||||
let dtor = this.read_pointer(dtor)?;
|
||||
|
||||
// Extract the function type out of the signature (that seems easier than constructing it ourselves).
|
||||
|
|
@ -520,7 +520,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
// Hence we can mostly ignore the input `attr_place`.
|
||||
let [attr_place, addr_place, size_place] =
|
||||
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
|
||||
let _attr_place = this.deref_operand(attr_place)?;
|
||||
let _attr_place = this.deref_operand_as(attr_place, this.libc_ty_layout("pthread_attr_t"))?;
|
||||
let addr_place = this.deref_operand(addr_place)?;
|
||||
let size_place = this.deref_operand(size_place)?;
|
||||
|
||||
|
|
@ -563,7 +563,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
this.check_no_isolation("`getpwuid_r`")?;
|
||||
|
||||
let uid = this.read_scalar(uid)?.to_u32()?;
|
||||
let pwd = this.deref_operand(pwd)?;
|
||||
let pwd = this.deref_operand_as(pwd, this.libc_ty_layout("passwd"))?;
|
||||
let buf = this.read_pointer(buf)?;
|
||||
let buflen = this.read_target_usize(buflen)?;
|
||||
let result = this.deref_operand(result)?;
|
||||
|
|
|
|||
|
|
@ -344,7 +344,8 @@ trait EvalContextExtPrivate<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx
|
|||
let (created_sec, created_nsec) = metadata.created.unwrap_or((0, 0));
|
||||
let (modified_sec, modified_nsec) = metadata.modified.unwrap_or((0, 0));
|
||||
|
||||
let buf = this.deref_operand(buf_op)?;
|
||||
let buf = this.deref_operand_as(buf_op, this.libc_ty_layout("stat"))?;
|
||||
|
||||
this.write_int_fields_named(
|
||||
&[
|
||||
("st_dev", 0),
|
||||
|
|
@ -1013,15 +1014,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
return Ok(-1);
|
||||
}
|
||||
|
||||
// Under normal circumstances, we would use `deref_operand(statxbuf_op)` to produce a
|
||||
// proper `MemPlace` and then write the results of this function to it. However, the
|
||||
// `syscall` function is untyped. This means that all the `statx` parameters are provided
|
||||
// as `isize`s instead of having the proper types. Thus, we have to recover the layout of
|
||||
// `statxbuf_op` by using the `libc::statx` struct type.
|
||||
let statxbuf = {
|
||||
let statx_layout = this.libc_ty_layout("statx");
|
||||
MPlaceTy::from_aligned_ptr(statxbuf_ptr, statx_layout)
|
||||
};
|
||||
let statxbuf = this.deref_operand_as(statxbuf_op, this.libc_ty_layout("statx"))?;
|
||||
|
||||
let path = this.read_path_from_c_str(pathname_ptr)?.into_owned();
|
||||
// See <https://github.com/rust-lang/rust/pull/79196> for a discussion of argument sizes.
|
||||
|
|
@ -1427,7 +1420,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
// pub d_name: [c_char; 1024],
|
||||
// }
|
||||
|
||||
let entry_place = this.deref_operand(entry_op)?;
|
||||
let entry_place = this.deref_operand_as(entry_op, this.libc_ty_layout("dirent"))?;
|
||||
let name_place = this.mplace_field(&entry_place, 5)?;
|
||||
|
||||
let file_name = dir_entry.file_name(); // not a Path as there are no separators!
|
||||
|
|
@ -1443,8 +1436,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
);
|
||||
}
|
||||
|
||||
let entry_place = this.deref_operand(entry_op)?;
|
||||
|
||||
// If the host is a Unix system, fill in the inode number with its real value.
|
||||
// If not, use 0 as a fallback value.
|
||||
#[cfg(unix)]
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
let epoll_ctl_del = this.eval_libc_i32("EPOLL_CTL_DEL");
|
||||
|
||||
if op == epoll_ctl_add || op == epoll_ctl_mod {
|
||||
let event = this.deref_operand(event)?;
|
||||
let event = this.deref_operand_as(event, this.libc_ty_layout("epoll_event"))?;
|
||||
|
||||
let events = this.mplace_field(&event, 0)?;
|
||||
let events = this.read_scalar(&events.into())?.to_u32()?;
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
|
||||
this.read_scalar(pid)?.to_i32()?;
|
||||
this.read_target_usize(cpusetsize)?;
|
||||
this.deref_operand(mask)?;
|
||||
this.deref_operand_as(mask, this.libc_ty_layout("cpu_set_t"))?;
|
||||
// FIXME: we just return an error; `num_cpus` then falls back to `sysconf`.
|
||||
let einval = this.eval_libc("EINVAL");
|
||||
this.set_last_error(einval)?;
|
||||
|
|
|
|||
|
|
@ -85,8 +85,10 @@ pub fn futex<'tcx>(
|
|||
return Ok(());
|
||||
}
|
||||
|
||||
// `deref_operand` but not actually dereferencing the ptr yet (it might be NULL!).
|
||||
let timeout = this.ref_to_mplace(&this.read_immediate(&args[3])?)?;
|
||||
let timeout = this.deref_pointer_as(
|
||||
&this.read_immediate(&args[3])?,
|
||||
this.libc_ty_layout("timespec"),
|
||||
)?;
|
||||
let timeout_time = if this.ptr_is_null(timeout.ptr)? {
|
||||
None
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -36,7 +36,13 @@ fn mutexattr_get_kind<'mir, 'tcx: 'mir>(
|
|||
ecx: &MiriInterpCx<'mir, 'tcx>,
|
||||
attr_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
ecx.read_scalar_at_offset(attr_op, 0, ecx.machine.layouts.i32)?.to_i32()
|
||||
ecx.read_scalar_at_offset(
|
||||
attr_op,
|
||||
0,
|
||||
ecx.libc_ty_layout("pthread_mutexattr_t"),
|
||||
ecx.machine.layouts.i32,
|
||||
)?
|
||||
.to_i32()
|
||||
}
|
||||
|
||||
fn mutexattr_set_kind<'mir, 'tcx: 'mir>(
|
||||
|
|
@ -44,7 +50,13 @@ fn mutexattr_set_kind<'mir, 'tcx: 'mir>(
|
|||
attr_op: &OpTy<'tcx, Provenance>,
|
||||
kind: i32,
|
||||
) -> InterpResult<'tcx, ()> {
|
||||
ecx.write_scalar_at_offset(attr_op, 0, Scalar::from_i32(kind), ecx.machine.layouts.i32)
|
||||
ecx.write_scalar_at_offset(
|
||||
attr_op,
|
||||
0,
|
||||
Scalar::from_i32(kind),
|
||||
ecx.libc_ty_layout("pthread_mutexattr_t"),
|
||||
ecx.machine.layouts.i32,
|
||||
)
|
||||
}
|
||||
|
||||
// pthread_mutex_t is between 24 and 48 bytes, depending on the platform.
|
||||
|
|
@ -60,14 +72,20 @@ fn mutex_get_id<'mir, 'tcx: 'mir>(
|
|||
ecx: &mut MiriInterpCx<'mir, 'tcx>,
|
||||
mutex_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, MutexId> {
|
||||
ecx.mutex_get_or_create_id(mutex_op, 4)
|
||||
ecx.mutex_get_or_create_id(mutex_op, ecx.libc_ty_layout("pthread_mutex_t"), 4)
|
||||
}
|
||||
|
||||
fn mutex_reset_id<'mir, 'tcx: 'mir>(
|
||||
ecx: &mut MiriInterpCx<'mir, 'tcx>,
|
||||
mutex_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, ()> {
|
||||
ecx.write_scalar_at_offset(mutex_op, 4, Scalar::from_i32(0), ecx.machine.layouts.u32)
|
||||
ecx.write_scalar_at_offset(
|
||||
mutex_op,
|
||||
4,
|
||||
Scalar::from_i32(0),
|
||||
ecx.libc_ty_layout("pthread_mutex_t"),
|
||||
ecx.machine.layouts.u32,
|
||||
)
|
||||
}
|
||||
|
||||
fn mutex_get_kind<'mir, 'tcx: 'mir>(
|
||||
|
|
@ -75,7 +93,13 @@ fn mutex_get_kind<'mir, 'tcx: 'mir>(
|
|||
mutex_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let offset = if ecx.pointer_size().bytes() == 8 { 16 } else { 12 };
|
||||
ecx.read_scalar_at_offset(mutex_op, offset, ecx.machine.layouts.i32)?.to_i32()
|
||||
ecx.read_scalar_at_offset(
|
||||
mutex_op,
|
||||
offset,
|
||||
ecx.libc_ty_layout("pthread_mutex_t"),
|
||||
ecx.machine.layouts.i32,
|
||||
)?
|
||||
.to_i32()
|
||||
}
|
||||
|
||||
fn mutex_set_kind<'mir, 'tcx: 'mir>(
|
||||
|
|
@ -84,7 +108,13 @@ fn mutex_set_kind<'mir, 'tcx: 'mir>(
|
|||
kind: i32,
|
||||
) -> InterpResult<'tcx, ()> {
|
||||
let offset = if ecx.pointer_size().bytes() == 8 { 16 } else { 12 };
|
||||
ecx.write_scalar_at_offset(mutex_op, offset, Scalar::from_i32(kind), ecx.machine.layouts.i32)
|
||||
ecx.write_scalar_at_offset(
|
||||
mutex_op,
|
||||
offset,
|
||||
Scalar::from_i32(kind),
|
||||
ecx.libc_ty_layout("pthread_mutex_t"),
|
||||
ecx.machine.layouts.i32,
|
||||
)
|
||||
}
|
||||
|
||||
// pthread_rwlock_t is between 32 and 56 bytes, depending on the platform.
|
||||
|
|
@ -98,7 +128,7 @@ fn rwlock_get_id<'mir, 'tcx: 'mir>(
|
|||
ecx: &mut MiriInterpCx<'mir, 'tcx>,
|
||||
rwlock_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, RwLockId> {
|
||||
ecx.rwlock_get_or_create_id(rwlock_op, 4)
|
||||
ecx.rwlock_get_or_create_id(rwlock_op, ecx.libc_ty_layout("pthread_rwlock_t"), 4)
|
||||
}
|
||||
|
||||
// pthread_condattr_t
|
||||
|
|
@ -111,7 +141,13 @@ fn condattr_get_clock_id<'mir, 'tcx: 'mir>(
|
|||
ecx: &MiriInterpCx<'mir, 'tcx>,
|
||||
attr_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
ecx.read_scalar_at_offset(attr_op, 0, ecx.machine.layouts.i32)?.to_i32()
|
||||
ecx.read_scalar_at_offset(
|
||||
attr_op,
|
||||
0,
|
||||
ecx.libc_ty_layout("pthread_condattr_t"),
|
||||
ecx.machine.layouts.i32,
|
||||
)?
|
||||
.to_i32()
|
||||
}
|
||||
|
||||
fn condattr_set_clock_id<'mir, 'tcx: 'mir>(
|
||||
|
|
@ -119,7 +155,13 @@ fn condattr_set_clock_id<'mir, 'tcx: 'mir>(
|
|||
attr_op: &OpTy<'tcx, Provenance>,
|
||||
clock_id: i32,
|
||||
) -> InterpResult<'tcx, ()> {
|
||||
ecx.write_scalar_at_offset(attr_op, 0, Scalar::from_i32(clock_id), ecx.machine.layouts.i32)
|
||||
ecx.write_scalar_at_offset(
|
||||
attr_op,
|
||||
0,
|
||||
Scalar::from_i32(clock_id),
|
||||
ecx.libc_ty_layout("pthread_condattr_t"),
|
||||
ecx.machine.layouts.i32,
|
||||
)
|
||||
}
|
||||
|
||||
// pthread_cond_t
|
||||
|
|
@ -135,21 +177,33 @@ fn cond_get_id<'mir, 'tcx: 'mir>(
|
|||
ecx: &mut MiriInterpCx<'mir, 'tcx>,
|
||||
cond_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, CondvarId> {
|
||||
ecx.condvar_get_or_create_id(cond_op, 4)
|
||||
ecx.condvar_get_or_create_id(cond_op, ecx.libc_ty_layout("pthread_cond_t"), 4)
|
||||
}
|
||||
|
||||
fn cond_reset_id<'mir, 'tcx: 'mir>(
|
||||
ecx: &mut MiriInterpCx<'mir, 'tcx>,
|
||||
cond_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, ()> {
|
||||
ecx.write_scalar_at_offset(cond_op, 4, Scalar::from_i32(0), ecx.machine.layouts.u32)
|
||||
ecx.write_scalar_at_offset(
|
||||
cond_op,
|
||||
4,
|
||||
Scalar::from_i32(0),
|
||||
ecx.libc_ty_layout("pthread_cond_t"),
|
||||
ecx.machine.layouts.u32,
|
||||
)
|
||||
}
|
||||
|
||||
fn cond_get_clock_id<'mir, 'tcx: 'mir>(
|
||||
ecx: &MiriInterpCx<'mir, 'tcx>,
|
||||
cond_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
ecx.read_scalar_at_offset(cond_op, 8, ecx.machine.layouts.i32)?.to_i32()
|
||||
ecx.read_scalar_at_offset(
|
||||
cond_op,
|
||||
8,
|
||||
ecx.libc_ty_layout("pthread_cond_t"),
|
||||
ecx.machine.layouts.i32,
|
||||
)?
|
||||
.to_i32()
|
||||
}
|
||||
|
||||
fn cond_set_clock_id<'mir, 'tcx: 'mir>(
|
||||
|
|
@ -157,7 +211,13 @@ fn cond_set_clock_id<'mir, 'tcx: 'mir>(
|
|||
cond_op: &OpTy<'tcx, Provenance>,
|
||||
clock_id: i32,
|
||||
) -> InterpResult<'tcx, ()> {
|
||||
ecx.write_scalar_at_offset(cond_op, 8, Scalar::from_i32(clock_id), ecx.machine.layouts.i32)
|
||||
ecx.write_scalar_at_offset(
|
||||
cond_op,
|
||||
8,
|
||||
Scalar::from_i32(clock_id),
|
||||
ecx.libc_ty_layout("pthread_cond_t"),
|
||||
ecx.machine.layouts.i32,
|
||||
)
|
||||
}
|
||||
|
||||
/// Try to reacquire the mutex associated with the condition variable after we
|
||||
|
|
@ -285,7 +345,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
// However, the way libstd uses the pthread APIs works in our favor here, so we can get away with this.
|
||||
// This can always be revisited to have some external state to catch double-destroys
|
||||
// but not complain about the above code. See https://github.com/rust-lang/miri/pull/1933
|
||||
this.write_uninit(&this.deref_operand(attr_op)?.into())?;
|
||||
this.write_uninit(
|
||||
&this.deref_operand_as(attr_op, this.libc_ty_layout("pthread_mutexattr_t"))?.into(),
|
||||
)?;
|
||||
|
||||
Ok(0)
|
||||
}
|
||||
|
|
@ -437,7 +499,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
mutex_get_id(this, mutex_op)?;
|
||||
|
||||
// This might lead to false positives, see comment in pthread_mutexattr_destroy
|
||||
this.write_uninit(&this.deref_operand(mutex_op)?.into())?;
|
||||
this.write_uninit(
|
||||
&this.deref_operand_as(mutex_op, this.libc_ty_layout("pthread_mutex_t"))?.into(),
|
||||
)?;
|
||||
// FIXME: delete interpreter state associated with this mutex.
|
||||
|
||||
Ok(0)
|
||||
|
|
@ -560,7 +624,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
rwlock_get_id(this, rwlock_op)?;
|
||||
|
||||
// This might lead to false positives, see comment in pthread_mutexattr_destroy
|
||||
this.write_uninit(&this.deref_operand(rwlock_op)?.into())?;
|
||||
this.write_uninit(
|
||||
&this.deref_operand_as(rwlock_op, this.libc_ty_layout("pthread_rwlock_t"))?.into(),
|
||||
)?;
|
||||
// FIXME: delete interpreter state associated with this rwlock.
|
||||
|
||||
Ok(0)
|
||||
|
|
@ -624,7 +690,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
condattr_get_clock_id(this, attr_op)?;
|
||||
|
||||
// This might lead to false positives, see comment in pthread_mutexattr_destroy
|
||||
this.write_uninit(&this.deref_operand(attr_op)?.into())?;
|
||||
this.write_uninit(
|
||||
&this.deref_operand_as(attr_op, this.libc_ty_layout("pthread_condattr_t"))?.into(),
|
||||
)?;
|
||||
|
||||
Ok(0)
|
||||
}
|
||||
|
|
@ -715,7 +783,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
|
||||
// Extract the timeout.
|
||||
let clock_id = cond_get_clock_id(this, cond_op)?;
|
||||
let duration = match this.read_timespec(&this.deref_operand(abstime_op)?)? {
|
||||
let duration = match this
|
||||
.read_timespec(&this.deref_operand_as(abstime_op, this.libc_ty_layout("timespec"))?)?
|
||||
{
|
||||
Some(duration) => duration,
|
||||
None => {
|
||||
let einval = this.eval_libc("EINVAL");
|
||||
|
|
@ -797,7 +867,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
cond_get_clock_id(this, cond_op)?;
|
||||
|
||||
// This might lead to false positives, see comment in pthread_mutexattr_destroy
|
||||
this.write_uninit(&this.deref_operand(cond_op)?.into())?;
|
||||
this.write_uninit(
|
||||
&this.deref_operand_as(cond_op, this.libc_ty_layout("pthread_cond_t"))?.into(),
|
||||
)?;
|
||||
// FIXME: delete interpreter state associated with this condvar.
|
||||
|
||||
Ok(0)
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
let thread_info_place = this.deref_operand(thread)?;
|
||||
let thread_info_place = this.deref_operand_as(thread, this.libc_ty_layout("pthread_t"))?;
|
||||
|
||||
let start_routine = this.read_pointer(start_routine)?;
|
||||
|
||||
|
|
|
|||
|
|
@ -10,8 +10,6 @@ use shims::windows::handle::{EvalContextExt as _, Handle, PseudoHandle};
|
|||
use shims::windows::sync::EvalContextExt as _;
|
||||
use shims::windows::thread::EvalContextExt as _;
|
||||
|
||||
use smallvec::SmallVec;
|
||||
|
||||
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
|
||||
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
fn emulate_foreign_item_by_name(
|
||||
|
|
@ -92,7 +90,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
let buf = this.read_pointer(buf)?;
|
||||
let n = this.read_scalar(n)?.to_u32()?;
|
||||
let byte_offset = this.read_target_usize(byte_offset)?; // is actually a pointer
|
||||
let io_status_block = this.deref_operand(io_status_block)?;
|
||||
let io_status_block = this
|
||||
.deref_operand_as(io_status_block, this.windows_ty_layout("IO_STATUS_BLOCK"))?;
|
||||
|
||||
if byte_offset != 0 {
|
||||
throw_unsup_format!(
|
||||
|
|
@ -187,54 +186,20 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
// Also called from `page_size` crate.
|
||||
let [system_info] =
|
||||
this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
|
||||
let system_info = this.deref_operand(system_info)?;
|
||||
let system_info =
|
||||
this.deref_operand_as(system_info, this.windows_ty_layout("SYSTEM_INFO"))?;
|
||||
// Initialize with `0`.
|
||||
this.write_bytes_ptr(
|
||||
system_info.ptr,
|
||||
iter::repeat(0u8).take(system_info.layout.size.bytes_usize()),
|
||||
)?;
|
||||
// Set selected fields.
|
||||
let word_layout = this.machine.layouts.u16;
|
||||
let dword_layout = this.machine.layouts.u32;
|
||||
let usize_layout = this.machine.layouts.usize;
|
||||
|
||||
// Using `mplace_field` is error-prone, see: https://github.com/rust-lang/miri/issues/2136.
|
||||
// Pointer fields have different sizes on different targets.
|
||||
// To avoid all these issue we calculate the offsets ourselves.
|
||||
let field_sizes = [
|
||||
word_layout.size, // 0, wProcessorArchitecture : WORD
|
||||
word_layout.size, // 1, wReserved : WORD
|
||||
dword_layout.size, // 2, dwPageSize : DWORD
|
||||
usize_layout.size, // 3, lpMinimumApplicationAddress : LPVOID
|
||||
usize_layout.size, // 4, lpMaximumApplicationAddress : LPVOID
|
||||
usize_layout.size, // 5, dwActiveProcessorMask : DWORD_PTR
|
||||
dword_layout.size, // 6, dwNumberOfProcessors : DWORD
|
||||
dword_layout.size, // 7, dwProcessorType : DWORD
|
||||
dword_layout.size, // 8, dwAllocationGranularity : DWORD
|
||||
word_layout.size, // 9, wProcessorLevel : WORD
|
||||
word_layout.size, // 10, wProcessorRevision : WORD
|
||||
];
|
||||
let field_offsets: SmallVec<[Size; 11]> = field_sizes
|
||||
.iter()
|
||||
.copied()
|
||||
.scan(Size::ZERO, |a, x| {
|
||||
let res = Some(*a);
|
||||
*a = a.checked_add(x, this).unwrap();
|
||||
res
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Set page size.
|
||||
let page_size = system_info.offset(field_offsets[2], dword_layout, &this.tcx)?;
|
||||
this.write_scalar(
|
||||
Scalar::from_int(this.machine.page_size, dword_layout.size),
|
||||
&page_size.into(),
|
||||
)?;
|
||||
// Set number of processors.
|
||||
let num_cpus = system_info.offset(field_offsets[6], dword_layout, &this.tcx)?;
|
||||
this.write_scalar(
|
||||
Scalar::from_int(this.machine.num_cpus, dword_layout.size),
|
||||
&num_cpus.into(),
|
||||
this.write_int_fields_named(
|
||||
&[
|
||||
("dwPageSize", this.machine.page_size.into()),
|
||||
("dwNumberOfProcessors", this.machine.num_cpus.into()),
|
||||
],
|
||||
&system_info,
|
||||
)?;
|
||||
}
|
||||
|
||||
|
|
@ -426,6 +391,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
let [console, buffer_info] =
|
||||
this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
|
||||
this.read_target_isize(console)?;
|
||||
// FIXME: this should use deref_operand_as, but CONSOLE_SCREEN_BUFFER_INFO is not in std
|
||||
this.deref_operand(buffer_info)?;
|
||||
// Indicate an error.
|
||||
// FIXME: we should set last_error, but to what?
|
||||
|
|
|
|||
|
|
@ -7,10 +7,6 @@ use crate::concurrency::sync::{CondvarLock, RwLockMode};
|
|||
use crate::concurrency::thread::MachineCallback;
|
||||
use crate::*;
|
||||
|
||||
const SRWLOCK_ID_OFFSET: u64 = 0;
|
||||
const INIT_ONCE_ID_OFFSET: u64 = 0;
|
||||
const CONDVAR_ID_OFFSET: u64 = 0;
|
||||
|
||||
impl<'mir, 'tcx> EvalContextExtPriv<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
|
||||
trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
/// Try to reacquire the lock associated with the condition variable after we
|
||||
|
|
@ -41,6 +37,33 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Windows sync primitives are pointer sized.
|
||||
// We only use the first 4 bytes for the id.
|
||||
|
||||
fn srwlock_get_id(
|
||||
&mut self,
|
||||
rwlock_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, RwLockId> {
|
||||
let this = self.eval_context_mut();
|
||||
this.rwlock_get_or_create_id(rwlock_op, this.windows_ty_layout("SRWLOCK"), 0)
|
||||
}
|
||||
|
||||
fn init_once_get_id(
|
||||
&mut self,
|
||||
init_once_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, InitOnceId> {
|
||||
let this = self.eval_context_mut();
|
||||
this.init_once_get_or_create_id(init_once_op, this.windows_ty_layout("INIT_ONCE"), 0)
|
||||
}
|
||||
|
||||
fn condvar_get_id(
|
||||
&mut self,
|
||||
condvar_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, CondvarId> {
|
||||
let this = self.eval_context_mut();
|
||||
this.condvar_get_or_create_id(condvar_op, this.windows_ty_layout("CONDITION_VARIABLE"), 0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
|
||||
|
|
@ -48,7 +71,7 @@ impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx>
|
|||
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
fn AcquireSRWLockExclusive(&mut self, lock_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
let id = this.rwlock_get_or_create_id(lock_op, SRWLOCK_ID_OFFSET)?;
|
||||
let id = this.srwlock_get_id(lock_op)?;
|
||||
let active_thread = this.get_active_thread();
|
||||
|
||||
if this.rwlock_is_locked(id) {
|
||||
|
|
@ -72,7 +95,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
lock_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, Scalar<Provenance>> {
|
||||
let this = self.eval_context_mut();
|
||||
let id = this.rwlock_get_or_create_id(lock_op, SRWLOCK_ID_OFFSET)?;
|
||||
let id = this.srwlock_get_id(lock_op)?;
|
||||
let active_thread = this.get_active_thread();
|
||||
|
||||
if this.rwlock_is_locked(id) {
|
||||
|
|
@ -86,7 +109,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
|
||||
fn ReleaseSRWLockExclusive(&mut self, lock_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
let id = this.rwlock_get_or_create_id(lock_op, SRWLOCK_ID_OFFSET)?;
|
||||
let id = this.srwlock_get_id(lock_op)?;
|
||||
let active_thread = this.get_active_thread();
|
||||
|
||||
if !this.rwlock_writer_unlock(id, active_thread) {
|
||||
|
|
@ -101,7 +124,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
|
||||
fn AcquireSRWLockShared(&mut self, lock_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
let id = this.rwlock_get_or_create_id(lock_op, SRWLOCK_ID_OFFSET)?;
|
||||
let id = this.srwlock_get_id(lock_op)?;
|
||||
let active_thread = this.get_active_thread();
|
||||
|
||||
if this.rwlock_is_write_locked(id) {
|
||||
|
|
@ -118,7 +141,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
lock_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, Scalar<Provenance>> {
|
||||
let this = self.eval_context_mut();
|
||||
let id = this.rwlock_get_or_create_id(lock_op, SRWLOCK_ID_OFFSET)?;
|
||||
let id = this.srwlock_get_id(lock_op)?;
|
||||
let active_thread = this.get_active_thread();
|
||||
|
||||
if this.rwlock_is_write_locked(id) {
|
||||
|
|
@ -131,7 +154,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
|
||||
fn ReleaseSRWLockShared(&mut self, lock_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
let id = this.rwlock_get_or_create_id(lock_op, SRWLOCK_ID_OFFSET)?;
|
||||
let id = this.srwlock_get_id(lock_op)?;
|
||||
let active_thread = this.get_active_thread();
|
||||
|
||||
if !this.rwlock_reader_unlock(id, active_thread) {
|
||||
|
|
@ -154,7 +177,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
let this = self.eval_context_mut();
|
||||
let active_thread = this.get_active_thread();
|
||||
|
||||
let id = this.init_once_get_or_create_id(init_once_op, INIT_ONCE_ID_OFFSET)?;
|
||||
let id = this.init_once_get_id(init_once_op)?;
|
||||
let flags = this.read_scalar(flags_op)?.to_u32()?;
|
||||
let pending_place = this.deref_operand(pending_op)?.into();
|
||||
let context = this.read_pointer(context_op)?;
|
||||
|
|
@ -229,7 +252,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
) -> InterpResult<'tcx, Scalar<Provenance>> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
let id = this.init_once_get_or_create_id(init_once_op, INIT_ONCE_ID_OFFSET)?;
|
||||
let id = this.init_once_get_id(init_once_op)?;
|
||||
let flags = this.read_scalar(flags_op)?.to_u32()?;
|
||||
let context = this.read_pointer(context_op)?;
|
||||
|
||||
|
|
@ -372,8 +395,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
) -> InterpResult<'tcx, Scalar<Provenance>> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
let condvar_id = this.condvar_get_or_create_id(condvar_op, CONDVAR_ID_OFFSET)?;
|
||||
let lock_id = this.rwlock_get_or_create_id(lock_op, SRWLOCK_ID_OFFSET)?;
|
||||
let condvar_id = this.condvar_get_id(condvar_op)?;
|
||||
let lock_id = this.srwlock_get_id(lock_op)?;
|
||||
let timeout_ms = this.read_scalar(timeout_op)?.to_u32()?;
|
||||
let flags = this.read_scalar(flags_op)?.to_u32()?;
|
||||
|
||||
|
|
@ -456,7 +479,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
|
||||
fn WakeConditionVariable(&mut self, condvar_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
let condvar_id = this.condvar_get_or_create_id(condvar_op, CONDVAR_ID_OFFSET)?;
|
||||
let condvar_id = this.condvar_get_id(condvar_op)?;
|
||||
|
||||
if let Some((thread, lock)) = this.condvar_signal(condvar_id) {
|
||||
if let CondvarLock::RwLock { id, mode } = lock {
|
||||
|
|
@ -475,7 +498,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
condvar_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
let condvar_id = this.condvar_get_or_create_id(condvar_op, CONDVAR_ID_OFFSET)?;
|
||||
let condvar_id = this.condvar_get_id(condvar_op)?;
|
||||
|
||||
while let Some((thread, lock)) = this.condvar_signal(condvar_id) {
|
||||
if let CondvarLock::RwLock { id, mode } = lock {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue