Skip to content

Commit 954eddf

Browse files
committed
update to FnVal changes; implement basic Dlsym support and use it for getentropy
1 parent 10af387 commit 954eddf

File tree

6 files changed

+111
-44
lines changed

6 files changed

+111
-44
lines changed

src/eval.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc::mir;
99

1010
use crate::{
1111
InterpResult, InterpError, InterpretCx, StackPopCleanup, struct_error,
12-
Scalar, Tag, Pointer,
12+
Scalar, Tag, Pointer, FnVal,
1313
MemoryExtra, MiriMemoryKind, Evaluator, TlsEvalContextExt,
1414
};
1515

@@ -84,7 +84,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
8484
let mut args = ecx.frame().body.args_iter();
8585

8686
// First argument: pointer to `main()`.
87-
let main_ptr = ecx.memory_mut().create_fn_alloc(main_instance);
87+
let main_ptr = ecx.memory_mut().create_fn_alloc(FnVal::Instance(main_instance));
8888
let dest = ecx.eval_place(&mir::Place::Base(mir::PlaceBase::Local(args.next().unwrap())))?;
8989
ecx.write_scalar(Scalar::Ptr(main_ptr), dest)?;
9090

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ pub use rustc_mir::interpret::{self, AllocMap, PlaceTy};
3131
pub use crate::shims::{EvalContextExt as ShimsEvalContextExt};
3232
pub use crate::shims::foreign_items::EvalContextExt as ForeignItemsEvalContextExt;
3333
pub use crate::shims::intrinsics::EvalContextExt as IntrinsicsEvalContextExt;
34+
pub use crate::shims::dlsym::{Dlsym, EvalContextExt as DlsymEvalContextExt};
3435
pub use crate::operator::EvalContextExt as OperatorEvalContextExt;
3536
pub use crate::tls::{EvalContextExt as TlsEvalContextExt, TlsData};
3637
pub use crate::range_map::RangeMap;

src/machine.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
128128
type MemoryExtra = MemoryExtra;
129129
type AllocExtra = AllocExtra;
130130
type PointerTag = Tag;
131+
type ExtraFnVal = Dlsym;
131132

132133
type MemoryMap = MonoHashMap<AllocId, (MemoryKind<MiriMemoryKind>, Allocation<Tag, Self::AllocExtra>)>;
133134

@@ -138,7 +139,6 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
138139
ecx.machine.validate
139140
}
140141

141-
/// Returns `Ok()` when the function was handled; fail otherwise.
142142
#[inline(always)]
143143
fn find_fn(
144144
ecx: &mut InterpretCx<'mir, 'tcx, Self>,
@@ -150,6 +150,17 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
150150
ecx.find_fn(instance, args, dest, ret)
151151
}
152152

153+
#[inline(always)]
154+
fn call_extra_fn(
155+
ecx: &mut InterpretCx<'mir, 'tcx, Self>,
156+
fn_val: Dlsym,
157+
args: &[OpTy<'tcx, Tag>],
158+
dest: Option<PlaceTy<'tcx, Tag>>,
159+
ret: Option<mir::BasicBlock>,
160+
) -> InterpResult<'tcx> {
161+
ecx.call_dlsym(fn_val, args, dest, ret)
162+
}
163+
153164
#[inline(always)]
154165
fn call_intrinsic(
155166
ecx: &mut rustc_mir::interpret::InterpretCx<'mir, 'tcx, Self>,

src/shims/dlsym.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
use rustc::mir;
2+
3+
use crate::*;
4+
5+
#[derive(Debug, Copy, Clone)]
6+
pub enum Dlsym {
7+
GetEntropy,
8+
}
9+
10+
impl Dlsym {
11+
pub fn from_str(name: &str) -> Option<Dlsym> {
12+
use self::Dlsym::*;
13+
Some(match name {
14+
"getentropy" => GetEntropy,
15+
_ => return None,
16+
})
17+
}
18+
}
19+
20+
impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
21+
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
22+
fn call_dlsym(
23+
&mut self,
24+
dlsym: Dlsym,
25+
args: &[OpTy<'tcx, Tag>],
26+
dest: Option<PlaceTy<'tcx, Tag>>,
27+
ret: Option<mir::BasicBlock>,
28+
) -> InterpResult<'tcx> {
29+
use self::Dlsym::*;
30+
31+
let this = self.eval_context_mut();
32+
33+
let dest = dest.expect("we don't support any diverging dlsym");
34+
let ret = ret.expect("dest is `Some` but ret is `None`");
35+
36+
match dlsym {
37+
GetEntropy => {
38+
let ptr = this.read_scalar(args[0])?.not_undef()?;
39+
let len = this.read_scalar(args[1])?.to_usize(this)?;
40+
this.gen_random(len as usize, ptr)?;
41+
this.write_null(dest)?;
42+
}
43+
}
44+
45+
this.goto_block(Some(ret))?;
46+
this.dump_place(*dest);
47+
Ok(())
48+
}
49+
}

src/shims/foreign_items.rs

Lines changed: 46 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
286286
// neither of which have any effect on our current PRNG
287287
let _flags = this.read_scalar(args[3])?.to_i32()?;
288288

289-
gen_random(this, len as usize, ptr)?;
289+
this.gen_random(len as usize, ptr)?;
290290
this.write_scalar(Scalar::from_uint(len, dest.layout.size), dest)?;
291291
}
292292
id => {
@@ -303,10 +303,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
303303
let symbol_name = this.memory().get(symbol.alloc_id)?.read_c_str(tcx, symbol)?;
304304
let err = format!("bad c unicode symbol: {:?}", symbol_name);
305305
let symbol_name = ::std::str::from_utf8(symbol_name).unwrap_or(&err);
306-
return err!(Unimplemented(format!(
307-
"miri does not support dynamically loading libraries (requested symbol: {})",
308-
symbol_name
309-
)));
306+
if let Some(dlsym) = Dlsym::from_str(symbol_name) {
307+
let ptr = this.memory_mut().create_fn_alloc(FnVal::Other(dlsym));
308+
this.write_scalar(Scalar::from(ptr), dest)?;
309+
} else {
310+
return err!(Unimplemented(format!(
311+
"Unsupported dlsym: {}", symbol_name
312+
)));
313+
}
310314
}
311315

312316
"__rust_maybe_catch_panic" => {
@@ -319,7 +323,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
319323
// We abort on panic, so not much is going on here, but we still have to call the closure.
320324
let f = this.read_scalar(args[0])?.to_ptr()?;
321325
let data = this.read_scalar(args[1])?.not_undef()?;
322-
let f_instance = this.memory().get_fn(f)?;
326+
let f_instance = this.memory().get_fn(f)?.as_instance()?;
323327
this.write_null(dest)?;
324328
trace!("__rust_maybe_catch_panic: {:?}", f_instance);
325329

@@ -638,7 +642,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
638642

639643
// Extract the function type out of the signature (that seems easier than constructing it ourselves).
640644
let dtor = match this.read_scalar(args[1])?.not_undef()? {
641-
Scalar::Ptr(dtor_ptr) => Some(this.memory().get_fn(dtor_ptr)?),
645+
Scalar::Ptr(dtor_ptr) => Some(this.memory().get_fn(dtor_ptr)?.as_instance()?),
642646
Scalar::Raw { data: 0, size } => {
643647
// NULL pointer
644648
assert_eq!(size as u64, this.memory().pointer_size().bytes());
@@ -750,7 +754,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
750754
"SecRandomCopyBytes" => {
751755
let len = this.read_scalar(args[1])?.to_usize(this)?;
752756
let ptr = this.read_scalar(args[2])?.not_undef()?;
753-
gen_random(this, len as usize, ptr)?;
757+
this.gen_random(len as usize, ptr)?;
754758
this.write_null(dest)?;
755759
}
756760

@@ -911,7 +915,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
911915
"SystemFunction036" => {
912916
let ptr = this.read_scalar(args[0])?.not_undef()?;
913917
let len = this.read_scalar(args[1])?.to_u32()?;
914-
gen_random(this, len as usize, ptr)?;
918+
this.gen_random(len as usize, ptr)?;
915919
this.write_scalar(Scalar::from_bool(true), dest)?;
916920
}
917921

@@ -947,36 +951,37 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
947951
}
948952
return Ok(None);
949953
}
950-
}
951-
952-
fn gen_random<'mir, 'tcx>(
953-
this: &mut MiriEvalContext<'mir, 'tcx>,
954-
len: usize,
955-
dest: Scalar<Tag>,
956-
) -> InterpResult<'tcx> {
957-
if len == 0 {
958-
// Nothing to do
959-
return Ok(());
960-
}
961-
let ptr = dest.to_ptr()?;
962-
963-
let data = match &mut this.memory_mut().extra.rng {
964-
Some(rng) => {
965-
let mut rng = rng.borrow_mut();
966-
let mut data = vec![0; len];
967-
rng.fill_bytes(&mut data);
968-
data
969-
}
970-
None => {
971-
return err!(Unimplemented(
972-
"miri does not support gathering system entropy in deterministic mode!
973-
Use '-Zmiri-seed=<seed>' to enable random number generation.
974-
WARNING: Miri does *not* generate cryptographically secure entropy -
975-
do not use Miri to run any program that needs secure random number generation".to_owned(),
976-
));
954+
955+
fn gen_random(
956+
&mut self,
957+
len: usize,
958+
dest: Scalar<Tag>,
959+
) -> InterpResult<'tcx> {
960+
if len == 0 {
961+
// Nothing to do
962+
return Ok(());
977963
}
978-
};
979-
let tcx = &{this.tcx.tcx};
980-
this.memory_mut().get_mut(ptr.alloc_id)?
981-
.write_bytes(tcx, ptr, &data)
982-
}
964+
let this = self.eval_context_mut();
965+
let ptr = dest.to_ptr()?;
966+
967+
let data = match &mut this.memory_mut().extra.rng {
968+
Some(rng) => {
969+
let mut rng = rng.borrow_mut();
970+
let mut data = vec![0; len];
971+
rng.fill_bytes(&mut data);
972+
data
973+
}
974+
None => {
975+
return err!(Unimplemented(
976+
"miri does not support gathering system entropy in deterministic mode!
977+
Use '-Zmiri-seed=<seed>' to enable random number generation.
978+
WARNING: Miri does *not* generate cryptographically secure entropy -
979+
do not use Miri to run any program that needs secure random number generation".to_owned(),
980+
));
981+
}
982+
};
983+
let tcx = &{this.tcx.tcx};
984+
this.memory_mut().get_mut(ptr.alloc_id)?
985+
.write_bytes(tcx, ptr, &data)
986+
}
987+
}

src/shims/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
pub mod foreign_items;
22
pub mod intrinsics;
3+
pub mod dlsym;
34

45
use rustc::{ty, mir};
56

0 commit comments

Comments
 (0)