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=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-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=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-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=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
|
TEST_TARGET=thumbv7em-none-eabihf run_tests_minimal no_std
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
|
|
||||||
use crate::shims::unix::android::thread::prctl;
|
use crate::shims::unix::android::thread::prctl;
|
||||||
|
use crate::shims::unix::linux::syscall::syscall;
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
pub fn is_dyn_sym(_name: &str) -> bool {
|
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)?;
|
this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dynamically invoked syscalls
|
||||||
|
"syscall" => syscall(this, link_name, abi, args, dest)?,
|
||||||
|
|
||||||
// Threading
|
// Threading
|
||||||
"prctl" => prctl(this, link_name, abi, args, dest)?,
|
"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::epoll::EvalContextExt as _;
|
||||||
use self::shims::unix::linux::eventfd::EvalContextExt as _;
|
use self::shims::unix::linux::eventfd::EvalContextExt as _;
|
||||||
use self::shims::unix::linux::mem::EvalContextExt as _;
|
use self::shims::unix::linux::mem::EvalContextExt as _;
|
||||||
use self::shims::unix::linux::sync::futex;
|
use self::shims::unix::linux::syscall::syscall;
|
||||||
use crate::helpers::check_min_arg_count;
|
|
||||||
use crate::machine::{SIGRTMAX, SIGRTMIN};
|
use crate::machine::{SIGRTMAX, SIGRTMIN};
|
||||||
use crate::shims::unix::*;
|
use crate::shims::unix::*;
|
||||||
use crate::*;
|
use crate::*;
|
||||||
@ -117,53 +116,7 @@ fn emulate_foreign_item_inner(
|
|||||||
|
|
||||||
// Dynamically invoked syscalls
|
// Dynamically invoked syscalls
|
||||||
"syscall" => {
|
"syscall" => {
|
||||||
// We do not use `check_shim` here because `syscall` is variadic. The argument
|
syscall(this, link_name, abi, args, dest)?;
|
||||||
// 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}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Miscellaneous
|
// Miscellaneous
|
||||||
|
@ -3,3 +3,4 @@
|
|||||||
pub mod foreign_items;
|
pub mod foreign_items;
|
||||||
pub mod mem;
|
pub mod mem;
|
||||||
pub mod sync;
|
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: linux
|
||||||
|
//@only-target: android
|
||||||
//@compile-flags: -Zmiri-disable-isolation
|
//@compile-flags: -Zmiri-disable-isolation
|
||||||
|
|
||||||
// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
|
// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
|
||||||
|
@ -28,26 +28,27 @@ fn test_getrandom() {
|
|||||||
|
|
||||||
let mut buf = [0u8; 5];
|
let mut buf = [0u8; 5];
|
||||||
unsafe {
|
unsafe {
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||||
assert_eq!(
|
{
|
||||||
libc::syscall(
|
assert_eq!(
|
||||||
libc::SYS_getrandom,
|
libc::syscall(
|
||||||
ptr::null_mut::<libc::c_void>(),
|
libc::SYS_getrandom,
|
||||||
0 as libc::size_t,
|
ptr::null_mut::<libc::c_void>(),
|
||||||
0 as libc::c_uint,
|
0 as libc::size_t,
|
||||||
),
|
0 as libc::c_uint,
|
||||||
0,
|
),
|
||||||
);
|
0,
|
||||||
#[cfg(target_os = "linux")]
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
libc::syscall(
|
libc::syscall(
|
||||||
libc::SYS_getrandom,
|
libc::SYS_getrandom,
|
||||||
buf.as_mut_ptr() as *mut libc::c_void,
|
buf.as_mut_ptr() as *mut libc::c_void,
|
||||||
5 as libc::size_t,
|
5 as libc::size_t,
|
||||||
0 as libc::c_uint,
|
0 as libc::c_uint,
|
||||||
),
|
),
|
||||||
5,
|
5,
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
libc::getrandom(ptr::null_mut::<libc::c_void>(), 0 as libc::size_t, 0 as libc::c_uint),
|
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