-481068a707679257e2a738b40987246e0420e787
+b820c761744db080ff7a4ba3ac88d259065cb836
use crate::{
InterpResult, InterpError, InterpCx, StackPopCleanup, struct_error,
- Scalar, Tag, Pointer,
+ Scalar, Tag, Pointer, FnVal,
MemoryExtra, MiriMemoryKind, Evaluator, TlsEvalContextExt,
};
let mut args = ecx.frame().body.args_iter();
// First argument: pointer to `main()`.
- let main_ptr = ecx.memory_mut().create_fn_alloc(main_instance);
+ let main_ptr = ecx.memory_mut().create_fn_alloc(FnVal::Instance(main_instance));
let dest = ecx.eval_place(&mir::Place::Base(mir::PlaceBase::Local(args.next().unwrap())))?;
ecx.write_scalar(Scalar::Ptr(main_ptr), dest)?;
use std::mem;
-use rustc::ty::{self, layout::{self, Size}};
+use rustc::ty::{self, layout::{self, Size, Align}};
use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX};
+use rand::RngCore;
+
use crate::*;
impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
})
}
+ /// Generate some random bytes, and write them to `dest`.
+ fn gen_random(
+ &mut self,
+ len: usize,
+ ptr: Scalar<Tag>,
+ ) -> InterpResult<'tcx> {
+ let this = self.eval_context_mut();
+
+ let ptr = match this.memory().check_ptr_access(ptr, Size::from_bytes(len as u64), Align::from_bytes(1).unwrap())? {
+ Some(ptr) => ptr,
+ None => return Ok(()), // zero-sized access
+ };
+
+ let data = match &mut this.memory_mut().extra.rng {
+ Some(rng) => {
+ let mut rng = rng.borrow_mut();
+ let mut data = vec![0; len];
+ rng.fill_bytes(&mut data);
+ data
+ }
+ None => {
+ return err!(Unimplemented(
+ "miri does not support gathering system entropy in deterministic mode!
+ Use '-Zmiri-seed=<seed>' to enable random number generation.
+ WARNING: Miri does *not* generate cryptographically secure entropy -
+ do not use Miri to run any program that needs secure random number generation".to_owned(),
+ ));
+ }
+ };
+ let tcx = &{this.tcx.tcx};
+ this.memory_mut().get_mut(ptr.alloc_id)?
+ .write_bytes(tcx, ptr, &data)
+ }
+
/// Visits the memory covered by `place`, sensitive to freezing: the 3rd parameter
/// will be true if this is frozen, false if this is in an `UnsafeCell`.
fn visit_freeze_sensitive(
pub use crate::shims::foreign_items::EvalContextExt as ForeignItemsEvalContextExt;
pub use crate::shims::intrinsics::EvalContextExt as IntrinsicsEvalContextExt;
pub use crate::shims::tls::{EvalContextExt as TlsEvalContextExt, TlsData};
+pub use crate::shims::dlsym::{Dlsym, EvalContextExt as DlsymEvalContextExt};
pub use crate::operator::EvalContextExt as OperatorEvalContextExt;
pub use crate::range_map::RangeMap;
pub use crate::helpers::{EvalContextExt as HelpersEvalContextExt};
pub use crate::mono_hash_map::MonoHashMap;
pub use crate::stacked_borrows::{EvalContextExt as StackedBorEvalContextExt, Tag, Permission, Stack, Stacks, Item};
pub use crate::machine::{
- PAGE_SIZE, STACK_ADDR, NUM_CPUS,
+ PAGE_SIZE, STACK_ADDR, STACK_SIZE, NUM_CPUS,
MemoryExtra, AllocExtra, MiriMemoryKind, Evaluator, MiriEvalContext, MiriEvalContextExt,
};
pub use crate::eval::{eval_main, create_ecx, MiriConfig};
use syntax::attr;
use syntax::symbol::sym;
use rustc::hir::def_id::DefId;
-use rustc::ty::{self, layout::{Size, LayoutOf}, query::TyCtxtAt};
+use rustc::ty::{self, layout::{Size, LayoutOf}, TyCtxt};
use rustc::mir;
use crate::*;
// Some global facts about the emulated machine.
pub const PAGE_SIZE: u64 = 4*1024; // FIXME: adjust to target architecture
-pub const STACK_ADDR: u64 = 16*PAGE_SIZE; // not really about the "stack", but where we start assigning integer addresses to allocations
+pub const STACK_ADDR: u64 = 32*PAGE_SIZE; // not really about the "stack", but where we start assigning integer addresses to allocations
+pub const STACK_SIZE: u64 = 16*PAGE_SIZE; // whatever
pub const NUM_CPUS: u64 = 1;
/// Extra memory kinds
type MemoryExtra = MemoryExtra;
type AllocExtra = AllocExtra;
type PointerTag = Tag;
+ type ExtraFnVal = Dlsym;
type MemoryMap = MonoHashMap<AllocId, (MemoryKind<MiriMemoryKind>, Allocation<Tag, Self::AllocExtra>)>;
ecx.memory().extra.validate
}
- /// Returns `Ok()` when the function was handled; fail otherwise.
#[inline(always)]
fn find_fn(
ecx: &mut InterpCx<'mir, 'tcx, Self>,
ecx.find_fn(instance, args, dest, ret)
}
+ #[inline(always)]
+ fn call_extra_fn(
+ ecx: &mut InterpCx<'mir, 'tcx, Self>,
+ fn_val: Dlsym,
+ args: &[OpTy<'tcx, Tag>],
+ dest: Option<PlaceTy<'tcx, Tag>>,
+ ret: Option<mir::BasicBlock>,
+ ) -> InterpResult<'tcx> {
+ ecx.call_dlsym(fn_val, args, dest, ret)
+ }
+
#[inline(always)]
fn call_intrinsic(
ecx: &mut rustc_mir::interpret::InterpCx<'mir, 'tcx, Self>,
}
fn find_foreign_static(
+ tcx: TyCtxt<'tcx>,
def_id: DefId,
- tcx: TyCtxtAt<'tcx>,
) -> InterpResult<'tcx, Cow<'tcx, Allocation>> {
let attrs = tcx.get_attrs(def_id);
let link_name = match attr::first_attr_value_str_by_name(&attrs, sym::link_name) {
}
fn tag_allocation<'b>(
+ memory_extra: &MemoryExtra,
id: AllocId,
alloc: Cow<'b, Allocation>,
kind: Option<MemoryKind<Self::MemoryKinds>>,
- memory: &Memory<'mir, 'tcx, Self>,
) -> (Cow<'b, Allocation<Self::PointerTag, Self::AllocExtra>>, Self::PointerTag) {
let kind = kind.expect("we set our STATIC_KIND so this cannot be None");
let alloc = alloc.into_owned();
- let (stacks, base_tag) = if !memory.extra.validate {
+ let (stacks, base_tag) = if !memory_extra.validate {
(None, Tag::Untagged)
} else {
let (stacks, base_tag) = Stacks::new_allocation(
id,
Size::from_bytes(alloc.bytes.len() as u64),
- Rc::clone(&memory.extra.stacked_borrows),
+ Rc::clone(&memory_extra.stacked_borrows),
kind,
);
(Some(stacks), base_tag)
assert!(alloc.relocations.is_empty(), "Only statics can come initialized with inner pointers");
// Now we can rely on the inner pointers being static, too.
}
- let mut memory_extra = memory.extra.stacked_borrows.borrow_mut();
+ let mut stacked_borrows = memory_extra.stacked_borrows.borrow_mut();
let alloc: Allocation<Tag, Self::AllocExtra> = Allocation {
bytes: alloc.bytes,
relocations: Relocations::from_presorted(
// The allocations in the relocations (pointers stored *inside* this allocation)
// all get the base pointer tag.
.map(|&(offset, ((), alloc))| {
- let tag = if !memory.extra.validate {
+ let tag = if !memory_extra.validate {
Tag::Untagged
} else {
- memory_extra.static_base_ptr(alloc)
+ stacked_borrows.static_base_ptr(alloc)
};
(offset, (tag, alloc))
})
#[inline(always)]
fn tag_static_base_pointer(
+ memory_extra: &MemoryExtra,
id: AllocId,
- memory: &Memory<'mir, 'tcx, Self>,
) -> Self::PointerTag {
- if !memory.extra.validate {
+ if !memory_extra.validate {
Tag::Untagged
} else {
- memory.extra.stacked_borrows.borrow_mut().static_base_ptr(id)
+ memory_extra.stacked_borrows.borrow_mut().static_base_ptr(id)
}
}
}
fn int_to_ptr(
- int: u64,
memory: &Memory<'mir, 'tcx, Self>,
+ int: u64,
) -> InterpResult<'tcx, Pointer<Self::PointerTag>> {
if int == 0 {
err!(InvalidNullPointerUsage)
}
fn ptr_to_int(
- ptr: Pointer<Self::PointerTag>,
memory: &Memory<'mir, 'tcx, Self>,
+ ptr: Pointer<Self::PointerTag>,
) -> InterpResult<'tcx, u64> {
if memory.extra.rng.is_none() {
err!(ReadPointerAsBytes)
--- /dev/null
+use rustc::mir;
+
+use crate::*;
+
+#[derive(Debug, Copy, Clone)]
+pub enum Dlsym {
+ GetEntropy,
+}
+
+impl Dlsym {
+ // Returns an error for unsupported symbols, and None if this symbol
+ // should become a NULL pointer (pretend it does not exist).
+ pub fn from_str(name: &str) -> InterpResult<'static, Option<Dlsym>> {
+ use self::Dlsym::*;
+ Ok(match name {
+ "getentropy" => Some(GetEntropy),
+ "__pthread_get_minstack" => None,
+ _ =>
+ return err!(Unimplemented(format!(
+ "Unsupported dlsym: {}", name
+ ))),
+ })
+ }
+}
+
+impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
+pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
+ fn call_dlsym(
+ &mut self,
+ dlsym: Dlsym,
+ args: &[OpTy<'tcx, Tag>],
+ dest: Option<PlaceTy<'tcx, Tag>>,
+ ret: Option<mir::BasicBlock>,
+ ) -> InterpResult<'tcx> {
+ use self::Dlsym::*;
+
+ let this = self.eval_context_mut();
+
+ let dest = dest.expect("we don't support any diverging dlsym");
+ let ret = ret.expect("dest is `Some` but ret is `None`");
+
+ match dlsym {
+ GetEntropy => {
+ let ptr = this.read_scalar(args[0])?.not_undef()?;
+ let len = this.read_scalar(args[1])?.to_usize(this)?;
+ this.gen_random(len as usize, ptr)?;
+ this.write_null(dest)?;
+ }
+ }
+
+ this.goto_block(Some(ret))?;
+ this.dump_place(*dest);
+ Ok(())
+ }
+}
use syntax::attr;
use syntax::symbol::sym;
-use rand::RngCore;
-
use crate::*;
impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
// neither of which have any effect on our current PRNG
let _flags = this.read_scalar(args[3])?.to_i32()?;
- gen_random(this, len as usize, ptr)?;
+ this.gen_random(len as usize, ptr)?;
this.write_scalar(Scalar::from_uint(len, dest.layout.size), dest)?;
}
id => {
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
- )));
+ if let Some(dlsym) = Dlsym::from_str(symbol_name)? {
+ let ptr = this.memory_mut().create_fn_alloc(FnVal::Other(dlsym));
+ this.write_scalar(Scalar::from(ptr), dest)?;
+ } else {
+ this.write_null(dest)?;
+ }
}
"__rust_maybe_catch_panic" => {
// vtable_ptr: *mut usize,
// ) -> u32
// We abort on panic, so not much is going on here, but we still have to call the closure.
- let f = this.read_scalar(args[0])?.to_ptr()?;
+ let f = this.read_scalar(args[0])?.not_undef()?;
let data = this.read_scalar(args[1])?.not_undef()?;
- let f_instance = this.memory().get_fn(f)?;
+ let f_instance = this.memory().get_fn(f)?.as_instance()?;
this.write_null(dest)?;
trace!("__rust_maybe_catch_panic: {:?}", f_instance);
// Extract the function type out of the signature (that seems easier than constructing it ourselves).
let dtor = match this.test_null(this.read_scalar(args[1])?.not_undef()?)? {
- Some(dtor_ptr) => Some(this.memory().get_fn(dtor_ptr.to_ptr()?)?),
+ Some(dtor_ptr) => Some(this.memory().get_fn(dtor_ptr)?.as_instance()?),
None => None,
};
this.write_null(dest)?;
}
- // Determine stack base address.
- "pthread_attr_init" | "pthread_attr_destroy" | "pthread_attr_get_np" |
- "pthread_getattr_np" | "pthread_self" | "pthread_get_stacksize_np" => {
+ // Stack size/address stuff.
+ "pthread_attr_init" | "pthread_attr_destroy" | "pthread_self" |
+ "pthread_attr_setstacksize" => {
this.write_null(dest)?;
}
"pthread_attr_getstack" => {
- // Second argument is where we are supposed to write the stack size.
- let ptr = this.deref_operand(args[1])?;
- // Just any address.
- let stack_addr = Scalar::from_uint(STACK_ADDR, args[1].layout.size);
- this.write_scalar(stack_addr, ptr.into())?;
+ let addr_place = this.deref_operand(args[1])?;
+ let size_place = this.deref_operand(args[2])?;
+
+ this.write_scalar(
+ Scalar::from_uint(STACK_ADDR, addr_place.layout.size),
+ addr_place.into(),
+ )?;
+ this.write_scalar(
+ Scalar::from_uint(STACK_SIZE, size_place.layout.size),
+ size_place.into(),
+ )?;
+
// Return success (`0`).
this.write_null(dest)?;
}
- "pthread_get_stackaddr_np" => {
- // Just any address.
- let stack_addr = Scalar::from_uint(STACK_ADDR, dest.layout.size);
- this.write_scalar(stack_addr, dest)?;
+
+ // We don't support threading.
+ "pthread_create" => {
+ return err!(Unimplemented(format!("Miri does not support threading")));
}
// Stub out calls for condvar, mutex and rwlock, to just return `0`.
}
// macOS API stubs.
+ "pthread_attr_get_np" | "pthread_getattr_np" => {
+ this.write_null(dest)?;
+ }
+ "pthread_get_stackaddr_np" => {
+ let stack_addr = Scalar::from_uint(STACK_ADDR, dest.layout.size);
+ this.write_scalar(stack_addr, dest)?;
+ }
+ "pthread_get_stacksize_np" => {
+ let stack_size = Scalar::from_uint(STACK_SIZE, dest.layout.size);
+ this.write_scalar(stack_size, dest)?;
+ }
"_tlv_atexit" => {
// FIXME: register the destructor.
},
"SecRandomCopyBytes" => {
let len = this.read_scalar(args[1])?.to_usize(this)?;
let ptr = this.read_scalar(args[2])?.not_undef()?;
- gen_random(this, len as usize, ptr)?;
+ this.gen_random(len as usize, ptr)?;
this.write_null(dest)?;
}
"SystemFunction036" => {
let ptr = this.read_scalar(args[0])?.not_undef()?;
let len = this.read_scalar(args[1])?.to_u32()?;
- gen_random(this, len as usize, ptr)?;
+ this.gen_random(len as usize, ptr)?;
this.write_scalar(Scalar::from_bool(true), dest)?;
}
}
return Ok(None);
}
-}
-
-fn gen_random<'mir, 'tcx>(
- this: &mut MiriEvalContext<'mir, 'tcx>,
- len: usize,
- dest: Scalar<Tag>,
-) -> InterpResult<'tcx> {
- if len == 0 {
- // Nothing to do
- return Ok(());
- }
- let ptr = dest.to_ptr()?;
-
- let data = match &mut this.memory_mut().extra.rng {
- Some(rng) => {
- let mut rng = rng.borrow_mut();
- let mut data = vec![0; len];
- rng.fill_bytes(&mut data);
- data
- }
- None => {
- return err!(Unimplemented(
- "miri does not support gathering system entropy in deterministic mode!
- Use '-Zmiri-seed=<seed>' to enable random number generation.
- WARNING: Miri does *not* generate cryptographically secure entropy -
- do not use Miri to run any program that needs secure random number generation".to_owned(),
- ));
- }
- };
- let tcx = &{this.tcx.tcx};
- this.memory_mut().get_mut(ptr.alloc_id)?
- .write_bytes(tcx, ptr, &data)
-}
+}
\ No newline at end of file
pub mod foreign_items;
pub mod intrinsics;
pub mod tls;
+pub mod dlsym;
use rustc::{ty, mir};
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-[[package]]
-name = "bitflags"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
[[package]]
name = "byteorder"
version = "1.3.2"
"rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
-[[package]]
-name = "cloudabi"
-version = "0.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "fuchsia-cprng"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
[[package]]
name = "getrandom"
-version = "0.1.3"
+version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "lazy_static"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
[[package]]
name = "libc"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "getrandom 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "getrandom 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_chacha 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "getrandom 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "getrandom 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
]
[[package]]
-name = "winapi"
-version = "0.3.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "winapi-i686-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "winapi-x86_64-pc-windows-gnu"
-version = "0.4.0"
+name = "spin"
+version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0e49efa51329a5fd37e7c79db4621af617cd4e3e5bc224939808d076077077bf"
-"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd"
"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
"checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101"
-"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
-"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
-"checksum getrandom 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8d1dffef07351aafe6ef177e4dd2b8dcf503e6bc765dea3b0de9ed149a3db1ec"
+"checksum getrandom 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e65cce4e5084b14874c4e7097f38cab54f47ee554f9194673456ea379dcc4c55"
"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
"checksum libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "6281b86796ba5e4366000be6e9e18bf35580adf9e63fbe2294aadb587613a319"
"checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273"
"checksum rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "615e683324e75af5d43d8f7a39ffe3ee4a9dc42c5c701167a71dc59c3a493aca"
"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
"checksum rand_pcg 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e196346cbbc5c70c77e7b4926147ee8e383a38ee4d15d58a08098b169e492b6"
-"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770"
-"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
-"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+"checksum spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55"
--- /dev/null
+use std::thread;
+
+// error-pattern: Miri does not support threading
+
+fn main() {
+ thread::spawn(|| {});
+}