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