1use rustc_middle::ty::Ty;
2use rustc_span::Symbol;
3use rustc_target::callconv::FnAbi;
4use rustc_target::spec::Os;
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_create1" => {
29 this.assert_target_os(Os::Illumos, "epoll_create1");
30 let [flag] = &this
31 .check_shim_sig(shim_sig!(extern "C" fn(i32) -> i32), (link_name, abi, 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] = &this.check_shim_sig(
38 shim_sig!(extern "C" fn(i32, i32, i32, *libc::epoll_event) -> i32),
39 (link_name, abi, args),
40 )?;
41 let result = this.epoll_ctl(epfd, op, fd, event)?;
42 this.write_scalar(result, dest)?;
43 }
44 "epoll_wait" => {
45 this.assert_target_os(Os::Illumos, "epoll_wait");
46 let [epfd, events, maxevents, timeout] = &this.check_shim_sig(
47 shim_sig!(extern "C" fn(i32, *libc::epoll_event, i32, i32) -> i32),
48 (link_name, abi, args),
49 )?;
50 this.epoll_wait(epfd, events, maxevents, timeout, dest)?;
51 }
52 "eventfd" => {
53 this.assert_target_os(Os::Illumos, "eventfd");
54 let [val, flag] = &this.check_shim_sig(
55 shim_sig!(extern "C" fn(u32, i32) -> i32),
56 (link_name, abi, args),
57 )?;
58 let result = this.eventfd(val, flag)?;
59 this.write_scalar(result, dest)?;
60 }
61
62 "pthread_setname_np" => {
64 let [thread, name] = &this.check_shim_sig(
65 shim_sig!(extern "C" fn(libc::pthread_t, *_) -> i32),
66 (link_name, abi, args),
67 )?;
68 let max_len = 32;
71 let res = match this.pthread_setname_np(
73 this.read_scalar(thread)?,
74 this.read_scalar(name)?,
75 max_len,
76 false,
77 )? {
78 ThreadNameResult::Ok => Scalar::from_u32(0),
79 ThreadNameResult::NameTooLong => this.eval_libc("ERANGE"),
80 };
81 this.write_scalar(res, dest)?;
82 }
83 "pthread_getname_np" => {
84 let [thread, name, len] = &this.check_shim_sig(
85 shim_sig!(extern "C" fn(libc::pthread_t, *_, usize) -> i32),
86 (link_name, abi, args),
87 )?;
88 let res = match this.pthread_getname_np(
90 this.read_scalar(thread)?,
91 this.read_scalar(name)?,
92 this.read_scalar(len)?,
93 false,
94 )? {
95 ThreadNameResult::Ok => Scalar::from_u32(0),
96 ThreadNameResult::NameTooLong => this.eval_libc("ERANGE"),
97 };
98 this.write_scalar(res, dest)?;
99 }
100
101 "__xnet_socketpair" => {
103 let [domain, type_, protocol, sv] = &this.check_shim_sig(
104 shim_sig!(extern "C" fn(i32, i32, i32, *i32) -> i32),
105 (link_name, abi, args),
106 )?;
107 let result = this.socketpair(domain, type_, protocol, sv)?;
108 this.write_scalar(result, dest)?;
109 }
110
111 "__xnet_socket" | "__xnet7_socket" => {
113 let [domain, type_, protocol] = &this.check_shim_sig(
114 shim_sig!(extern "C" fn(i32, i32, i32) -> i32),
115 (link_name, abi, args),
116 )?;
117 let result = this.socket(domain, type_, protocol)?;
118 this.write_scalar(result, dest)?;
119 }
120 "__xnet_bind" => {
121 let [socket, address, address_len] = &this.check_shim_sig(
122 shim_sig!(extern "C" fn(i32, *libc::sockaddr, libc::socklen_t) -> i32),
123 (link_name, abi, args),
124 )?;
125 let result = this.bind(socket, address, address_len)?;
126 this.write_scalar(result, dest)?;
127 }
128 "__xnet_connect" => {
129 let [socket, address, address_len] = &this.check_shim_sig(
130 shim_sig!(extern "C" fn(i32, *libc::sockaddr, libc::socklen_t) -> i32),
131 (link_name, abi, args),
132 )?;
133 this.connect(socket, address, address_len, dest)?;
134 }
135 "__xnet_sendto" => {
136 let [socket, buffer, length, flags, dest_addr, dest_addr_len] = &this.check_shim_sig(
137 shim_sig!(extern "C" fn(i32, *_, libc::size_t, i32, *libc::sockaddr, libc::socklen_t) -> libc::ssize_t),
138 (link_name, abi, args),
139 )?;
140 this.send(socket, buffer, length, flags, Some((dest_addr, dest_addr_len)), dest)?;
141 }
142 "__xnet_getaddrinfo" => {
143 let [node, service, hints, res] = &this.check_shim_sig(
144 shim_sig!(extern "C" fn(*_, *_, *_, **_) -> i32),
145 (link_name, abi, args),
146 )?;
147 let result = this.getaddrinfo(node, service, hints, res)?;
148 this.write_scalar(result, dest)?;
149 }
150 "__xnet_getsockopt" => {
151 let [socket, level, option_name, option_value, option_len] = &this.check_shim_sig(
152 shim_sig!(extern "C" fn(i32, i32, i32, *_, *_) -> i32),
153 (link_name, abi, args),
154 )?;
155 let result =
156 this.getsockopt(socket, level, option_name, option_value, option_len)?;
157 this.write_scalar(result, dest)?;
158 }
159
160 "___errno" => {
162 let [] = &this
163 .check_shim_sig(shim_sig!(extern "C" fn() -> *_), (link_name, abi, args))?;
164 let errno_place = this.last_error_place()?;
165 this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?;
166 }
167
168 "stack_getbounds" => {
169 let [stack] = &this.check_shim_sig(
171 shim_sig!(extern "C" fn(*libc::stack_t) -> i32),
172 (link_name, abi, args),
173 )?;
174 let stack = this.deref_pointer(stack)?;
175
176 this.write_int_fields_named(
177 &[
178 ("ss_sp", this.machine.stack_addr.into()),
179 ("ss_size", this.machine.stack_size.into()),
180 ("ss_flags", 0),
183 ],
184 &stack,
185 )?;
186
187 this.write_int(0, dest)?;
188 }
189
190 "pset_info" => {
191 let [pset, tpe, cpus, list] = &this.check_shim_sig(
193 shim_sig!(extern "C" fn(i32, *_, *u32, *_) -> i32),
194 (link_name, abi, args),
195 )?;
196 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(cpus)?;
219 this.write_scalar(Scalar::from_u32(this.machine.num_cpus), &cpus)?;
220 this.write_int(0, dest)?;
221 }
222
223 "__sysconf_xpg7" => {
224 let [val] = &this.check_shim_sig(
225 shim_sig!(extern "C" fn(i32) -> isize),
226 (link_name, abi, args),
227 )?;
228 let result = this.sysconf(val)?;
229 this.write_scalar(result, dest)?;
230 }
231
232 _ => return interp_ok(EmulateItemResult::NotSupported),
233 }
234 interp_ok(EmulateItemResult::NeedsReturn)
235 }
236}