Skip to content

Commit 2ca1b94

Browse files
committed
update to FnVal changes; implement basic Dlsym support and use it for getentropy
1 parent cb09fab commit 2ca1b94

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
@@ -11,7 +11,7 @@ use rustc::mir;
1111

1212
use crate::{
1313
InterpResult, InterpError, InterpCx, StackPopCleanup, struct_error,
14-
Scalar, Tag, Pointer,
14+
Scalar, Tag, Pointer, FnVal,
1515
MemoryExtra, MiriMemoryKind, Evaluator, TlsEvalContextExt,
1616
};
1717

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

9595
// First argument: pointer to `main()`.
96-
let main_ptr = ecx.memory_mut().create_fn_alloc(main_instance);
96+
let main_ptr = ecx.memory_mut().create_fn_alloc(FnVal::Instance(main_instance));
9797
let dest = ecx.eval_place(&mir::Place::Base(mir::PlaceBase::Local(args.next().unwrap())))?;
9898
ecx.write_scalar(Scalar::Ptr(main_ptr), dest)?;
9999

src/lib.rs

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

src/machine.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
135135
type MemoryExtra = MemoryExtra;
136136
type AllocExtra = AllocExtra;
137137
type PointerTag = Tag;
138+
type ExtraFnVal = Dlsym;
138139

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

@@ -145,7 +146,6 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
145146
ecx.memory().extra.validate
146147
}
147148

148-
/// Returns `Ok()` when the function was handled; fail otherwise.
149149
#[inline(always)]
150150
fn find_fn(
151151
ecx: &mut InterpCx<'mir, 'tcx, Self>,
@@ -157,6 +157,17 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
157157
ecx.find_fn(instance, args, dest, ret)
158158
}
159159

160+
#[inline(always)]
161+
fn call_extra_fn(
162+
ecx: &mut InterpCx<'mir, 'tcx, Self>,
163+
fn_val: Dlsym,
164+
args: &[OpTy<'tcx, Tag>],
165+
dest: Option<PlaceTy<'tcx, Tag>>,
166+
ret: Option<mir::BasicBlock>,
167+
) -> InterpResult<'tcx> {
168+
ecx.call_dlsym(fn_val, args, dest, ret)
169+
}
170+
160171
#[inline(always)]
161172
fn call_intrinsic(
162173
ecx: &mut rustc_mir::interpret::InterpCx<'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
@@ -307,7 +307,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
307307
// neither of which have any effect on our current PRNG
308308
let _flags = this.read_scalar(args[3])?.to_i32()?;
309309

310-
gen_random(this, len as usize, ptr)?;
310+
this.gen_random(len as usize, ptr)?;
311311
this.write_scalar(Scalar::from_uint(len, dest.layout.size), dest)?;
312312
}
313313
id => {
@@ -324,10 +324,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
324324
let symbol_name = this.memory().get(symbol.alloc_id)?.read_c_str(tcx, symbol)?;
325325
let err = format!("bad c unicode symbol: {:?}", symbol_name);
326326
let symbol_name = ::std::str::from_utf8(symbol_name).unwrap_or(&err);
327-
return err!(Unimplemented(format!(
328-
"miri does not support dynamically loading libraries (requested symbol: {})",
329-
symbol_name
330-
)));
327+
if let Some(dlsym) = Dlsym::from_str(symbol_name) {
328+
let ptr = this.memory_mut().create_fn_alloc(FnVal::Other(dlsym));
329+
this.write_scalar(Scalar::from(ptr), dest)?;
330+
} else {
331+
return err!(Unimplemented(format!(
332+
"Unsupported dlsym: {}", symbol_name
333+
)));
334+
}
331335
}
332336

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

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

660664
// Extract the function type out of the signature (that seems easier than constructing it ourselves).
661665
let dtor = match this.test_null(this.read_scalar(args[1])?.not_undef()?)? {
662-
Some(dtor_ptr) => Some(this.memory().get_fn(dtor_ptr.to_ptr()?)?),
666+
Some(dtor_ptr) => Some(this.memory().get_fn(dtor_ptr)?.as_instance()?),
663667
None => None,
664668
};
665669

@@ -766,7 +770,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
766770
"SecRandomCopyBytes" => {
767771
let len = this.read_scalar(args[1])?.to_usize(this)?;
768772
let ptr = this.read_scalar(args[2])?.not_undef()?;
769-
gen_random(this, len as usize, ptr)?;
773+
this.gen_random(len as usize, ptr)?;
770774
this.write_null(dest)?;
771775
}
772776

@@ -934,7 +938,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
934938
"SystemFunction036" => {
935939
let ptr = this.read_scalar(args[0])?.not_undef()?;
936940
let len = this.read_scalar(args[1])?.to_u32()?;
937-
gen_random(this, len as usize, ptr)?;
941+
this.gen_random(len as usize, ptr)?;
938942
this.write_scalar(Scalar::from_bool(true), dest)?;
939943
}
940944

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

src/shims/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
pub mod foreign_items;
22
pub mod intrinsics;
33
pub mod tls;
4+
pub mod dlsym;
45

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

0 commit comments

Comments
 (0)