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