implement mach_absolute_time for macOS

This commit is contained in:
Ralf Jung 2020-03-20 15:54:41 +01:00
parent 04c937e281
commit f430e54456
3 changed files with 27 additions and 10 deletions

View File

@ -66,6 +66,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
let result = this.gettimeofday(args[0], args[1])?;
this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?;
}
"mach_absolute_time" => {
let result = this.mach_absolute_time()?;
this.write_scalar(Scalar::from_uint(result, dest.layout.size), dest)?;
}
// Other shims
"pthread_attr_get_np" => {

View File

@ -574,8 +574,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
buf_op: OpTy<'tcx, Tag>,
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
this.check_no_isolation("stat")?;
this.assert_platform("macos", "stat");
this.check_no_isolation("stat")?;
// `stat` always follows symlinks.
this.macos_stat_or_lstat(true, path_op, buf_op)
}
@ -587,8 +587,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
buf_op: OpTy<'tcx, Tag>,
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
this.check_no_isolation("lstat")?;
this.assert_platform("macos", "lstat");
this.check_no_isolation("lstat")?;
this.macos_stat_or_lstat(false, path_op, buf_op)
}
@ -599,8 +599,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
this.check_no_isolation("fstat")?;
this.assert_platform("macos", "fstat");
this.check_no_isolation("fstat")?;
let fd = this.read_scalar(fd_op)?.to_i32()?;
@ -621,8 +621,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
this.check_no_isolation("statx")?;
this.assert_platform("linux", "statx");
this.check_no_isolation("statx")?;
let statxbuf_scalar = this.read_scalar(statxbuf_op)?.not_undef()?;
let pathname_scalar = this.read_scalar(pathname_op)?.not_undef()?;
@ -880,8 +880,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
this.check_no_isolation("readdir64_r")?;
this.assert_platform("linux", "readdir64_r");
this.check_no_isolation("readdir64_r")?;
let dirp = this.read_scalar(dirp_op)?.to_machine_usize(this)?;
@ -967,8 +967,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
this.check_no_isolation("readdir_r")?;
this.assert_platform("macos", "readdir_r");
this.check_no_isolation("readdir_r")?;
let dirp = this.read_scalar(dirp_op)?.to_machine_usize(this)?;

View File

@ -1,4 +1,5 @@
use std::time::{Duration, SystemTime, Instant};
use std::convert::TryFrom;
use crate::stacked_borrows::Tag;
use crate::*;
@ -12,7 +13,6 @@ pub fn system_time_to_duration<'tcx>(time: &SystemTime) -> InterpResult<'tcx, Du
impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
// Foreign function used by linux
fn clock_gettime(
&mut self,
clk_id_op: OpTy<'tcx, Tag>,
@ -20,8 +20,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
this.assert_platform("linux", "clock_gettime");
this.check_no_isolation("clock_gettime")?;
this.assert_platform("linux");
let clk_id = this.read_scalar(clk_id_op)?.to_i32()?;
let tp = this.deref_operand(tp_op)?;
@ -50,7 +50,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
Ok(0)
}
// Foreign function used by generic unix (in particular macOS)
fn gettimeofday(
&mut self,
tv_op: OpTy<'tcx, Tag>,
@ -58,8 +58,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
this.assert_platform("macos", "gettimeofday");
this.check_no_isolation("gettimeofday")?;
this.assert_platform("macos");
// Using tz is obsolete and should always be null
let tz = this.read_scalar(tz_op)?.not_undef()?;
@ -84,4 +84,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
Ok(0)
}
fn mach_absolute_time(&self) -> InterpResult<'tcx, u64> {
let this = self.eval_context_ref();
this.assert_platform("macos", "mach_absolute_time");
this.check_no_isolation("mach_absolute_time")?;
// This returns a u64, with time units determined dynamically by `mach_timebase_info`.
// We return plain nanoseconds.
let duration = Instant::now().duration_since(this.machine.time_anchor);
u64::try_from(duration.as_nanos())
.map_err(|_| err_unsup_format!("programs running longer than 2^64 nanoseconds are not supported").into())
}
}