Skip to content

Commit

Permalink
Auto merge of #3285 - sunfishcode:sunfishcode/mmap64, r=RalfJung
Browse files Browse the repository at this point in the history
Implement the `mmap64` foreign item.

`mmap64` is like `mmap` but uses a 64-bit integer instead of `off_t` for the offset parameter.
  • Loading branch information
bors committed Feb 11, 2024
2 parents d2e219c + d914d5e commit 36651cb
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 16 deletions.
1 change: 1 addition & 0 deletions src/shims/unix/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {

"mmap" => {
let [addr, length, prot, flags, fd, offset] = this.check_shim(abi, Abi::C {unwind: false}, link_name, args)?;
let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off_t").size)?;
let ptr = this.mmap(addr, length, prot, flags, fd, offset)?;
this.write_scalar(ptr, dest)?;
}
Expand Down
9 changes: 9 additions & 0 deletions src/shims/unix/linux/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use shims::unix::fs::EvalContextExt as _;
use shims::unix::linux::fd::EvalContextExt as _;
use shims::unix::linux::mem::EvalContextExt as _;
use shims::unix::linux::sync::futex;
use shims::unix::mem::EvalContextExt as _;
use shims::unix::sync::EvalContextExt as _;
use shims::unix::thread::EvalContextExt as _;

Expand Down Expand Up @@ -43,6 +44,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let result = this.linux_readdir64(dirp)?;
this.write_scalar(result, dest)?;
}
"mmap64" => {
let [addr, length, prot, flags, fd, offset] =
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let offset = this.read_scalar(offset)?.to_i64()?;
let ptr = this.mmap(addr, length, prot, flags, fd, offset.into())?;
this.write_scalar(ptr, dest)?;
}

// Linux-only
"sync_file_range" => {
let [fd, offset, nbytes, flags] =
Expand Down
3 changes: 1 addition & 2 deletions src/shims/unix/mem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
prot: &OpTy<'tcx, Provenance>,
flags: &OpTy<'tcx, Provenance>,
fd: &OpTy<'tcx, Provenance>,
offset: &OpTy<'tcx, Provenance>,
offset: i128,
) -> InterpResult<'tcx, Scalar<Provenance>> {
let this = self.eval_context_mut();

Expand All @@ -36,7 +36,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let prot = this.read_scalar(prot)?.to_i32()?;
let flags = this.read_scalar(flags)?.to_i32()?;
let fd = this.read_scalar(fd)?.to_i32()?;
let offset = this.read_target_usize(offset)?;

let map_private = this.eval_libc_i32("MAP_PRIVATE");
let map_anonymous = this.eval_libc_i32("MAP_ANONYMOUS");
Expand Down
39 changes: 25 additions & 14 deletions tests/pass-dep/shims/mmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,25 @@
use std::io::Error;
use std::{ptr, slice};

fn test_mmap() {
fn test_mmap<Offset: Default>(
mmap: unsafe extern "C" fn(
*mut libc::c_void,
libc::size_t,
libc::c_int,
libc::c_int,
libc::c_int,
Offset,
) -> *mut libc::c_void,
) {
let page_size = page_size::get();
let ptr = unsafe {
libc::mmap(
mmap(
ptr::null_mut(),
page_size,
libc::PROT_READ | libc::PROT_WRITE,
libc::MAP_PRIVATE | libc::MAP_ANONYMOUS,
-1,
0,
Default::default(),
)
};
assert!(!ptr.is_null());
Expand All @@ -35,40 +44,40 @@ fn test_mmap() {

// Test all of our error conditions
let ptr = unsafe {
libc::mmap(
mmap(
ptr::null_mut(),
page_size,
libc::PROT_READ | libc::PROT_WRITE,
libc::MAP_PRIVATE | libc::MAP_SHARED, // Can't be both private and shared
-1,
0,
Default::default(),
)
};
assert_eq!(ptr, libc::MAP_FAILED);
assert_eq!(Error::last_os_error().raw_os_error().unwrap(), libc::EINVAL);

let ptr = unsafe {
libc::mmap(
mmap(
ptr::null_mut(),
0, // Can't map no memory
libc::PROT_READ | libc::PROT_WRITE,
libc::MAP_PRIVATE | libc::MAP_ANONYMOUS,
-1,
0,
Default::default(),
)
};
assert_eq!(ptr, libc::MAP_FAILED);
assert_eq!(Error::last_os_error().raw_os_error().unwrap(), libc::EINVAL);

let ptr = unsafe {
libc::mmap(
mmap(
ptr::invalid_mut(page_size * 64),
page_size,
libc::PROT_READ | libc::PROT_WRITE,
// We don't support MAP_FIXED
libc::MAP_PRIVATE | libc::MAP_ANONYMOUS | libc::MAP_FIXED,
-1,
0,
Default::default(),
)
};
assert_eq!(ptr, libc::MAP_FAILED);
Expand All @@ -77,13 +86,13 @@ fn test_mmap() {
// We don't support protections other than read+write
for prot in [libc::PROT_NONE, libc::PROT_EXEC, libc::PROT_READ, libc::PROT_WRITE] {
let ptr = unsafe {
libc::mmap(
mmap(
ptr::null_mut(),
page_size,
prot,
libc::MAP_PRIVATE | libc::MAP_ANONYMOUS,
-1,
0,
Default::default(),
)
};
assert_eq!(ptr, libc::MAP_FAILED);
Expand All @@ -93,13 +102,13 @@ fn test_mmap() {
// We report an error for mappings whose length cannot be rounded up to a multiple of
// the page size.
let ptr = unsafe {
libc::mmap(
mmap(
ptr::null_mut(),
usize::MAX - 1,
libc::PROT_READ | libc::PROT_WRITE,
libc::MAP_PRIVATE | libc::MAP_ANONYMOUS,
-1,
0,
Default::default(),
)
};
assert_eq!(ptr, libc::MAP_FAILED);
Expand Down Expand Up @@ -163,7 +172,9 @@ fn test_mremap() {
}

fn main() {
test_mmap();
test_mmap(libc::mmap);
#[cfg(target_os = "linux")]
test_mmap(libc::mmap64);
#[cfg(target_os = "linux")]
test_mremap();
}

0 comments on commit 36651cb

Please sign in to comment.