miri/shims/unix/solarish/
foreign_items.rs

1use rustc_abi::CanonAbi;
2use rustc_middle::ty::Ty;
3use rustc_span::Symbol;
4use rustc_target::callconv::FnAbi;
5
6use crate::shims::unix::foreign_items::EvalContextExt as _;
7use crate::shims::unix::linux_like::epoll::EvalContextExt as _;
8use crate::shims::unix::linux_like::eventfd::EvalContextExt as _;
9use crate::shims::unix::*;
10use crate::*;
11
12pub fn is_dyn_sym(name: &str) -> bool {
13    matches!(name, "pthread_setname_np")
14}
15
16impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
17pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
18    fn emulate_foreign_item_inner(
19        &mut self,
20        link_name: Symbol,
21        abi: &FnAbi<'tcx, Ty<'tcx>>,
22        args: &[OpTy<'tcx>],
23        dest: &MPlaceTy<'tcx>,
24    ) -> InterpResult<'tcx, EmulateItemResult> {
25        let this = self.eval_context_mut();
26        match link_name.as_str() {
27            // epoll, eventfd (NOT available on Solaris!)
28            "epoll_create1" => {
29                this.assert_target_os("illumos", "epoll_create1");
30                let [flag] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
31                let result = this.epoll_create1(flag)?;
32                this.write_scalar(result, dest)?;
33            }
34            "epoll_ctl" => {
35                this.assert_target_os("illumos", "epoll_ctl");
36                let [epfd, op, fd, event] =
37                    this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
38                let result = this.epoll_ctl(epfd, op, fd, event)?;
39                this.write_scalar(result, dest)?;
40            }
41            "epoll_wait" => {
42                this.assert_target_os("illumos", "epoll_wait");
43                let [epfd, events, maxevents, timeout] =
44                    this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
45                this.epoll_wait(epfd, events, maxevents, timeout, dest)?;
46            }
47            "eventfd" => {
48                this.assert_target_os("illumos", "eventfd");
49                let [val, flag] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
50                let result = this.eventfd(val, flag)?;
51                this.write_scalar(result, dest)?;
52            }
53
54            // Threading
55            "pthread_setname_np" => {
56                let [thread, name] =
57                    this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
58                // THREAD_NAME_MAX allows a thread name of 31+1 length
59                // https://github.com/illumos/illumos-gate/blob/7671517e13b8123748eda4ef1ee165c6d9dba7fe/usr/src/uts/common/sys/thread.h#L613
60                let max_len = 32;
61                // See https://illumos.org/man/3C/pthread_setname_np for the error codes.
62                let res = match this.pthread_setname_np(
63                    this.read_scalar(thread)?,
64                    this.read_scalar(name)?,
65                    max_len,
66                    /* truncate */ false,
67                )? {
68                    ThreadNameResult::Ok => Scalar::from_u32(0),
69                    ThreadNameResult::NameTooLong => this.eval_libc("ERANGE"),
70                    ThreadNameResult::ThreadNotFound => this.eval_libc("ESRCH"),
71                };
72                this.write_scalar(res, dest)?;
73            }
74            "pthread_getname_np" => {
75                let [thread, name, len] =
76                    this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
77                // See https://illumos.org/man/3C/pthread_getname_np for the error codes.
78                let res = match this.pthread_getname_np(
79                    this.read_scalar(thread)?,
80                    this.read_scalar(name)?,
81                    this.read_scalar(len)?,
82                    /* truncate */ false,
83                )? {
84                    ThreadNameResult::Ok => Scalar::from_u32(0),
85                    ThreadNameResult::NameTooLong => this.eval_libc("ERANGE"),
86                    ThreadNameResult::ThreadNotFound => this.eval_libc("ESRCH"),
87                };
88                this.write_scalar(res, dest)?;
89            }
90
91            // File related shims
92            "stat" | "stat64" => {
93                let [path, buf] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
94                let result = this.macos_fbsd_solarish_stat(path, buf)?;
95                this.write_scalar(result, dest)?;
96            }
97            "lstat" | "lstat64" => {
98                let [path, buf] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
99                let result = this.macos_fbsd_solarish_lstat(path, buf)?;
100                this.write_scalar(result, dest)?;
101            }
102            "fstat" | "fstat64" => {
103                let [fd, buf] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
104                let result = this.macos_fbsd_solarish_fstat(fd, buf)?;
105                this.write_scalar(result, dest)?;
106            }
107            "readdir" => {
108                let [dirp] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
109                let result = this.linux_solarish_readdir64("dirent", dirp)?;
110                this.write_scalar(result, dest)?;
111            }
112
113            // Sockets and pipes
114            "__xnet_socketpair" => {
115                let [domain, type_, protocol, sv] =
116                    this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
117                let result = this.socketpair(domain, type_, protocol, sv)?;
118                this.write_scalar(result, dest)?;
119            }
120
121            // Miscellaneous
122            "___errno" => {
123                let [] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
124                let errno_place = this.last_error_place()?;
125                this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?;
126            }
127
128            "stack_getbounds" => {
129                let [stack] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
130                let stack = this.deref_pointer_as(stack, this.libc_ty_layout("stack_t"))?;
131
132                this.write_int_fields_named(
133                    &[
134                        ("ss_sp", this.machine.stack_addr.into()),
135                        ("ss_size", this.machine.stack_size.into()),
136                        // field set to 0 means not in an alternate signal stack
137                        // https://docs.oracle.com/cd/E86824_01/html/E54766/stack-getbounds-3c.html
138                        ("ss_flags", 0),
139                    ],
140                    &stack,
141                )?;
142
143                this.write_null(dest)?;
144            }
145
146            "pset_info" => {
147                let [pset, tpe, cpus, list] =
148                    this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
149                // We do not need to handle the current process cpu mask, available_parallelism
150                // implementation pass null anyway. We only care for the number of
151                // cpus.
152                // https://docs.oracle.com/cd/E88353_01/html/E37841/pset-info-2.html
153
154                let pset = this.read_scalar(pset)?.to_i32()?;
155                let tpe = this.read_pointer(tpe)?;
156                let list = this.read_pointer(list)?;
157
158                let ps_myid = this.eval_libc_i32("PS_MYID");
159                if ps_myid != pset {
160                    throw_unsup_format!("pset_info is only supported with pset==PS_MYID");
161                }
162
163                if !this.ptr_is_null(tpe)? {
164                    throw_unsup_format!("pset_info is only supported with type==NULL");
165                }
166
167                if !this.ptr_is_null(list)? {
168                    throw_unsup_format!("pset_info is only supported with list==NULL");
169                }
170
171                let cpus = this.deref_pointer_as(cpus, this.machine.layouts.u32)?;
172                this.write_scalar(Scalar::from_u32(this.machine.num_cpus), &cpus)?;
173                this.write_null(dest)?;
174            }
175
176            "__sysconf_xpg7" => {
177                let [val] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
178                let result = this.sysconf(val)?;
179                this.write_scalar(result, dest)?;
180            }
181
182            _ => return interp_ok(EmulateItemResult::NotSupported),
183        }
184        interp_ok(EmulateItemResult::NeedsReturn)
185    }
186}