1use std::ffi::OsStr;
2use std::str;
3use std::time::Duration;
4
5use rustc_abi::Size;
6use rustc_middle::ty::Ty;
7use rustc_span::Symbol;
8use rustc_target::callconv::FnAbi;
9use rustc_target::spec::{Env, Os, Target};
10
11use self::shims::unix::android::foreign_items as android;
12use self::shims::unix::freebsd::foreign_items as freebsd;
13use self::shims::unix::linux::foreign_items as linux;
14use self::shims::unix::macos::foreign_items as macos;
15use self::shims::unix::netbsd::foreign_items as netbsd;
16use self::shims::unix::solarish::foreign_items as solarish;
17use crate::shims::alloc::EvalContextExt as _;
18use crate::shims::cpu_affinity::EvalContextExt as _;
19use crate::shims::files::FD_LIMIT;
20use crate::shims::unix::*;
21use crate::{shim_sig, *};
22
23pub fn is_dyn_sym(name: &str, target: &Target) -> bool {
24 match name {
25 "strlen" => true,
27 "signal" => true,
30 "getentropy" | "getrandom" => true,
32 "futimens" => true,
35 "preadv" | "pwritev" if !matches!(target.os, Os::Solaris) => true,
39 _ =>
41 match target.os {
42 Os::Android => android::is_dyn_sym(name),
43 Os::FreeBsd => freebsd::is_dyn_sym(name),
44 Os::Linux => linux::is_dyn_sym(name, target),
45 Os::MacOs => macos::is_dyn_sym(name),
46 Os::Solaris | Os::Illumos => solarish::is_dyn_sym(name),
47 Os::NetBsd => netbsd::is_dyn_sym(name),
48 _ => false,
49 },
50 }
51}
52
53impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
54pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
55 fn sysconf(&self, val: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
57 let ecx = self.eval_context_ref();
58
59 let name = ecx.read_scalar(val)?.to_i32()?;
60 static SYSCONFS: &[(&str, fn(&MiriInterpCx<'_>) -> i64)] = &[
63 ("_SC_PAGESIZE", |ecx| ecx.machine.page_size.try_into().unwrap()),
64 ("_SC_PAGE_SIZE", |ecx| ecx.machine.page_size.try_into().unwrap()),
65 ("_SC_NPROCESSORS_CONF", |ecx| ecx.machine.num_cpus.into()),
66 ("_SC_NPROCESSORS_ONLN", |ecx| ecx.machine.num_cpus.into()),
67 ("_SC_GETPW_R_SIZE_MAX", |_ecx| 512),
70 ("_SC_OPEN_MAX", |_ecx| FD_LIMIT.into()),
73 ("_SC_HOST_NAME_MAX", |_ecx| 255),
75 ];
76 for &(sysconf_name, value) in SYSCONFS {
77 let sysconf_name = ecx.eval_libc_i32(sysconf_name);
78 if sysconf_name == name {
79 let value = Scalar::from_target_isize(value(ecx), ecx);
80 return interp_ok(value);
81 }
82 }
83 throw_unsup_format!("unimplemented sysconf name: {}", name)
84 }
85
86 fn strerror_r(
87 &mut self,
88 errnum: &OpTy<'tcx>,
89 buf: &OpTy<'tcx>,
90 buflen: &OpTy<'tcx>,
91 ) -> InterpResult<'tcx, Scalar> {
92 let this = self.eval_context_mut();
93
94 let errnum = this.read_scalar(errnum)?;
95 let buf = this.read_pointer(buf)?;
96 let buflen = this.read_target_usize(buflen)?;
97 let error = this.try_errnum_to_io_error(errnum)?;
98 let formatted = match error {
99 Some(err) => format!("{err}"),
100 None => format!("<unknown errnum in strerror_r: {errnum}>"),
101 };
102 let (complete, _) = this.write_os_str_to_c_str(OsStr::new(&formatted), buf, buflen)?;
103 if complete {
104 interp_ok(Scalar::from_i32(0))
105 } else {
106 interp_ok(Scalar::from_i32(this.eval_libc_i32("ERANGE")))
107 }
108 }
109
110 fn emulate_foreign_item_inner(
111 &mut self,
112 link_name: Symbol,
113 abi: &FnAbi<'tcx, Ty<'tcx>>,
114 args: &[OpTy<'tcx>],
115 dest: &MPlaceTy<'tcx>,
116 ) -> InterpResult<'tcx, EmulateItemResult> {
117 let this = self.eval_context_mut();
118
119 if this.machine.communicate() {
120 this.poll_and_unblock(Some(Duration::ZERO))?;
127 }
128
129 match link_name.as_str() {
131 "getenv" => {
133 let [name] = &this
134 .check_shim_sig(shim_sig!(extern "C" fn(*_) -> *_), (link_name, abi, args))?;
135 let result = this.getenv(name)?;
136 this.write_pointer(result, dest)?;
137 }
138 "unsetenv" => {
139 let [name] = &this
140 .check_shim_sig(shim_sig!(extern "C" fn(*_) -> i32), (link_name, abi, args))?;
141 let result = this.unsetenv(name)?;
142 this.write_scalar(result, dest)?;
143 }
144 "setenv" => {
145 let [name, value, overwrite] = &this.check_shim_sig(
146 shim_sig!(extern "C" fn(*_, *_, i32) -> i32),
147 (link_name, abi, args),
148 )?;
149 this.read_scalar(overwrite)?.to_i32()?;
150 let result = this.setenv(name, value)?;
151 this.write_scalar(result, dest)?;
152 }
153 "getcwd" => {
154 let [buf, size] = &this.check_shim_sig(
155 shim_sig!(extern "C" fn(*_, usize) -> *_),
156 (link_name, abi, args),
157 )?;
158 let result = this.getcwd(buf, size)?;
159 this.write_pointer(result, dest)?;
160 }
161 "gethostname" => {
162 let [name, len] = &this.check_shim_sig(
163 shim_sig!(extern "C" fn(*_, usize) -> i32),
164 (link_name, abi, args),
165 )?;
166 let result = this.gethostname(name, len)?;
167 this.write_scalar(result, dest)?;
168 }
169 "chdir" => {
170 let [path] = &this
171 .check_shim_sig(shim_sig!(extern "C" fn(*_) -> i32), (link_name, abi, args))?;
172 let result = this.chdir(path)?;
173 this.write_scalar(result, dest)?;
174 }
175 "getpid" => {
176 let [] = &this.check_shim_sig(
177 shim_sig!(extern "C" fn() -> libc::pid_t),
178 (link_name, abi, args),
179 )?;
180 let result = this.getpid()?;
181 this.write_scalar(result, dest)?;
182 }
183 "uname" => {
184 this.check_target_os(
186 &[Os::Linux, Os::Android, Os::MacOs, Os::Solaris, Os::Illumos],
187 link_name,
188 )?;
189
190 let [uname] = &this.check_shim_sig(
191 shim_sig!(extern "C" fn(*libc::utsname) -> i32),
192 (link_name, abi, args),
193 )?;
194 let result = this.uname(uname, None)?;
195 this.write_scalar(result, dest)?;
196 }
197 "sysconf" => {
198 let [val] = &this.check_shim_sig(
199 shim_sig!(extern "C" fn(i32) -> isize),
200 (link_name, abi, args),
201 )?;
202 let result = this.sysconf(val)?;
203 this.write_scalar(result, dest)?;
204 }
205
206 "read" => {
208 let [fd, buf, count] = &this.check_shim_sig(
209 shim_sig!(extern "C" fn(i32, *_, usize) -> isize),
210 (link_name, abi, args),
211 )?;
212 let fd = this.read_scalar(fd)?.to_i32()?;
213 let buf = this.read_pointer(buf)?;
214 let count = this.read_target_usize(count)?;
215 this.read(fd, buf, count, None, dest)?;
216 }
217 "write" => {
218 let [fd, buf, n] = &this.check_shim_sig(
219 shim_sig!(extern "C" fn(i32, *_, usize) -> isize),
220 (link_name, abi, args),
221 )?;
222 let fd = this.read_scalar(fd)?.to_i32()?;
223 let buf = this.read_pointer(buf)?;
224 let count = this.read_target_usize(n)?;
225 trace!("Called write({:?}, {:?}, {:?})", fd, buf, count);
226 this.write(fd, buf, count, None, dest)?;
227 }
228 "readv" => {
229 let [fd, iov, iovcnt] = &this.check_shim_sig(
230 shim_sig!(extern "C" fn(i32, *libc::iovec, i32) -> isize),
231 (link_name, abi, args),
232 )?;
233 this.readv(fd, iov, iovcnt, None, dest)?;
234 }
235 "writev" => {
236 let [fd, iov, iovcnt] = &this.check_shim_sig(
237 shim_sig!(extern "C" fn(i32, *libc::iovec, i32) -> isize),
238 (link_name, abi, args),
239 )?;
240 this.writev(fd, iov, iovcnt, None, dest)?;
241 }
242 "pread" => {
243 let [fd, buf, count, offset] = &this.check_shim_sig(
244 shim_sig!(extern "C" fn(i32, *_, usize, libc::off_t) -> isize),
245 (link_name, abi, args),
246 )?;
247 let fd = this.read_scalar(fd)?.to_i32()?;
248 let buf = this.read_pointer(buf)?;
249 let count = this.read_target_usize(count)?;
250 let offset = this.read_scalar(offset)?.to_int(offset.layout.size)?;
251 this.read(fd, buf, count, Some(offset), dest)?;
252 }
253 "pwrite" => {
254 let [fd, buf, n, offset] = &this.check_shim_sig(
255 shim_sig!(extern "C" fn(i32, *_, usize, libc::off_t) -> isize),
256 (link_name, abi, args),
257 )?;
258 let fd = this.read_scalar(fd)?.to_i32()?;
259 let buf = this.read_pointer(buf)?;
260 let count = this.read_target_usize(n)?;
261 let offset = this.read_scalar(offset)?.to_int(offset.layout.size)?;
262 trace!("Called pwrite({:?}, {:?}, {:?}, {:?})", fd, buf, count, offset);
263 this.write(fd, buf, count, Some(offset), dest)?;
264 }
265 "preadv" => {
266 let [fd, iov, iovcnt, offset] = &this.check_shim_sig(
267 shim_sig!(extern "C" fn(i32, *libc::iovec, i32, libc::off_t) -> isize),
268 (link_name, abi, args),
269 )?;
270 this.readv(fd, iov, iovcnt, Some(offset), dest)?;
271 }
272 "pwritev" => {
273 let [fd, iov, iovcnt, offset] = &this.check_shim_sig(
274 shim_sig!(extern "C" fn(i32, *libc::iovec, i32, libc::off_t) -> isize),
275 (link_name, abi, args),
276 )?;
277 this.writev(fd, iov, iovcnt, Some(offset), dest)?;
278 }
279
280 "close" => {
281 let [fd] = &this
282 .check_shim_sig(shim_sig!(extern "C" fn(i32) -> i32), (link_name, abi, args))?;
283 let fd = this.read_scalar(fd)?.to_i32()?;
284 let result = this.close(fd)?;
285 this.write_scalar(result, dest)?;
286 }
287 "fcntl" => {
288 let ([fd_num, cmd], varargs) = this.check_shim_sig_variadic(
289 shim_sig!(extern "C" fn(i32, i32, ...) -> i32),
290 (link_name, abi, args),
291 )?;
292 let result = this.fcntl(&fd_num, &cmd, varargs)?;
293 this.write_scalar(result, dest)?;
294 }
295 "dup" => {
296 let [old_fd] = &this
297 .check_shim_sig(shim_sig!(extern "C" fn(i32) -> i32), (link_name, abi, args))?;
298 let old_fd = this.read_scalar(old_fd)?.to_i32()?;
299 let new_fd = this.dup(old_fd)?;
300 this.write_scalar(new_fd, dest)?;
301 }
302 "dup2" => {
303 let [old_fd, new_fd] = &this.check_shim_sig(
304 shim_sig!(extern "C" fn(i32, i32) -> i32),
305 (link_name, abi, args),
306 )?;
307 let old_fd = this.read_scalar(old_fd)?.to_i32()?;
308 let new_fd = this.read_scalar(new_fd)?.to_i32()?;
309 let result = this.dup2(old_fd, new_fd)?;
310 this.write_scalar(result, dest)?;
311 }
312 "flock" => {
313 this.check_target_os(
315 &[Os::Linux, Os::Android, Os::FreeBsd, Os::MacOs, Os::Illumos],
316 link_name,
317 )?;
318
319 let [fd, op] = &this.check_shim_sig(
320 shim_sig!(extern "C" fn(i32, i32) -> i32),
321 (link_name, abi, args),
322 )?;
323 let fd = this.read_scalar(fd)?.to_i32()?;
324 let op = this.read_scalar(op)?.to_i32()?;
325 let result = this.flock(fd, op)?;
326 this.write_scalar(result, dest)?;
327 }
328 "ioctl" => {
329 let op_is_ulong = match this.tcx.sess.target.os {
332 Os::FreeBsd | Os::NetBsd | Os::MacOs => true,
333 Os::Linux if this.tcx.sess.target.env == Env::Gnu => true,
334 _ => false,
335 };
336 let ([fd, op], varargs) = this.check_shim_sig_variadic(
337 if op_is_ulong {
338 shim_sig!(extern "C" fn(i32, usize, ...) -> i32)
339 } else {
340 shim_sig!(extern "C" fn(i32, i32, ...) -> i32)
341 },
342 (link_name, abi, args),
343 )?;
344 let result = this.ioctl(&fd, &op, varargs)?;
345 this.write_scalar(result, dest)?;
346 }
347
348 "open" => {
350 let ([path_raw, flag], varargs) = this.check_shim_sig_variadic(
353 shim_sig!(extern "C" fn(*_, i32, ...) -> i32),
354 (link_name, abi, args),
355 )?;
356 let result = this.open(None, &path_raw, &flag, varargs)?;
357 this.write_scalar(result, dest)?;
358 }
359 "openat" => {
360 let ([dirfd, path_raw, flag], varargs) = this.check_shim_sig_variadic(
361 shim_sig!(extern "C" fn(i32, *_, i32, ...) -> i32),
362 (link_name, abi, args),
363 )?;
364 let result = this.open(Some(&dirfd), &path_raw, &flag, varargs)?;
365 this.write_scalar(result, dest)?;
366 }
367 "unlink" => {
368 let [path] = &this
370 .check_shim_sig(shim_sig!(extern "C" fn(*_) -> i32), (link_name, abi, args))?;
371 let result = this.unlink(path)?;
372 this.write_scalar(result, dest)?;
373 }
374 "symlink" => {
375 let [target, linkpath] = &this.check_shim_sig(
377 shim_sig!(extern "C" fn(*_, *_) -> i32),
378 (link_name, abi, args),
379 )?;
380 let result = this.symlink(target, linkpath)?;
381 this.write_scalar(result, dest)?;
382 }
383 "linkat" => {
384 let [oldfd, oldpath, newfd, newpath, flags] = &this.check_shim_sig(
385 shim_sig!(extern "C" fn(i32, *_, i32, *_, i32) -> i32),
386 (link_name, abi, args),
387 )?;
388 let result = this.linkat(oldfd, oldpath, newfd, newpath, flags)?;
389 this.write_scalar(result, dest)?;
390 }
391 "fstat" => {
392 let [fd, buf] = &this.check_shim_sig(
393 shim_sig!(extern "C" fn(i32, *libc::stat) -> i32),
394 (link_name, abi, args),
395 )?;
396 let result = this.fstat(fd, buf)?;
397 this.write_scalar(result, dest)?;
398 }
399 "lstat" => {
400 let [path, buf] = &this.check_shim_sig(
401 shim_sig!(extern "C" fn(*_, *libc::stat) -> i32),
402 (link_name, abi, args),
403 )?;
404 let result = this.lstat(path, buf)?;
405 this.write_scalar(result, dest)?;
406 }
407 "stat" => {
408 let [path, buf] = &this.check_shim_sig(
409 shim_sig!(extern "C" fn(*_, *libc::stat) -> i32),
410 (link_name, abi, args),
411 )?;
412 let result = this.stat(path, buf)?;
413 this.write_scalar(result, dest)?;
414 }
415 "fstatat" => {
416 let [dirfd, path, buf, flags] = &this.check_shim_sig(
417 shim_sig!(extern "C" fn(i32, *_, *libc::stat, i32) -> i32),
418 (link_name, abi, args),
419 )?;
420 let result = this.fstatat(dirfd, path, buf, flags)?;
421 this.write_scalar(result, dest)?;
422 }
423 "chmod" => {
424 let [path, mode] = &this.check_shim_sig(
425 shim_sig!(extern "C" fn(*_, libc::mode_t) -> i32),
426 (link_name, abi, args),
427 )?;
428 let result = this.chmod(path, mode)?;
429 this.write_scalar(result, dest)?;
430 }
431 "fchmod" => {
432 let [fd, mode] = &this.check_shim_sig(
433 shim_sig!(extern "C" fn(i32, libc::mode_t) -> i32),
434 (link_name, abi, args),
435 )?;
436 let result = this.fchmod(fd, mode)?;
437 this.write_scalar(result, dest)?;
438 }
439 "rename" => {
440 let [oldpath, newpath] = &this.check_shim_sig(
441 shim_sig!(extern "C" fn(*_, *_) -> i32),
442 (link_name, abi, args),
443 )?;
444 let result = this.rename(oldpath, newpath)?;
445 this.write_scalar(result, dest)?;
446 }
447 "mkdir" => {
448 let [path, mode] = &this.check_shim_sig(
449 shim_sig!(extern "C" fn(*_, libc::mode_t) -> i32),
450 (link_name, abi, args),
451 )?;
452 let result = this.mkdir(path, mode)?;
453 this.write_scalar(result, dest)?;
454 }
455 "rmdir" => {
456 let [path] = &this
457 .check_shim_sig(shim_sig!(extern "C" fn(*_) -> i32), (link_name, abi, args))?;
458 let result = this.rmdir(path)?;
459 this.write_scalar(result, dest)?;
460 }
461 "opendir" => {
462 let [name] = &this
463 .check_shim_sig(shim_sig!(extern "C" fn(*_) -> *_), (link_name, abi, args))?;
464 let result = this.opendir(name)?;
465 this.write_scalar(result, dest)?;
466 }
467 "closedir" => {
468 let [dirp] = &this
469 .check_shim_sig(shim_sig!(extern "C" fn(*_) -> i32), (link_name, abi, args))?;
470 let result = this.closedir(dirp)?;
471 this.write_scalar(result, dest)?;
472 }
473 "readdir" => {
474 let [dirp] = &this
475 .check_shim_sig(shim_sig!(extern "C" fn(*_) -> *_), (link_name, abi, args))?;
476 this.readdir(dirp, dest, "dirent")?;
477 }
478 "dirfd" => {
479 let [dirp] = &this
480 .check_shim_sig(shim_sig!(extern "C" fn(*_) -> i32), (link_name, abi, args))?;
481 this.dirfd(dirp, dest)?;
482 }
483 "lseek" => {
484 let [fd, offset, whence] = &this.check_shim_sig(
485 shim_sig!(extern "C" fn(i32, libc::off_t, i32) -> libc::off_t),
486 (link_name, abi, args),
487 )?;
488 let fd = this.read_scalar(fd)?.to_i32()?;
489 let offset = this.read_scalar(offset)?.to_int(offset.layout.size)?;
490 let whence = this.read_scalar(whence)?.to_i32()?;
491 this.lseek(fd, offset, whence, dest)?;
492 }
493 "ftruncate" => {
494 let [fd, length] = &this.check_shim_sig(
495 shim_sig!(extern "C" fn(i32, libc::off_t) -> i32),
496 (link_name, abi, args),
497 )?;
498 let fd = this.read_scalar(fd)?.to_i32()?;
499 let length = this.read_scalar(length)?.to_int(length.layout.size)?;
500 let result = this.ftruncate64(fd, length)?;
501 this.write_scalar(result, dest)?;
502 }
503 "fsync" => {
504 let [fd] = &this
505 .check_shim_sig(shim_sig!(extern "C" fn(i32) -> i32), (link_name, abi, args))?;
506 let result = this.fsync(fd)?;
507 this.write_scalar(result, dest)?;
508 }
509 "fdatasync" => {
510 this.check_target_os(
512 &[Os::Linux, Os::FreeBsd, Os::NetBsd, Os::Solaris, Os::Illumos, Os::Android],
513 link_name,
514 )?;
515 let [fd] = &this
516 .check_shim_sig(shim_sig!(extern "C" fn(i32) -> i32), (link_name, abi, args))?;
517 let result = this.fdatasync(fd)?;
518 this.write_scalar(result, dest)?;
519 }
520 "futimens" => {
521 let [fd, times] = &this.check_shim_sig(
522 shim_sig!(extern "C" fn(i32, *libc::timespec) -> i32),
523 (link_name, abi, args),
524 )?;
525 let result = this.futimens(fd, times)?;
526 this.write_scalar(result, dest)?;
527 }
528 "utimensat" => {
529 let [dirfd, path, times, flags] = &this.check_shim_sig(
530 shim_sig!(extern "C" fn(i32, *_, *libc::timespec, i32) -> i32),
531 (link_name, abi, args),
532 )?;
533 let result = this.utimensat(dirfd, path, times, flags)?;
534 this.write_scalar(result, dest)?;
535 }
536 "readlink" => {
537 let [pathname, buf, bufsize] = &this.check_shim_sig(
538 shim_sig!(extern "C" fn(*_, *_, usize) -> isize),
539 (link_name, abi, args),
540 )?;
541 let result = this.readlink(pathname, buf, bufsize)?;
542 this.write_scalar(Scalar::from_target_isize(result, this), dest)?;
543 }
544 "posix_fadvise" => {
545 let [fd, offset, len, advice] = &this.check_shim_sig(
546 shim_sig!(extern "C" fn(i32, libc::off_t, libc::off_t, i32) -> i32),
547 (link_name, abi, args),
548 )?;
549 this.read_scalar(fd)?.to_i32()?;
550 this.read_scalar(offset)?.to_int(offset.layout.size)?;
551 this.read_scalar(len)?.to_int(len.layout.size)?;
552 this.read_scalar(advice)?.to_i32()?;
553 this.write_int(0, dest)?;
555 }
556
557 "posix_fallocate" => {
558 this.check_target_os(
560 &[Os::Linux, Os::FreeBsd, Os::Solaris, Os::Illumos, Os::Android],
561 link_name,
562 )?;
563
564 let [fd, offset, len] = &this.check_shim_sig(
565 shim_sig!(extern "C" fn(i32, libc::off_t, libc::off_t) -> i32),
566 (link_name, abi, args),
567 )?;
568
569 let fd = this.read_scalar(fd)?.to_i32()?;
570 let offset =
572 i64::try_from(this.read_scalar(offset)?.to_int(offset.layout.size)?).unwrap();
573 let len = i64::try_from(this.read_scalar(len)?.to_int(len.layout.size)?).unwrap();
574
575 let result = this.posix_fallocate(fd, offset, len)?;
576 this.write_scalar(result, dest)?;
577 }
578
579 "realpath" => {
580 let [path, resolved_path] = &this.check_shim_sig(
581 shim_sig!(extern "C" fn(*_, *_) -> *_),
582 (link_name, abi, args),
583 )?;
584 let result = this.realpath(path, resolved_path)?;
585 this.write_scalar(result, dest)?;
586 }
587 "mkstemp" => {
588 let [template] = &this
589 .check_shim_sig(shim_sig!(extern "C" fn(*_) -> i32), (link_name, abi, args))?;
590 let result = this.mkstemp(template)?;
591 this.write_scalar(result, dest)?;
592 }
593
594 "poll" => {
596 let [fds, nfds, timeout] = &this.check_shim_sig(
597 shim_sig!(extern "C" fn(*libc::pollfd, libc::nfds_t, i32) -> i32),
598 (link_name, abi, args),
599 )?;
600 this.poll(fds, nfds, timeout, dest)?;
601 }
602
603 "socketpair" => {
605 let [domain, type_, protocol, sv] = &this.check_shim_sig(
606 shim_sig!(extern "C" fn(i32, i32, i32, *i32) -> i32),
607 (link_name, abi, args),
608 )?;
609 let result = this.socketpair(domain, type_, protocol, sv)?;
610 this.write_scalar(result, dest)?;
611 }
612 "pipe" => {
613 let [pipefd] = &this.check_shim_sig(
614 shim_sig!(extern "C" fn(*i32) -> i32),
615 (link_name, abi, args),
616 )?;
617 let result = this.pipe2(pipefd, None)?;
618 this.write_scalar(result, dest)?;
619 }
620 "pipe2" => {
621 this.check_target_os(
623 &[Os::Linux, Os::Android, Os::FreeBsd, Os::Solaris, Os::Illumos],
624 link_name,
625 )?;
626
627 let [pipefd, flags] = &this.check_shim_sig(
628 shim_sig!(extern "C" fn(*i32, i32) -> i32),
629 (link_name, abi, args),
630 )?;
631 let result = this.pipe2(pipefd, Some(flags))?;
632 this.write_scalar(result, dest)?;
633 }
634 "socket" => {
635 let [domain, type_, protocol] = &this.check_shim_sig(
636 shim_sig!(extern "C" fn(i32, i32, i32) -> i32),
637 (link_name, abi, args),
638 )?;
639 let result = this.socket(domain, type_, protocol)?;
640 this.write_scalar(result, dest)?;
641 }
642 "bind" => {
643 let [socket, address, address_len] = &this.check_shim_sig(
644 shim_sig!(extern "C" fn(i32, *libc::sockaddr, libc::socklen_t) -> i32),
645 (link_name, abi, args),
646 )?;
647 let result = this.bind(socket, address, address_len)?;
648 this.write_scalar(result, dest)?;
649 }
650 "listen" => {
651 let [socket, backlog] = &this.check_shim_sig(
652 shim_sig!(extern "C" fn(i32, i32) -> i32),
653 (link_name, abi, args),
654 )?;
655 let result = this.listen(socket, backlog)?;
656 this.write_scalar(result, dest)?;
657 }
658 "accept" => {
659 let [socket, address, address_len] = &this.check_shim_sig(
660 shim_sig!(extern "C" fn(i32, *libc::sockaddr, *libc::socklen_t) -> i32),
661 (link_name, abi, args),
662 )?;
663 this.accept4(socket, address, address_len, None, dest)?;
664 }
665 "accept4" => {
666 let [socket, address, address_len, flags] = &this.check_shim_sig(
667 shim_sig!(extern "C" fn(i32, *libc::sockaddr, *libc::socklen_t, i32) -> i32),
668 (link_name, abi, args),
669 )?;
670 this.accept4(socket, address, address_len, Some(flags), dest)?;
671 }
672 "connect" => {
673 let [socket, address, address_len] = &this.check_shim_sig(
674 shim_sig!(extern "C" fn(i32, *libc::sockaddr, libc::socklen_t) -> i32),
675 (link_name, abi, args),
676 )?;
677 this.connect(socket, address, address_len, dest)?;
678 }
679 "send" => {
680 let [socket, buffer, length, flags] = &this.check_shim_sig(
681 shim_sig!(extern "C" fn(i32, *_, libc::size_t, i32) -> libc::ssize_t),
682 (link_name, abi, args),
683 )?;
684 this.send(socket, buffer, length, flags, None, dest)?;
685 }
686 "sendto" => {
687 let [socket, buffer, length, flags, dest_addr, dest_addr_len] = &this.check_shim_sig(
688 shim_sig!(extern "C" fn(i32, *_, libc::size_t, i32, *libc::sockaddr, libc::socklen_t) -> libc::ssize_t),
689 (link_name, abi, args),
690 )?;
691 this.send(socket, buffer, length, flags, Some((dest_addr, dest_addr_len)), dest)?;
692 }
693 "recv" => {
694 let [socket, buffer, length, flags] = &this.check_shim_sig(
695 shim_sig!(extern "C" fn(i32, *_, libc::size_t, i32) -> libc::ssize_t),
696 (link_name, abi, args),
697 )?;
698 this.recv(socket, buffer, length, flags, None, dest)?;
699 }
700 "recvfrom" => {
701 let [socket, buffer, length, flags, dest_addr, dest_addr_len] = &this.check_shim_sig(
702 shim_sig!(extern "C" fn(i32, *_, libc::size_t, i32, *libc::sockaddr, *libc::socklen_t) -> libc::ssize_t),
703 (link_name, abi, args),
704 )?;
705 this.recv(socket, buffer, length, flags, Some((dest_addr, dest_addr_len)), dest)?;
706 }
707 "setsockopt" => {
708 let [socket, level, option_name, option_value, option_len] = &this.check_shim_sig(
709 shim_sig!(extern "C" fn(i32, i32, i32, *_, libc::socklen_t) -> i32),
710 (link_name, abi, args),
711 )?;
712 let result =
713 this.setsockopt(socket, level, option_name, option_value, option_len)?;
714 this.write_scalar(result, dest)?;
715 }
716 "getsockopt" => {
717 let [socket, level, option_name, option_value, option_len] = &this.check_shim_sig(
718 shim_sig!(extern "C" fn(i32, i32, i32, *_, *_) -> i32),
719 (link_name, abi, args),
720 )?;
721 let result =
722 this.getsockopt(socket, level, option_name, option_value, option_len)?;
723 this.write_scalar(result, dest)?;
724 }
725 "getsockname" => {
726 let [socket, address, address_len] = &this.check_shim_sig(
727 shim_sig!(extern "C" fn(i32, *libc::sockaddr, *libc::socklen_t) -> i32),
728 (link_name, abi, args),
729 )?;
730 let result = this.getsockname(socket, address, address_len)?;
731 this.write_scalar(result, dest)?;
732 }
733 "getpeername" => {
734 let [socket, address, address_len] = &this.check_shim_sig(
735 shim_sig!(extern "C" fn(i32, *libc::sockaddr, *libc::socklen_t) -> i32),
736 (link_name, abi, args),
737 )?;
738 this.getpeername(socket, address, address_len, dest)?;
739 }
740 "shutdown" => {
741 let [sockfd, how] = &this.check_shim_sig(
742 shim_sig!(extern "C" fn(i32, i32) -> i32),
743 (link_name, abi, args),
744 )?;
745 let result = this.shutdown(sockfd, how)?;
746 this.write_scalar(result, dest)?;
747 }
748 "getaddrinfo" => {
749 let [node, service, hints, res] = &this.check_shim_sig(
750 shim_sig!(extern "C" fn(*_, *_, *_, **_) -> i32),
751 (link_name, abi, args),
752 )?;
753 let result = this.getaddrinfo(node, service, hints, res)?;
754 this.write_scalar(result, dest)?;
755 }
756 "freeaddrinfo" => {
757 let [res] = &this
758 .check_shim_sig(shim_sig!(extern "C" fn(*_) -> ()), (link_name, abi, args))?;
759 this.freeaddrinfo(res)?;
760 }
761
762 "gettimeofday" => {
764 let [tv, tz] = &this.check_shim_sig(
765 shim_sig!(extern "C" fn(*libc::timeval, *libc::timezone) -> i32),
766 (link_name, abi, args),
767 )?;
768 let result = this.gettimeofday(tv, tz)?;
769 this.write_scalar(result, dest)?;
770 }
771 "localtime_r" => {
772 let [timep, result_op] = &this.check_shim_sig(
773 shim_sig!(extern "C" fn(*libc::time_t, *libc::tm) -> *libc::tm),
774 (link_name, abi, args),
775 )?;
776 let result = this.localtime_r(timep, result_op)?;
777 this.write_pointer(result, dest)?;
778 }
779 "clock_gettime" => {
780 let [clk_id, tp] = &this.check_shim_sig(
781 shim_sig!(extern "C" fn(libc::clockid_t, *libc::timespec) -> i32),
782 (link_name, abi, args),
783 )?;
784 this.clock_gettime(clk_id, tp, dest)?;
785 }
786
787 "posix_memalign" => {
789 let [memptr, align, size] = &this.check_shim_sig(
790 shim_sig!(extern "C" fn(**_, usize, usize) -> i32),
791 (link_name, abi, args),
792 )?;
793 let result = this.posix_memalign(memptr, align, size)?;
794 this.write_scalar(result, dest)?;
795 }
796
797 "mmap" => {
798 let [addr, length, prot, flags, fd, offset] = &this.check_shim_sig(
799 shim_sig!(extern "C" fn(*_, usize, i32, i32, i32, libc::off_t) -> *_),
800 (link_name, abi, args),
801 )?;
802 let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off_t").size)?;
803 let ptr = this.mmap(addr, length, prot, flags, fd, offset)?;
804 this.write_scalar(ptr, dest)?;
805 }
806 "munmap" => {
807 let [addr, length] = &this.check_shim_sig(
808 shim_sig!(extern "C" fn(*_, usize) -> i32),
809 (link_name, abi, args),
810 )?;
811 let result = this.munmap(addr, length)?;
812 this.write_scalar(result, dest)?;
813 }
814 "mprotect" => {
815 let [addr, length, prot] = &this.check_shim_sig(
816 shim_sig!(extern "C" fn(*_, usize, i32) -> i32),
817 (link_name, abi, args),
818 )?;
819 let result = this.mprotect(addr, length, prot)?;
820 this.write_scalar(result, dest)?;
821 }
822 "madvise" => {
823 let [addr, length, advice] = &this.check_shim_sig(
824 shim_sig!(extern "C" fn(*_, usize, i32) -> i32),
825 (link_name, abi, args),
826 )?;
827 let result = this.madvise(addr, length, advice)?;
828 this.write_scalar(result, dest)?;
829 }
830
831 "reallocarray" => {
832 this.check_target_os(&[Os::Linux, Os::FreeBsd, Os::Android], link_name)?;
834
835 let [ptr, nmemb, size] = &this.check_shim_sig(
836 shim_sig!(extern "C" fn(*_, usize, usize) -> *_),
837 (link_name, abi, args),
838 )?;
839 let ptr = this.read_pointer(ptr)?;
840 let nmemb = this.read_target_usize(nmemb)?;
841 let size = this.read_target_usize(size)?;
842 match this.compute_size_in_bytes(Size::from_bytes(size), nmemb) {
848 None => {
849 this.set_last_error(LibcError("ENOMEM"))?;
850 this.write_int(0, dest)?;
851 }
852 Some(len) => {
853 let res = this.realloc(ptr, len.bytes())?;
854 this.write_pointer(res, dest)?;
855 }
856 }
857 }
858 "aligned_alloc" => {
859 let [align, size] = &this.check_shim_sig(
862 shim_sig!(extern "C" fn(usize, usize) -> *_),
863 (link_name, abi, args),
864 )?;
865 let res = this.aligned_alloc(align, size)?;
866 this.write_pointer(res, dest)?;
867 }
868
869 "dlsym" => {
871 let [handle, symbol] = &this.check_shim_sig(
872 shim_sig!(extern "C" fn(*_, *_) -> *_),
873 (link_name, abi, args),
874 )?;
875 this.read_target_usize(handle)?;
876 let symbol = this.read_pointer(symbol)?;
877 let name = this.read_c_str(symbol)?;
878 let Ok(name) = str::from_utf8(name) else {
879 throw_unsup_format!("dlsym: non UTF-8 symbol name not supported")
880 };
881 if this.is_dyn_sym(name) {
882 let ptr = this.fn_ptr(FnVal::Other(DynSym::from_str(name)));
883 this.write_pointer(ptr, dest)?;
884 } else if let Some(&ptr) = this.machine.extern_statics.get(&Symbol::intern(name)) {
885 this.write_pointer(ptr, dest)?;
886 } else {
887 this.write_int(0, dest)?;
888 }
889 }
890
891 "pthread_key_create" => {
893 let [key, dtor] = &this.check_shim_sig(
894 shim_sig!(extern "C" fn(*libc::pthread_key_t, fn(..) -> _) -> i32),
895 (link_name, abi, args),
896 )?;
897 let key_place = this.deref_pointer(key)?;
898 let dtor = this.read_pointer(dtor)?;
899
900 let dtor = if !this.ptr_is_null(dtor)? {
902 Some((
903 this.get_ptr_fn(dtor)?.as_instance()?,
904 this.machine.current_user_relevant_span(),
905 ))
906 } else {
907 None
908 };
909
910 let key = this.machine.tls.create_tls_key(dtor, key_place.layout.size)?;
912 this.write_scalar(Scalar::from_uint(key, key_place.layout.size), &key_place)?;
913
914 this.write_int(0, dest)?;
916 }
917 "pthread_key_delete" => {
918 let [key] = &this.check_shim_sig(
919 shim_sig!(extern "C" fn(libc::pthread_key_t) -> i32),
920 (link_name, abi, args),
921 )?;
922 let key = this.read_scalar(key)?.to_bits(key.layout.size)?;
923 this.machine.tls.delete_tls_key(key)?;
924 this.write_int(0, dest)?;
926 }
927 "pthread_getspecific" => {
928 let [key] = &this.check_shim_sig(
929 shim_sig!(extern "C" fn(libc::pthread_key_t) -> *_),
930 (link_name, abi, args),
931 )?;
932 let key = this.read_scalar(key)?.to_bits(key.layout.size)?;
933 let active_thread = this.active_thread();
934 let ptr = this.machine.tls.load_tls_key(key, active_thread)?;
935 this.write_pointer(ptr, dest)?;
936 }
937 "pthread_setspecific" => {
938 let [key, new_ptr] = &this.check_shim_sig(
939 shim_sig!(extern "C" fn(libc::pthread_key_t, *_) -> i32),
940 (link_name, abi, args),
941 )?;
942 let key = this.read_scalar(key)?.to_bits(key.layout.size)?;
943 let active_thread = this.active_thread();
944 let new_data = this.read_pointer(new_ptr)?;
945 this.machine.tls.store_tls_key(key, active_thread, new_data)?;
946
947 this.write_int(0, dest)?;
949 }
950
951 "pthread_mutexattr_init" => {
953 let [attr] = &this.check_shim_sig(
954 shim_sig!(extern "C" fn(*libc::pthread_mutexattr_t) -> i32),
955 (link_name, abi, args),
956 )?;
957 this.pthread_mutexattr_init(attr)?;
958 this.write_int(0, dest)?;
959 }
960 "pthread_mutexattr_settype" => {
961 let [attr, kind] = &this.check_shim_sig(
962 shim_sig!(extern "C" fn(*libc::pthread_mutexattr_t, i32) -> i32),
963 (link_name, abi, args),
964 )?;
965 let result = this.pthread_mutexattr_settype(attr, kind)?;
966 this.write_scalar(result, dest)?;
967 }
968 "pthread_mutexattr_destroy" => {
969 let [attr] = &this.check_shim_sig(
970 shim_sig!(extern "C" fn(*libc::pthread_mutexattr_t) -> i32),
971 (link_name, abi, args),
972 )?;
973 this.pthread_mutexattr_destroy(attr)?;
974 this.write_int(0, dest)?;
975 }
976 "pthread_mutex_init" => {
977 let [mutex, attr] = &this.check_shim_sig(
978 shim_sig!(extern "C" fn(*libc::pthread_mutex_t, *libc::pthread_mutexattr_t) -> i32),
979 (link_name, abi, args),
980 )?;
981 this.pthread_mutex_init(mutex, attr)?;
982 this.write_int(0, dest)?;
983 }
984 "pthread_mutex_lock" => {
985 let [mutex] = &this.check_shim_sig(
986 shim_sig!(extern "C" fn(*libc::pthread_mutex_t) -> i32),
987 (link_name, abi, args),
988 )?;
989 this.pthread_mutex_lock(mutex, dest)?;
990 }
991 "pthread_mutex_trylock" => {
992 let [mutex] = &this.check_shim_sig(
993 shim_sig!(extern "C" fn(*libc::pthread_mutex_t) -> i32),
994 (link_name, abi, args),
995 )?;
996 let result = this.pthread_mutex_trylock(mutex)?;
997 this.write_scalar(result, dest)?;
998 }
999 "pthread_mutex_unlock" => {
1000 let [mutex] = &this.check_shim_sig(
1001 shim_sig!(extern "C" fn(*libc::pthread_mutex_t) -> i32),
1002 (link_name, abi, args),
1003 )?;
1004 let result = this.pthread_mutex_unlock(mutex)?;
1005 this.write_scalar(result, dest)?;
1006 }
1007 "pthread_mutex_destroy" => {
1008 let [mutex] = &this.check_shim_sig(
1009 shim_sig!(extern "C" fn(*libc::pthread_mutex_t) -> i32),
1010 (link_name, abi, args),
1011 )?;
1012 this.pthread_mutex_destroy(mutex)?;
1013 this.write_int(0, dest)?;
1014 }
1015 "pthread_rwlock_rdlock" => {
1016 let [rwlock] = &this.check_shim_sig(
1017 shim_sig!(extern "C" fn(*libc::pthread_rwlock_t) -> i32),
1018 (link_name, abi, args),
1019 )?;
1020 this.pthread_rwlock_rdlock(rwlock, dest)?;
1021 }
1022 "pthread_rwlock_tryrdlock" => {
1023 let [rwlock] = &this.check_shim_sig(
1024 shim_sig!(extern "C" fn(*libc::pthread_rwlock_t) -> i32),
1025 (link_name, abi, args),
1026 )?;
1027 let result = this.pthread_rwlock_tryrdlock(rwlock)?;
1028 this.write_scalar(result, dest)?;
1029 }
1030 "pthread_rwlock_wrlock" => {
1031 let [rwlock] = &this.check_shim_sig(
1032 shim_sig!(extern "C" fn(*libc::pthread_rwlock_t) -> i32),
1033 (link_name, abi, args),
1034 )?;
1035 this.pthread_rwlock_wrlock(rwlock, dest)?;
1036 }
1037 "pthread_rwlock_trywrlock" => {
1038 let [rwlock] = &this.check_shim_sig(
1039 shim_sig!(extern "C" fn(*libc::pthread_rwlock_t) -> i32),
1040 (link_name, abi, args),
1041 )?;
1042 let result = this.pthread_rwlock_trywrlock(rwlock)?;
1043 this.write_scalar(result, dest)?;
1044 }
1045 "pthread_rwlock_unlock" => {
1046 let [rwlock] = &this.check_shim_sig(
1047 shim_sig!(extern "C" fn(*libc::pthread_rwlock_t) -> i32),
1048 (link_name, abi, args),
1049 )?;
1050 this.pthread_rwlock_unlock(rwlock)?;
1051 this.write_int(0, dest)?;
1052 }
1053 "pthread_rwlock_destroy" => {
1054 let [rwlock] = &this.check_shim_sig(
1055 shim_sig!(extern "C" fn(*libc::pthread_rwlock_t) -> i32),
1056 (link_name, abi, args),
1057 )?;
1058 this.pthread_rwlock_destroy(rwlock)?;
1059 this.write_int(0, dest)?;
1060 }
1061 "pthread_condattr_init" => {
1062 let [attr] = &this.check_shim_sig(
1063 shim_sig!(extern "C" fn(*libc::pthread_condattr_t) -> i32),
1064 (link_name, abi, args),
1065 )?;
1066 this.pthread_condattr_init(attr)?;
1067 this.write_int(0, dest)?;
1068 }
1069 "pthread_condattr_setclock" => {
1070 let [attr, clock_id] = &this.check_shim_sig(
1071 shim_sig!(extern "C" fn(*libc::pthread_condattr_t, i32) -> i32),
1072 (link_name, abi, args),
1073 )?;
1074 let result = this.pthread_condattr_setclock(attr, clock_id)?;
1075 this.write_scalar(result, dest)?;
1076 }
1077 "pthread_condattr_getclock" => {
1078 let [attr, clock_id] = &this.check_shim_sig(
1079 shim_sig!(extern "C" fn(*libc::pthread_condattr_t, *libc::clockid_t) -> i32),
1080 (link_name, abi, args),
1081 )?;
1082 this.pthread_condattr_getclock(attr, clock_id)?;
1083 this.write_int(0, dest)?;
1084 }
1085 "pthread_condattr_destroy" => {
1086 let [attr] = &this.check_shim_sig(
1087 shim_sig!(extern "C" fn(*libc::pthread_condattr_t) -> i32),
1088 (link_name, abi, args),
1089 )?;
1090 this.pthread_condattr_destroy(attr)?;
1091 this.write_int(0, dest)?;
1092 }
1093 "pthread_cond_init" => {
1094 let [cond, attr] = &this.check_shim_sig(
1095 shim_sig!(extern "C" fn(*libc::pthread_cond_t, *libc::pthread_condattr_t) -> i32),
1096 (link_name, abi, args),
1097 )?;
1098 this.pthread_cond_init(cond, attr)?;
1099 this.write_int(0, dest)?;
1100 }
1101 "pthread_cond_signal" => {
1102 let [cond] = &this.check_shim_sig(
1103 shim_sig!(extern "C" fn(*libc::pthread_cond_t) -> i32),
1104 (link_name, abi, args),
1105 )?;
1106 this.pthread_cond_signal(cond)?;
1107 this.write_int(0, dest)?;
1108 }
1109 "pthread_cond_broadcast" => {
1110 let [cond] = &this.check_shim_sig(
1111 shim_sig!(extern "C" fn(*libc::pthread_cond_t) -> i32),
1112 (link_name, abi, args),
1113 )?;
1114 this.pthread_cond_broadcast(cond)?;
1115 this.write_int(0, dest)?;
1116 }
1117 "pthread_cond_wait" => {
1118 let [cond, mutex] = &this.check_shim_sig(
1119 shim_sig!(extern "C" fn(*libc::pthread_cond_t, *libc::pthread_mutex_t) -> i32),
1120 (link_name, abi, args),
1121 )?;
1122 this.pthread_cond_wait(cond, mutex, dest)?;
1123 }
1124 "pthread_cond_timedwait" => {
1125 let [cond, mutex, abstime] = &this.check_shim_sig(
1126 shim_sig!(extern "C" fn(*libc::pthread_cond_t, *libc::pthread_mutex_t, *libc::timespec) -> i32),
1127 (link_name, abi, args),
1128 )?;
1129 this.pthread_cond_timedwait(
1130 cond, mutex, abstime, dest, false,
1131 )?;
1132 }
1133 "pthread_cond_destroy" => {
1134 let [cond] = &this.check_shim_sig(
1135 shim_sig!(extern "C" fn(*libc::pthread_cond_t) -> i32),
1136 (link_name, abi, args),
1137 )?;
1138 this.pthread_cond_destroy(cond)?;
1139 this.write_int(0, dest)?;
1140 }
1141 "sem_init" => {
1142 let [sem, pshared, value] = &this.check_shim_sig(
1143 shim_sig!(extern "C" fn(*libc::sem_t, i32, u32) -> i32),
1144 (link_name, abi, args),
1145 )?;
1146 this.pthread_sem_init(sem, pshared, value, dest)?;
1147 }
1148 "sem_wait" => {
1149 let [sem] = &this.check_shim_sig(
1150 shim_sig!(extern "C" fn(*libc::sem_t) -> i32),
1151 (link_name, abi, args),
1152 )?;
1153 this.pthread_sem_wait(sem, dest)?;
1154 }
1155 "sem_timedwait" => {
1156 let [sem, abs_timeout] = &this.check_shim_sig(
1157 shim_sig!(extern "C" fn(*libc::sem_t, *libc::timespec) -> i32),
1158 (link_name, abi, args),
1159 )?;
1160 this.pthread_sem_timedwait(sem, abs_timeout, dest)?;
1161 }
1162 "sem_post" => {
1163 let [sem] = &this.check_shim_sig(
1164 shim_sig!(extern "C" fn(*libc::sem_t) -> i32),
1165 (link_name, abi, args),
1166 )?;
1167 this.pthread_sem_post(sem, dest)?;
1168 }
1169 "sem_destroy" => {
1170 let [sem] = &this.check_shim_sig(
1171 shim_sig!(extern "C" fn(*libc::sem_t) -> i32),
1172 (link_name, abi, args),
1173 )?;
1174 this.pthread_sem_destroy(sem, dest)?;
1175 }
1176
1177 "pthread_create" => {
1179 let [thread, attr, start, arg] = &this.check_shim_sig(
1180 shim_sig!(extern "C" fn(*libc::pthread_t, *_, fn(..) -> _, *_) -> i32),
1181 (link_name, abi, args),
1182 )?;
1183 this.pthread_create(thread, attr, start, arg)?;
1184 this.write_int(0, dest)?;
1185 }
1186 "pthread_join" => {
1187 let [thread, retval] = &this.check_shim_sig(
1188 shim_sig!(extern "C" fn(libc::pthread_t, *_) -> i32),
1189 (link_name, abi, args),
1190 )?;
1191 this.pthread_join(thread, retval, dest)?;
1192 }
1193 "pthread_detach" => {
1194 let [thread] = &this.check_shim_sig(
1195 shim_sig!(extern "C" fn(libc::pthread_t) -> i32),
1196 (link_name, abi, args),
1197 )?;
1198 let res = this.pthread_detach(thread)?;
1199 this.write_scalar(res, dest)?;
1200 }
1201 "pthread_self" => {
1202 let [] = &this.check_shim_sig(
1203 shim_sig!(extern "C" fn() -> libc::pthread_t),
1204 (link_name, abi, args),
1205 )?;
1206 let res = this.pthread_self()?;
1207 this.write_scalar(res, dest)?;
1208 }
1209 "sched_yield" => {
1210 let [] = &this
1212 .check_shim_sig(shim_sig!(extern "C" fn() -> i32), (link_name, abi, args))?;
1213 this.sched_yield()?;
1214 this.write_int(0, dest)?;
1215 }
1216 "nanosleep" => {
1217 let [duration, rem] = &this.check_shim_sig(
1218 shim_sig!(extern "C" fn(*libc::timespec, *_) -> i32),
1219 (link_name, abi, args),
1220 )?;
1221 let result = this.nanosleep(duration, rem)?;
1222 this.write_scalar(result, dest)?;
1223 }
1224 "clock_nanosleep" => {
1225 this.check_target_os(
1227 &[Os::FreeBsd, Os::Linux, Os::Android, Os::Solaris, Os::Illumos],
1228 link_name,
1229 )?;
1230
1231 let [clock_id, flags, req, rem] = &this.check_shim_sig(
1232 shim_sig!(extern "C" fn(libc::clockid_t, i32, *libc::timespec, *_) -> i32),
1233 (link_name, abi, args),
1234 )?;
1235 let result = this.clock_nanosleep(clock_id, flags, req, rem)?;
1236 this.write_scalar(result, dest)?;
1237 }
1238 "sched_getaffinity" => {
1239 this.check_target_os(&[Os::Linux, Os::FreeBsd, Os::Android], link_name)?;
1241
1242 let [pid, cpusetsize, mask] = &this.check_shim_sig(
1243 shim_sig!(extern "C" fn(libc::pid_t, usize, *_) -> i32),
1244 (link_name, abi, args),
1245 )?;
1246 this.sched_getaffinity(pid, cpusetsize, mask, dest)?;
1247 }
1248 "sched_setaffinity" => {
1249 this.check_target_os(&[Os::Linux, Os::FreeBsd, Os::Android], link_name)?;
1251
1252 let [pid, cpusetsize, mask] = &this.check_shim_sig(
1253 shim_sig!(extern "C" fn(libc::pid_t, usize, *_) -> i32),
1254 (link_name, abi, args),
1255 )?;
1256 this.sched_setaffinity(pid, cpusetsize, mask, dest)?;
1257 }
1258
1259 "isatty" => {
1261 let [fd] = &this
1262 .check_shim_sig(shim_sig!(extern "C" fn(i32) -> i32), (link_name, abi, args))?;
1263 let result = this.isatty(fd)?;
1264 this.write_scalar(result, dest)?;
1265 }
1266 "pthread_atfork" => {
1267 let [prepare, parent, child] = &this.check_shim_sig(
1269 shim_sig!(extern "C" fn(fn(..) -> _, fn(..) -> _, fn(..) -> _) -> i32),
1270 (link_name, abi, args),
1271 )?;
1272 this.read_pointer(prepare)?;
1273 this.read_pointer(parent)?;
1274 this.read_pointer(child)?;
1275 this.write_int(0, dest)?;
1277 }
1278 "strerror_r" => {
1279 let [errnum, buf, buflen] = &this.check_shim_sig(
1280 shim_sig!(extern "C" fn(i32, *_, usize) -> i32),
1281 (link_name, abi, args),
1282 )?;
1283 let result = this.strerror_r(errnum, buf, buflen)?;
1284 this.write_scalar(result, dest)?;
1285 }
1286 "getentropy" => {
1287 this.check_target_os(
1290 &[Os::Linux, Os::MacOs, Os::FreeBsd, Os::Illumos, Os::Solaris, Os::Android],
1291 link_name,
1292 )?;
1293
1294 let [buf, bufsize] = &this.check_shim_sig(
1295 shim_sig!(extern "C" fn(*_, usize) -> i32),
1296 (link_name, abi, args),
1297 )?;
1298 let buf = this.read_pointer(buf)?;
1299 let bufsize = this.read_target_usize(bufsize)?;
1300
1301 if bufsize > 256 {
1307 this.set_errno_and_return_neg1(LibcError("EIO"), dest)?;
1308 } else {
1309 this.gen_random(buf, bufsize)?;
1310 this.write_int(0, dest)?;
1311 }
1312 }
1313 "getrandom" => {
1314 this.check_target_os(
1317 &[Os::Linux, Os::FreeBsd, Os::Illumos, Os::Solaris, Os::Android],
1318 link_name,
1319 )?;
1320
1321 let [ptr, len, flags] = &this.check_shim_sig(
1322 shim_sig!(extern "C" fn(*_, usize, u32) -> isize),
1323 (link_name, abi, args),
1324 )?;
1325 let ptr = this.read_pointer(ptr)?;
1326 let len = this.read_target_usize(len)?;
1327 let _flags = this.read_scalar(flags)?.to_i32()?;
1328 this.gen_random(ptr, len)?;
1330 this.write_scalar(Scalar::from_target_usize(len, this), dest)?;
1331 }
1332 "arc4random_buf" => {
1333 this.check_target_os(&[Os::FreeBsd, Os::Illumos, Os::Solaris], link_name)?;
1336
1337 let [ptr, len] = &this.check_shim_sig(
1338 shim_sig!(extern "C" fn(*_, usize) -> ()),
1339 (link_name, abi, args),
1340 )?;
1341 let ptr = this.read_pointer(ptr)?;
1342 let len = this.read_target_usize(len)?;
1343 this.gen_random(ptr, len)?;
1344 }
1345 "_Unwind_RaiseException" => {
1346 this.check_target_os(
1360 &[Os::Linux, Os::FreeBsd, Os::Illumos, Os::Solaris, Os::Android, Os::MacOs],
1361 link_name,
1362 )?;
1363
1364 let [payload] = &this.check_shim_sig(
1366 shim_sig!(extern "C" fn(*_) -> panic_unwind::imp::uw::_Unwind_Reason_Code),
1369 (link_name, abi, args),
1370 )?;
1371 this.handle_miri_start_unwind(payload)?;
1372 return interp_ok(EmulateItemResult::NeedsUnwind);
1373 }
1374 "getuid" | "geteuid" => {
1375 let [] = &this.check_shim_sig(
1376 shim_sig!(extern "C" fn() -> libc::uid_t),
1377 (link_name, abi, args),
1378 )?;
1379 this.write_int(UID, dest)?;
1381 }
1382 "pause" => {
1383 let [] = &this
1384 .check_shim_sig(shim_sig!(extern "C" fn() -> i32), (link_name, abi, args))?;
1385 this.block_thread(
1388 BlockReason::Pause,
1389 None,
1390 callback!(@capture<'tcx> {}
1391 |_ecx, _unblock: UnblockKind| {
1392 panic!("should never unblock")
1393 }),
1394 );
1395 }
1396
1397 "pthread_attr_getguardsize" if this.frame_in_std() => {
1400 let [_attr, guard_size] = &this.check_shim_sig(
1401 shim_sig!(extern "C" fn(*_, *usize) -> i32),
1402 (link_name, abi, args),
1403 )?;
1404 let guard_size = this.deref_pointer(guard_size)?;
1405 this.write_scalar(
1406 Scalar::from_uint(this.machine.page_size, guard_size.layout.size),
1407 &guard_size,
1408 )?;
1409
1410 this.write_int(0, dest)?;
1412 }
1413
1414 "pthread_attr_init" | "pthread_attr_destroy" if this.frame_in_std() => {
1415 let [_] = &this
1416 .check_shim_sig(shim_sig!(extern "C" fn(*_) -> i32), (link_name, abi, args))?;
1417 this.write_int(0, dest)?;
1418 }
1419
1420 "pthread_attr_setstacksize" if this.frame_in_std() => {
1421 let [_, _] = &this.check_shim_sig(
1422 shim_sig!(extern "C" fn(*_, usize) -> i32),
1423 (link_name, abi, args),
1424 )?;
1425 this.write_int(0, dest)?;
1426 }
1427
1428 "pthread_attr_getstack" if this.frame_in_std() => {
1429 let [attr_place, addr_place, size_place] = &this.check_shim_sig(
1432 shim_sig!(extern "C" fn(*libc::pthread_attr_t, *usize, *usize) -> i32),
1433 (link_name, abi, args),
1434 )?;
1435 let _attr_place = this.deref_pointer(attr_place)?;
1436 let addr_place = this.deref_pointer(addr_place)?;
1437 let size_place = this.deref_pointer(size_place)?;
1438
1439 this.write_scalar(
1440 Scalar::from_uint(this.machine.stack_addr, this.pointer_size()),
1441 &addr_place,
1442 )?;
1443 this.write_scalar(
1444 Scalar::from_uint(this.machine.stack_size, this.pointer_size()),
1445 &size_place,
1446 )?;
1447
1448 this.write_int(0, dest)?;
1450 }
1451
1452 "signal" if this.frame_in_std() => {
1453 let [_, _] = &this.check_shim_sig(
1454 shim_sig!(extern "C" fn(i32, libc::sighandler_t) -> libc::sighandler_t),
1455 (link_name, abi, args),
1456 )?;
1457 this.write_int(0, dest)?;
1458 }
1459 "sigaltstack" if this.frame_in_std() => {
1460 let [_, _] = &this.check_shim_sig(
1461 shim_sig!(extern "C" fn(*_, *_) -> i32),
1462 (link_name, abi, args),
1463 )?;
1464 this.write_int(0, dest)?;
1465 }
1466 "sigaction" if this.frame_in_std() => {
1467 let [_, _, _] = &this.check_shim_sig(
1468 shim_sig!(extern "C" fn(i32, *_, *_) -> i32),
1469 (link_name, abi, args),
1470 )?;
1471 this.write_int(0, dest)?;
1472 }
1473
1474 "getpwuid_r" | "__posix_getpwuid_r" if this.frame_in_std() => {
1475 let [uid, pwd, buf, buflen, result] = &this.check_shim_sig(
1477 shim_sig!(extern "C" fn(libc::uid_t, *libc::passwd, *_, usize, **_) -> i32),
1478 (link_name, abi, args),
1479 )?;
1480 this.check_no_isolation("`getpwuid_r`")?;
1481
1482 let uid = this.read_scalar(uid)?.to_u32()?;
1483 let pwd = this.deref_pointer(pwd)?;
1484 let buf = this.read_pointer(buf)?;
1485 let buflen = this.read_target_usize(buflen)?;
1486 let result = this.deref_pointer(result)?;
1487
1488 if uid != UID {
1490 throw_unsup_format!("`getpwuid_r` on other users is not supported");
1491 }
1492
1493 this.write_uninit(&pwd)?;
1496
1497 #[allow(deprecated)]
1499 let home_dir = std::env::home_dir().unwrap();
1500 let (written, _) = this.write_path_to_c_str(&home_dir, buf, buflen)?;
1501 let pw_dir = this.project_field_named(&pwd, "pw_dir")?;
1502 this.write_pointer(buf, &pw_dir)?;
1503
1504 if written {
1505 this.write_pointer(pwd.ptr(), &result)?;
1506 this.write_int(0, dest)?;
1507 } else {
1508 this.write_int(0, &result)?;
1509 this.write_scalar(this.eval_libc("ERANGE"), dest)?;
1510 }
1511 }
1512
1513 _ => {
1515 let target_os = &this.tcx.sess.target.os;
1516 return match target_os {
1517 Os::Android =>
1518 android::EvalContextExt::emulate_foreign_item_inner(
1519 this, link_name, abi, args, dest,
1520 ),
1521 Os::FreeBsd =>
1522 freebsd::EvalContextExt::emulate_foreign_item_inner(
1523 this, link_name, abi, args, dest,
1524 ),
1525 Os::Linux =>
1526 linux::EvalContextExt::emulate_foreign_item_inner(
1527 this, link_name, abi, args, dest,
1528 ),
1529 Os::MacOs =>
1530 macos::EvalContextExt::emulate_foreign_item_inner(
1531 this, link_name, abi, args, dest,
1532 ),
1533 Os::Solaris | Os::Illumos =>
1534 solarish::EvalContextExt::emulate_foreign_item_inner(
1535 this, link_name, abi, args, dest,
1536 ),
1537 Os::NetBsd =>
1538 netbsd::EvalContextExt::emulate_foreign_item_inner(
1539 this, link_name, abi, args, dest,
1540 ),
1541 _ => interp_ok(EmulateItemResult::NotSupported),
1542 };
1543 }
1544 };
1545
1546 interp_ok(EmulateItemResult::NeedsReturn)
1547 }
1548}