Skip to content

Commit 31996bd

Browse files
committed
update to FnVal changes; implement basic Dlsym support and use it for getentropy
1 parent 048b00d commit 31996bd

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
@@ -30,6 +30,7 @@ pub use rustc_mir::interpret::{self, AllocMap, PlaceTy};
3030

3131
pub use crate::shims::foreign_items::EvalContextExt as ForeignItemsEvalContextExt;
3232
pub use crate::shims::intrinsics::EvalContextExt as IntrinsicsEvalContextExt;
33+
pub use crate::shims::dlsym::{Dlsym, EvalContextExt as DlsymEvalContextExt};
3334
pub use crate::operator::EvalContextExt as OperatorEvalContextExt;
3435
pub use crate::tls::{EvalContextExt as TlsEvalContextExt, TlsData};
3536
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
@@ -311,7 +311,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
311311
// neither of which have any effect on our current PRNG
312312
let _flags = this.read_scalar(args[3])?.to_i32()?;
313313

314-
gen_random(this, len as usize, ptr)?;
314+
this.gen_random(len as usize, ptr)?;
315315
this.write_scalar(Scalar::from_uint(len, dest.layout.size), dest)?;
316316
}
317317
id => {
@@ -328,10 +328,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
328328
let symbol_name = this.memory().get(symbol.alloc_id)?.read_c_str(tcx, symbol)?;
329329
let err = format!("bad c unicode symbol: {:?}", symbol_name);
330330
let symbol_name = ::std::str::from_utf8(symbol_name).unwrap_or(&err);
331-
return err!(Unimplemented(format!(
332-
"miri does not support dynamically loading libraries (requested symbol: {})",
333-
symbol_name
334-
)));
331+
if let Some(dlsym) = Dlsym::from_str(symbol_name) {
332+
let ptr = this.memory_mut().create_fn_alloc(FnVal::Other(dlsym));
333+
this.write_scalar(Scalar::from(ptr), dest)?;
334+
} else {
335+
return err!(Unimplemented(format!(
336+
"Unsupported dlsym: {}", symbol_name
337+
)));
338+
}
335339
}
336340

337341
"__rust_maybe_catch_panic" => {
@@ -344,7 +348,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
344348
// We abort on panic, so not much is going on here, but we still have to call the closure.
345349
let f = this.read_scalar(args[0])?.to_ptr()?;
346350
let data = this.read_scalar(args[1])?.not_undef()?;
347-
let f_instance = this.memory().get_fn(f)?;
351+
let f_instance = this.memory().get_fn(f)?.as_instance()?;
348352
this.write_null(dest)?;
349353
trace!("__rust_maybe_catch_panic: {:?}", f_instance);
350354

@@ -663,7 +667,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
663667

664668
// Extract the function type out of the signature (that seems easier than constructing it ourselves).
665669
let dtor = match this.read_scalar(args[1])?.not_undef()? {
666-
Scalar::Ptr(dtor_ptr) => Some(this.memory().get_fn(dtor_ptr)?),
670+
Scalar::Ptr(dtor_ptr) => Some(this.memory().get_fn(dtor_ptr)?.as_instance()?),
667671
Scalar::Raw { data: 0, size } => {
668672
// NULL pointer
669673
assert_eq!(size as u64, this.memory().pointer_size().bytes());
@@ -775,7 +779,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
775779
"SecRandomCopyBytes" => {
776780
let len = this.read_scalar(args[1])?.to_usize(this)?;
777781
let ptr = this.read_scalar(args[2])?.not_undef()?;
778-
gen_random(this, len as usize, ptr)?;
782+
this.gen_random(len as usize, ptr)?;
779783
this.write_null(dest)?;
780784
}
781785

@@ -936,7 +940,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
936940
"SystemFunction036" => {
937941
let ptr = this.read_scalar(args[0])?.not_undef()?;
938942
let len = this.read_scalar(args[1])?.to_u32()?;
939-
gen_random(this, len as usize, ptr)?;
943+
this.gen_random(len as usize, ptr)?;
940944
this.write_scalar(Scalar::from_bool(true), dest)?;
941945
}
942946

@@ -972,36 +976,37 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
972976
}
973977
return Ok(None);
974978
}
975-
}
976-
977-
fn gen_random<'mir, 'tcx>(
978-
this: &mut MiriEvalContext<'mir, 'tcx>,
979-
len: usize,
980-
dest: Scalar<Tag>,
981-
) -> InterpResult<'tcx> {
982-
if len == 0 {
983-
// Nothing to do
984-
return Ok(());
985-
}
986-
let ptr = dest.to_ptr()?;
987-
988-
let data = match &mut this.memory_mut().extra.rng {
989-
Some(rng) => {
990-
let mut rng = rng.borrow_mut();
991-
let mut data = vec![0; len];
992-
rng.fill_bytes(&mut data);
993-
data
994-
}
995-
None => {
996-
return err!(Unimplemented(
997-
"miri does not support gathering system entropy in deterministic mode!
998-
Use '-Zmiri-seed=<seed>' to enable random number generation.
999-
WARNING: Miri does *not* generate cryptographically secure entropy -
1000-
do not use Miri to run any program that needs secure random number generation".to_owned(),
1001-
));
979+
980+
fn gen_random(
981+
&mut self,
982+
len: usize,
983+
dest: Scalar<Tag>,
984+
) -> InterpResult<'tcx> {
985+
if len == 0 {
986+
// Nothing to do
987+
return Ok(());
1002988
}
1003-
};
1004-
let tcx = &{this.tcx.tcx};
1005-
this.memory_mut().get_mut(ptr.alloc_id)?
1006-
.write_bytes(tcx, ptr, &data)
1007-
}
989+
let this = self.eval_context_mut();
990+
let ptr = dest.to_ptr()?;
991+
992+
let data = match &mut this.memory_mut().extra.rng {
993+
Some(rng) => {
994+
let mut rng = rng.borrow_mut();
995+
let mut data = vec![0; len];
996+
rng.fill_bytes(&mut data);
997+
data
998+
}
999+
None => {
1000+
return err!(Unimplemented(
1001+
"miri does not support gathering system entropy in deterministic mode!
1002+
Use '-Zmiri-seed=<seed>' to enable random number generation.
1003+
WARNING: Miri does *not* generate cryptographically secure entropy -
1004+
do not use Miri to run any program that needs secure random number generation".to_owned(),
1005+
));
1006+
}
1007+
};
1008+
let tcx = &{this.tcx.tcx};
1009+
this.memory_mut().get_mut(ptr.alloc_id)?
1010+
.write_bytes(tcx, ptr, &data)
1011+
}
1012+
}

src/shims/mod.rs

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

0 commit comments

Comments
 (0)