Skip to main content

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;
5use rustc_target::spec::Os;
6
7use crate::shims::unix::foreign_items::EvalContextExt as _;
8use crate::shims::unix::linux_like::epoll::EvalContextExt as _;
9use crate::shims::unix::linux_like::eventfd::EvalContextExt as _;
10use crate::shims::unix::*;
11use crate::*;
12
13pub fn is_dyn_sym(name: &str) -> bool {
14    matches!(name, "pthread_setname_np")
15}
16
17impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
18pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
19    fn emulate_foreign_item_inner(
20        &mut self,
21        link_name: Symbol,
22        abi: &FnAbi<'tcx, Ty<'tcx>>,
23        args: &[OpTy<'tcx>],
24        dest: &MPlaceTy<'tcx>,
25    ) -> InterpResult<'tcx, EmulateItemResult> {
26        let this = self.eval_context_mut();
27        match link_name.as_str() {
28            // epoll, eventfd (NOT available on Solaris!)
29            "epoll_create1" => {
30                this.assert_target_os(Os::Illumos, "epoll_create1");
31                let [flag] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
32                let result = this.epoll_create1(flag)?;
33                this.write_scalar(result, dest)?;
34            }
35            "epoll_ctl" => {
36                this.assert_target_os(Os::Illumos, "epoll_ctl");
37                let [epfd, op, fd, event] =
38                    this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
39                let result = this.epoll_ctl(epfd, op, fd, event)?;
40                this.write_scalar(result, dest)?;
41            }
42            "epoll_wait" => {
43                this.assert_target_os(Os::Illumos, "epoll_wait");
44                let [epfd, events, maxevents, timeout] =
45                    this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
46                this.epoll_wait(epfd, events, maxevents, timeout, dest)?;
47            }
48            "eventfd" => {
49                this.assert_target_os(Os::Illumos, "eventfd");
50                let [val, flag] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
51                let result = this.eventfd(val, flag)?;
52                this.write_scalar(result, dest)?;
53            }
54
55            // Threading
56            "pthread_setname_np" => {
57                let [thread, name] =
58                    this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
59                // THREAD_NAME_MAX allows a thread name of 31+1 length
60                // https://github.com/illumos/illumos-gate/blob/7671517e13b8123748eda4ef1ee165c6d9dba7fe/usr/src/uts/common/sys/thread.h#L613
61                let max_len = 32;
62                // See https://illumos.org/man/3C/pthread_setname_np for the error codes.
63                let res = match this.pthread_setname_np(
64                    this.read_scalar(thread)?,
65                    this.read_scalar(name)?,
66                    max_len,
67                    /* truncate */ false,
68                )? {
69                    ThreadNameResult::Ok => Scalar::from_u32(0),
70                    ThreadNameResult::NameTooLong => this.eval_libc("ERANGE"),
71                    ThreadNameResult::ThreadNotFound => this.eval_libc("ESRCH"),
72                };
73                this.write_scalar(res, dest)?;
74            }
75            "pthread_getname_np" => {
76                let [thread, name, len] =
77                    this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
78                // See https://illumos.org/man/3C/pthread_getname_np for the error codes.
79                let res = match this.pthread_getname_np(
80                    this.read_scalar(thread)?,
81                    this.read_scalar(name)?,
82                    this.read_scalar(len)?,
83                    /* truncate */ false,
84                )? {
85                    ThreadNameResult::Ok => Scalar::from_u32(0),
86                    ThreadNameResult::NameTooLong => this.eval_libc("ERANGE"),
87                    ThreadNameResult::ThreadNotFound => this.eval_libc("ESRCH"),
88                };
89                this.write_scalar(res, dest)?;
90            }
91
92            // File related shims
93            "stat" => {
94                // FIXME: This does not have a direct test (#3179).
95                let [path, buf] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
96                let result = this.stat(path, buf)?;
97                this.write_scalar(result, dest)?;
98            }
99            "lstat" => {
100                // FIXME: This does not have a direct test (#3179).
101                let [path, buf] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
102                let result = this.lstat(path, buf)?;
103                this.write_scalar(result, dest)?;
104            }
105
106            // Sockets and pipes
107            "__xnet_socketpair" => {
108                let [domain, type_, protocol, sv] =
109                    this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
110                let result = this.socketpair(domain, type_, protocol, sv)?;
111                this.write_scalar(result, dest)?;
112            }
113
114            // Network sockets
115            "__xnet_socket" | "__xnet7_socket" => {
116                let [domain, type_, protocol] = this.check_shim_sig(
117                    shim_sig!(extern "C" fn(i32, i32, i32) -> i32),
118                    link_name,
119                    abi,
120                    args,
121                )?;
122                let result = this.socket(domain, type_, protocol)?;
123                this.write_scalar(result, dest)?;
124            }
125            "__xnet_bind" => {
126                let [socket, address, address_len] = this.check_shim_sig(
127                    shim_sig!(extern "C" fn(i32, *const _, libc::socklen_t) -> i32),
128                    link_name,
129                    abi,
130                    args,
131                )?;
132                let result = this.bind(socket, address, address_len)?;
133                this.write_scalar(result, dest)?;
134            }
135            "__xnet_connect" => {
136                let [socket, address, address_len] = this.check_shim_sig(
137                    shim_sig!(extern "C" fn(i32, *const _, libc::socklen_t) -> i32),
138                    link_name,
139                    abi,
140                    args,
141                )?;
142                this.connect(socket, address, address_len, dest)?;
143            }
144            "__xnet_getaddrinfo" => {
145                let [node, service, hints, res] = this.check_shim_sig(
146                    shim_sig!(extern "C" fn(*const _, *const _, *const _, *mut _) -> i32),
147                    link_name,
148                    abi,
149                    args,
150                )?;
151                let result = this.getaddrinfo(node, service, hints, res)?;
152                this.write_scalar(result, dest)?;
153            }
154            "__xnet_getsockopt" => {
155                let [socket, level, option_name, option_value, option_len] = this.check_shim_sig(
156                    shim_sig!(extern "C" fn(i32, i32, i32, *mut _, *mut _) -> i32),
157                    link_name,
158                    abi,
159                    args,
160                )?;
161                let result =
162                    this.getsockopt(socket, level, option_name, option_value, option_len)?;
163                this.write_scalar(result, dest)?;
164            }
165
166            // Miscellaneous
167            "___errno" => {
168                let [] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
169                let errno_place = this.last_error_place()?;
170                this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?;
171            }
172
173            "stack_getbounds" => {
174                // FIXME: This does not have a direct test (#3179).
175                let [stack] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
176                let stack = this.deref_pointer_as(stack, this.libc_ty_layout("stack_t"))?;
177
178                this.write_int_fields_named(
179                    &[
180                        ("ss_sp", this.machine.stack_addr.into()),
181                        ("ss_size", this.machine.stack_size.into()),
182                        // field set to 0 means not in an alternate signal stack
183                        // https://docs.oracle.com/cd/E86824_01/html/E54766/stack-getbounds-3c.html
184                        ("ss_flags", 0),
185                    ],
186                    &stack,
187                )?;
188
189                this.write_null(dest)?;
190            }
191
192            "pset_info" => {
193                // FIXME: This does not have a direct test (#3179).
194                let [pset, tpe, cpus, list] =
195                    this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
196                // We do not need to handle the current process cpu mask, available_parallelism
197                // implementation pass null anyway. We only care for the number of
198                // cpus.
199                // https://docs.oracle.com/cd/E88353_01/html/E37841/pset-info-2.html
200
201                let pset = this.read_scalar(pset)?.to_i32()?;
202                let tpe = this.read_pointer(tpe)?;
203                let list = this.read_pointer(list)?;
204
205                let ps_myid = this.eval_libc_i32("PS_MYID");
206                if ps_myid != pset {
207                    throw_unsup_format!("pset_info is only supported with pset==PS_MYID");
208                }
209
210                if !this.ptr_is_null(tpe)? {
211                    throw_unsup_format!("pset_info is only supported with type==NULL");
212                }
213
214                if !this.ptr_is_null(list)? {
215                    throw_unsup_format!("pset_info is only supported with list==NULL");
216                }
217
218                let cpus = this.deref_pointer_as(cpus, this.machine.layouts.u32)?;
219                this.write_scalar(Scalar::from_u32(this.machine.num_cpus), &cpus)?;
220                this.write_null(dest)?;
221            }
222
223            "__sysconf_xpg7" => {
224                let [val] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
225                let result = this.sysconf(val)?;
226                this.write_scalar(result, dest)?;
227            }
228
229            _ => return interp_ok(EmulateItemResult::NotSupported),
230        }
231        interp_ok(EmulateItemResult::NeedsReturn)
232    }
233}