impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
/// Gets an instance for a path.
-fn resolve_did<'mir, 'tcx>(tcx: TyCtxt<'tcx>, path: &[&str]) -> InterpResult<'tcx, DefId> {
+fn try_resolve_did<'mir, 'tcx>(tcx: TyCtxt<'tcx>, path: &[&str]) -> Option<DefId> {
tcx.crates()
.iter()
.find(|&&krate| tcx.original_crate_name(krate).as_str() == path[0])
}
None
})
- .ok_or_else(|| {
- err_unsup_format!("failed to find required Rust item: {:?}", path).into()
- })
}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
/// Gets an instance for a path.
- fn resolve_path(&self, path: &[&str]) -> InterpResult<'tcx, ty::Instance<'tcx>> {
- Ok(ty::Instance::mono(
- self.eval_context_ref().tcx.tcx,
- resolve_did(self.eval_context_ref().tcx.tcx, path)?,
- ))
+ fn resolve_path(&self, path: &[&str]) -> ty::Instance<'tcx> {
+ let did = try_resolve_did(self.eval_context_ref().tcx.tcx, path)
+ .unwrap_or_else(|| panic!("failed to find required Rust item: {:?}", path));
+ ty::Instance::mono(self.eval_context_ref().tcx.tcx, did)
+ }
+
+ /// Evaluates the scalar at the specified path. Returns Some(val)
+ /// if the path could be resolved, and None otherwise
+ fn eval_path_scalar(
+ &mut self,
+ path: &[&str],
+ ) -> InterpResult<'tcx, ScalarMaybeUndef<Tag>> {
+ let this = self.eval_context_mut();
+ let instance = this.resolve_path(path);
+ let cid = GlobalId { instance, promoted: None };
+ let const_val = this.const_eval_raw(cid)?;
+ let const_val = this.read_scalar(const_val.into())?;
+ return Ok(const_val);
+ }
+
+ /// Helper function to get a `libc` constant as a `Scalar`.
+ fn eval_libc(&mut self, name: &str) -> InterpResult<'tcx, Scalar<Tag>> {
+ self.eval_context_mut()
+ .eval_path_scalar(&["libc", name])?
+ .not_undef()
+ }
+
+ /// Helper function to get a `libc` constant as an `i32`.
+ fn eval_libc_i32(&mut self, name: &str) -> InterpResult<'tcx, i32> {
+ self.eval_libc(name)?.to_i32()
+ }
+
+ /// Helper function to get the `TyLayout` of a `libc` type
+ fn libc_ty_layout(&mut self, name: &str) -> InterpResult<'tcx, TyLayout<'tcx>> {
+ let this = self.eval_context_mut();
+ let ty = this.resolve_path(&["libc", name]).monomorphic_ty(*this.tcx);
+ this.layout_of(ty)
}
/// Write a 0 of the appropriate size to `dest`.
if this.machine.communicate {
// Fill the buffer using the host's rng.
getrandom::getrandom(&mut data)
- .map_err(|err| err_unsup_format!("getrandom failed: {}", err))?;
+ .map_err(|err| err_unsup_format!("host getrandom failed: {}", err))?;
} else {
let rng = this.memory.extra.rng.get_mut();
rng.fill_bytes(&mut data);
}
}
- /// Helper function to get a `libc` constant as a `Scalar`.
- fn eval_libc(&mut self, name: &str) -> InterpResult<'tcx, Scalar<Tag>> {
- self.eval_context_mut()
- .eval_path_scalar(&["libc", name])?
- .ok_or_else(|| err_unsup_format!("Path libc::{} cannot be resolved.", name))?
- .not_undef()
- }
-
- /// Helper function to get a `libc` constant as an `i32`.
- fn eval_libc_i32(&mut self, name: &str) -> InterpResult<'tcx, i32> {
- self.eval_libc(name)?.to_i32()
- }
-
- /// Helper function to get the `TyLayout` of a `libc` type
- fn libc_ty_layout(&mut self, name: &str) -> InterpResult<'tcx, TyLayout<'tcx>> {
- let this = self.eval_context_mut();
- let ty = this.resolve_path(&["libc", name])?.monomorphic_ty(*this.tcx);
- this.layout_of(ty)
- }
-
// Writes several `ImmTy`s contiguosly into memory. This is useful when you have to pack
// different values into a struct.
fn write_packed_immediates(
) -> InterpResult<'tcx, ImmTy<'tcx, Tag>> {
let int = int.into();
Ok(ImmTy::try_from_int(int, layout).ok_or_else(|| {
- err_unsup_format!("Signed value {:#x} does not fit in {} bits", int, layout.size.bits())
+ err_unsup_format!("signed value {:#x} does not fit in {} bits", int, layout.size.bits())
})?)
}
) -> InterpResult<'tcx, ImmTy<'tcx, Tag>> {
let int = int.into();
Ok(ImmTy::try_from_uint(int, layout).ok_or_else(|| {
- err_unsup_format!("Signed value {:#x} does not fit in {} bits", int, layout.size.bits())
+ err_unsup_format!("unsigned value {:#x} does not fit in {} bits", int, layout.size.bits())
})?)
}
.expect("No panic runtime found!");
let panic_runtime = tcx.crate_name(*panic_runtime);
let start_panic_instance =
- this.resolve_path(&[&*panic_runtime.as_str(), link_name])?;
+ this.resolve_path(&[&*panic_runtime.as_str(), link_name]);
return Ok(Some(&*this.load_mir(start_panic_instance.def, None)?));
}
_ => {}
}
Ok(())
}
-
- /// Evaluates the scalar at the specified path. Returns Some(val)
- /// if the path could be resolved, and None otherwise
- fn eval_path_scalar(
- &mut self,
- path: &[&str],
- ) -> InterpResult<'tcx, Option<ScalarMaybeUndef<Tag>>> {
- let this = self.eval_context_mut();
- if let Ok(instance) = this.resolve_path(path) {
- let cid = GlobalId { instance, promoted: None };
- let const_val = this.const_eval_raw(cid)?;
- let const_val = this.read_scalar(const_val.into())?;
- return Ok(Some(const_val));
- }
- return Ok(None);
- }
}
trace!("sysconf() called with name {}", name);
// TODO: Cache the sysconf integers via Miri's global cache.
- let paths = &[
- (&["libc", "_SC_PAGESIZE"], Scalar::from_int(PAGE_SIZE, dest.layout.size)),
- (&["libc", "_SC_GETPW_R_SIZE_MAX"], Scalar::from_int(-1, dest.layout.size)),
- (
- &["libc", "_SC_NPROCESSORS_ONLN"],
- Scalar::from_int(NUM_CPUS, dest.layout.size),
- ),
+ let sysconfs = &[
+ ("_SC_PAGESIZE", Scalar::from_int(PAGE_SIZE, dest.layout.size)),
+ ("_SC_GETPW_R_SIZE_MAX", Scalar::from_int(-1, dest.layout.size)),
+ ("_SC_NPROCESSORS_ONLN", Scalar::from_int(NUM_CPUS, dest.layout.size)),
];
let mut result = None;
- for &(path, path_value) in paths {
- if let Some(val) = this.eval_path_scalar(path)? {
- let val = val.to_i32()?;
- if val == name {
- result = Some(path_value);
- break;
- }
+ for &(sysconf_name, value) in sysconfs {
+ let sysconf_name = this.eval_libc_i32(sysconf_name)?;
+ if sysconf_name == name {
+ result = Some(value);
+ break;
}
}
if let Some(result) = result {
"syscall" => {
let sys_getrandom = this
- .eval_path_scalar(&["libc", "SYS_getrandom"])?
- .expect("Failed to get libc::SYS_getrandom")
+ .eval_libc("SYS_getrandom")?
.to_machine_usize(this)?;
let sys_statx = this
- .eval_path_scalar(&["libc", "SYS_statx"])?
- .expect("Failed to get libc::SYS_statx")
+ .eval_libc("SYS_statx")?
.to_machine_usize(this)?;
match this.read_scalar(args[0])?.to_machine_usize(this)? {
// FIXME: This long path is required because `libc::statx` is an struct and also a
// function and `resolve_path` is returning the latter.
let statx_ty = this
- .resolve_path(&["libc", "unix", "linux_like", "linux", "gnu", "statx"])?
+ .resolve_path(&["libc", "unix", "linux_like", "linux", "gnu", "statx"])
.monomorphic_ty(*this.tcx);
let statxbuf_ty = this.tcx.mk_mut_ptr(statx_ty);
let statxbuf_layout = this.layout_of(statxbuf_ty)?;
// `flags` should be a `c_int` but the `syscall` function provides an `isize`.
let flags: i32 =
this.read_scalar(flags_op)?.to_machine_isize(&*this.tcx)?.try_into().map_err(|e| {
- err_unsup_format!("Failed to convert pointer sized operand to integer: {}", e)
+ err_unsup_format!("failed to convert pointer sized operand to integer: {}", e)
})?;
let empty_path_flag = flags & this.eval_libc("AT_EMPTY_PATH")?.to_i32()? != 0;
// `dirfd` should be a `c_int` but the `syscall` function provides an `isize`.
let dirfd: i32 =
this.read_scalar(dirfd_op)?.to_machine_isize(&*this.tcx)?.try_into().map_err(|e| {
- err_unsup_format!("Failed to convert pointer sized operand to integer: {}", e)
+ err_unsup_format!("failed to convert pointer sized operand to integer: {}", e)
})?;
// We only support:
// * interpreting `path` as an absolute directory,
(path.as_os_str().is_empty() && empty_path_flag)
) {
throw_unsup_format!(
- "Using statx is only supported with absolute paths, relative paths with the file \
+ "using statx is only supported with absolute paths, relative paths with the file \
descriptor `AT_FDCWD`, and empty paths with the `AT_EMPTY_PATH` flag set and any \
file descriptor"
)
let dirp = this.read_scalar(dirp_op)?.to_machine_usize(this)?;
let dir_iter = this.machine.dir_handler.streams.get_mut(&dirp).ok_or_else(|| {
- err_unsup_format!("The DIR pointer passed to readdir64_r did not come from opendir")
+ err_unsup_format!("the DIR pointer passed to readdir64_r did not come from opendir")
})?;
match dir_iter.next() {
Some(Ok(dir_entry)) => {
let dirp = this.read_scalar(dirp_op)?.to_machine_usize(this)?;
let dir_iter = this.machine.dir_handler.streams.get_mut(&dirp).ok_or_else(|| {
- err_unsup_format!("The DIR pointer passed to readdir_r did not come from opendir")
+ err_unsup_format!("the DIR pointer passed to readdir_r did not come from opendir")
})?;
match dir_iter.next() {
Some(Ok(dir_entry)) => {
/// Returns the time elapsed between the provided time and the unix epoch as a `Duration`.
pub fn system_time_to_duration<'tcx>(time: &SystemTime) -> InterpResult<'tcx, Duration> {
time.duration_since(SystemTime::UNIX_EPOCH)
- .map_err(|_| err_unsup_format!("Times before the Unix epoch are not supported").into())
+ .map_err(|_| err_unsup_format!("times before the Unix epoch are not supported").into())
}
impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}