1use rustc_middle::ty::Ty;
2use rustc_span::Symbol;
3use rustc_target::callconv::{Conv, FnAbi};
45use crate::helpers::check_min_vararg_count;
6use crate::shims::unix::linux_like::eventfd::EvalContextExt as _;
7use crate::shims::unix::linux_like::sync::futex;
8use crate::*;
910pub fn syscall<'tcx>(
11 ecx: &mut MiriInterpCx<'tcx>,
12 link_name: Symbol,
13 abi: &FnAbi<'tcx, Ty<'tcx>>,
14 args: &[OpTy<'tcx>],
15 dest: &MPlaceTy<'tcx>,
16) -> InterpResult<'tcx> {
17let ([op], varargs) = ecx.check_shim_variadic(abi, Conv::C, link_name, args)?;
18// The syscall variadic function is legal to call with more arguments than needed,
19 // extra arguments are simply ignored. The important check is that when we use an
20 // argument, we have to also check all arguments *before* it to ensure that they
21 // have the right type.
2223let sys_getrandom = ecx.eval_libc("SYS_getrandom").to_target_usize(ecx)?;
24let sys_futex = ecx.eval_libc("SYS_futex").to_target_usize(ecx)?;
25let sys_eventfd2 = ecx.eval_libc("SYS_eventfd2").to_target_usize(ecx)?;
2627match ecx.read_target_usize(op)? {
28// `libc::syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), GRND_NONBLOCK)`
29 // is called if a `HashMap` is created the regular way (e.g. HashMap<K, V>).
30num if num == sys_getrandom => {
31// Used by getrandom 0.1
32 // The first argument is the syscall id, so skip over it.
33let [ptr, len, flags] = check_min_vararg_count("syscall(SYS_getrandom, ...)", varargs)?;
3435let ptr = ecx.read_pointer(ptr)?;
36let len = ecx.read_target_usize(len)?;
37// The only supported flags are GRND_RANDOM and GRND_NONBLOCK,
38 // neither of which have any effect on our current PRNG.
39 // See <https://github.com/rust-lang/rust/pull/79196> for a discussion of argument sizes.
40let _flags = ecx.read_scalar(flags)?.to_i32()?;
4142 ecx.gen_random(ptr, len)?;
43 ecx.write_scalar(Scalar::from_target_usize(len, ecx), dest)?;
44 }
45// `futex` is used by some synchronization primitives.
46num if num == sys_futex => {
47 futex(ecx, varargs, dest)?;
48 }
49 num if num == sys_eventfd2 => {
50let [initval, flags] = check_min_vararg_count("syscall(SYS_evetfd2, ...)", varargs)?;
5152let result = ecx.eventfd(initval, flags)?;
53 ecx.write_int(result.to_i32()?, dest)?;
54 }
55 num => {
56throw_unsup_format!("syscall: unsupported syscall number {num}");
57 }
58 };
5960 interp_ok(())
61}