use crate::*;
use rustc_target::abi::Size;
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
fn mremap(
&mut self,
old_address: &OpTy<'tcx, Provenance>,
old_size: &OpTy<'tcx, Provenance>,
new_size: &OpTy<'tcx, Provenance>,
flags: &OpTy<'tcx, Provenance>,
) -> InterpResult<'tcx, Scalar<Provenance>> {
let this = self.eval_context_mut();
let old_address = this.read_target_usize(old_address)?;
let old_size = this.read_target_usize(old_size)?;
let new_size = this.read_target_usize(new_size)?;
let flags = this.read_scalar(flags)?.to_i32()?;
#[allow(clippy::arithmetic_side_effects)] if old_address % this.machine.page_size != 0 || new_size == 0 {
this.set_last_error(Scalar::from_i32(this.eval_libc_i32("EINVAL")))?;
return Ok(this.eval_libc("MAP_FAILED"));
}
if flags & this.eval_libc_i32("MREMAP_FIXED") != 0 {
throw_unsup_format!("Miri does not support mremap wth MREMAP_FIXED");
}
if flags & this.eval_libc_i32("MREMAP_DONTUNMAP") != 0 {
throw_unsup_format!("Miri does not support mremap wth MREMAP_DONTUNMAP");
}
if flags & this.eval_libc_i32("MREMAP_MAYMOVE") == 0 {
this.set_last_error(Scalar::from_i32(this.eval_libc_i32("EINVAL")))?;
return Ok(Scalar::from_maybe_pointer(Pointer::null(), this));
}
let old_address = Machine::ptr_from_addr_cast(this, old_address)?;
let align = this.machine.page_align();
let ptr = this.reallocate_ptr(
old_address,
Some((Size::from_bytes(old_size), align)),
Size::from_bytes(new_size),
align,
MiriMemoryKind::Mmap.into(),
)?;
if let Some(increase) = new_size.checked_sub(old_size) {
this.write_bytes_ptr(
ptr.offset(Size::from_bytes(old_size), this).unwrap().into(),
std::iter::repeat(0u8).take(usize::try_from(increase).unwrap()),
)
.unwrap();
}
Machine::expose_ptr(this, ptr)?;
Ok(Scalar::from_pointer(ptr, this))
}
}