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 "pread" => {
230 let [fd, buf, count, offset] = this.check_shim_sig(
232 shim_sig!(extern "C" fn(i32, *mut _, usize, libc::off_t) -> isize),
233 link_name,
234 abi,
235 args,
236 )?;
237 let fd = this.read_scalar(fd)?.to_i32()?;
238 let buf = this.read_pointer(buf)?;
239 let count = this.read_target_usize(count)?;
240 let offset = this.read_scalar(offset)?.to_int(offset.layout.size)?;
241 this.read(fd, buf, count, Some(offset), dest)?;
242 }
243 "pwrite" => {
244 let [fd, buf, n, offset] = this.check_shim_sig(
246 shim_sig!(extern "C" fn(i32, *const _, usize, libc::off_t) -> isize),
247 link_name,
248 abi,
249 args,
250 )?;
251 let fd = this.read_scalar(fd)?.to_i32()?;
252 let buf = this.read_pointer(buf)?;
253 let count = this.read_target_usize(n)?;
254 let offset = this.read_scalar(offset)?.to_int(offset.layout.size)?;
255 trace!("Called pwrite({:?}, {:?}, {:?}, {:?})", fd, buf, count, offset);
256 this.write(fd, buf, count, Some(offset), dest)?;
257 }
258 "close" => {
259 let [fd] = this.check_shim_sig(
260 shim_sig!(extern "C" fn(i32) -> i32),
261 link_name,
262 abi,
263 args,
264 )?;
265 let result = this.close(fd)?;
266 this.write_scalar(result, dest)?;
267 }
268 "fcntl" => {
269 let ([fd_num, cmd], varargs) =
270 this.check_shim_sig_variadic_lenient(abi, CanonAbi::C, link_name, args)?;
271 let result = this.fcntl(fd_num, cmd, varargs)?;
272 this.write_scalar(result, dest)?;
273 }
274 "dup" => {
275 let [old_fd] = this.check_shim_sig(
276 shim_sig!(extern "C" fn(i32) -> i32),
277 link_name,
278 abi,
279 args,
280 )?;
281 let old_fd = this.read_scalar(old_fd)?.to_i32()?;
282 let new_fd = this.dup(old_fd)?;
283 this.write_scalar(new_fd, dest)?;
284 }
285 "dup2" => {
286 let [old_fd, new_fd] = this.check_shim_sig(
287 shim_sig!(extern "C" fn(i32, i32) -> i32),
288 link_name,
289 abi,
290 args,
291 )?;
292 let old_fd = this.read_scalar(old_fd)?.to_i32()?;
293 let new_fd = this.read_scalar(new_fd)?.to_i32()?;
294 let result = this.dup2(old_fd, new_fd)?;
295 this.write_scalar(result, dest)?;
296 }
297 "flock" => {
298 this.check_target_os(&[Os::Linux, Os::FreeBsd, Os::MacOs, Os::Illumos], link_name)?;
300
301 let [fd, op] = this.check_shim_sig(
302 shim_sig!(extern "C" fn(i32, i32) -> i32),
303 link_name,
304 abi,
305 args,
306 )?;
307 let fd = this.read_scalar(fd)?.to_i32()?;
308 let op = this.read_scalar(op)?.to_i32()?;
309 let result = this.flock(fd, op)?;
310 this.write_scalar(result, dest)?;
311 }
312 "ioctl" => {
313 let ([fd, op], varargs) =
314 this.check_shim_sig_variadic_lenient(abi, CanonAbi::C, link_name, args)?;
315 let result = this.ioctl(fd, op, varargs)?;
316 this.write_scalar(result, dest)?;
317 }
318
319 "open" => {
321 let ([path_raw, flag], varargs) =
324 this.check_shim_sig_variadic_lenient(abi, CanonAbi::C, link_name, args)?;
325 let result = this.open(path_raw, flag, varargs)?;
326 this.write_scalar(result, dest)?;
327 }
328 "unlink" => {
329 let [path] = this.check_shim_sig(
331 shim_sig!(extern "C" fn(*const _) -> i32),
332 link_name,
333 abi,
334 args,
335 )?;
336 let result = this.unlink(path)?;
337 this.write_scalar(result, dest)?;
338 }
339 "symlink" => {
340 let [target, linkpath] = this.check_shim_sig(
342 shim_sig!(extern "C" fn(*const _, *const _) -> i32),
343 link_name,
344 abi,
345 args,
346 )?;
347 let result = this.symlink(target, linkpath)?;
348 this.write_scalar(result, dest)?;
349 }
350 "fstat" => {
351 let [fd, buf] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
352 let result = this.fstat(fd, buf)?;
353 this.write_scalar(result, dest)?;
354 }
355 "lstat" => {
356 let [path, buf] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
357 let result = this.lstat(path, buf)?;
358 this.write_scalar(result, dest)?;
359 }
360 "stat" => {
361 let [path, buf] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
362 let result = this.stat(path, buf)?;
363 this.write_scalar(result, dest)?;
364 }
365 "chmod" => {
366 let [path, mode] = this.check_shim_sig(
367 shim_sig!(extern "C" fn(*const _, libc::mode_t) -> i32),
368 link_name,
369 abi,
370 args,
371 )?;
372 let result = this.chmod(path, mode)?;
373 this.write_scalar(result, dest)?;
374 }
375 "fchmod" => {
376 let [fd, mode] = this.check_shim_sig(
377 shim_sig!(extern "C" fn(i32, libc::mode_t) -> i32),
378 link_name,
379 abi,
380 args,
381 )?;
382 let result = this.fchmod(fd, mode)?;
383 this.write_scalar(result, dest)?;
384 }
385 "rename" => {
386 let [oldpath, newpath] = 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.rename(oldpath, newpath)?;
394 this.write_scalar(result, dest)?;
395 }
396 "mkdir" => {
397 let [path, mode] = this.check_shim_sig(
399 shim_sig!(extern "C" fn(*const _, libc::mode_t) -> i32),
400 link_name,
401 abi,
402 args,
403 )?;
404 let result = this.mkdir(path, mode)?;
405 this.write_scalar(result, dest)?;
406 }
407 "rmdir" => {
408 let [path] = this.check_shim_sig(
410 shim_sig!(extern "C" fn(*const _) -> i32),
411 link_name,
412 abi,
413 args,
414 )?;
415 let result = this.rmdir(path)?;
416 this.write_scalar(result, dest)?;
417 }
418 "opendir" => {
419 let [name] = this.check_shim_sig(
420 shim_sig!(extern "C" fn(*const _) -> *mut _),
421 link_name,
422 abi,
423 args,
424 )?;
425 let result = this.opendir(name)?;
426 this.write_scalar(result, dest)?;
427 }
428 "closedir" => {
429 let [dirp] = this.check_shim_sig(
430 shim_sig!(extern "C" fn(*mut _) -> i32),
431 link_name,
432 abi,
433 args,
434 )?;
435 let result = this.closedir(dirp)?;
436 this.write_scalar(result, dest)?;
437 }
438 "readdir" => {
439 let [dirp] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
440 this.readdir(dirp, dest)?;
441 }
442 "lseek" => {
443 let [fd, offset, whence] = this.check_shim_sig(
445 shim_sig!(extern "C" fn(i32, libc::off_t, i32) -> libc::off_t),
446 link_name,
447 abi,
448 args,
449 )?;
450 let fd = this.read_scalar(fd)?.to_i32()?;
451 let offset = this.read_scalar(offset)?.to_int(offset.layout.size)?;
452 let whence = this.read_scalar(whence)?.to_i32()?;
453 this.lseek(fd, offset, whence, dest)?;
454 }
455 "ftruncate" => {
456 let [fd, length] = this.check_shim_sig(
457 shim_sig!(extern "C" fn(i32, libc::off_t) -> i32),
458 link_name,
459 abi,
460 args,
461 )?;
462 let fd = this.read_scalar(fd)?.to_i32()?;
463 let length = this.read_scalar(length)?.to_int(length.layout.size)?;
464 let result = this.ftruncate64(fd, length)?;
465 this.write_scalar(result, dest)?;
466 }
467 "fsync" => {
468 let [fd] = this.check_shim_sig(
470 shim_sig!(extern "C" fn(i32) -> i32),
471 link_name,
472 abi,
473 args,
474 )?;
475 let result = this.fsync(fd)?;
476 this.write_scalar(result, dest)?;
477 }
478 "fdatasync" => {
479 let [fd] = this.check_shim_sig(
481 shim_sig!(extern "C" fn(i32) -> i32),
482 link_name,
483 abi,
484 args,
485 )?;
486 let result = this.fdatasync(fd)?;
487 this.write_scalar(result, dest)?;
488 }
489 "readlink" => {
490 let [pathname, buf, bufsize] = this.check_shim_sig(
491 shim_sig!(extern "C" fn(*const _, *mut _, usize) -> isize),
492 link_name,
493 abi,
494 args,
495 )?;
496 let result = this.readlink(pathname, buf, bufsize)?;
497 this.write_scalar(Scalar::from_target_isize(result, this), dest)?;
498 }
499 "posix_fadvise" => {
500 let [fd, offset, len, advice] = this.check_shim_sig(
501 shim_sig!(extern "C" fn(i32, libc::off_t, libc::off_t, i32) -> i32),
502 link_name,
503 abi,
504 args,
505 )?;
506 this.read_scalar(fd)?.to_i32()?;
507 this.read_scalar(offset)?.to_int(offset.layout.size)?;
508 this.read_scalar(len)?.to_int(len.layout.size)?;
509 this.read_scalar(advice)?.to_i32()?;
510 this.write_null(dest)?;
512 }
513
514 "posix_fallocate" => {
515 this.check_target_os(
517 &[Os::Linux, Os::FreeBsd, Os::Solaris, Os::Illumos, Os::Android],
518 link_name,
519 )?;
520
521 let [fd, offset, len] = this.check_shim_sig(
522 shim_sig!(extern "C" fn(i32, libc::off_t, libc::off_t) -> i32),
523 link_name,
524 abi,
525 args,
526 )?;
527
528 let fd = this.read_scalar(fd)?.to_i32()?;
529 let offset =
531 i64::try_from(this.read_scalar(offset)?.to_int(offset.layout.size)?).unwrap();
532 let len = i64::try_from(this.read_scalar(len)?.to_int(len.layout.size)?).unwrap();
533
534 let result = this.posix_fallocate(fd, offset, len)?;
535 this.write_scalar(result, dest)?;
536 }
537
538 "realpath" => {
539 let [path, resolved_path] = this.check_shim_sig(
540 shim_sig!(extern "C" fn(*const _, *mut _) -> *mut _),
541 link_name,
542 abi,
543 args,
544 )?;
545 let result = this.realpath(path, resolved_path)?;
546 this.write_scalar(result, dest)?;
547 }
548 "mkstemp" => {
549 let [template] = this.check_shim_sig(
550 shim_sig!(extern "C" fn(*mut _) -> i32),
551 link_name,
552 abi,
553 args,
554 )?;
555 let result = this.mkstemp(template)?;
556 this.write_scalar(result, dest)?;
557 }
558
559 "socketpair" => {
561 let [domain, type_, protocol, sv] = this.check_shim_sig(
562 shim_sig!(extern "C" fn(i32, i32, i32, *mut _) -> i32),
563 link_name,
564 abi,
565 args,
566 )?;
567 let result = this.socketpair(domain, type_, protocol, sv)?;
568 this.write_scalar(result, dest)?;
569 }
570 "pipe" => {
571 let [pipefd] = this.check_shim_sig(
572 shim_sig!(extern "C" fn(*mut _) -> i32),
573 link_name,
574 abi,
575 args,
576 )?;
577 let result = this.pipe2(pipefd, None)?;
578 this.write_scalar(result, dest)?;
579 }
580 "pipe2" => {
581 this.check_target_os(
583 &[Os::Linux, Os::Android, Os::FreeBsd, Os::Solaris, Os::Illumos],
584 link_name,
585 )?;
586
587 let [pipefd, flags] = this.check_shim_sig(
588 shim_sig!(extern "C" fn(*mut _, i32) -> i32),
589 link_name,
590 abi,
591 args,
592 )?;
593 let result = this.pipe2(pipefd, Some(flags))?;
594 this.write_scalar(result, dest)?;
595 }
596
597 "socket" => {
599 let [domain, type_, protocol] = this.check_shim_sig(
600 shim_sig!(extern "C" fn(i32, i32, i32) -> i32),
601 link_name,
602 abi,
603 args,
604 )?;
605 let result = this.socket(domain, type_, protocol)?;
606 this.write_scalar(result, dest)?;
607 }
608 "bind" => {
609 let [socket, address, address_len] = this.check_shim_sig(
610 shim_sig!(extern "C" fn(i32, *const _, libc::socklen_t) -> i32),
611 link_name,
612 abi,
613 args,
614 )?;
615 let result = this.bind(socket, address, address_len)?;
616 this.write_scalar(result, dest)?;
617 }
618 "listen" => {
619 let [socket, backlog] = this.check_shim_sig(
620 shim_sig!(extern "C" fn(i32, i32) -> i32),
621 link_name,
622 abi,
623 args,
624 )?;
625 let result = this.listen(socket, backlog)?;
626 this.write_scalar(result, dest)?;
627 }
628 "accept" => {
629 let [socket, address, address_len] = this.check_shim_sig(
630 shim_sig!(extern "C" fn(i32, *mut _, *mut _) -> i32),
631 link_name,
632 abi,
633 args,
634 )?;
635 this.accept4(socket, address, address_len, None, dest)?;
636 }
637 "accept4" => {
638 let [socket, address, address_len, flags] = this.check_shim_sig(
639 shim_sig!(extern "C" fn(i32, *mut _, *mut _, i32) -> i32),
640 link_name,
641 abi,
642 args,
643 )?;
644 this.accept4(socket, address, address_len, Some(flags), dest)?;
645 }
646 "connect" => {
647 let [socket, address, address_len] = this.check_shim_sig(
648 shim_sig!(extern "C" fn(i32, *const _, libc::socklen_t) -> i32),
649 link_name,
650 abi,
651 args,
652 )?;
653 this.connect(socket, address, address_len, dest)?;
654 }
655 "send" => {
656 let [socket, buffer, length, flags] = this.check_shim_sig(
657 shim_sig!(extern "C" fn(i32, *const _, libc::size_t, i32) -> libc::ssize_t),
658 link_name,
659 abi,
660 args,
661 )?;
662 this.send(socket, buffer, length, flags, dest)?;
663 }
664 "recv" => {
665 let [socket, buffer, length, flags] = this.check_shim_sig(
666 shim_sig!(extern "C" fn(i32, *mut _, libc::size_t, i32) -> libc::ssize_t),
667 link_name,
668 abi,
669 args,
670 )?;
671 this.recv(socket, buffer, length, flags, dest)?;
672 }
673 "setsockopt" => {
674 let [socket, level, option_name, option_value, option_len] = this.check_shim_sig(
675 shim_sig!(extern "C" fn(i32, i32, i32, *const _, libc::socklen_t) -> i32),
676 link_name,
677 abi,
678 args,
679 )?;
680 let result =
681 this.setsockopt(socket, level, option_name, option_value, option_len)?;
682 this.write_scalar(result, dest)?;
683 }
684 "getsockopt" => {
685 let [socket, level, option_name, option_value, option_len] = this.check_shim_sig(
686 shim_sig!(extern "C" fn(i32, i32, i32, *mut _, *mut _) -> i32),
687 link_name,
688 abi,
689 args,
690 )?;
691 let result =
692 this.getsockopt(socket, level, option_name, option_value, option_len)?;
693 this.write_scalar(result, dest)?;
694 }
695 "getsockname" => {
696 let [socket, address, address_len] = this.check_shim_sig(
697 shim_sig!(extern "C" fn(i32, *mut _, *mut _) -> i32),
698 link_name,
699 abi,
700 args,
701 )?;
702 let result = this.getsockname(socket, address, address_len)?;
703 this.write_scalar(result, dest)?;
704 }
705 "getpeername" => {
706 let [socket, address, address_len] = this.check_shim_sig(
707 shim_sig!(extern "C" fn(i32, *mut _, *mut _) -> i32),
708 link_name,
709 abi,
710 args,
711 )?;
712 this.getpeername(socket, address, address_len, dest)?;
713 }
714 "shutdown" => {
715 let [sockfd, how] = this.check_shim_sig(
716 shim_sig!(extern "C" fn(i32, i32) -> i32),
717 link_name,
718 abi,
719 args,
720 )?;
721 let result = this.shutdown(sockfd, how)?;
722 this.write_scalar(result, dest)?;
723 }
724 "getaddrinfo" => {
725 let [node, service, hints, res] = this.check_shim_sig(
726 shim_sig!(extern "C" fn(*const _, *const _, *const _, *mut _) -> i32),
727 link_name,
728 abi,
729 args,
730 )?;
731 let result = this.getaddrinfo(node, service, hints, res)?;
732 this.write_scalar(result, dest)?;
733 }
734 "freeaddrinfo" => {
735 let [res] = this.check_shim_sig(
736 shim_sig!(extern "C" fn(*mut _) -> ()),
737 link_name,
738 abi,
739 args,
740 )?;
741 this.freeaddrinfo(res)?;
742 }
743
744 "gettimeofday" => {
746 let [tv, tz] = this.check_shim_sig(
747 shim_sig!(extern "C" fn(*mut _, *mut _) -> i32),
748 link_name,
749 abi,
750 args,
751 )?;
752 let result = this.gettimeofday(tv, tz)?;
753 this.write_scalar(result, dest)?;
754 }
755 "localtime_r" => {
756 let [timep, result_op] = this.check_shim_sig(
757 shim_sig!(extern "C" fn(*const _, *mut _) -> *mut _),
758 link_name,
759 abi,
760 args,
761 )?;
762 let result = this.localtime_r(timep, result_op)?;
763 this.write_pointer(result, dest)?;
764 }
765 "clock_gettime" => {
766 let [clk_id, tp] = this.check_shim_sig(
767 shim_sig!(extern "C" fn(libc::clockid_t, *mut _) -> i32),
768 link_name,
769 abi,
770 args,
771 )?;
772 this.clock_gettime(clk_id, tp, dest)?;
773 }
774
775 "posix_memalign" => {
777 let [memptr, align, size] =
778 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
779 let result = this.posix_memalign(memptr, align, size)?;
780 this.write_scalar(result, dest)?;
781 }
782
783 "mmap" => {
784 let [addr, length, prot, flags, fd, offset] =
785 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
786 let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off_t").size)?;
787 let ptr = this.mmap(addr, length, prot, flags, fd, offset)?;
788 this.write_scalar(ptr, dest)?;
789 }
790 "munmap" => {
791 let [addr, length] =
792 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
793 let result = this.munmap(addr, length)?;
794 this.write_scalar(result, dest)?;
795 }
796
797 "reallocarray" => {
798 this.check_target_os(&[Os::Linux, Os::FreeBsd, Os::Android], link_name)?;
800
801 let [ptr, nmemb, size] =
802 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
803 let ptr = this.read_pointer(ptr)?;
804 let nmemb = this.read_target_usize(nmemb)?;
805 let size = this.read_target_usize(size)?;
806 match this.compute_size_in_bytes(Size::from_bytes(size), nmemb) {
812 None => {
813 this.set_last_error(LibcError("ENOMEM"))?;
814 this.write_null(dest)?;
815 }
816 Some(len) => {
817 let res = this.realloc(ptr, len.bytes())?;
818 this.write_pointer(res, dest)?;
819 }
820 }
821 }
822 "aligned_alloc" => {
823 let [align, size] =
826 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
827 let res = this.aligned_alloc(align, size)?;
828 this.write_pointer(res, dest)?;
829 }
830
831 "dlsym" => {
833 let [handle, symbol] =
834 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
835 this.read_target_usize(handle)?;
836 let symbol = this.read_pointer(symbol)?;
837 let name = this.read_c_str(symbol)?;
838 let Ok(name) = str::from_utf8(name) else {
839 throw_unsup_format!("dlsym: non UTF-8 symbol name not supported")
840 };
841 if is_dyn_sym(name, &this.tcx.sess.target.os) {
842 let ptr = this.fn_ptr(FnVal::Other(DynSym::from_str(name)));
843 this.write_pointer(ptr, dest)?;
844 } else if let Some(&ptr) = this.machine.extern_statics.get(&Symbol::intern(name)) {
845 this.write_pointer(ptr, dest)?;
846 } else {
847 this.write_null(dest)?;
848 }
849 }
850
851 "pthread_key_create" => {
853 let [key, dtor] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
854 let key_place = this.deref_pointer_as(key, this.libc_ty_layout("pthread_key_t"))?;
855 let dtor = this.read_pointer(dtor)?;
856
857 let dtor = if !this.ptr_is_null(dtor)? {
859 Some((
860 this.get_ptr_fn(dtor)?.as_instance()?,
861 this.machine.current_user_relevant_span(),
862 ))
863 } else {
864 None
865 };
866
867 let key_type = key.layout.ty
870 .builtin_deref(true)
871 .ok_or_else(|| err_ub_format!(
872 "wrong signature used for `pthread_key_create`: first argument must be a raw pointer."
873 ))?;
874 let key_layout = this.layout_of(key_type)?;
875
876 let key = this.machine.tls.create_tls_key(dtor, key_layout.size)?;
878 this.write_scalar(Scalar::from_uint(key, key_layout.size), &key_place)?;
879
880 this.write_null(dest)?;
882 }
883 "pthread_key_delete" => {
884 let [key] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
886 let key = this.read_scalar(key)?.to_bits(key.layout.size)?;
887 this.machine.tls.delete_tls_key(key)?;
888 this.write_null(dest)?;
890 }
891 "pthread_getspecific" => {
892 let [key] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
894 let key = this.read_scalar(key)?.to_bits(key.layout.size)?;
895 let active_thread = this.active_thread();
896 let ptr = this.machine.tls.load_tls(key, active_thread, this)?;
897 this.write_scalar(ptr, dest)?;
898 }
899 "pthread_setspecific" => {
900 let [key, new_ptr] =
902 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
903 let key = this.read_scalar(key)?.to_bits(key.layout.size)?;
904 let active_thread = this.active_thread();
905 let new_data = this.read_scalar(new_ptr)?;
906 this.machine.tls.store_tls(key, active_thread, new_data, &*this.tcx)?;
907
908 this.write_null(dest)?;
910 }
911
912 "pthread_mutexattr_init" => {
914 let [attr] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
915 this.pthread_mutexattr_init(attr)?;
916 this.write_null(dest)?;
917 }
918 "pthread_mutexattr_settype" => {
919 let [attr, kind] =
920 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
921 let result = this.pthread_mutexattr_settype(attr, kind)?;
922 this.write_scalar(result, dest)?;
923 }
924 "pthread_mutexattr_destroy" => {
925 let [attr] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
926 this.pthread_mutexattr_destroy(attr)?;
927 this.write_null(dest)?;
928 }
929 "pthread_mutex_init" => {
930 let [mutex, attr] =
931 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
932 this.pthread_mutex_init(mutex, attr)?;
933 this.write_null(dest)?;
934 }
935 "pthread_mutex_lock" => {
936 let [mutex] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
937 this.pthread_mutex_lock(mutex, dest)?;
938 }
939 "pthread_mutex_trylock" => {
940 let [mutex] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
941 let result = this.pthread_mutex_trylock(mutex)?;
942 this.write_scalar(result, dest)?;
943 }
944 "pthread_mutex_unlock" => {
945 let [mutex] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
946 let result = this.pthread_mutex_unlock(mutex)?;
947 this.write_scalar(result, dest)?;
948 }
949 "pthread_mutex_destroy" => {
950 let [mutex] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
951 this.pthread_mutex_destroy(mutex)?;
952 this.write_int(0, dest)?;
953 }
954 "pthread_rwlock_rdlock" => {
955 let [rwlock] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
956 this.pthread_rwlock_rdlock(rwlock, dest)?;
957 }
958 "pthread_rwlock_tryrdlock" => {
959 let [rwlock] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
960 let result = this.pthread_rwlock_tryrdlock(rwlock)?;
961 this.write_scalar(result, dest)?;
962 }
963 "pthread_rwlock_wrlock" => {
964 let [rwlock] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
965 this.pthread_rwlock_wrlock(rwlock, dest)?;
966 }
967 "pthread_rwlock_trywrlock" => {
968 let [rwlock] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
969 let result = this.pthread_rwlock_trywrlock(rwlock)?;
970 this.write_scalar(result, dest)?;
971 }
972 "pthread_rwlock_unlock" => {
973 let [rwlock] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
974 this.pthread_rwlock_unlock(rwlock)?;
975 this.write_null(dest)?;
976 }
977 "pthread_rwlock_destroy" => {
978 let [rwlock] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
979 this.pthread_rwlock_destroy(rwlock)?;
980 this.write_null(dest)?;
981 }
982 "pthread_condattr_init" => {
983 let [attr] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
984 this.pthread_condattr_init(attr)?;
985 this.write_null(dest)?;
986 }
987 "pthread_condattr_setclock" => {
988 let [attr, clock_id] =
989 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
990 let result = this.pthread_condattr_setclock(attr, clock_id)?;
991 this.write_scalar(result, dest)?;
992 }
993 "pthread_condattr_getclock" => {
994 let [attr, clock_id] =
995 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
996 this.pthread_condattr_getclock(attr, clock_id)?;
997 this.write_null(dest)?;
998 }
999 "pthread_condattr_destroy" => {
1000 let [attr] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1001 this.pthread_condattr_destroy(attr)?;
1002 this.write_null(dest)?;
1003 }
1004 "pthread_cond_init" => {
1005 let [cond, attr] =
1006 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1007 this.pthread_cond_init(cond, attr)?;
1008 this.write_null(dest)?;
1009 }
1010 "pthread_cond_signal" => {
1011 let [cond] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1012 this.pthread_cond_signal(cond)?;
1013 this.write_null(dest)?;
1014 }
1015 "pthread_cond_broadcast" => {
1016 let [cond] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1017 this.pthread_cond_broadcast(cond)?;
1018 this.write_null(dest)?;
1019 }
1020 "pthread_cond_wait" => {
1021 let [cond, mutex] =
1022 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1023 this.pthread_cond_wait(cond, mutex, dest)?;
1024 }
1025 "pthread_cond_timedwait" => {
1026 let [cond, mutex, abstime] =
1027 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1028 this.pthread_cond_timedwait(
1029 cond, mutex, abstime, dest, false,
1030 )?;
1031 }
1032 "pthread_cond_destroy" => {
1033 let [cond] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1034 this.pthread_cond_destroy(cond)?;
1035 this.write_null(dest)?;
1036 }
1037
1038 "pthread_create" => {
1040 let [thread, attr, start, arg] =
1041 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1042 this.pthread_create(thread, attr, start, arg)?;
1043 this.write_null(dest)?;
1044 }
1045 "pthread_join" => {
1046 let [thread, retval] =
1047 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1048 this.pthread_join(thread, retval, dest)?;
1049 }
1050 "pthread_detach" => {
1051 let [thread] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1052 let res = this.pthread_detach(thread)?;
1053 this.write_scalar(res, dest)?;
1054 }
1055 "pthread_self" => {
1056 let [] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1057 let res = this.pthread_self()?;
1058 this.write_scalar(res, dest)?;
1059 }
1060 "sched_yield" => {
1061 let [] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1063 this.sched_yield()?;
1064 this.write_null(dest)?;
1065 }
1066 "nanosleep" => {
1067 let [duration, rem] =
1068 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1069 let result = this.nanosleep(duration, rem)?;
1070 this.write_scalar(result, dest)?;
1071 }
1072 "clock_nanosleep" => {
1073 this.check_target_os(
1075 &[Os::FreeBsd, Os::Linux, Os::Android, Os::Solaris, Os::Illumos],
1076 link_name,
1077 )?;
1078
1079 let [clock_id, flags, req, rem] =
1080 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1081 let result = this.clock_nanosleep(clock_id, flags, req, rem)?;
1082 this.write_scalar(result, dest)?;
1083 }
1084 "sched_getaffinity" => {
1085 this.check_target_os(&[Os::Linux, Os::FreeBsd, Os::Android], link_name)?;
1087
1088 let [pid, cpusetsize, mask] =
1089 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1090 let pid = this.read_scalar(pid)?.to_u32()?;
1091 let cpusetsize = this.read_target_usize(cpusetsize)?;
1092 let mask = this.read_pointer(mask)?;
1093
1094 let thread_id = if pid == 0 {
1095 this.active_thread()
1096 } else if matches!(this.tcx.sess.target.os, Os::Linux | Os::Android) {
1097 let Some(thread_id) = this.get_thread_id_from_linux_tid(pid) else {
1099 this.set_last_error_and_return(LibcError("ESRCH"), dest)?;
1100 return interp_ok(EmulateItemResult::NeedsReturn);
1101 };
1102 thread_id
1103 } else {
1104 throw_unsup_format!(
1105 "`sched_getaffinity` is only supported with a pid of 0 (indicating the current thread) on non-Linux platforms"
1106 )
1107 };
1108
1109 let chunk_size = CpuAffinityMask::chunk_size(this);
1111
1112 if this.ptr_is_null(mask)? {
1113 this.set_last_error_and_return(LibcError("EFAULT"), dest)?;
1114 } else if cpusetsize == 0 || cpusetsize.checked_rem(chunk_size).unwrap() != 0 {
1115 this.set_last_error_and_return(LibcError("EINVAL"), dest)?;
1117 } else if let Some(cpuset) = this.machine.thread_cpu_affinity.get(&thread_id) {
1118 let cpuset = cpuset.clone();
1119 let byte_count =
1121 Ord::min(cpuset.as_slice().len(), cpusetsize.try_into().unwrap());
1122 this.write_bytes_ptr(mask, cpuset.as_slice()[..byte_count].iter().copied())?;
1123 this.write_null(dest)?;
1124 } else {
1125 this.set_last_error_and_return(LibcError("ESRCH"), dest)?;
1127 }
1128 }
1129 "sched_setaffinity" => {
1130 this.check_target_os(&[Os::Linux, Os::FreeBsd, Os::Android], link_name)?;
1132
1133 let [pid, cpusetsize, mask] =
1134 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1135 let pid = this.read_scalar(pid)?.to_u32()?;
1136 let cpusetsize = this.read_target_usize(cpusetsize)?;
1137 let mask = this.read_pointer(mask)?;
1138
1139 let thread_id = if pid == 0 {
1140 this.active_thread()
1141 } else if matches!(this.tcx.sess.target.os, Os::Linux | Os::Android) {
1142 let Some(thread_id) = this.get_thread_id_from_linux_tid(pid) else {
1144 this.set_last_error_and_return(LibcError("ESRCH"), dest)?;
1145 return interp_ok(EmulateItemResult::NeedsReturn);
1146 };
1147 thread_id
1148 } else {
1149 throw_unsup_format!(
1150 "`sched_setaffinity` is only supported with a pid of 0 (indicating the current thread) on non-Linux platforms"
1151 )
1152 };
1153
1154 if this.ptr_is_null(mask)? {
1155 this.set_last_error_and_return(LibcError("EFAULT"), dest)?;
1156 } else {
1157 let bits_slice =
1161 this.read_bytes_ptr_strip_provenance(mask, Size::from_bytes(cpusetsize))?;
1162 let bits_array: [u8; CpuAffinityMask::CPU_MASK_BYTES] =
1164 std::array::from_fn(|i| bits_slice.get(i).copied().unwrap_or(0));
1165 match CpuAffinityMask::from_array(this, this.machine.num_cpus, bits_array) {
1166 Some(cpuset) => {
1167 this.machine.thread_cpu_affinity.insert(thread_id, cpuset);
1168 this.write_null(dest)?;
1169 }
1170 None => {
1171 this.set_last_error_and_return(LibcError("EINVAL"), dest)?;
1173 }
1174 }
1175 }
1176 }
1177
1178 "isatty" => {
1180 let [fd] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1181 let result = this.isatty(fd)?;
1182 this.write_scalar(result, dest)?;
1183 }
1184 "pthread_atfork" => {
1185 let [prepare, parent, child] =
1187 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1188 this.read_pointer(prepare)?;
1189 this.read_pointer(parent)?;
1190 this.read_pointer(child)?;
1191 this.write_null(dest)?;
1193 }
1194 "getentropy" => {
1195 this.check_target_os(
1198 &[Os::Linux, Os::MacOs, Os::FreeBsd, Os::Illumos, Os::Solaris, Os::Android],
1199 link_name,
1200 )?;
1201
1202 let [buf, bufsize] =
1203 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1204 let buf = this.read_pointer(buf)?;
1205 let bufsize = this.read_target_usize(bufsize)?;
1206
1207 if bufsize > 256 {
1213 this.set_last_error_and_return(LibcError("EIO"), dest)?;
1214 } else {
1215 this.gen_random(buf, bufsize)?;
1216 this.write_null(dest)?;
1217 }
1218 }
1219
1220 "strerror_r" => {
1221 let [errnum, buf, buflen] =
1222 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1223 let result = this.strerror_r(errnum, buf, buflen)?;
1224 this.write_scalar(result, dest)?;
1225 }
1226
1227 "getrandom" => {
1228 this.check_target_os(
1231 &[Os::Linux, Os::FreeBsd, Os::Illumos, Os::Solaris, Os::Android],
1232 link_name,
1233 )?;
1234
1235 let [ptr, len, flags] =
1236 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1237 let ptr = this.read_pointer(ptr)?;
1238 let len = this.read_target_usize(len)?;
1239 let _flags = this.read_scalar(flags)?.to_i32()?;
1240 this.gen_random(ptr, len)?;
1242 this.write_scalar(Scalar::from_target_usize(len, this), dest)?;
1243 }
1244 "arc4random_buf" => {
1245 this.check_target_os(&[Os::FreeBsd, Os::Illumos, Os::Solaris], link_name)?;
1248
1249 let [ptr, len] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1250 let ptr = this.read_pointer(ptr)?;
1251 let len = this.read_target_usize(len)?;
1252 this.gen_random(ptr, len)?;
1253 }
1254 "_Unwind_RaiseException" => {
1255 this.check_target_os(
1269 &[Os::Linux, Os::FreeBsd, Os::Illumos, Os::Solaris, Os::Android, Os::MacOs],
1270 link_name,
1271 )?;
1272
1273 let [payload] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1275 this.handle_miri_start_unwind(payload)?;
1276 return interp_ok(EmulateItemResult::NeedsUnwind);
1277 }
1278 "getuid" | "geteuid" => {
1279 let [] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1280 this.write_int(UID, dest)?;
1282 }
1283
1284 "pthread_attr_getguardsize" if this.frame_in_std() => {
1287 let [_attr, guard_size] =
1288 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1289 let guard_size_layout = this.machine.layouts.usize;
1290 let guard_size = this.deref_pointer_as(guard_size, guard_size_layout)?;
1291 this.write_scalar(
1292 Scalar::from_uint(this.machine.page_size, guard_size_layout.size),
1293 &guard_size,
1294 )?;
1295
1296 this.write_null(dest)?;
1298 }
1299
1300 "pthread_attr_init" | "pthread_attr_destroy" if this.frame_in_std() => {
1301 let [_] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1302 this.write_null(dest)?;
1303 }
1304 "pthread_attr_setstacksize" if this.frame_in_std() => {
1305 let [_, _] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1306 this.write_null(dest)?;
1307 }
1308
1309 "pthread_attr_getstack" if this.frame_in_std() => {
1310 let [attr_place, addr_place, size_place] =
1313 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1314 let _attr_place =
1315 this.deref_pointer_as(attr_place, this.libc_ty_layout("pthread_attr_t"))?;
1316 let addr_place = this.deref_pointer_as(addr_place, this.machine.layouts.usize)?;
1317 let size_place = this.deref_pointer_as(size_place, this.machine.layouts.usize)?;
1318
1319 this.write_scalar(
1320 Scalar::from_uint(this.machine.stack_addr, this.pointer_size()),
1321 &addr_place,
1322 )?;
1323 this.write_scalar(
1324 Scalar::from_uint(this.machine.stack_size, this.pointer_size()),
1325 &size_place,
1326 )?;
1327
1328 this.write_null(dest)?;
1330 }
1331
1332 "signal" | "sigaltstack" if this.frame_in_std() => {
1333 let [_, _] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1334 this.write_null(dest)?;
1335 }
1336 "sigaction" | "mprotect" if this.frame_in_std() => {
1337 let [_, _, _] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1338 this.write_null(dest)?;
1339 }
1340
1341 "getpwuid_r" | "__posix_getpwuid_r" if this.frame_in_std() => {
1342 let [uid, pwd, buf, buflen, result] =
1344 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
1345 this.check_no_isolation("`getpwuid_r`")?;
1346
1347 let uid = this.read_scalar(uid)?.to_u32()?;
1348 let pwd = this.deref_pointer_as(pwd, this.libc_ty_layout("passwd"))?;
1349 let buf = this.read_pointer(buf)?;
1350 let buflen = this.read_target_usize(buflen)?;
1351 let result = this.deref_pointer_as(result, this.machine.layouts.mut_raw_ptr)?;
1352
1353 if uid != UID {
1355 throw_unsup_format!("`getpwuid_r` on other users is not supported");
1356 }
1357
1358 this.write_uninit(&pwd)?;
1361
1362 #[allow(deprecated)]
1364 let home_dir = std::env::home_dir().unwrap();
1365 let (written, _) = this.write_path_to_c_str(&home_dir, buf, buflen)?;
1366 let pw_dir = this.project_field_named(&pwd, "pw_dir")?;
1367 this.write_pointer(buf, &pw_dir)?;
1368
1369 if written {
1370 this.write_pointer(pwd.ptr(), &result)?;
1371 this.write_null(dest)?;
1372 } else {
1373 this.write_null(&result)?;
1374 this.write_scalar(this.eval_libc("ERANGE"), dest)?;
1375 }
1376 }
1377
1378 _ => {
1380 let target_os = &this.tcx.sess.target.os;
1381 return match target_os {
1382 Os::Android =>
1383 android::EvalContextExt::emulate_foreign_item_inner(
1384 this, link_name, abi, args, dest,
1385 ),
1386 Os::FreeBsd =>
1387 freebsd::EvalContextExt::emulate_foreign_item_inner(
1388 this, link_name, abi, args, dest,
1389 ),
1390 Os::Linux =>
1391 linux::EvalContextExt::emulate_foreign_item_inner(
1392 this, link_name, abi, args, dest,
1393 ),
1394 Os::MacOs =>
1395 macos::EvalContextExt::emulate_foreign_item_inner(
1396 this, link_name, abi, args, dest,
1397 ),
1398 Os::Solaris | Os::Illumos =>
1399 solarish::EvalContextExt::emulate_foreign_item_inner(
1400 this, link_name, abi, args, dest,
1401 ),
1402 _ => interp_ok(EmulateItemResult::NotSupported),
1403 };
1404 }
1405 };
1406
1407 interp_ok(EmulateItemResult::NeedsReturn)
1408 }
1409}