- // FIXME: The libc syscall() function is a variadic function.
- // It's valid to call it with more arguments than a syscall
- // needs, so none of these syscalls should use check_arg_count.
- // It's even valid to call it with the wrong type of arguments,
- // as long as they'd end up in the same place with the calling
- // convention used. (E.g. using a `usize` instead of a pointer.)
- // It's not directly clear which number, size, and type of arguments
- // are acceptable in which cases and which aren't. (E.g. some
- // types might take up the space of two registers.)
- // So this needs to be researched first.
-
- let sys_getrandom = this
- .eval_libc("SYS_getrandom")?
- .to_machine_usize(this)?;
-
- let sys_statx = this
- .eval_libc("SYS_statx")?
- .to_machine_usize(this)?;
-
- let sys_futex = this
- .eval_libc("SYS_futex")?
- .to_machine_usize(this)?;
+ check_abi(this, abi, Abi::C { unwind: false })?;
+ // The syscall variadic function is legal to call with more arguments than needed,
+ // extra arguments are simply ignored. However, all arguments need to be scalars;
+ // other types might be treated differently by the calling convention.
+ for arg in args {
+ if !matches!(arg.layout.abi, rustc_target::abi::Abi::Scalar(_)) {
+ throw_ub_format!(
+ "`syscall` arguments must all have scalar layout, but {} does not",
+ arg.layout.ty
+ );
+ }
+ }
+
+ let sys_getrandom = this.eval_libc("SYS_getrandom")?.to_machine_usize(this)?;
+
+ let sys_statx = this.eval_libc("SYS_statx")?.to_machine_usize(this)?;
+
+ let sys_futex = this.eval_libc("SYS_futex")?.to_machine_usize(this)?;