From 2cfb3a6750b730bc15dac6e0c319e10ec6045636 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 3 Apr 2024 11:31:38 +0200 Subject: [PATCH] shims/linux: move epoll and eventfd into their own files, together with their FD types --- src/tools/miri/src/shims/unix/fd.rs | 2 + .../src/shims/unix/linux/{fd.rs => epoll.rs} | 93 +++++++++---------- .../unix/linux/{fd/event.rs => eventfd.rs} | 62 +++++++++++-- .../miri/src/shims/unix/linux/fd/epoll.rs | 47 ---------- .../src/shims/unix/linux/foreign_items.rs | 3 +- src/tools/miri/src/shims/unix/linux/mod.rs | 3 +- src/tools/miri/src/shims/unix/socket.rs | 1 - 7 files changed, 105 insertions(+), 106 deletions(-) rename src/tools/miri/src/shims/unix/linux/{fd.rs => epoll.rs} (75%) rename src/tools/miri/src/shims/unix/linux/{fd/event.rs => eventfd.rs} (50%) delete mode 100644 src/tools/miri/src/shims/unix/linux/fd/epoll.rs diff --git a/src/tools/miri/src/shims/unix/fd.rs b/src/tools/miri/src/shims/unix/fd.rs index bc9348ee0e8c..a5fe38b902de 100644 --- a/src/tools/miri/src/shims/unix/fd.rs +++ b/src/tools/miri/src/shims/unix/fd.rs @@ -52,6 +52,8 @@ pub trait FileDescriptor: std::fmt::Debug + Any { fn dup(&mut self) -> io::Result>; fn is_tty(&self, _communicate_allowed: bool) -> bool { + // Most FDs are not tty's and the consequence of a wrong `false` are minor, + // so we use a default impl here. false } } diff --git a/src/tools/miri/src/shims/unix/linux/fd.rs b/src/tools/miri/src/shims/unix/linux/epoll.rs similarity index 75% rename from src/tools/miri/src/shims/unix/linux/fd.rs rename to src/tools/miri/src/shims/unix/linux/epoll.rs index 7d5177e5c424..82e0bffff77d 100644 --- a/src/tools/miri/src/shims/unix/linux/fd.rs +++ b/src/tools/miri/src/shims/unix/linux/epoll.rs @@ -1,12 +1,50 @@ -use std::cell::Cell; +use std::io; + +use rustc_data_structures::fx::FxHashMap; use crate::shims::unix::*; use crate::*; -use epoll::{Epoll, EpollEvent}; -use event::Event; -pub mod epoll; -pub mod event; +/// An `Epoll` file descriptor connects file handles and epoll events +#[derive(Clone, Debug, Default)] +struct Epoll { + /// The file descriptors we are watching, and what we are watching for. + file_descriptors: FxHashMap, +} + +/// Epoll Events associate events with data. +/// These fields are currently unused by miri. +/// This matches the `epoll_event` struct defined +/// by the epoll_ctl man page. For more information +/// see the man page: +/// +/// +#[derive(Clone, Debug)] +struct EpollEvent { + #[allow(dead_code)] + events: u32, + /// `Scalar` is used to represent the + /// `epoll_data` type union. + #[allow(dead_code)] + data: Scalar, +} + +impl FileDescriptor for Epoll { + fn name(&self) -> &'static str { + "epoll" + } + + fn dup(&mut self) -> io::Result> { + Ok(Box::new(self.clone())) + } + + fn close<'tcx>( + self: Box, + _communicate_allowed: bool, + ) -> InterpResult<'tcx, io::Result> { + Ok(Ok(0)) + } +} impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { @@ -156,49 +194,4 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { Ok(Scalar::from_i32(this.fd_not_found()?)) } } - - /// This function creates an `Event` that is used as an event wait/notify mechanism by - /// user-space applications, and by the kernel to notify user-space applications of events. - /// The `Event` contains an `u64` counter maintained by the kernel. The counter is initialized - /// with the value specified in the `initval` argument. - /// - /// A new file descriptor referring to the `Event` is returned. The `read`, `write`, `poll`, - /// `select`, and `close` operations can be performed on the file descriptor. For more - /// information on these operations, see the man page linked below. - /// - /// The `flags` are not currently implemented for eventfd. - /// The `flags` may be bitwise ORed to change the behavior of `eventfd`: - /// `EFD_CLOEXEC` - Set the close-on-exec (`FD_CLOEXEC`) flag on the new file descriptor. - /// `EFD_NONBLOCK` - Set the `O_NONBLOCK` file status flag on the new open file description. - /// `EFD_SEMAPHORE` - miri does not support semaphore-like semantics. - /// - /// - #[expect(clippy::needless_if)] - fn eventfd( - &mut self, - val: &OpTy<'tcx, Provenance>, - flags: &OpTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, Scalar> { - let this = self.eval_context_mut(); - - let val = this.read_scalar(val)?.to_u32()?; - let flags = this.read_scalar(flags)?.to_i32()?; - - let efd_cloexec = this.eval_libc_i32("EFD_CLOEXEC"); - let efd_nonblock = this.eval_libc_i32("EFD_NONBLOCK"); - let efd_semaphore = this.eval_libc_i32("EFD_SEMAPHORE"); - - if flags & (efd_cloexec | efd_nonblock | efd_semaphore) == 0 { - throw_unsup_format!("{flags} is unsupported"); - } - // FIXME handle the cloexec and nonblock flags - if flags & efd_cloexec == efd_cloexec {} - if flags & efd_nonblock == efd_nonblock {} - if flags & efd_semaphore == efd_semaphore { - throw_unsup_format!("EFD_SEMAPHORE is unsupported"); - } - - let fd = this.machine.fds.insert_fd(Box::new(Event { val: Cell::new(val.into()) })); - Ok(Scalar::from_i32(fd)) - } } diff --git a/src/tools/miri/src/shims/unix/linux/fd/event.rs b/src/tools/miri/src/shims/unix/linux/eventfd.rs similarity index 50% rename from src/tools/miri/src/shims/unix/linux/fd/event.rs rename to src/tools/miri/src/shims/unix/linux/eventfd.rs index 0eb4befd52fb..4e066493d274 100644 --- a/src/tools/miri/src/shims/unix/linux/fd/event.rs +++ b/src/tools/miri/src/shims/unix/linux/eventfd.rs @@ -1,11 +1,13 @@ -use crate::shims::unix::FileDescriptor; +//! Linux `eventfd` implementation. +//! Currently just a stub. +use std::cell::Cell; +use std::io; -use rustc_const_eval::interpret::InterpResult; use rustc_middle::ty::TyCtxt; use rustc_target::abi::Endian; -use std::cell::Cell; -use std::io; +use crate::shims::unix::*; +use crate::*; /// A kind of file descriptor created by `eventfd`. /// The `Event` type isn't currently written to by `eventfd`. @@ -15,10 +17,10 @@ use std::io; /// /// #[derive(Debug)] -pub struct Event { +struct Event { /// The object contains an unsigned 64-bit integer (uint64_t) counter that is maintained by the /// kernel. This counter is initialized with the value specified in the argument initval. - pub val: Cell, + val: Cell, } impl FileDescriptor for Event { @@ -70,3 +72,51 @@ impl FileDescriptor for Event { Ok(Ok(8)) } } + +impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} +pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { + /// This function creates an `Event` that is used as an event wait/notify mechanism by + /// user-space applications, and by the kernel to notify user-space applications of events. + /// The `Event` contains an `u64` counter maintained by the kernel. The counter is initialized + /// with the value specified in the `initval` argument. + /// + /// A new file descriptor referring to the `Event` is returned. The `read`, `write`, `poll`, + /// `select`, and `close` operations can be performed on the file descriptor. For more + /// information on these operations, see the man page linked below. + /// + /// The `flags` are not currently implemented for eventfd. + /// The `flags` may be bitwise ORed to change the behavior of `eventfd`: + /// `EFD_CLOEXEC` - Set the close-on-exec (`FD_CLOEXEC`) flag on the new file descriptor. + /// `EFD_NONBLOCK` - Set the `O_NONBLOCK` file status flag on the new open file description. + /// `EFD_SEMAPHORE` - miri does not support semaphore-like semantics. + /// + /// + #[expect(clippy::needless_if)] + fn eventfd( + &mut self, + val: &OpTy<'tcx, Provenance>, + flags: &OpTy<'tcx, Provenance>, + ) -> InterpResult<'tcx, Scalar> { + let this = self.eval_context_mut(); + + let val = this.read_scalar(val)?.to_u32()?; + let flags = this.read_scalar(flags)?.to_i32()?; + + let efd_cloexec = this.eval_libc_i32("EFD_CLOEXEC"); + let efd_nonblock = this.eval_libc_i32("EFD_NONBLOCK"); + let efd_semaphore = this.eval_libc_i32("EFD_SEMAPHORE"); + + if flags & (efd_cloexec | efd_nonblock | efd_semaphore) == 0 { + throw_unsup_format!("{flags} is unsupported"); + } + // FIXME handle the cloexec and nonblock flags + if flags & efd_cloexec == efd_cloexec {} + if flags & efd_nonblock == efd_nonblock {} + if flags & efd_semaphore == efd_semaphore { + throw_unsup_format!("EFD_SEMAPHORE is unsupported"); + } + + let fd = this.machine.fds.insert_fd(Box::new(Event { val: Cell::new(val.into()) })); + Ok(Scalar::from_i32(fd)) + } +} diff --git a/src/tools/miri/src/shims/unix/linux/fd/epoll.rs b/src/tools/miri/src/shims/unix/linux/fd/epoll.rs deleted file mode 100644 index f2da76ca98d7..000000000000 --- a/src/tools/miri/src/shims/unix/linux/fd/epoll.rs +++ /dev/null @@ -1,47 +0,0 @@ -use crate::*; - -use crate::shims::unix::FileDescriptor; - -use rustc_data_structures::fx::FxHashMap; -use std::io; - -/// An `Epoll` file descriptor connects file handles and epoll events -#[derive(Clone, Debug, Default)] -pub struct Epoll { - /// The file descriptors we are watching, and what we are watching for. - pub file_descriptors: FxHashMap, -} - -/// Epoll Events associate events with data. -/// These fields are currently unused by miri. -/// This matches the `epoll_event` struct defined -/// by the epoll_ctl man page. For more information -/// see the man page: -/// -/// -#[derive(Clone, Debug)] -pub struct EpollEvent { - #[allow(dead_code)] - pub events: u32, - /// `Scalar` is used to represent the - /// `epoll_data` type union. - #[allow(dead_code)] - pub data: Scalar, -} - -impl FileDescriptor for Epoll { - fn name(&self) -> &'static str { - "epoll" - } - - fn dup(&mut self) -> io::Result> { - Ok(Box::new(self.clone())) - } - - fn close<'tcx>( - self: Box, - _communicate_allowed: bool, - ) -> InterpResult<'tcx, io::Result> { - Ok(Ok(0)) - } -} diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs index 7e600f4c54bb..2aaec3f5a0b4 100644 --- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs @@ -6,7 +6,8 @@ use crate::machine::SIGRTMIN; use crate::shims::unix::*; use crate::*; use shims::foreign_items::EmulateForeignItemResult; -use shims::unix::linux::fd::EvalContextExt as _; +use shims::unix::linux::epoll::EvalContextExt as _; +use shims::unix::linux::eventfd::EvalContextExt as _; use shims::unix::linux::mem::EvalContextExt as _; use shims::unix::linux::sync::futex; diff --git a/src/tools/miri/src/shims/unix/linux/mod.rs b/src/tools/miri/src/shims/unix/linux/mod.rs index fe18f1a32fd4..84b604eb9b82 100644 --- a/src/tools/miri/src/shims/unix/linux/mod.rs +++ b/src/tools/miri/src/shims/unix/linux/mod.rs @@ -1,4 +1,5 @@ -pub mod fd; +pub mod epoll; +pub mod eventfd; pub mod foreign_items; pub mod mem; pub mod sync; diff --git a/src/tools/miri/src/shims/unix/socket.rs b/src/tools/miri/src/shims/unix/socket.rs index aa06425ffa1a..84ddd746fb58 100644 --- a/src/tools/miri/src/shims/unix/socket.rs +++ b/src/tools/miri/src/shims/unix/socket.rs @@ -6,7 +6,6 @@ use crate::*; /// Pair of connected sockets. /// /// We currently don't allow sending any data through this pair, so this can be just a dummy. -/// FIXME: show proper errors when trying to send/receive #[derive(Debug)] struct SocketPair;