diff --git a/src/machine.rs b/src/machine.rs index bb43cb9550..5984aee984 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -253,6 +253,23 @@ impl MemoryExtra { this.write_scalar(Scalar::from_u8(0), &place.into())?; Self::add_extern_static(this, "_tls_used", place.ptr); } + "android" => + 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 (provenance, offset) = + this.memory.create_fn_alloc(FnVal::Other(dlsym)).into_parts(); + let ptr = Pointer::new(Some(provenance), offset); + 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 1855d65d6c..4befaf26aa 100644 --- a/src/shims/dlsym.rs +++ b/src/shims/dlsym.rs @@ -18,7 +18,8 @@ impl Dlsym { pub fn from_str(name: &[u8], target_os: &str) -> InterpResult<'static, Option> { let name = &*String::from_utf8_lossy(name); Ok(match target_os { - "linux" | "macos" => posix::Dlsym::from_str(name, target_os)?.map(Dlsym::Posix), + "linux" | "macos" | "android" => + 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 fd77286885..3670a444e8 100644 --- a/src/shims/env.rs +++ b/src/shims/env.rs @@ -116,7 +116,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx let this = self.eval_context_mut(); let target_os = &this.tcx.sess.target.os; assert!( - target_os == "linux" || target_os == "macos", + matches!(target_os.as_str(), "linux" | "macos" | "android"), "`getenv` is only available for the UNIX target family" ); @@ -214,7 +214,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx let mut this = self.eval_context_mut(); let target_os = &this.tcx.sess.target.os; assert!( - target_os == "linux" || target_os == "macos", + matches!(target_os.as_str(), "linux" | "macos" | "android"), "`setenv` is only available for the UNIX target family" ); @@ -288,7 +288,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx let this = self.eval_context_mut(); let target_os = &this.tcx.sess.target.os; assert!( - target_os == "linux" || target_os == "macos", + matches!(target_os.as_str(), "linux" | "macos" | "android"), "`unsetenv` is only available for the UNIX target family" ); @@ -322,7 +322,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx let this = self.eval_context_mut(); let target_os = &this.tcx.sess.target.os; assert!( - target_os == "linux" || target_os == "macos", + matches!(target_os.as_str(), "linux" | "macos" | "android"), "`getcwd` is only available for the UNIX target family" ); @@ -381,7 +381,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx let this = self.eval_context_mut(); let target_os = &this.tcx.sess.target.os; assert!( - target_os == "linux" || target_os == "macos", + matches!(target_os.as_str(), "linux" | "macos" | "android"), "`getcwd` is only available for the UNIX target family" ); diff --git a/src/shims/foreign_items.rs b/src/shims/foreign_items.rs index b07db95351..64ec9dcf8c 100644 --- a/src/shims/foreign_items.rs +++ b/src/shims/foreign_items.rs @@ -687,7 +687,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // Platform-specific shims _ => match this.tcx.sess.target.os.as_str() { - "linux" | "macos" => return shims::posix::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest, ret), + "linux" | "macos" | "android" => 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..679b0ad65c --- /dev/null +++ b/src/shims/posix/android/dlsym.rs @@ -0,0 +1,49 @@ +use helpers::check_arg_count; +use log::trace; +use rustc_middle::mir; + +use crate::*; + +#[derive(Debug, Copy, Clone)] +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(name: &str) -> InterpResult<'static, 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 + _ => 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>], + ret: Option<(&PlaceTy<'tcx, Tag>, mir::BasicBlock)>, + ) -> InterpResult<'tcx> { + let this = self.eval_context_mut(); + let (dest, ret) = ret.expect("we don't support any diverging dlsym"); + assert!(this.tcx.sess.target.os == "android"); + + 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 b07bf91a69..9cb76156a2 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!(), }) } @@ -39,6 +42,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx match dlsym { Dlsym::Linux(dlsym) => linux::EvalContextExt::call_dlsym(this, dlsym, args, ret), Dlsym::MacOs(dlsym) => macos::EvalContextExt::call_dlsym(this, dlsym, args, ret), + Dlsym::Android(dlsym) => android::EvalContextExt::call_dlsym(this, dlsym, args, ret), } } } diff --git a/src/shims/posix/foreign_items.rs b/src/shims/posix/foreign_items.rs index 02fb7089c3..4a3a5f67b8 100644 --- a/src/shims/posix/foreign_items.rs +++ b/src/shims/posix/foreign_items.rs @@ -465,6 +465,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx match this.tcx.sess.target.os.as_str() { "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::linux::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest, ret), _ => unreachable!(), } } 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;