update to FnVal changes; implement basic Dlsym support and use it for getentropy
This commit is contained in:
parent
cb09fab5ff
commit
2ca1b94e6d
6 changed files with 110 additions and 43 deletions
|
|
@ -11,7 +11,7 @@ use rustc::mir;
|
|||
|
||||
use crate::{
|
||||
InterpResult, InterpError, InterpCx, StackPopCleanup, struct_error,
|
||||
Scalar, Tag, Pointer,
|
||||
Scalar, Tag, Pointer, FnVal,
|
||||
MemoryExtra, MiriMemoryKind, Evaluator, TlsEvalContextExt,
|
||||
};
|
||||
|
||||
|
|
@ -93,7 +93,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
|
|||
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)?;
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ pub use crate::shims::{EvalContextExt as ShimsEvalContextExt};
|
|||
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};
|
||||
|
|
|
|||
|
|
@ -135,6 +135,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
|
|||
type MemoryExtra = MemoryExtra;
|
||||
type AllocExtra = AllocExtra;
|
||||
type PointerTag = Tag;
|
||||
type ExtraFnVal = Dlsym;
|
||||
|
||||
type MemoryMap = MonoHashMap<AllocId, (MemoryKind<MiriMemoryKind>, Allocation<Tag, Self::AllocExtra>)>;
|
||||
|
||||
|
|
@ -145,7 +146,6 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
|
|||
ecx.memory().extra.validate
|
||||
}
|
||||
|
||||
/// Returns `Ok()` when the function was handled; fail otherwise.
|
||||
#[inline(always)]
|
||||
fn find_fn(
|
||||
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
|
|
@ -157,6 +157,17 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
|
|||
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>,
|
||||
|
|
|
|||
49
src/shims/dlsym.rs
Normal file
49
src/shims/dlsym.rs
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
use rustc::mir;
|
||||
|
||||
use crate::*;
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum Dlsym {
|
||||
GetEntropy,
|
||||
}
|
||||
|
||||
impl Dlsym {
|
||||
pub fn from_str(name: &str) -> Option<Dlsym> {
|
||||
use self::Dlsym::*;
|
||||
Some(match name {
|
||||
"getentropy" => GetEntropy,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
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(())
|
||||
}
|
||||
}
|
||||
|
|
@ -307,7 +307,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'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 => {
|
||||
|
|
@ -324,10 +324,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||
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 {
|
||||
return err!(Unimplemented(format!(
|
||||
"Unsupported dlsym: {}", symbol_name
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
"__rust_maybe_catch_panic" => {
|
||||
|
|
@ -340,7 +344,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||
// 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 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);
|
||||
|
||||
|
|
@ -659,7 +663,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||
|
||||
// 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,
|
||||
};
|
||||
|
||||
|
|
@ -766,7 +770,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||
"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)?;
|
||||
}
|
||||
|
||||
|
|
@ -934,7 +938,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||
"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)?;
|
||||
}
|
||||
|
||||
|
|
@ -966,36 +970,37 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||
}
|
||||
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(());
|
||||
fn gen_random(
|
||||
&mut self,
|
||||
len: usize,
|
||||
dest: Scalar<Tag>,
|
||||
) -> InterpResult<'tcx> {
|
||||
if len == 0 {
|
||||
// Nothing to do
|
||||
return Ok(());
|
||||
}
|
||||
let this = self.eval_context_mut();
|
||||
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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
pub mod foreign_items;
|
||||
pub mod intrinsics;
|
||||
pub mod tls;
|
||||
pub mod dlsym;
|
||||
|
||||
use rustc::{ty, mir};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue