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