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