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