miri/shims/unix/solarish/
foreign_items.rs

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