Skip to content

Commit

Permalink
Fix MacOS (crudely)
Browse files Browse the repository at this point in the history
  • Loading branch information
saethlin committed Sep 22, 2022
1 parent 4852975 commit a0a1679
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 13 deletions.
6 changes: 5 additions & 1 deletion src/shims/unix/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let result = this.munmap(addr, length)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"mprotect" => {
let [addr, length, prot] = this.check_shim(abi, Abi::C {unwind: false}, link_name, args)?;
let result = this.mprotect(addr, length, prot)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}

// Dynamic symbol loading
"dlsym" => {
Expand Down Expand Up @@ -556,7 +561,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
this.write_null(dest)?;
}
| "sigaction"
| "mprotect"
if this.frame_in_std() => {
let [_, _, _] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
this.write_null(dest)?;
Expand Down
10 changes: 0 additions & 10 deletions src/shims/unix/macos/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,16 +179,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
this.pthread_setname_np(thread, this.read_scalar(name)?)?;
}

// Incomplete shims that we "stub out" just to get pre-main initialization code to work.
// These shims are enabled only when the caller is in the standard library.
"mmap" if this.frame_in_std() => {
// This is a horrible hack, but since the guard page mechanism calls mmap and expects a particular return value, we just give it that value.
let [addr, _, _, _, _, _] =
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let addr = this.read_scalar(addr)?;
this.write_scalar(addr, dest)?;
}

_ => return Ok(EmulateByNameResult::NotSupported),
};

Expand Down
53 changes: 51 additions & 2 deletions src/shims/unix/mem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ fn round_up_to_multiple_of_page_size(length: u64) -> Option<u64> {
(length.checked_add(PAGE_SIZE - 1)? / PAGE_SIZE).checked_mul(PAGE_SIZE)
}

impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
fn mmap(
&mut self,
addr: &OpTy<'tcx, Provenance>,
Expand Down Expand Up @@ -53,6 +53,20 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
}

if !this.ptr_is_null(addr)? {
let map_fixed = this.eval_libc_i32("MAP_FIXED")?;
if (prot, flags, fd, offset)
== (prot_read | prot_write, map_private | map_anonymous | map_fixed, -1, 0)
{
let map_length = round_up_to_multiple_of_page_size(length).unwrap_or(u64::MAX);
this.machine.mappings.push(Mapping {
ptr: addr,
alloc_id: AllocId(core::num::NonZeroU64::new(u64::MAX).unwrap()),
len: map_length,
can_read: true,
can_write: true,
});
return Ok(addr);
}
throw_unsup_format!("Miri does not support non-null pointers to mmap");
}

Expand Down Expand Up @@ -192,4 +206,39 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
Ok(0)
// It is not an error if the indicated range does not contain any mapped pages.
}

fn mprotect(
&mut self,
addr: &OpTy<'tcx, Provenance>,
length: &OpTy<'tcx, Provenance>,
prot: &OpTy<'tcx, Provenance>,
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
let addr = this.read_pointer(addr)?;
let length = this.read_scalar(length)?.to_machine_usize(this)?;
let prot = this.read_scalar(prot)?.to_i32()?;

let prot_read = this.eval_libc_i32("PROT_READ")?;
let prot_write = this.eval_libc_i32("PROT_WRITE")?;

let map = this.machine.mappings.iter_mut().find(|map| {
let start = map.ptr.addr();
let end = map.ptr.addr() + Size::from_bytes(map.len);
addr.addr() >= start && addr.addr() < end
});

if let Some(map) = map {
if map.ptr.addr() == addr.addr() && map.len == length {
map.can_read = prot & prot_read > 0;
map.can_write = prot & prot_write > 0;
} else {
throw_unsup_format!("Miri does not support partial mprotect");
}
Ok(0)
} else {
let einval = this.eval_libc("EINVAL")?;
this.set_last_error(einval)?;
Ok(-1)
}
}
}

0 comments on commit a0a1679

Please sign in to comment.