diff --git a/src/fn_call.rs b/src/fn_call.rs index 720737b539..8e228778a2 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -1,6 +1,6 @@ use rustc::ty; use rustc::ty::layout::{Align, LayoutOf, Size}; -use rustc::hir::def_id::DefId; +use rustc::hir::def_id::{DefId, DefIndex, CrateNum}; use rustc::mir; use syntax::attr; @@ -15,7 +15,23 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a, dest: Option>, ret: Option, ) -> EvalResult<'tcx, Option<&'mir mir::Mir<'tcx>>> { + + // HACK: normal evaluation never sees `ReservedForIncrCompCache`, so we use it + // to signify a dlsym loaded thing + if let ty::InstanceDef::Item(did) = instance.def { + if let CrateNum::ReservedForIncrCompCache = did.krate { + let id = did.index.as_raw_u32(); + self.emulate_dlsym_item( + id, + args, + dest.unwrap(), + ret.unwrap(), + )?; + return Ok(None); + } + } let this = self.eval_context_mut(); + trace!("eval_fn_call: {:#?}, {:?}", instance, dest.map(|place| *place)); // first run the common hooks also supported by CTFE @@ -199,10 +215,23 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a, let symbol_name = this.memory().get(symbol.alloc_id)?.read_c_str(tcx, symbol)?; let err = format!("bad c unicode symbol: {:?}", symbol_name); let symbol_name = ::std::str::from_utf8(symbol_name).unwrap_or(&err); - return err!(Unimplemented(format!( - "miri does not support dynamically loading libraries (requested symbol: {})", - symbol_name - ))); + let id = match symbol_name { + "epoll_create1" => 0, + _ => return err!(Unimplemented(format!( + "miri does not support dynamically loading symbol `{}`", + symbol_name, + ))), + }; + let did = DefId { + krate: CrateNum::ReservedForIncrCompCache, + index: DefIndex::from_raw_u32(id), + }; + let instance = ty::Instance { + def: ty::InstanceDef::Item(did), + substs: this.tcx.mk_substs([].iter()), + }; + let ptr = this.memory_mut().create_fn_alloc(instance); + this.write_scalar(Scalar::from(ptr.with_default_tag()), dest)?; } "__rust_maybe_catch_panic" => { @@ -677,6 +706,13 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a, this.write_scalar(Scalar::Ptr(this.machine.cmd_line.unwrap()), dest)?; } + "sched_getaffinity" => { + let _pid = this.read_scalar(args[0])?.to_i32()?; + let _cpusetsize = this.read_scalar(args[1])?.to_usize(this)?; + let _mask = this.read_scalar(args[2])?.to_ptr()?; + this.write_null(dest)?; + } + // We can't execute anything else _ => { return err!(Unimplemented( @@ -693,4 +729,23 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a, fn write_null(&mut self, dest: PlaceTy<'tcx, Borrow>) -> EvalResult<'tcx> { self.eval_context_mut().write_scalar(Scalar::from_int(0, dest.layout.size), dest) } + + // FIXME: unify with emulate_foreign_item if we ever end up having overlap + fn emulate_dlsym_item( + &mut self, + id: u32, + args: &[OpTy<'tcx, Borrow>], + dest: PlaceTy<'tcx, Borrow>, + ret: mir::BasicBlock, + ) -> EvalResult<'tcx> { + let this = self.eval_context_mut(); + match id { + // epoll_create1 + 0 => { + this.write_null(dest)?; + }, + _ => unreachable!(), + } + Ok(()) + } } diff --git a/src/operator.rs b/src/operator.rs index 4b110224a0..efdd1b1c5d 100644 --- a/src/operator.rs +++ b/src/operator.rs @@ -157,10 +157,12 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, ' assert_eq!(size as u64, self.pointer_size().bytes()); let bits = bits as u64; - // Case I: Comparing with NULL - if bits == 0 { - // Test if the ptr is in-bounds. Then it cannot be NULL. - // Even dangling pointers cannot be NULL. + // Case I: Comparing with small integers + if bits <= 1 { + // Test if the ptr is in-bounds. Then it cannot be a small integer. + // Even dangling pointers cannot be small integers. + // The only exception is wasm and some embedded devices, but that's a different + // story: https://github.com/rust-lang/rust/issues/57897 if self.memory().check_bounds_ptr(ptr, InboundsCheck::MaybeDead).is_ok() { return Ok(false); } @@ -185,7 +187,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, ' // without wrapping around the address space. { // Compute the highest address at which this allocation could live. - // Substract one more, because it must be possible to add the size + // Subtract one more, because it must be possible to add the size // to the base address without overflowing -- IOW, the very last address // of the address space is never dereferencable (but it can be in-bounds, i.e., // one-past-the-end). diff --git a/tests/run-pass/tokio.rs b/tests/run-pass/tokio.rs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tokio_test/Cargo.toml b/tokio_test/Cargo.toml new file mode 100644 index 0000000000..46f5ea2548 --- /dev/null +++ b/tokio_test/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "tokio_test" +version = "0.1.0" +authors = ["Oliver Scherer "] +edition = "2018" + +[dependencies] +tokio = "0.1.14" +futures = "0.1.25" diff --git a/tokio_test/src/main.rs b/tokio_test/src/main.rs new file mode 100644 index 0000000000..81611486f5 --- /dev/null +++ b/tokio_test/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + tokio::run(futures::future::ok::<_, ()>(())) +}