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(
346 &[Os::Linux, Os::Android, Os::FreeBsd, Os::MacOs, Os::Illumos],
347 link_name,
348 )?;
349
350 let [fd, op] = this.check_shim_sig(
351 shim_sig!(extern "C" fn(i32, i32) -> i32),
352 link_name,
353 abi,
354 args,
355 )?;
356 let fd = this.read_scalar(fd)?.to_i32()?;
357 let op = this.read_scalar(op)?.to_i32()?;
358 let result = this.flock(fd, op)?;
359 this.write_scalar(result, dest)?;
360 }
361 "ioctl" => {
362 let ([fd, op], varargs) =
363 this.check_shim_sig_variadic_lenient(abi, CanonAbi::C, link_name, args)?;
364 let result = this.ioctl(fd, op, varargs)?;
365 this.write_scalar(result, dest)?;
366 }
367
368 "open" => {
370 let ([path_raw, flag], varargs) =
373 this.check_shim_sig_variadic_lenient(abi, CanonAbi::C, link_name, args)?;
374 let result = this.open(path_raw, flag, varargs)?;
375 this.write_scalar(result, dest)?;
376 }
377 "unlink" => {
378 let [path] = this.check_shim_sig(
380 shim_sig!(extern "C" fn(*const _) -> i32),
381 link_name,
382 abi,
383 args,
384 )?;
385 let result = this.unlink(path)?;
386 this.write_scalar(result, dest)?;
387 }
388 "symlink" => {
389 let [target, linkpath] = this.check_shim_sig(
391 shim_sig!(extern "C" fn(*const _, *const _) -> i32),
392 link_name,
393 abi,
394 args,
395 )?;
396 let result = this.symlink(target, linkpath)?;
397 this.write_scalar(result, dest)?;
398 }
399 "linkat" => {
400 let [oldfd, oldpath, newfd, newpath, flags] = this.check_shim_sig(
401 shim_sig!(extern "C" fn(i32, *const _, i32, *const _, i32) -> i32),
402 link_name,
403 abi,
404 args,
405 )?;
406 let result = this.linkat(oldfd, oldpath, newfd, newpath, flags)?;
407 this.write_scalar(result, dest)?;
408 }
409 "fstat" => {
410 let [fd, buf] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
411 let result = this.fstat(fd, buf)?;
412 this.write_scalar(result, dest)?;
413 }
414 "lstat" => {
415 let [path, buf] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
416 let result = this.lstat(path, buf)?;
417 this.write_scalar(result, dest)?;
418 }
419 "stat" => {
420 let [path, buf] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
421 let result = this.stat(path, buf)?;
422 this.write_scalar(result, dest)?;
423 }
424 "chmod" => {
425 let [path, mode] = this.check_shim_sig(
426 shim_sig!(extern "C" fn(*const _, libc::mode_t) -> i32),
427 link_name,
428 abi,
429 args,
430 )?;
431 let result = this.chmod(path, mode)?;
432 this.write_scalar(result, dest)?;
433 }
434 "fchmod" => {
435 let [fd, mode] = this.check_shim_sig(
436 shim_sig!(extern "C" fn(i32, libc::mode_t) -> i32),
437 link_name,
438 abi,
439 args,
440 )?;
441 let result = this.fchmod(fd, mode)?;
442 this.write_scalar(result, dest)?;
443 }
444 "rename" => {
445 let [oldpath, newpath] = this.check_shim_sig(
447 shim_sig!(extern "C" fn(*const _, *const _) -> i32),
448 link_name,
449 abi,
450 args,
451 )?;
452 let result = this.rename(oldpath, newpath)?;
453 this.write_scalar(result, dest)?;
454 }
455 "mkdir" => {
456 let [path, mode] = this.check_shim_sig(
458 shim_sig!(extern "C" fn(*const _, libc::mode_t) -> i32),
459 link_name,
460 abi,
461 args,
462 )?;
463 let result = this.mkdir(path, mode)?;
464 this.write_scalar(result, dest)?;
465 }
466 "rmdir" => {
467 let [path] = this.check_shim_sig(
469 shim_sig!(extern "C" fn(*const _) -> i32),
470 link_name,
471 abi,
472 args,
473 )?;
474 let result = this.rmdir(path)?;
475 this.write_scalar(result, dest)?;
476 }
477 "opendir" => {
478 let [name] = this.check_shim_sig(
479 shim_sig!(extern "C" fn(*const _) -> *mut _),
480 link_name,
481 abi,
482 args,
483 )?;
484 let result = this.opendir(name)?;
485 this.write_scalar(result, dest)?;
486 }
487 "closedir" => {
488 let [dirp] = this.check_shim_sig(
489 shim_sig!(extern "C" fn(*mut _) -> i32),
490 link_name,
491 abi,
492 args,
493 )?;
494 let result = this.closedir(dirp)?;
495 this.write_scalar(result, dest)?;
496 }
497 "readdir" => {
498 let [dirp] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
499 this.readdir(dirp, dest)?;
500 }
501 "lseek" => {
502 let [fd, offset, whence] = this.check_shim_sig(
504 shim_sig!(extern "C" fn(i32, libc::off_t, i32) -> libc::off_t),
505 link_name,
506 abi,
507 args,
508 )?;
509 let fd = this.read_scalar(fd)?.to_i32()?;
510 let offset = this.read_scalar(offset)?.to_int(offset.layout.size)?;
511 let whence = this.read_scalar(whence)?.to_i32()?;
512 this.lseek(fd, offset, whence, dest)?;
513 }
514 "ftruncate" => {
515 let [fd, length] = this.check_shim_sig(
516 shim_sig!(extern "C" fn(i32, libc::off_t) -> i32),
517 link_name,
518 abi,
519 args,
520 )?;
521 let fd = this.read_scalar(fd)?.to_i32()?;
522 let length = this.read_scalar(length)?.to_int(length.layout.size)?;
523 let result = this.ftruncate64(fd, length)?;
524 this.write_scalar(result, dest)?;
525 }
526 "fsync" => {
527 let [fd] = this.check_shim_sig(
529 shim_sig!(extern "C" fn(i32) -> i32),
530 link_name,
531 abi,
532 args,
533 )?;
534 let result = this.fsync(fd)?;
535 this.write_scalar(result, dest)?;
536 }
537 "fdatasync" => {
538 let [fd] = this.check_shim_sig(
540 shim_sig!(extern "C" fn(i32) -> i32),
541 link_name,
542 abi,
543 args,
544 )?;
545 let result = this.fdatasync(fd)?;
546 this.write_scalar(result, dest)?;
547 }
548 "readlink" => {
549 let [pathname, buf, bufsize] = this.check_shim_sig(
550 shim_sig!(extern "C" fn(*const _, *mut _, usize) -> isize),
551 link_name,
552 abi,
553 args,
554 )?;
555 let result = this.readlink(pathname, buf, bufsize)?;
556 this.write_scalar(Scalar::from_target_isize(result, this), dest)?;
557 }
558 "posix_fadvise" => {
559 let [fd, offset, len, advice] = this.check_shim_sig(
560 shim_sig!(extern "C" fn(i32, libc::off_t, libc::off_t, i32) -> i32),
561 link_name,
562 abi,
563 args,
564 )?;
565 this.read_scalar(fd)?.to_i32()?;
566 this.read_scalar(offset)?.to_int(offset.layout.size)?;
567 this.read_scalar(len)?.to_int(len.layout.size)?;
568 this.read_scalar(advice)?.to_i32()?;
569 this.write_null(dest)?;
571 }
572
573 "posix_fallocate" => {
574 this.check_target_os(
576 &[Os::Linux, Os::FreeBsd, Os::Solaris, Os::Illumos, Os::Android],
577 link_name,
578 )?;
579
580 let [fd, offset, len] = this.check_shim_sig(
581 shim_sig!(extern "C" fn(i32, libc::off_t, libc::off_t) -> i32),
582 link_name,
583 abi,
584 args,
585 )?;
586
587 let fd = this.read_scalar(fd)?.to_i32()?;
588 let offset =
590 i64::try_from(this.read_scalar(offset)?.to_int(offset.layout.size)?).unwrap();
591 let len = i64::try_from(this.read_scalar(len)?.to_int(len.layout.size)?).unwrap();
592
593 let result = this.posix_fallocate(fd, offset, len)?;
594 this.write_scalar(result, dest)?;
595 }
596
597 "realpath" => {
598 let [path, resolved_path] = this.check_shim_sig(
599 shim_sig!(extern "C" fn(*const _, *mut _) -> *mut _),
600 link_name,
601 abi,
602 args,
603 )?;
604 let result = this.realpath(path, resolved_path)?;
605 this.write_scalar(result, dest)?;
606 }
607 "mkstemp" => {
608 let [template] = this.check_shim_sig(
609 shim_sig!(extern "C" fn(*mut _) -> i32),
610 link_name,
611 abi,
612 args,
613 )?;
614 let result = this.mkstemp(template)?;
615 this.write_scalar(result, dest)?;
616 }
617
618 "socketpair" => {
620 let [domain, type_, protocol, sv] = this.check_shim_sig(
621 shim_sig!(extern "C" fn(i32, i32, i32, *mut _) -> i32),
622 link_name,
623 abi,
624 args,
625 )?;
626 let result = this.socketpair(domain, type_, protocol, sv)?;
627 this.write_scalar(result, dest)?;
628 }
629 "pipe" => {
630 let [pipefd] = this.check_shim_sig(
631 shim_sig!(extern "C" fn(*mut _) -> i32),
632 link_name,
633 abi,
634 args,
635 )?;
636 let result = this.pipe2(pipefd, None)?;
637 this.write_scalar(result, dest)?;
638 }
639 "pipe2" => {
640 this.check_target_os(
642 &[Os::Linux, Os::Android, Os::FreeBsd, Os::Solaris, Os::Illumos],
643 link_name,
644 )?;
645
646 let [pipefd, flags] = this.check_shim_sig(
647 shim_sig!(extern "C" fn(*mut _, i32) -> i32),
648 link_name,
649 abi,
650 args,
651 )?;
652 let result = this.pipe2(pipefd, Some(flags))?;
653 this.write_scalar(result, dest)?;
654 }
655
656 "socket" => {
658 let [domain, type_, protocol] = this.check_shim_sig(
659 shim_sig!(extern "C" fn(i32, i32, i32) -> i32),
660 link_name,
661 abi,
662 args,
663 )?;
664 let result = this.socket(domain, type_, protocol)?;
665 this.write_scalar(result, dest)?;
666 }
667 "bind" => {
668 let [socket, address, address_len] = this.check_shim_sig(
669 shim_sig!(extern "C" fn(i32, *const _, libc::socklen_t) -> i32),
670 link_name,
671 abi,
672 args,
673 )?;
674 let result = this.bind(socket, address, address_len)?;
675 this.write_scalar(result, dest)?;
676 }
677 "listen" => {
678 let [socket, backlog] = this.check_shim_sig(
679 shim_sig!(extern "C" fn(i32, i32) -> i32),
680 link_name,
681 abi,
682 args,
683 )?;
684 let result = this.listen(socket, backlog)?;
685 this.write_scalar(result, dest)?;
686 }
687 "accept" => {
688 let [socket, address, address_len] = this.check_shim_sig(
689 shim_sig!(extern "C" fn(i32, *mut _, *mut _) -> i32),
690 link_name,
691 abi,
692 args,
693 )?;
694 this.accept4(socket, address, address_len, None, dest)?;
695 }
696 "accept4" => {
697 let [socket, address, address_len, flags] = this.check_shim_sig(
698 shim_sig!(extern "C" fn(i32, *mut _, *mut _, i32) -> i32),
699 link_name,
700 abi,
701 args,
702 )?;
703 this.accept4(socket, address, address_len, Some(flags), dest)?;
704 }
705 "connect" => {
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 this.connect(socket, address, address_len, dest)?;
713 }
714 "send" => {
715 let [socket, buffer, length, flags] = this.check_shim_sig(
716 shim_sig!(extern "C" fn(i32, *const _, libc::size_t, i32) -> libc::ssize_t),
717 link_name,
718 abi,
719 args,
720 )?;
721 this.send(socket, buffer, length, flags, dest)?;
722 }
723 "recv" => {
724 let [socket, buffer, length, flags] = this.check_shim_sig(
725 shim_sig!(extern "C" fn(i32, *mut _, libc::size_t, i32) -> libc::ssize_t),
726 link_name,
727 abi,
728 args,
729 )?;
730 this.recv(socket, buffer, length, flags, dest)?;
731 }
732 "setsockopt" => {
733 let [socket, level, option_name, option_value, option_len] = this.check_shim_sig(
734 shim_sig!(extern "C" fn(i32, i32, i32, *const _, libc::socklen_t) -> i32),
735 link_name,
736 abi,
737 args,
738 )?;
739 let result =
740 this.setsockopt(socket, level, option_name, option_value, option_len)?;
741 this.write_scalar(result, dest)?;
742 }
743 "getsockopt" => {
744 let [socket, level, option_name, option_value, option_len] = this.check_shim_sig(
745 shim_sig!(extern "C" fn(i32, i32, i32, *mut _, *mut _) -> i32),
746 link_name,
747 abi,
748 args,
749 )?;
750 let result =
751 this.getsockopt(socket, level, option_name, option_value, option_len)?;
752 this.write_scalar(result, dest)?;
753 }
754 "getsockname" => {
755 let [socket, address, address_len] = this.check_shim_sig(
756 shim_sig!(extern "C" fn(i32, *mut _, *mut _) -> i32),
757 link_name,
758 abi,
759 args,
760 )?;
761 let result = this.getsockname(socket, address, address_len)?;
762 this.write_scalar(result, dest)?;
763 }
764 "getpeername" => {
765 let [socket, address, address_len] = this.check_shim_sig(
766 shim_sig!(extern "C" fn(i32, *mut _, *mut _) -> i32),
767 link_name,
768 abi,
769 args,
770 )?;
771 this.getpeername(socket, address, address_len, dest)?;
772 }
773 "shutdown" => {
774 let [sockfd, how] = this.check_shim_sig(
775 shim_sig!(extern "C" fn(i32, i32) -> i32),
776 link_name,
777 abi,
778 args,
779 )?;
780 let result = this.shutdown(sockfd, how)?;
781 this.write_scalar(result, dest)?;
782 }
783 "getaddrinfo" => {
784 let [node, service, hints, res] = this.check_shim_sig(
785 shim_sig!(extern "C" fn(*const _, *const _, *const _, *mut _) -> i32),
786 link_name,
787 abi,
788 args,
789 )?;
790 let result = this.getaddrinfo(node, service, hints, res)?;
791 this.write_scalar(result, dest)?;
792 }
793 "freeaddrinfo" => {
794 let [res] = this.check_shim_sig(
795 shim_sig!(extern "C" fn(*mut _) -> ()),
796 link_name,
797 abi,
798 args,
799 )?;
800 this.freeaddrinfo(res)?;
801 }
802
803 "gettimeofday" => {
805 let [tv, tz] = this.check_shim_sig(
806 shim_sig!(extern "C" fn(*mut _, *mut _) -> i32),
807 link_name,
808 abi,
809 args,
810 )?;
811 let result = this.gettimeofday(tv, tz)?;
812 this.write_scalar(result, dest)?;
813 }
814 "localtime_r" => {
815 let [timep, result_op] = this.check_shim_sig(
816 shim_sig!(extern "C" fn(*const _, *mut _) -> *mut _),
817 link_name,
818 abi,
819 args,
820 )?;
821 let result = this.localtime_r(timep, result_op)?;
822 this.write_pointer(result, dest)?;
823 }
824 "clock_gettime" => {
825 let [clk_id, tp] = this.check_shim_sig(
826 shim_sig!(extern "C" fn(libc::clockid_t, *mut _) -> i32),
827 link_name,
828 abi,
829 args,
830 )?;
831 this.clock_gettime(clk_id, tp, dest)?;
832 }
833
834 "posix_memalign" => {
836 let [memptr, align, size] =
837 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
838 let result = this.posix_memalign(memptr, align, size)?;
839 this.write_scalar(result, dest)?;
840 }
841
842 "mmap" => {
843 let [addr, length, prot, flags, fd, offset] = this.check_shim_sig(
844 shim_sig!(extern "C" fn(*mut _, usize, i32, i32, i32, libc::off_t) -> *mut _),
845 link_name,
846 abi,
847 args,
848 )?;
849 let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off_t").size)?;
850 let ptr = this.mmap(addr, length, prot, flags, fd, offset)?;
851 this.write_scalar(ptr, dest)?;
852 }
853 "munmap" => {
854 let [addr, length] = this.check_shim_sig(
855 shim_sig!(extern "C" fn(*mut _, usize) -> i32),
856 link_name,
857 abi,
858 args,
859 )?;
860 let result = this.munmap(addr, length)?;
861 this.write_scalar(result, dest)?;
862 }
863 "mprotect" => {
864 let [addr, length, prot] = this.check_shim_sig(
865 shim_sig!(extern "C" fn(*mut _, usize, i32) -> i32),
866 link_name,
867 abi,
868 args,
869 )?;
870 let result = this.mprotect(addr, length, prot)?;
871 this.write_scalar(result, dest)?;
872 }
873 "madvise" => {
874 let [addr, length, advice] = this.check_shim_sig(
875 shim_sig!(extern "C" fn(*mut _, usize, i32) -> i32),
876 link_name,
877 abi,
878 args,
879 )?;
880 let result = this.madvise(addr, length, advice)?;
881 this.write_scalar(result, dest)?;
882 }
883
884 "reallocarray" => {
885 this.check_target_os(&[Os::Linux, Os::FreeBsd, Os::Android], link_name)?;
887
888 let [ptr, nmemb, size] =
889 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
890 let ptr = this.read_pointer(ptr)?;
891 let nmemb = this.read_target_usize(nmemb)?;
892 let size = this.read_target_usize(size)?;
893 match this.compute_size_in_bytes(Size::from_bytes(size), nmemb) {
899 None => {
900 this.set_last_error(LibcError("ENOMEM"))?;
901 this.write_null(dest)?;
902 }
903 Some(len) => {
904 let res = this.realloc(ptr, len.bytes())?;
905 this.write_pointer(res, dest)?;
906 }
907 }
908 }
909 "aligned_alloc" => {
910 let [align, size] =
913 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
914 let res = this.aligned_alloc(align, size)?;
915 this.write_pointer(res, dest)?;
916 }
917
918 "dlsym" => {
920 let [handle, symbol] =
921 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
922 this.read_target_usize(handle)?;
923 let symbol = this.read_pointer(symbol)?;
924 let name = this.read_c_str(symbol)?;
925 let Ok(name) = str::from_utf8(name) else {
926 throw_unsup_format!("dlsym: non UTF-8 symbol name not supported")
927 };
928 if is_dyn_sym(name, &this.tcx.sess.target.os) {
929 let ptr = this.fn_ptr(FnVal::Other(DynSym::from_str(name)));
930 this.write_pointer(ptr, dest)?;
931 } else if let Some(&ptr) = this.machine.extern_statics.get(&Symbol::intern(name)) {
932 this.write_pointer(ptr, dest)?;
933 } else {
934 this.write_null(dest)?;
935 }
936 }
937
938 "pthread_key_create" => {
940 let [key, dtor] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
941 let key_place = this.deref_pointer_as(key, this.libc_ty_layout("pthread_key_t"))?;
942 let dtor = this.read_pointer(dtor)?;
943
944 let dtor = if !this.ptr_is_null(dtor)? {
946 Some((
947 this.get_ptr_fn(dtor)?.as_instance()?,
948 this.machine.current_user_relevant_span(),
949 ))
950 } else {
951 None
952 };
953
954 let key_type = key.layout.ty
957 .builtin_deref(true)
958 .ok_or_else(|| err_ub_format!(
959 "wrong signature used for `pthread_key_create`: first argument must be a raw pointer."
960 ))?;
961 let key_layout = this.layout_of(key_type)?;
962
963 let key = this.machine.tls.create_tls_key(dtor, key_layout.size)?;
965 this.write_scalar(Scalar::from_uint(key, key_layout.size), &key_place)?;
966
967 this.write_null(dest)?;
969 }
970 "pthread_key_delete" => {
971 let [key] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
973 let key = this.read_scalar(key)?.to_bits(key.layout.size)?;
974 this.machine.tls.delete_tls_key(key)?;
975 this.write_null(dest)?;
977 }
978 "pthread_getspecific" => {
979 let [key] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
981 let key = this.read_scalar(key)?.to_bits(key.layout.size)?;
982 let active_thread = this.active_thread();
983 let ptr = this.machine.tls.load_tls(key, active_thread, this)?;
984 this.write_scalar(ptr, dest)?;
985 }
986 "pthread_setspecific" => {
987 let [key, new_ptr] =
989 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
990 let key = this.read_scalar(key)?.to_bits(key.layout.size)?;
991 let active_thread = this.active_thread();
992 let new_data = this.read_scalar(new_ptr)?;
993 this.machine.tls.store_tls(key, active_thread, new_data, &*this.tcx)?;
994
995 this.write_null(dest)?;
997 }
998
999 "pthread_mutexattr_init" => {
1001 let [attr] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1002 this.pthread_mutexattr_init(attr)?;
1003 this.write_null(dest)?;
1004 }
1005 "pthread_mutexattr_settype" => {
1006 let [attr, kind] =
1007 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1008 let result = this.pthread_mutexattr_settype(attr, kind)?;
1009 this.write_scalar(result, dest)?;
1010 }
1011 "pthread_mutexattr_destroy" => {
1012 let [attr] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1013 this.pthread_mutexattr_destroy(attr)?;
1014 this.write_null(dest)?;
1015 }
1016 "pthread_mutex_init" => {
1017 let [mutex, attr] =
1018 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1019 this.pthread_mutex_init(mutex, attr)?;
1020 this.write_null(dest)?;
1021 }
1022 "pthread_mutex_lock" => {
1023 let [mutex] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1024 this.pthread_mutex_lock(mutex, dest)?;
1025 }
1026 "pthread_mutex_trylock" => {
1027 let [mutex] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1028 let result = this.pthread_mutex_trylock(mutex)?;
1029 this.write_scalar(result, dest)?;
1030 }
1031 "pthread_mutex_unlock" => {
1032 let [mutex] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1033 let result = this.pthread_mutex_unlock(mutex)?;
1034 this.write_scalar(result, dest)?;
1035 }
1036 "pthread_mutex_destroy" => {
1037 let [mutex] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1038 this.pthread_mutex_destroy(mutex)?;
1039 this.write_int(0, dest)?;
1040 }
1041 "pthread_rwlock_rdlock" => {
1042 let [rwlock] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1043 this.pthread_rwlock_rdlock(rwlock, dest)?;
1044 }
1045 "pthread_rwlock_tryrdlock" => {
1046 let [rwlock] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1047 let result = this.pthread_rwlock_tryrdlock(rwlock)?;
1048 this.write_scalar(result, dest)?;
1049 }
1050 "pthread_rwlock_wrlock" => {
1051 let [rwlock] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1052 this.pthread_rwlock_wrlock(rwlock, dest)?;
1053 }
1054 "pthread_rwlock_trywrlock" => {
1055 let [rwlock] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1056 let result = this.pthread_rwlock_trywrlock(rwlock)?;
1057 this.write_scalar(result, dest)?;
1058 }
1059 "pthread_rwlock_unlock" => {
1060 let [rwlock] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1061 this.pthread_rwlock_unlock(rwlock)?;
1062 this.write_null(dest)?;
1063 }
1064 "pthread_rwlock_destroy" => {
1065 let [rwlock] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1066 this.pthread_rwlock_destroy(rwlock)?;
1067 this.write_null(dest)?;
1068 }
1069 "pthread_condattr_init" => {
1070 let [attr] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1071 this.pthread_condattr_init(attr)?;
1072 this.write_null(dest)?;
1073 }
1074 "pthread_condattr_setclock" => {
1075 let [attr, clock_id] =
1076 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1077 let result = this.pthread_condattr_setclock(attr, clock_id)?;
1078 this.write_scalar(result, dest)?;
1079 }
1080 "pthread_condattr_getclock" => {
1081 let [attr, clock_id] =
1082 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1083 this.pthread_condattr_getclock(attr, clock_id)?;
1084 this.write_null(dest)?;
1085 }
1086 "pthread_condattr_destroy" => {
1087 let [attr] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1088 this.pthread_condattr_destroy(attr)?;
1089 this.write_null(dest)?;
1090 }
1091 "pthread_cond_init" => {
1092 let [cond, attr] =
1093 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1094 this.pthread_cond_init(cond, attr)?;
1095 this.write_null(dest)?;
1096 }
1097 "pthread_cond_signal" => {
1098 let [cond] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1099 this.pthread_cond_signal(cond)?;
1100 this.write_null(dest)?;
1101 }
1102 "pthread_cond_broadcast" => {
1103 let [cond] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1104 this.pthread_cond_broadcast(cond)?;
1105 this.write_null(dest)?;
1106 }
1107 "pthread_cond_wait" => {
1108 let [cond, mutex] =
1109 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1110 this.pthread_cond_wait(cond, mutex, dest)?;
1111 }
1112 "pthread_cond_timedwait" => {
1113 let [cond, mutex, abstime] =
1114 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1115 this.pthread_cond_timedwait(
1116 cond, mutex, abstime, dest, false,
1117 )?;
1118 }
1119 "pthread_cond_destroy" => {
1120 let [cond] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1121 this.pthread_cond_destroy(cond)?;
1122 this.write_null(dest)?;
1123 }
1124
1125 "pthread_create" => {
1127 let [thread, attr, start, arg] =
1128 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1129 this.pthread_create(thread, attr, start, arg)?;
1130 this.write_null(dest)?;
1131 }
1132 "pthread_join" => {
1133 let [thread, retval] =
1134 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1135 this.pthread_join(thread, retval, dest)?;
1136 }
1137 "pthread_detach" => {
1138 let [thread] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1139 let res = this.pthread_detach(thread)?;
1140 this.write_scalar(res, dest)?;
1141 }
1142 "pthread_self" => {
1143 let [] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1144 let res = this.pthread_self()?;
1145 this.write_scalar(res, dest)?;
1146 }
1147 "sched_yield" => {
1148 let [] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1150 this.sched_yield()?;
1151 this.write_null(dest)?;
1152 }
1153 "nanosleep" => {
1154 let [duration, rem] =
1155 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1156 let result = this.nanosleep(duration, rem)?;
1157 this.write_scalar(result, dest)?;
1158 }
1159 "clock_nanosleep" => {
1160 this.check_target_os(
1162 &[Os::FreeBsd, Os::Linux, Os::Android, Os::Solaris, Os::Illumos],
1163 link_name,
1164 )?;
1165
1166 let [clock_id, flags, req, rem] =
1167 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1168 let result = this.clock_nanosleep(clock_id, flags, req, rem)?;
1169 this.write_scalar(result, dest)?;
1170 }
1171 "sched_getaffinity" => {
1172 this.check_target_os(&[Os::Linux, Os::FreeBsd, Os::Android], link_name)?;
1174
1175 let [pid, cpusetsize, mask] =
1176 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1177 let pid = this.read_scalar(pid)?.to_u32()?;
1178 let cpusetsize = this.read_target_usize(cpusetsize)?;
1179 let mask = this.read_pointer(mask)?;
1180
1181 if this.machine.thread_cpu_affinity.is_none() {
1182 throw_unsup_format!(
1183 "`sched_getaffinity` is not supported on #![no_core] programs"
1184 )
1185 }
1186
1187 let thread_id = if pid == 0 {
1188 this.active_thread()
1189 } else if matches!(this.tcx.sess.target.os, Os::Linux | Os::Android) {
1190 let Some(thread_id) = this.get_thread_id_from_linux_tid(pid) else {
1192 this.set_errno_and_return_neg1(LibcError("ESRCH"), dest)?;
1193 return interp_ok(EmulateItemResult::NeedsReturn);
1194 };
1195 thread_id
1196 } else {
1197 throw_unsup_format!(
1198 "`sched_getaffinity` is only supported with a pid of 0 (indicating the current thread) on non-Linux platforms"
1199 )
1200 };
1201
1202 let chunk_size = CpuAffinityMask::chunk_size(this);
1204
1205 if this.ptr_is_null(mask)? {
1206 this.set_errno_and_return_neg1(LibcError("EFAULT"), dest)?;
1207 } else if cpusetsize == 0 || cpusetsize.checked_rem(chunk_size).unwrap() != 0 {
1208 this.set_errno_and_return_neg1(LibcError("EINVAL"), dest)?;
1210 } else if let Some(cpuset) =
1211 this.machine.thread_cpu_affinity.as_ref().unwrap().get(&thread_id)
1212 {
1213 let cpuset = cpuset.clone();
1214 let byte_count =
1216 Ord::min(cpuset.as_slice().len(), cpusetsize.try_into().unwrap());
1217 this.write_bytes_ptr(mask, cpuset.as_slice()[..byte_count].iter().copied())?;
1218 this.write_null(dest)?;
1219 } else {
1220 this.set_errno_and_return_neg1(LibcError("ESRCH"), dest)?;
1222 }
1223 }
1224 "sched_setaffinity" => {
1225 this.check_target_os(&[Os::Linux, Os::FreeBsd, Os::Android], link_name)?;
1227
1228 let [pid, cpusetsize, mask] =
1229 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1230 let pid = this.read_scalar(pid)?.to_u32()?;
1231 let cpusetsize = this.read_target_usize(cpusetsize)?;
1232 let mask = this.read_pointer(mask)?;
1233
1234 if this.machine.thread_cpu_affinity.is_none() {
1235 throw_unsup_format!(
1236 "`sched_setaffinity` is not supported on #![no_core] programs"
1237 )
1238 }
1239
1240 let thread_id = if pid == 0 {
1241 this.active_thread()
1242 } else if matches!(this.tcx.sess.target.os, Os::Linux | Os::Android) {
1243 let Some(thread_id) = this.get_thread_id_from_linux_tid(pid) else {
1245 this.set_errno_and_return_neg1(LibcError("ESRCH"), dest)?;
1246 return interp_ok(EmulateItemResult::NeedsReturn);
1247 };
1248 thread_id
1249 } else {
1250 throw_unsup_format!(
1251 "`sched_setaffinity` is only supported with a pid of 0 (indicating the current thread) on non-Linux platforms"
1252 )
1253 };
1254
1255 if this.ptr_is_null(mask)? {
1256 this.set_errno_and_return_neg1(LibcError("EFAULT"), dest)?;
1257 } else {
1258 let bits_slice =
1262 this.read_bytes_ptr_strip_provenance(mask, Size::from_bytes(cpusetsize))?;
1263 let bits_array: [u8; CpuAffinityMask::CPU_MASK_BYTES] =
1265 std::array::from_fn(|i| bits_slice.get(i).copied().unwrap_or(0));
1266 match CpuAffinityMask::from_array(this, this.machine.num_cpus, bits_array) {
1267 Some(cpuset) => {
1268 this.machine
1269 .thread_cpu_affinity
1270 .as_mut()
1271 .unwrap()
1272 .insert(thread_id, cpuset);
1273 this.write_null(dest)?;
1274 }
1275 None => {
1276 this.set_errno_and_return_neg1(LibcError("EINVAL"), dest)?;
1278 }
1279 }
1280 }
1281 }
1282
1283 "isatty" => {
1285 let [fd] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1286 let result = this.isatty(fd)?;
1287 this.write_scalar(result, dest)?;
1288 }
1289 "pthread_atfork" => {
1290 let [prepare, parent, child] =
1292 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1293 this.read_pointer(prepare)?;
1294 this.read_pointer(parent)?;
1295 this.read_pointer(child)?;
1296 this.write_null(dest)?;
1298 }
1299 "getentropy" => {
1300 this.check_target_os(
1303 &[Os::Linux, Os::MacOs, Os::FreeBsd, Os::Illumos, Os::Solaris, Os::Android],
1304 link_name,
1305 )?;
1306
1307 let [buf, bufsize] =
1308 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1309 let buf = this.read_pointer(buf)?;
1310 let bufsize = this.read_target_usize(bufsize)?;
1311
1312 if bufsize > 256 {
1318 this.set_errno_and_return_neg1(LibcError("EIO"), dest)?;
1319 } else {
1320 this.gen_random(buf, bufsize)?;
1321 this.write_null(dest)?;
1322 }
1323 }
1324
1325 "strerror_r" => {
1326 let [errnum, buf, buflen] =
1327 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1328 let result = this.strerror_r(errnum, buf, buflen)?;
1329 this.write_scalar(result, dest)?;
1330 }
1331
1332 "getrandom" => {
1333 this.check_target_os(
1336 &[Os::Linux, Os::FreeBsd, Os::Illumos, Os::Solaris, Os::Android],
1337 link_name,
1338 )?;
1339
1340 let [ptr, len, flags] =
1341 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1342 let ptr = this.read_pointer(ptr)?;
1343 let len = this.read_target_usize(len)?;
1344 let _flags = this.read_scalar(flags)?.to_i32()?;
1345 this.gen_random(ptr, len)?;
1347 this.write_scalar(Scalar::from_target_usize(len, this), dest)?;
1348 }
1349 "arc4random_buf" => {
1350 this.check_target_os(&[Os::FreeBsd, Os::Illumos, Os::Solaris], link_name)?;
1353
1354 let [ptr, len] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1355 let ptr = this.read_pointer(ptr)?;
1356 let len = this.read_target_usize(len)?;
1357 this.gen_random(ptr, len)?;
1358 }
1359 "_Unwind_RaiseException" => {
1360 this.check_target_os(
1374 &[Os::Linux, Os::FreeBsd, Os::Illumos, Os::Solaris, Os::Android, Os::MacOs],
1375 link_name,
1376 )?;
1377
1378 let [payload] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1380 this.handle_miri_start_unwind(payload)?;
1381 return interp_ok(EmulateItemResult::NeedsUnwind);
1382 }
1383 "getuid" | "geteuid" => {
1384 let [] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1385 this.write_int(UID, dest)?;
1387 }
1388
1389 "pthread_attr_getguardsize" if this.frame_in_std() => {
1392 let [_attr, guard_size] =
1393 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1394 let guard_size_layout = this.machine.layouts.usize;
1395 let guard_size = this.deref_pointer_as(guard_size, guard_size_layout)?;
1396 this.write_scalar(
1397 Scalar::from_uint(this.machine.page_size, guard_size_layout.size),
1398 &guard_size,
1399 )?;
1400
1401 this.write_null(dest)?;
1403 }
1404
1405 "pthread_attr_init" | "pthread_attr_destroy" if this.frame_in_std() => {
1406 let [_] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1407 this.write_null(dest)?;
1408 }
1409 "pthread_attr_setstacksize" if this.frame_in_std() => {
1410 let [_, _] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1411 this.write_null(dest)?;
1412 }
1413
1414 "pthread_attr_getstack" if this.frame_in_std() => {
1415 let [attr_place, addr_place, size_place] =
1418 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1419 let _attr_place =
1420 this.deref_pointer_as(attr_place, this.libc_ty_layout("pthread_attr_t"))?;
1421 let addr_place = this.deref_pointer_as(addr_place, this.machine.layouts.usize)?;
1422 let size_place = this.deref_pointer_as(size_place, this.machine.layouts.usize)?;
1423
1424 this.write_scalar(
1425 Scalar::from_uint(this.machine.stack_addr, this.pointer_size()),
1426 &addr_place,
1427 )?;
1428 this.write_scalar(
1429 Scalar::from_uint(this.machine.stack_size, this.pointer_size()),
1430 &size_place,
1431 )?;
1432
1433 this.write_null(dest)?;
1435 }
1436
1437 "signal" | "sigaltstack" if this.frame_in_std() => {
1438 let [_, _] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1439 this.write_null(dest)?;
1440 }
1441 "sigaction" if this.frame_in_std() => {
1442 let [_, _, _] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1443 this.write_null(dest)?;
1444 }
1445
1446 "getpwuid_r" | "__posix_getpwuid_r" if this.frame_in_std() => {
1447 let [uid, pwd, buf, buflen, result] =
1449 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1450 this.check_no_isolation("`getpwuid_r`")?;
1451
1452 let uid = this.read_scalar(uid)?.to_u32()?;
1453 let pwd = this.deref_pointer_as(pwd, this.libc_ty_layout("passwd"))?;
1454 let buf = this.read_pointer(buf)?;
1455 let buflen = this.read_target_usize(buflen)?;
1456 let result = this.deref_pointer_as(result, this.machine.layouts.mut_raw_ptr)?;
1457
1458 if uid != UID {
1460 throw_unsup_format!("`getpwuid_r` on other users is not supported");
1461 }
1462
1463 this.write_uninit(&pwd)?;
1466
1467 #[allow(deprecated)]
1469 let home_dir = std::env::home_dir().unwrap();
1470 let (written, _) = this.write_path_to_c_str(&home_dir, buf, buflen)?;
1471 let pw_dir = this.project_field_named(&pwd, "pw_dir")?;
1472 this.write_pointer(buf, &pw_dir)?;
1473
1474 if written {
1475 this.write_pointer(pwd.ptr(), &result)?;
1476 this.write_null(dest)?;
1477 } else {
1478 this.write_null(&result)?;
1479 this.write_scalar(this.eval_libc("ERANGE"), dest)?;
1480 }
1481 }
1482
1483 _ => {
1485 let target_os = &this.tcx.sess.target.os;
1486 return match target_os {
1487 Os::Android =>
1488 android::EvalContextExt::emulate_foreign_item_inner(
1489 this, link_name, abi, args, dest,
1490 ),
1491 Os::FreeBsd =>
1492 freebsd::EvalContextExt::emulate_foreign_item_inner(
1493 this, link_name, abi, args, dest,
1494 ),
1495 Os::Linux =>
1496 linux::EvalContextExt::emulate_foreign_item_inner(
1497 this, link_name, abi, args, dest,
1498 ),
1499 Os::MacOs =>
1500 macos::EvalContextExt::emulate_foreign_item_inner(
1501 this, link_name, abi, args, dest,
1502 ),
1503 Os::Solaris | Os::Illumos =>
1504 solarish::EvalContextExt::emulate_foreign_item_inner(
1505 this, link_name, abi, args, dest,
1506 ),
1507 _ => interp_ok(EmulateItemResult::NotSupported),
1508 };
1509 }
1510 };
1511
1512 interp_ok(EmulateItemResult::NeedsReturn)
1513 }
1514}