Android: Added syscall support
This commit is contained in:
parent
340d2f7847
commit
c8ce9e68d4
@ -154,7 +154,7 @@ case $HOST_TARGET in
|
||||
TEST_TARGET=i686-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random threadname pthread fs libc-pipe
|
||||
TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $BASIC $UNIX time hashmap random thread sync available-parallelism tls libc-pipe
|
||||
TEST_TARGET=x86_64-pc-solaris run_tests_minimal $BASIC $UNIX time hashmap random thread sync available-parallelism tls libc-pipe
|
||||
TEST_TARGET=aarch64-linux-android run_tests_minimal $BASIC $UNIX time hashmap threadname pthread
|
||||
TEST_TARGET=aarch64-linux-android run_tests_minimal $BASIC $UNIX time hashmap random sync threadname pthread
|
||||
TEST_TARGET=wasm32-wasip2 run_tests_minimal $BASIC wasm
|
||||
TEST_TARGET=wasm32-unknown-unknown run_tests_minimal no_std empty_main wasm # this target doesn't really have std
|
||||
TEST_TARGET=thumbv7em-none-eabihf run_tests_minimal no_std
|
||||
|
@ -2,6 +2,7 @@
|
||||
use rustc_target::spec::abi::Abi;
|
||||
|
||||
use crate::shims::unix::android::thread::prctl;
|
||||
use crate::shims::unix::linux::syscall::syscall;
|
||||
use crate::*;
|
||||
|
||||
pub fn is_dyn_sym(_name: &str) -> bool {
|
||||
@ -26,6 +27,9 @@ fn emulate_foreign_item_inner(
|
||||
this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?;
|
||||
}
|
||||
|
||||
// Dynamically invoked syscalls
|
||||
"syscall" => syscall(this, link_name, abi, args, dest)?,
|
||||
|
||||
// Threading
|
||||
"prctl" => prctl(this, link_name, abi, args, dest)?,
|
||||
|
||||
|
@ -4,8 +4,7 @@
|
||||
use self::shims::unix::linux::epoll::EvalContextExt as _;
|
||||
use self::shims::unix::linux::eventfd::EvalContextExt as _;
|
||||
use self::shims::unix::linux::mem::EvalContextExt as _;
|
||||
use self::shims::unix::linux::sync::futex;
|
||||
use crate::helpers::check_min_arg_count;
|
||||
use self::shims::unix::linux::syscall::syscall;
|
||||
use crate::machine::{SIGRTMAX, SIGRTMIN};
|
||||
use crate::shims::unix::*;
|
||||
use crate::*;
|
||||
@ -117,53 +116,7 @@ fn emulate_foreign_item_inner(
|
||||
|
||||
// Dynamically invoked syscalls
|
||||
"syscall" => {
|
||||
// We do not use `check_shim` here because `syscall` is variadic. The argument
|
||||
// count is checked bellow.
|
||||
this.check_abi_and_shim_symbol_clash(abi, Abi::C { unwind: false }, link_name)?;
|
||||
// The syscall variadic function is legal to call with more arguments than needed,
|
||||
// extra arguments are simply ignored. The important check is that when we use an
|
||||
// argument, we have to also check all arguments *before* it to ensure that they
|
||||
// have the right type.
|
||||
|
||||
let sys_getrandom = this.eval_libc("SYS_getrandom").to_target_usize(this)?;
|
||||
let sys_futex = this.eval_libc("SYS_futex").to_target_usize(this)?;
|
||||
let sys_eventfd2 = this.eval_libc("SYS_eventfd2").to_target_usize(this)?;
|
||||
|
||||
let [op] = check_min_arg_count("syscall", args)?;
|
||||
match this.read_target_usize(op)? {
|
||||
// `libc::syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), GRND_NONBLOCK)`
|
||||
// is called if a `HashMap` is created the regular way (e.g. HashMap<K, V>).
|
||||
num if num == sys_getrandom => {
|
||||
// Used by getrandom 0.1
|
||||
// The first argument is the syscall id, so skip over it.
|
||||
let [_, ptr, len, flags] =
|
||||
check_min_arg_count("syscall(SYS_getrandom, ...)", args)?;
|
||||
|
||||
let ptr = this.read_pointer(ptr)?;
|
||||
let len = this.read_target_usize(len)?;
|
||||
// The only supported flags are GRND_RANDOM and GRND_NONBLOCK,
|
||||
// neither of which have any effect on our current PRNG.
|
||||
// See <https://github.com/rust-lang/rust/pull/79196> for a discussion of argument sizes.
|
||||
let _flags = this.read_scalar(flags)?.to_i32()?;
|
||||
|
||||
this.gen_random(ptr, len)?;
|
||||
this.write_scalar(Scalar::from_target_usize(len, this), dest)?;
|
||||
}
|
||||
// `futex` is used by some synchronization primitives.
|
||||
num if num == sys_futex => {
|
||||
futex(this, args, dest)?;
|
||||
}
|
||||
num if num == sys_eventfd2 => {
|
||||
let [_, initval, flags] =
|
||||
check_min_arg_count("syscall(SYS_evetfd2, ...)", args)?;
|
||||
|
||||
let result = this.eventfd(initval, flags)?;
|
||||
this.write_int(result.to_i32()?, dest)?;
|
||||
}
|
||||
num => {
|
||||
throw_unsup_format!("syscall: unsupported syscall number {num}");
|
||||
}
|
||||
}
|
||||
syscall(this, link_name, abi, args, dest)?;
|
||||
}
|
||||
|
||||
// Miscellaneous
|
||||
|
@ -3,3 +3,4 @@
|
||||
pub mod foreign_items;
|
||||
pub mod mem;
|
||||
pub mod sync;
|
||||
pub mod syscall;
|
||||
|
63
src/tools/miri/src/shims/unix/linux/syscall.rs
Normal file
63
src/tools/miri/src/shims/unix/linux/syscall.rs
Normal file
@ -0,0 +1,63 @@
|
||||
use rustc_span::Symbol;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
|
||||
use self::shims::unix::linux::eventfd::EvalContextExt as _;
|
||||
use crate::helpers::check_min_arg_count;
|
||||
use crate::shims::unix::linux::sync::futex;
|
||||
use crate::*;
|
||||
|
||||
pub fn syscall<'tcx>(
|
||||
this: &mut MiriInterpCx<'tcx>,
|
||||
link_name: Symbol,
|
||||
abi: Abi,
|
||||
args: &[OpTy<'tcx>],
|
||||
dest: &MPlaceTy<'tcx>,
|
||||
) -> InterpResult<'tcx> {
|
||||
// We do not use `check_shim` here because `syscall` is variadic. The argument
|
||||
// count is checked bellow.
|
||||
this.check_abi_and_shim_symbol_clash(abi, Abi::C { unwind: false }, link_name)?;
|
||||
// The syscall variadic function is legal to call with more arguments than needed,
|
||||
// extra arguments are simply ignored. The important check is that when we use an
|
||||
// argument, we have to also check all arguments *before* it to ensure that they
|
||||
// have the right type.
|
||||
|
||||
let sys_getrandom = this.eval_libc("SYS_getrandom").to_target_usize(this)?;
|
||||
let sys_futex = this.eval_libc("SYS_futex").to_target_usize(this)?;
|
||||
let sys_eventfd2 = this.eval_libc("SYS_eventfd2").to_target_usize(this)?;
|
||||
|
||||
let [op] = check_min_arg_count("syscall", args)?;
|
||||
match this.read_target_usize(op)? {
|
||||
// `libc::syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), GRND_NONBLOCK)`
|
||||
// is called if a `HashMap` is created the regular way (e.g. HashMap<K, V>).
|
||||
num if num == sys_getrandom => {
|
||||
// Used by getrandom 0.1
|
||||
// The first argument is the syscall id, so skip over it.
|
||||
let [_, ptr, len, flags] = check_min_arg_count("syscall(SYS_getrandom, ...)", args)?;
|
||||
|
||||
let ptr = this.read_pointer(ptr)?;
|
||||
let len = this.read_target_usize(len)?;
|
||||
// The only supported flags are GRND_RANDOM and GRND_NONBLOCK,
|
||||
// neither of which have any effect on our current PRNG.
|
||||
// See <https://github.com/rust-lang/rust/pull/79196> for a discussion of argument sizes.
|
||||
let _flags = this.read_scalar(flags)?.to_i32()?;
|
||||
|
||||
this.gen_random(ptr, len)?;
|
||||
this.write_scalar(Scalar::from_target_usize(len, this), dest)?;
|
||||
}
|
||||
// `futex` is used by some synchronization primitives.
|
||||
num if num == sys_futex => {
|
||||
futex(this, args, dest)?;
|
||||
}
|
||||
num if num == sys_eventfd2 => {
|
||||
let [_, initval, flags] = check_min_arg_count("syscall(SYS_evetfd2, ...)", args)?;
|
||||
|
||||
let result = this.eventfd(initval, flags)?;
|
||||
this.write_int(result.to_i32()?, dest)?;
|
||||
}
|
||||
num => {
|
||||
throw_unsup_format!("syscall: unsupported syscall number {num}");
|
||||
}
|
||||
};
|
||||
|
||||
interp_ok(())
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
//@only-target: linux
|
||||
//@only-target: android
|
||||
//@compile-flags: -Zmiri-disable-isolation
|
||||
|
||||
// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
|
||||
|
@ -28,26 +28,27 @@ fn test_getrandom() {
|
||||
|
||||
let mut buf = [0u8; 5];
|
||||
unsafe {
|
||||
#[cfg(target_os = "linux")]
|
||||
assert_eq!(
|
||||
libc::syscall(
|
||||
libc::SYS_getrandom,
|
||||
ptr::null_mut::<libc::c_void>(),
|
||||
0 as libc::size_t,
|
||||
0 as libc::c_uint,
|
||||
),
|
||||
0,
|
||||
);
|
||||
#[cfg(target_os = "linux")]
|
||||
assert_eq!(
|
||||
libc::syscall(
|
||||
libc::SYS_getrandom,
|
||||
buf.as_mut_ptr() as *mut libc::c_void,
|
||||
5 as libc::size_t,
|
||||
0 as libc::c_uint,
|
||||
),
|
||||
5,
|
||||
);
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
{
|
||||
assert_eq!(
|
||||
libc::syscall(
|
||||
libc::SYS_getrandom,
|
||||
ptr::null_mut::<libc::c_void>(),
|
||||
0 as libc::size_t,
|
||||
0 as libc::c_uint,
|
||||
),
|
||||
0,
|
||||
);
|
||||
assert_eq!(
|
||||
libc::syscall(
|
||||
libc::SYS_getrandom,
|
||||
buf.as_mut_ptr() as *mut libc::c_void,
|
||||
5 as libc::size_t,
|
||||
0 as libc::c_uint,
|
||||
),
|
||||
5,
|
||||
);
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
libc::getrandom(ptr::null_mut::<libc::c_void>(), 0 as libc::size_t, 0 as libc::c_uint),
|
||||
|
Loading…
Reference in New Issue
Block a user