From c674cbabf5fc225cb0046c36ed3772f1b5bd4af7 Mon Sep 17 00:00:00 2001 From: Lander Brandt Date: Wed, 9 Mar 2022 11:38:40 -0800 Subject: [PATCH 1/3] add basic support for android targets Update UNIX OS assertion message Co-authored-by: Ralf Jung cleanup detection of unix OS fix issues with tests on Android minimum changes required to get most tests passing or ignored fix stderr line numbers --- ci.sh | 2 + src/helpers.rs | 28 +++++++++++++ src/machine.rs | 35 ++++++++++++++++ src/shims/dlsym.rs | 4 +- src/shims/env.rs | 33 ++++----------- src/shims/foreign_items.rs | 4 +- src/shims/posix/android/dlsym.rs | 53 ++++++++++++++++++++++++ src/shims/posix/android/foreign_items.rs | 28 +++++++++++++ src/shims/posix/android/mod.rs | 2 + src/shims/posix/dlsym.rs | 4 ++ src/shims/posix/foreign_items.rs | 18 ++++++++ src/shims/posix/fs.rs | 4 +- src/shims/posix/linux/foreign_items.rs | 15 +++++-- src/shims/posix/mod.rs | 1 + src/shims/posix/thread.rs | 2 +- src/shims/time.rs | 2 +- tests/fail/environ-gets-deallocated.rs | 2 +- tests/pass/concurrency/simple.rs | 1 + tests/pass/concurrency/sync.rs | 1 + tests/pass/current_dir.rs | 1 + tests/pass/current_dir_with_isolation.rs | 1 + tests/pass/fs.rs | 1 + tests/pass/fs_with_isolation.rs | 1 + tests/pass/hashmap.rs | 2 + tests/pass/libc.rs | 1 + 25 files changed, 209 insertions(+), 37 deletions(-) create mode 100644 src/shims/posix/android/dlsym.rs create mode 100644 src/shims/posix/android/foreign_items.rs create mode 100644 src/shims/posix/android/mod.rs diff --git a/ci.sh b/ci.sh index 01b86ff2f9..587efe1b6b 100755 --- a/ci.sh +++ b/ci.sh @@ -21,6 +21,7 @@ function run_tests { fi ./miri test --locked + if [ -z "${MIRI_TEST_TARGET+exists}" ]; then # Only for host architecture: tests with optimizations (`-O` is what cargo passes, but crank MIR # optimizations up all the way). @@ -50,6 +51,7 @@ case $HOST_TARGET in MIRI_TEST_TARGET=i686-unknown-linux-gnu run_tests MIRI_TEST_TARGET=aarch64-apple-darwin run_tests MIRI_TEST_TARGET=i686-pc-windows-msvc run_tests + MIRI_TEST_TARGET=aarch64-linux-android run_tests ;; x86_64-apple-darwin) MIRI_TEST_TARGET=mips64-unknown-linux-gnuabi64 run_tests # big-endian architecture diff --git a/src/helpers.rs b/src/helpers.rs index 8339ecde12..f54c395c8e 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -493,6 +493,28 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx ) } + /// Helper function used inside the shims of foreign functions to assert that the target OS + /// is based on the Linux kernel. It panics showing a message with the `name` of the foreign function + /// if this is not the case. + fn assert_target_os_is_linux_based(&self, name: &str) { + assert!( + matches!(self.eval_context_ref().tcx.sess.target.os.as_ref(), "linux" | "android"), + "`{}` is only available for supported Linux-based targets", + name, + ) + } + + /// Helper function used inside the shims of foreign functions to assert that the target OS + /// is part of the UNIX family. It panics showing a message with the `name` of the foreign function + /// if this is not the case. + fn assert_target_os_is_unix(&self, name: &str) { + assert!( + target_os_is_unix(self.eval_context_ref().tcx.sess.target.os.as_ref()), + "`{}` is only available for supported UNIX family targets", + name, + ); + } + /// Get last error variable as a place, lazily allocating thread-local storage for it if /// necessary. fn last_error_place(&mut self) -> InterpResult<'tcx, MPlaceTy<'tcx, Tag>> { @@ -883,3 +905,9 @@ impl std::fmt::Display for HexRange { write!(f, "[{:#x}..{:#x}]", self.0.start.bytes(), self.0.end().bytes()) } } + +/// Helper function used inside the shims of foreign functions to check that the `target_os` is +/// part of the UNIX family. +pub fn target_os_is_unix(target_os: &str) -> bool { + matches!(target_os, "linux" | "macos" | "android") +} diff --git a/src/machine.rs b/src/machine.rs index 9a358bb6d5..b85da88f0e 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -430,6 +430,41 @@ impl<'mir, 'tcx> Evaluator<'mir, 'tcx> { this.write_scalar(Scalar::from_u8(0), &place.into())?; Self::add_extern_static(this, "_tls_used", place.ptr); } + "android" => { + // "environ" + Self::add_extern_static( + this, + "environ", + this.machine.env_vars.environ.unwrap().ptr, + ); + // A couple zero-initialized pointer-sized extern statics. + // Most of them are for weak symbols, which we all set to null (indicating that the + // symbol is not supported, and triggering fallback code which ends up calling a + // syscall that we do support). + for name in &["__cxa_thread_atexit_impl", "getrandom", "statx"] { + let layout = this.machine.layouts.usize; + let place = this.allocate(layout, MiriMemoryKind::ExternStatic.into())?; + this.write_scalar(Scalar::from_machine_usize(0, this), &place.into())?; + Self::add_extern_static(this, name, place.ptr); + } + for symbol_name in &["signal", "bsd_signal"] { + let layout = this.machine.layouts.usize; + let dlsym = Dlsym::from_str(symbol_name.as_bytes(), &this.tcx.sess.target.os)? + .unwrap_or_else(|| { + panic!( + "hardcoded `extern static` symbol {} has no dlsym handler", + symbol_name + ) + }); + let ecx = this.eval_context_mut(); + let ptr = ecx.create_fn_alloc_ptr(FnVal::Other(dlsym)); + + let place = this.allocate(layout, MiriMemoryKind::ExternStatic.into())?; + this.write_pointer(ptr, &place.into())?; + + Self::add_extern_static(this, symbol_name, place.ptr); + } + } _ => {} // No "extern statics" supported on this target } Ok(()) diff --git a/src/shims/dlsym.rs b/src/shims/dlsym.rs index 05296d3a4e..a95524f09b 100644 --- a/src/shims/dlsym.rs +++ b/src/shims/dlsym.rs @@ -1,6 +1,7 @@ use rustc_middle::mir; use rustc_target::spec::abi::Abi; +use crate::helpers::target_os_is_unix; use crate::*; use shims::posix::dlsym as posix; use shims::windows::dlsym as windows; @@ -18,7 +19,8 @@ impl Dlsym { pub fn from_str<'tcx>(name: &[u8], target_os: &str) -> InterpResult<'tcx, Option> { let name = &*String::from_utf8_lossy(name); Ok(match target_os { - "linux" | "macos" => posix::Dlsym::from_str(name, target_os)?.map(Dlsym::Posix), + target if target_os_is_unix(target) => + posix::Dlsym::from_str(name, target_os)?.map(Dlsym::Posix), "windows" => windows::Dlsym::from_str(name)?.map(Dlsym::Windows), os => bug!("dlsym not implemented for target_os {}", os), }) diff --git a/src/shims/env.rs b/src/shims/env.rs index ae9b8c7514..c8546e9618 100644 --- a/src/shims/env.rs +++ b/src/shims/env.rs @@ -8,6 +8,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_middle::ty::layout::LayoutOf; use rustc_target::abi::Size; +use crate::helpers::target_os_is_unix; use crate::*; /// Check whether an operation that writes to a target buffer was successful. @@ -55,7 +56,7 @@ impl<'tcx> EnvVars<'tcx> { }; if forward { let var_ptr = match target_os { - "linux" | "macos" => + target if target_os_is_unix(target) => alloc_env_var_as_c_str(name.as_ref(), value.as_ref(), ecx)?, "windows" => alloc_env_var_as_wide_str(name.as_ref(), value.as_ref(), ecx)?, unsupported => @@ -113,11 +114,7 @@ impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mi pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> { fn getenv(&mut self, name_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, Pointer>> { let this = self.eval_context_mut(); - let target_os = &this.tcx.sess.target.os; - assert!( - target_os == "linux" || target_os == "macos", - "`getenv` is only available for the UNIX target family" - ); + this.assert_target_os_is_unix("getenv"); let name_ptr = this.read_pointer(name_op)?; let name = this.read_os_str_from_c_str(name_ptr)?; @@ -211,11 +208,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx value_op: &OpTy<'tcx, Tag>, ) -> InterpResult<'tcx, i32> { let this = self.eval_context_mut(); - let target_os = &this.tcx.sess.target.os; - assert!( - target_os == "linux" || target_os == "macos", - "`setenv` is only available for the UNIX target family" - ); + this.assert_target_os_is_unix("setenv"); let name_ptr = this.read_pointer(name_op)?; let value_ptr = this.read_pointer(value_op)?; @@ -285,11 +278,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx fn unsetenv(&mut self, name_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> { let this = self.eval_context_mut(); - let target_os = &this.tcx.sess.target.os; - assert!( - target_os == "linux" || target_os == "macos", - "`unsetenv` is only available for the UNIX target family" - ); + this.assert_target_os_is_unix("unsetenv"); let name_ptr = this.read_pointer(name_op)?; let mut success = None; @@ -319,11 +308,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx size_op: &OpTy<'tcx, Tag>, ) -> InterpResult<'tcx, Pointer>> { let this = self.eval_context_mut(); - let target_os = &this.tcx.sess.target.os; - assert!( - target_os == "linux" || target_os == "macos", - "`getcwd` is only available for the UNIX target family" - ); + this.assert_target_os_is_unix("getcwd"); let buf = this.read_pointer(buf_op)?; let size = this.read_scalar(size_op)?.to_machine_usize(&*this.tcx)?; @@ -378,11 +363,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx fn chdir(&mut self, path_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> { let this = self.eval_context_mut(); - let target_os = &this.tcx.sess.target.os; - assert!( - target_os == "linux" || target_os == "macos", - "`getcwd` is only available for the UNIX target family" - ); + this.assert_target_os_is_unix("chdir"); let path = this.read_path_from_c_str(this.read_pointer(path_op)?)?; diff --git a/src/shims/foreign_items.rs b/src/shims/foreign_items.rs index e978391801..37023eff5c 100644 --- a/src/shims/foreign_items.rs +++ b/src/shims/foreign_items.rs @@ -23,6 +23,7 @@ use rustc_target::{ use super::backtrace::EvalContextExt as _; use crate::helpers::convert::Truncate; +use crate::helpers::target_os_is_unix; use crate::*; /// Returned by `emulate_foreign_item_by_name`. @@ -700,9 +701,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx } } - // Platform-specific shims _ => match this.tcx.sess.target.os.as_ref() { - "linux" | "macos" => return shims::posix::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest, ret), + target if target_os_is_unix(target) => return shims::posix::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest, ret), "windows" => return shims::windows::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest, ret), target => throw_unsup_format!("the target `{}` is not supported", target), } diff --git a/src/shims/posix/android/dlsym.rs b/src/shims/posix/android/dlsym.rs new file mode 100644 index 0000000000..ddb6ba3e66 --- /dev/null +++ b/src/shims/posix/android/dlsym.rs @@ -0,0 +1,53 @@ +use helpers::check_arg_count; +use log::trace; +use rustc_middle::mir; + +use crate::*; + +#[derive(Debug, Copy, Clone)] +#[allow(non_camel_case_types)] +pub enum Dlsym { + signal, +} + +impl Dlsym { + // Returns an error for unsupported symbols, and None if this symbol + // should become a NULL pointer (pretend it does not exist). + pub fn from_str<'tcx>(name: &str) -> InterpResult<'tcx, Option> { + Ok(match &*name { + "__pthread_get_minstack" => None, + "getrandom" => None, // std falls back to syscall(SYS_getrandom, ...) when this is NULL. + "statx" => None, // std falls back to syscall(SYS_statx, ...) when this is NULL. + "signal" | "bsd_signal" => Some(Dlsym::signal), // these have the same signature/implementation + "android_set_abort_message" => None, // std falls back to just not doing anything when this is NULL. + _ => throw_unsup_format!("unsupported Android dlsym: {}", name), + }) + } +} + +impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {} +pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> { + fn call_dlsym( + &mut self, + dlsym: Dlsym, + args: &[OpTy<'tcx, Tag>], + dest: &PlaceTy<'tcx, Tag>, + ret: Option, + ) -> InterpResult<'tcx> { + let this = self.eval_context_mut(); + assert!(this.tcx.sess.target.os == "android"); + + let ret = ret.expect("we don't support any diverging dlsym"); + + match dlsym { + Dlsym::signal => { + let &[ref _sig, ref _func] = check_arg_count(args)?; + this.write_null(dest)?; + } + } + + trace!("{:?}", this.dump_place(**dest)); + this.go_to_block(ret); + Ok(()) + } +} diff --git a/src/shims/posix/android/foreign_items.rs b/src/shims/posix/android/foreign_items.rs new file mode 100644 index 0000000000..94a2c151b8 --- /dev/null +++ b/src/shims/posix/android/foreign_items.rs @@ -0,0 +1,28 @@ +use rustc_middle::mir; +use rustc_span::Symbol; +use rustc_target::spec::abi::Abi; + +use crate::*; +use shims::foreign_items::EmulateByNameResult; + +impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {} +pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> { + fn emulate_foreign_item_by_name( + &mut self, + link_name: Symbol, + abi: Abi, + args: &[OpTy<'tcx, Tag>], + dest: &PlaceTy<'tcx, Tag>, + ret: mir::BasicBlock, + ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> { + let this = self.eval_context_mut(); + + match &*link_name.as_str() { + _ => { + // By default we piggyback off the items emulated for Linux. For now this functions + // serves to make adding android-specific syscalls easy + return shims::posix::linux::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest, ret); + } + } + } +} diff --git a/src/shims/posix/android/mod.rs b/src/shims/posix/android/mod.rs new file mode 100644 index 0000000000..434f5f30b5 --- /dev/null +++ b/src/shims/posix/android/mod.rs @@ -0,0 +1,2 @@ +pub mod dlsym; +pub mod foreign_items; diff --git a/src/shims/posix/dlsym.rs b/src/shims/posix/dlsym.rs index 339110467c..ba10bef6ad 100644 --- a/src/shims/posix/dlsym.rs +++ b/src/shims/posix/dlsym.rs @@ -2,6 +2,7 @@ use rustc_middle::mir; use rustc_target::spec::abi::Abi; use crate::*; +use shims::posix::android::dlsym as android; use shims::posix::linux::dlsym as linux; use shims::posix::macos::dlsym as macos; @@ -9,6 +10,7 @@ use shims::posix::macos::dlsym as macos; pub enum Dlsym { Linux(linux::Dlsym), MacOs(macos::Dlsym), + Android(android::Dlsym), } impl Dlsym { @@ -18,6 +20,7 @@ impl Dlsym { Ok(match target_os { "linux" => linux::Dlsym::from_str(name)?.map(Dlsym::Linux), "macos" => macos::Dlsym::from_str(name)?.map(Dlsym::MacOs), + "android" => android::Dlsym::from_str(name)?.map(Dlsym::Android), _ => unreachable!(), }) } @@ -40,6 +43,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx match dlsym { Dlsym::Linux(dlsym) => linux::EvalContextExt::call_dlsym(this, dlsym, args, dest, ret), Dlsym::MacOs(dlsym) => macos::EvalContextExt::call_dlsym(this, dlsym, args, dest, ret), + Dlsym::Android(dlsym) => android::EvalContextExt::call_dlsym(this, dlsym, args, dest, ret), } } } diff --git a/src/shims/posix/foreign_items.rs b/src/shims/posix/foreign_items.rs index 566befb0ef..44a2d057f4 100644 --- a/src/shims/posix/foreign_items.rs +++ b/src/shims/posix/foreign_items.rs @@ -168,6 +168,23 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx } this.write_null(dest)?; } + "memalign" => { + let &[ref align, ref size] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let align = this.read_scalar(align)?.to_machine_usize(this)?; + let size = this.read_scalar(size)?.to_machine_usize(this)?; + + // Align must be power of 2. + if !align.is_power_of_two() { + throw_ub_format!("memalign: alignment must be a power of two, but is {}", align); + } + + let ptr = this.allocate_ptr( + Size::from_bytes(size), + Align::from_bytes(align).unwrap(), + MiriMemoryKind::C.into(), + )?; + this.write_pointer(ptr, dest)?; + } // Dynamic symbol loading "dlsym" => { @@ -479,6 +496,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx match this.tcx.sess.target.os.as_ref() { "linux" => return shims::posix::linux::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest, ret), "macos" => return shims::posix::macos::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest, ret), + "android" => return shims::posix::android::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest, ret), _ => unreachable!(), } } diff --git a/src/shims/posix/fs.rs b/src/shims/posix/fs.rs index 79539fd9c4..74db8aa69d 100644 --- a/src/shims/posix/fs.rs +++ b/src/shims/posix/fs.rs @@ -976,7 +976,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx ) -> InterpResult<'tcx, i32> { let this = self.eval_context_mut(); - this.assert_target_os("linux", "statx"); + this.assert_target_os_is_linux_based("statx"); let dirfd = this.read_scalar(dirfd_op)?.to_i32()?; let pathname_ptr = this.read_pointer(pathname_op)?; @@ -1278,7 +1278,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx fn linux_readdir64(&mut self, dirp_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - this.assert_target_os("linux", "readdir64"); + this.assert_target_os_is_linux_based("readdir64"); let dirp = this.read_scalar(dirp_op)?.to_machine_usize(this)?; diff --git a/src/shims/posix/linux/foreign_items.rs b/src/shims/posix/linux/foreign_items.rs index f966c63b72..d4edd80712 100644 --- a/src/shims/posix/linux/foreign_items.rs +++ b/src/shims/posix/linux/foreign_items.rs @@ -20,6 +20,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx _ret: mir::BasicBlock, ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> { let this = self.eval_context_mut(); + let target_os = this.tcx.sess.target.os.as_ref(); match &*link_name.as_str() { // errno @@ -30,7 +31,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx } // File related shims (but also see "syscall" below for statx) - // These symbols have different names on Linux and macOS, which is the only reason they are not + // These symbols have different names/signatures on Linux and macOS, which is the only reason they are not // in the `posix` module. "close" => { let [fd] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -134,7 +135,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx 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_statx = if target_os == "android" { + // libc's Android target currently does not support SYS_statx -- fail gracefully + None + } else { + Some(this.eval_libc("SYS_statx")?.to_machine_usize(this)?) + }; let sys_futex = this.eval_libc("SYS_futex")?.to_machine_usize(this)?; @@ -158,7 +164,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx } // `statx` is used by `libstd` to retrieve metadata information on `linux` // instead of using `stat`,`lstat` or `fstat` as on `macos`. - id if id == sys_statx => { + // + // the libc crate for android however cannot properly lookup this syscall, + // so we have to make this gracefull fail + id if sys_statx.map(|statx| statx == id).unwrap_or(false) => { // The first argument is the syscall id, so skip over it. if args.len() < 6 { throw_ub_format!( diff --git a/src/shims/posix/mod.rs b/src/shims/posix/mod.rs index f40dfaefb9..9a37d29051 100644 --- a/src/shims/posix/mod.rs +++ b/src/shims/posix/mod.rs @@ -5,6 +5,7 @@ mod fs; mod sync; mod thread; +mod android; mod linux; mod macos; diff --git a/src/shims/posix/thread.rs b/src/shims/posix/thread.rs index 88c3fb0bc8..21f4417763 100644 --- a/src/shims/posix/thread.rs +++ b/src/shims/posix/thread.rs @@ -97,7 +97,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx fn prctl(&mut self, args: &[OpTy<'tcx, Tag>]) -> InterpResult<'tcx, i32> { let this = self.eval_context_mut(); - this.assert_target_os("linux", "prctl"); + this.assert_target_os_is_linux_based("prctl"); if args.is_empty() { throw_ub_format!( diff --git a/src/shims/time.rs b/src/shims/time.rs index be453a429e..0809f41b55 100644 --- a/src/shims/time.rs +++ b/src/shims/time.rs @@ -22,7 +22,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx let this = self.eval_context_mut(); - this.assert_target_os("linux", "clock_gettime"); + this.assert_target_os_is_linux_based("clock_gettime"); this.check_no_isolation("`clock_gettime`")?; let clk_id = this.read_scalar(clk_id_op)?.to_i32()?; diff --git a/tests/fail/environ-gets-deallocated.rs b/tests/fail/environ-gets-deallocated.rs index b5a4441d2f..a6ccc4c16f 100644 --- a/tests/fail/environ-gets-deallocated.rs +++ b/tests/fail/environ-gets-deallocated.rs @@ -1,6 +1,6 @@ // ignore-windows: Windows does not have a global environ list that the program can access directly -#[cfg(target_os="linux")] +#[cfg(any(target_os="linux", target_os="android"))] fn get_environ() -> *const *const u8 { extern "C" { static mut environ: *const *const u8; diff --git a/tests/pass/concurrency/simple.rs b/tests/pass/concurrency/simple.rs index 40d8802472..8654dd21c1 100644 --- a/tests/pass/concurrency/simple.rs +++ b/tests/pass/concurrency/simple.rs @@ -1,4 +1,5 @@ // ignore-windows: Concurrency on Windows is not supported yet. +// ignore-android: `libc` crate does not support `PR_SET_NAME` on Android // compile-flags: -Zmiri-strict-provenance use std::thread; diff --git a/tests/pass/concurrency/sync.rs b/tests/pass/concurrency/sync.rs index 6889aad91c..818cf9f6d4 100644 --- a/tests/pass/concurrency/sync.rs +++ b/tests/pass/concurrency/sync.rs @@ -1,4 +1,5 @@ // ignore-windows: Concurrency on Windows is not supported yet. +// ignore-android: `libc` crate does not support `gettimeofday()` on Android // compile-flags: -Zmiri-disable-isolation -Zmiri-strict-provenance use std::sync::{Arc, Barrier, Condvar, Mutex, Once, RwLock}; diff --git a/tests/pass/current_dir.rs b/tests/pass/current_dir.rs index a88f820951..f8df9df36c 100644 --- a/tests/pass/current_dir.rs +++ b/tests/pass/current_dir.rs @@ -1,3 +1,4 @@ +// ignore-android: No foreign function support for __errno yet // compile-flags: -Zmiri-disable-isolation use std::env; use std::io::ErrorKind; diff --git a/tests/pass/current_dir_with_isolation.rs b/tests/pass/current_dir_with_isolation.rs index 98c44d57b6..65900364b3 100644 --- a/tests/pass/current_dir_with_isolation.rs +++ b/tests/pass/current_dir_with_isolation.rs @@ -1,3 +1,4 @@ +// ignore-android: No foreign function support for __errno yet // compile-flags: -Zmiri-isolation-error=warn-nobacktrace // normalize-stderr-test: "(getcwd|GetCurrentDirectoryW)" -> "$$GETCWD" // normalize-stderr-test: "(chdir|SetCurrentDirectoryW)" -> "$$SETCWD" diff --git a/tests/pass/fs.rs b/tests/pass/fs.rs index bc78cb560f..8d05219244 100644 --- a/tests/pass/fs.rs +++ b/tests/pass/fs.rs @@ -1,4 +1,5 @@ // ignore-windows: File handling is not implemented yet +// ignore-android: No foreign function support for __errno yet // compile-flags: -Zmiri-disable-isolation #![feature(rustc_private)] diff --git a/tests/pass/fs_with_isolation.rs b/tests/pass/fs_with_isolation.rs index cd91cd9be3..ac8bd4c7b4 100644 --- a/tests/pass/fs_with_isolation.rs +++ b/tests/pass/fs_with_isolation.rs @@ -1,4 +1,5 @@ // ignore-windows: File handling is not implemented yet +// ignore-android: No foreign function support for __errno yet // compile-flags: -Zmiri-isolation-error=warn-nobacktrace // normalize-stderr-test: "(stat(x)?)" -> "$$STAT" diff --git a/tests/pass/hashmap.rs b/tests/pass/hashmap.rs index 215f762efc..c964d2aa97 100644 --- a/tests/pass/hashmap.rs +++ b/tests/pass/hashmap.rs @@ -1,3 +1,5 @@ +// ignore-android: libc for Android does not have `SYS_statx` + use std::collections::HashMap; use std::hash::BuildHasher; diff --git a/tests/pass/libc.rs b/tests/pass/libc.rs index bf5ae98290..bc77d00b16 100644 --- a/tests/pass/libc.rs +++ b/tests/pass/libc.rs @@ -1,4 +1,5 @@ // ignore-windows: No libc on Windows +// ignore-android: libc's Android target does not have support for __errno_location yet // compile-flags: -Zmiri-disable-isolation #![feature(rustc_private)] From 6e20eefc3b3012e72c8efd577f375849b043ce7f Mon Sep 17 00:00:00 2001 From: Lander Brandt Date: Sat, 4 Jun 2022 10:45:22 -0700 Subject: [PATCH 2/3] fix pointer layout kind for Android's extern statics, add docs --- README.md | 3 +++ ci.sh | 3 ++- src/machine.rs | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 824a8d3e32..1506647023 100644 --- a/README.md +++ b/README.md @@ -214,6 +214,9 @@ degree documented below): supported on Windows. We also test `i686-pc-windows-msvc`, with the same reduced feature set. We might ship Miri with a nightly even when some features on these targets regress. +- `aarch64-linux-android` has basic support and should work for simple targets. + Some concurrency and filesystem operations are not supported and will fail at + runtime. ### Common Problems diff --git a/ci.sh b/ci.sh index 587efe1b6b..7e73288b9e 100755 --- a/ci.sh +++ b/ci.sh @@ -51,7 +51,8 @@ case $HOST_TARGET in MIRI_TEST_TARGET=i686-unknown-linux-gnu run_tests MIRI_TEST_TARGET=aarch64-apple-darwin run_tests MIRI_TEST_TARGET=i686-pc-windows-msvc run_tests - MIRI_TEST_TARGET=aarch64-linux-android run_tests + # TODO: Enable once https://github.com/rust-lang/rust/pull/94813 lands + # MIRI_TEST_TARGET=aarch64-linux-android run_tests ;; x86_64-apple-darwin) MIRI_TEST_TARGET=mips64-unknown-linux-gnuabi64 run_tests # big-endian architecture diff --git a/src/machine.rs b/src/machine.rs index b85da88f0e..3173a9d9e2 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -448,7 +448,7 @@ impl<'mir, 'tcx> Evaluator<'mir, 'tcx> { Self::add_extern_static(this, name, place.ptr); } for symbol_name in &["signal", "bsd_signal"] { - let layout = this.machine.layouts.usize; + let layout = this.machine.layouts.mut_raw_ptr; let dlsym = Dlsym::from_str(symbol_name.as_bytes(), &this.tcx.sess.target.os)? .unwrap_or_else(|| { panic!( From 5cbc9ac6a8685c6e63684e2a3a58a73df0c9b843 Mon Sep 17 00:00:00 2001 From: Lander Brandt Date: Sat, 4 Jun 2022 10:48:30 -0700 Subject: [PATCH 3/3] cargo fmt --- src/shims/posix/dlsym.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/shims/posix/dlsym.rs b/src/shims/posix/dlsym.rs index ba10bef6ad..ef333bf4e5 100644 --- a/src/shims/posix/dlsym.rs +++ b/src/shims/posix/dlsym.rs @@ -43,7 +43,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx match dlsym { Dlsym::Linux(dlsym) => linux::EvalContextExt::call_dlsym(this, dlsym, args, dest, ret), Dlsym::MacOs(dlsym) => macos::EvalContextExt::call_dlsym(this, dlsym, args, dest, ret), - Dlsym::Android(dlsym) => android::EvalContextExt::call_dlsym(this, dlsym, args, dest, ret), + Dlsym::Android(dlsym) => + android::EvalContextExt::call_dlsym(this, dlsym, args, dest, ret), } } }