Skip to content
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
46679bc
Add shims for RwLock::try_read/RwLock::try_write
divergentdave Jan 26, 2020
88f319f
Add failing tests for mutex and rwlock
divergentdave Jan 28, 2020
c2683da
Clean up test case
divergentdave Jan 29, 2020
dd9896b
Implement mutex and rwlock functions
divergentdave Feb 18, 2020
765050f
Revise mutex/rwlock memory layout for macOS compat
divergentdave Feb 18, 2020
dca83d7
Add test that exercises ReentrantMutex
divergentdave Feb 21, 2020
c773ca8
Style fixes
divergentdave Feb 22, 2020
5cc091b
Add test of recursive mutex using libc FFI
divergentdave Feb 22, 2020
d11315e
Fix misleading function names
divergentdave Mar 15, 2020
fd94255
Add comments explaining asserts
divergentdave Mar 17, 2020
141319a
Refactor sync shims with setters and getters
divergentdave Mar 22, 2020
ba3884d
Use checked addition/subtraction on lock counts
divergentdave Mar 22, 2020
e5e3256
Address review comments
divergentdave Mar 27, 2020
735fc12
Handle variation in layout of pthread_mutex_t
divergentdave Mar 28, 2020
de29546
Add and rearrange mutex tests
divergentdave Mar 28, 2020
c7466c9
Add TerminationInfo::Deadlock, use in mutex shim
divergentdave Mar 28, 2020
7f6df15
Rearrange functions
divergentdave Mar 28, 2020
bb06a0c
Restrict mutex static initializer test to Linux
divergentdave Mar 28, 2020
37ddde9
Implement TryEnterCriticalSection
divergentdave Mar 28, 2020
e1a1592
Set some explicit return value sizes
divergentdave Mar 28, 2020
8293d80
Set explicit return value size for windows shim
divergentdave Mar 28, 2020
ac8c98d
Store layouts of i32 and u32 inside Evaluator
divergentdave Mar 29, 2020
79f3307
Update comments, rearrange code
divergentdave Apr 5, 2020
100141f
Remove null checks, fall through to UB upon deref
divergentdave Apr 5, 2020
e794441
Use Deadlock machine stop uniformly
divergentdave Apr 5, 2020
d5d5a56
Add tests
divergentdave Apr 5, 2020
f9dc942
Changes to error handling
divergentdave Apr 5, 2020
134d6a2
Add tests, improve test coverage
divergentdave Apr 5, 2020
bc54c76
Eagerly compute i32 and u32 layouts
divergentdave Apr 5, 2020
0f5f0e1
Fix spelling typo
divergentdave Apr 6, 2020
80497e5
Clean up conditional compilation
divergentdave Apr 6, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ pub enum TerminationInfo {
Exit(i64),
Abort(Option<String>),
UnsupportedInIsolation(String),
ExperimentalUb { msg: String, url: String }
ExperimentalUb { msg: String, url: String },
Deadlock,
}

impl fmt::Debug for TerminationInfo {
Expand All @@ -29,6 +30,8 @@ impl fmt::Debug for TerminationInfo {
write!(f, "{}", msg),
ExperimentalUb { msg, .. } =>
write!(f, "{}", msg),
Deadlock =>
write!(f, "the evaluated program deadlocked"),
}
}
}
Expand Down Expand Up @@ -60,6 +63,7 @@ pub fn report_error<'tcx, 'mir>(
"unsupported operation",
ExperimentalUb { .. } =>
"Undefined Behavior",
Deadlock => "deadlock",
};
let helps = match info {
UnsupportedInIsolation(_) =>
Expand Down
6 changes: 4 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ pub use crate::shims::fs::{DirHandler, EvalContextExt as FileEvalContextExt, Fil
pub use crate::shims::intrinsics::EvalContextExt as IntrinsicsEvalContextExt;
pub use crate::shims::os_str::EvalContextExt as OsStrEvalContextExt;
pub use crate::shims::panic::{CatchUnwindData, EvalContextExt as PanicEvalContextExt};
pub use crate::shims::sync::{EvalContextExt as SyncEvalContextExt};
pub use crate::shims::time::EvalContextExt as TimeEvalContextExt;
pub use crate::shims::tls::{EvalContextExt as TlsEvalContextExt, TlsData};
pub use crate::shims::EvalContextExt as ShimsEvalContextExt;
Expand All @@ -50,8 +51,9 @@ pub use crate::diagnostics::{
pub use crate::eval::{create_ecx, eval_main, MiriConfig};
pub use crate::helpers::EvalContextExt as HelpersEvalContextExt;
pub use crate::machine::{
AllocExtra, Evaluator, FrameData, MemoryExtra, MiriEvalContext, MiriEvalContextExt,
MiriMemoryKind, NUM_CPUS, PAGE_SIZE, STACK_ADDR, STACK_SIZE,
AllocExtra, EvalContextExt as MachineEvalContextExt, Evaluator, FrameData, MemoryExtra,
MiriEvalContext, MiriEvalContextExt, MiriMemoryKind, NUM_CPUS, PAGE_SIZE, STACK_ADDR,
STACK_SIZE,
};
pub use crate::mono_hash_map::MonoHashMap;
pub use crate::operator::EvalContextExt as OperatorEvalContextExt;
Expand Down
53 changes: 52 additions & 1 deletion src/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use log::trace;
use rand::rngs::StdRng;

use rustc_data_structures::fx::FxHashMap;
use rustc_middle::{mir, ty};
use rustc_middle::{mir, ty::{self, layout::TyAndLayout}};
use rustc_target::abi::{LayoutOf, Size};
use rustc_ast::attr;
use rustc_span::symbol::{sym, Symbol};
Expand Down Expand Up @@ -146,6 +146,39 @@ impl MemoryExtra {
}
}

/// Cached layouts of primitive types
#[derive(Default)]
struct PrimitiveLayouts<'tcx> {
i32: RefCell<Option<TyAndLayout<'tcx>>>,
u32: RefCell<Option<TyAndLayout<'tcx>>>,
}

impl<'mir, 'tcx: 'mir> PrimitiveLayouts<'tcx> {
fn i32(&self, ecx: &MiriEvalContext<'mir, 'tcx>) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
{
let layout_ref = self.i32.borrow();
if layout_ref.is_some() {
return Ok(layout_ref.unwrap());
}
}
let layout = ecx.layout_of(ecx.tcx.types.i32)?;
*self.i32.borrow_mut() = Some(layout);
Ok(layout)
}

fn u32(&self, ecx: &MiriEvalContext<'mir, 'tcx>) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
{
let layout_ref = self.u32.borrow();
if layout_ref.is_some() {
return Ok(layout_ref.unwrap());
}
}
let layout = ecx.layout_of(ecx.tcx.types.u32)?;
*self.u32.borrow_mut() = Some(layout);
Ok(layout)
}
}

/// The machine itself.
pub struct Evaluator<'tcx> {
/// Environment variables set by `setenv`.
Expand Down Expand Up @@ -182,6 +215,9 @@ pub struct Evaluator<'tcx> {

/// The "time anchor" for this machine's monotone clock (for `Instant` simulation).
pub(crate) time_anchor: Instant,

/// Cached `TyLayout`s for primitive data types that are commonly used inside Miri.
primitive_layouts: PrimitiveLayouts<'tcx>,
}

impl<'tcx> Evaluator<'tcx> {
Expand All @@ -201,6 +237,7 @@ impl<'tcx> Evaluator<'tcx> {
dir_handler: Default::default(),
panic_payload: None,
time_anchor: Instant::now(),
primitive_layouts: PrimitiveLayouts::default(),
}
}
}
Expand All @@ -224,6 +261,20 @@ impl<'mir, 'tcx> MiriEvalContextExt<'mir, 'tcx> for MiriEvalContext<'mir, 'tcx>
}
}

impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for MiriEvalContext<'mir, 'tcx> {}
/// Provides convenience methods for use elsewhere
pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
fn i32_layout(&self) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
let this = self.eval_context_ref();
this.machine.primitive_layouts.i32(this)
}

fn u32_layout(&self) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
let this = self.eval_context_ref();
this.machine.primitive_layouts.u32(this)
}
}

/// Machine hook implementations.
impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
type MemoryKind = MiriMemoryKind;
Expand Down
88 changes: 73 additions & 15 deletions src/shims/foreign_items/posix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,25 +255,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
this.write_null(dest)?;
}

// Incomplete shims that we "stub out" just to get pre-main initialziation code to work.
// Incomplete shims that we "stub out" just to get pre-main initialization code to work.
// These shims are enabled only when the caller is in the standard library.
| "pthread_attr_init"
| "pthread_attr_destroy"
| "pthread_self"
| "pthread_attr_setstacksize" if this.frame().instance.to_string().starts_with("std::sys::unix::") => {
this.write_null(dest)?;
}
| "pthread_mutexattr_init"
| "pthread_mutexattr_settype"
| "pthread_mutex_init"
| "pthread_mutexattr_destroy"
| "pthread_mutex_lock"
| "pthread_mutex_unlock"
| "pthread_mutex_destroy"
| "pthread_rwlock_rdlock"
| "pthread_rwlock_unlock"
| "pthread_rwlock_wrlock"
| "pthread_rwlock_destroy"
| "pthread_attr_setstacksize"
| "pthread_condattr_init"
| "pthread_condattr_setclock"
| "pthread_cond_init"
Expand All @@ -282,6 +269,77 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
=> {
this.write_null(dest)?;
}

"pthread_mutexattr_init" => {
let result = this.pthread_mutexattr_init(args[0])?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}

"pthread_mutexattr_settype" => {
let result = this.pthread_mutexattr_settype(args[0], args[1])?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}

"pthread_mutexattr_destroy" => {
let result = this.pthread_mutexattr_destroy(args[0])?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}

"pthread_mutex_init" => {
let result = this.pthread_mutex_init(args[0], args[1])?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}

"pthread_mutex_lock" => {
let result = this.pthread_mutex_lock(args[0])?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}

"pthread_mutex_trylock" => {
let result = this.pthread_mutex_trylock(args[0])?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}

"pthread_mutex_unlock" => {
let result = this.pthread_mutex_unlock(args[0])?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}

"pthread_mutex_destroy" => {
let result = this.pthread_mutex_destroy(args[0])?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}

"pthread_rwlock_rdlock" => {
let result = this.pthread_rwlock_rdlock(args[0])?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}

"pthread_rwlock_tryrdlock" => {
let result = this.pthread_rwlock_tryrdlock(args[0])?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}

"pthread_rwlock_wrlock" => {
let result = this.pthread_rwlock_wrlock(args[0])?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}

"pthread_rwlock_trywrlock" => {
let result = this.pthread_rwlock_trywrlock(args[0])?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}

"pthread_rwlock_unlock" => {
let result = this.pthread_rwlock_unlock(args[0])?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}

"pthread_rwlock_destroy" => {
let result = this.pthread_rwlock_destroy(args[0])?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}

| "signal"
| "sigaction"
| "sigaltstack"
Expand Down
5 changes: 5 additions & 0 deletions src/shims/foreign_items/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// (Windows locks are reentrant, and we have only 1 thread,
// so not doing any futher checks here is at least not incorrect.)
}
"TryEnterCriticalSection" if this.frame().instance.to_string().starts_with("std::sys::windows::")
=> {
// There is only one thread, so this always succeeds and returns TRUE
this.write_scalar(Scalar::from_i32(1), dest)?;
}

_ => throw_unsup_format!("can't call foreign function: {}", link_name),
}
Expand Down
1 change: 1 addition & 0 deletions src/shims/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pub mod fs;
pub mod intrinsics;
pub mod os_str;
pub mod panic;
pub mod sync;
pub mod time;
pub mod tls;

Expand Down
Loading