miri/shims/unix/linux_like/
syscall.rs1use rustc_middle::ty::Ty;
2use rustc_span::Symbol;
3use rustc_target::callconv::FnAbi;
4use rustc_target::spec::Arch;
5
6use crate::shims::unix::env::EvalContextExt as _;
7use crate::shims::unix::fs::EvalContextExt as _;
8use crate::shims::unix::linux_like::eventfd::EvalContextExt as _;
9use crate::shims::unix::linux_like::sync::futex;
10use crate::shims::unix::socket::EvalContextExt as _;
11use crate::*;
12
13pub fn syscall<'tcx>(
14 ecx: &mut MiriInterpCx<'tcx>,
15 link_name: Symbol,
16 abi: &FnAbi<'tcx, Ty<'tcx>>,
17 args: &[OpTy<'tcx>],
18 dest: &MPlaceTy<'tcx>,
19) -> InterpResult<'tcx> {
20 let ([op], varargs) = ecx.check_shim_sig_variadic(
21 shim_sig!(extern "C" fn(isize, ...) -> isize),
22 (link_name, abi, args),
23 )?;
24 let sys_getrandom = ecx.eval_libc("SYS_getrandom").to_target_usize(ecx)?;
30 let sys_futex = if ecx.tcx.sess.target.arch == Arch::RiscV32 {
33 ecx.eval_libc("SYS_futex_time64")
34 } else {
35 ecx.eval_libc("SYS_futex")
36 }
37 .to_target_usize(ecx)?;
38 let sys_eventfd2 = ecx.eval_libc("SYS_eventfd2").to_target_usize(ecx)?;
39 let sys_gettid = ecx.eval_libc("SYS_gettid").to_target_usize(ecx)?;
40 let sys_accept4 = ecx.eval_libc("SYS_accept4").to_target_usize(ecx)?;
41 let sys_copy_file_range = ecx.eval_libc("SYS_copy_file_range").to_target_usize(ecx)?;
42
43 match ecx.read_target_usize(&op)? {
45 num if num == sys_getrandom => {
48 let ([ptr, len, flags], _) = ecx.check_varargs(
51 shim_varargs![*libc::c_void, usize, i32],
52 varargs,
53 "syscall(SYS_getrandom, ...)",
54 )?;
55
56 let ptr = ecx.read_pointer(&ptr)?;
57 let len = ecx.read_target_usize(&len)?;
58 let _flags = ecx.read_scalar(&flags)?.to_i32()?;
62
63 ecx.gen_random(ptr, len)?;
64 ecx.write_scalar(Scalar::from_target_usize(len, ecx), dest)?;
65 }
66 num if num == sys_futex => {
68 futex(ecx, varargs, dest)?;
69 }
70 num if num == sys_eventfd2 => {
71 let ([initval, flags], _) =
72 ecx.check_varargs(shim_varargs![u32, i32], varargs, "syscall(SYS_evetfd2, ...)")?;
73
74 let result = ecx.eventfd(&initval, &flags)?;
75 ecx.write_int(result.to_i32()?, dest)?;
76 }
77 num if num == sys_gettid => {
78 let result = ecx.unix_gettid("SYS_gettid")?;
79 ecx.write_int(result.to_u32()?, dest)?;
80 }
81 num if num == sys_accept4 => {
82 let ([socket, address, address_len, flags], _) = ecx.check_varargs(
84 shim_varargs![i32, *libc::sockaddr, *libc::socklen_t, i32],
85 varargs,
86 "syscall(SYS_accept4, ...)",
87 )?;
88 ecx.accept4(&socket, &address, &address_len, Some(&flags), dest)?;
89 }
90 num if num == sys_copy_file_range => {
91 let ([fd_in, off_in, fd_out, off_out, len, flags], _) = &ecx.check_varargs(
92 shim_varargs![i32, *libc::off_t, i32, *libc::off_t, libc::size_t, u32],
93 varargs,
94 "syscall(SYS_copy_file_range, ...)",
95 )?;
96 ecx.linux_copy_file_range(fd_in, off_in, fd_out, off_out, len, flags, dest)?;
97 }
98 _ => {
99 ecx.set_errno_and_return_neg1(LibcError("ENOSYS"), dest)?;
102 }
103 };
104
105 interp_ok(())
106}