Auto merge of #3616 - RalfJung:android, r=RalfJung

make basic things work on Android

Fixes https://github.com/rust-lang/miri/issues/3608
This commit is contained in:
bors 2024-05-19 10:14:36 +00:00
commit 0e41a801f3
9 changed files with 79 additions and 37 deletions

View File

@ -145,11 +145,12 @@ case $HOST_TARGET in
TEST_TARGET=s390x-unknown-linux-gnu run_tests # big-endian architecture of choice TEST_TARGET=s390x-unknown-linux-gnu run_tests # big-endian architecture of choice
# Partially supported targets (tier 2) # Partially supported targets (tier 2)
BASIC="empty_main integer vec string btreemap hello hashmap heap_alloc align" # ensures we have the basics: stdout/stderr, system allocator, randomness (for HashMap initialization) BASIC="empty_main integer vec string btreemap hello hashmap heap_alloc align" # ensures we have the basics: stdout/stderr, system allocator, randomness (for HashMap initialization)
TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal $BASIC panic/panic concurrency/simple atomic threadname libc-mem libc-misc libc-random libc-time fs env num_cpus UNIX="panic/panic concurrency/simple atomic libc-mem libc-misc libc-random env num_cpus" # the things that are very similar across all Unixes, and hence easily supported there
TEST_TARGET=i686-unknown-freebsd run_tests_minimal $BASIC panic/panic concurrency/simple atomic threadname libc-mem libc-misc libc-random libc-time fs env num_cpus TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal $BASIC $UNIX threadname libc-time fs
TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $BASIC panic/panic concurrency/simple pthread-sync libc-mem libc-misc libc-random env TEST_TARGET=i686-unknown-freebsd run_tests_minimal $BASIC $UNIX threadname libc-time fs
TEST_TARGET=x86_64-pc-solaris run_tests_minimal $BASIC panic/panic concurrency/simple pthread-sync libc-mem libc-misc libc-random env TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $BASIC $UNIX pthread-sync
TEST_TARGET=aarch64-linux-android run_tests_minimal empty_main hello panic/panic TEST_TARGET=x86_64-pc-solaris run_tests_minimal $BASIC $UNIX pthread-sync
TEST_TARGET=aarch64-linux-android run_tests_minimal $BASIC $UNIX
TEST_TARGET=wasm32-wasi run_tests_minimal empty_main wasm heap_alloc libc-mem TEST_TARGET=wasm32-wasi run_tests_minimal empty_main wasm heap_alloc libc-mem
TEST_TARGET=wasm32-unknown-unknown run_tests_minimal empty_main wasm TEST_TARGET=wasm32-unknown-unknown run_tests_minimal empty_main wasm
TEST_TARGET=thumbv7em-none-eabihf run_tests_minimal no_std TEST_TARGET=thumbv7em-none-eabihf run_tests_minimal no_std

View File

@ -55,6 +55,12 @@ pub fn init_extern_statics(this: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<
let val = ImmTy::from_int(val, this.machine.layouts.u8); let val = ImmTy::from_int(val, this.machine.layouts.u8);
Self::alloc_extern_static(this, "__rust_alloc_error_handler_should_panic", val)?; Self::alloc_extern_static(this, "__rust_alloc_error_handler_should_panic", val)?;
if this.target_os_is_unix() {
// "environ" is mandated by POSIX.
let environ = this.machine.env_vars.unix().environ();
Self::add_extern_static(this, "environ", environ);
}
match this.tcx.sess.target.os.as_ref() { match this.tcx.sess.target.os.as_ref() {
"linux" => { "linux" => {
Self::null_ptr_extern_statics( Self::null_ptr_extern_statics(
@ -62,23 +68,13 @@ pub fn init_extern_statics(this: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<
&["__cxa_thread_atexit_impl", "__clock_gettime64"], &["__cxa_thread_atexit_impl", "__clock_gettime64"],
)?; )?;
Self::weak_symbol_extern_statics(this, &["getrandom", "statx"])?; Self::weak_symbol_extern_statics(this, &["getrandom", "statx"])?;
// "environ"
let environ = this.machine.env_vars.unix().environ();
Self::add_extern_static(this, "environ", environ);
} }
"freebsd" => { "freebsd" => {
Self::null_ptr_extern_statics(this, &["__cxa_thread_atexit_impl"])?; Self::null_ptr_extern_statics(this, &["__cxa_thread_atexit_impl"])?;
// "environ"
let environ = this.machine.env_vars.unix().environ();
Self::add_extern_static(this, "environ", environ);
} }
"android" => { "android" => {
Self::null_ptr_extern_statics(this, &["bsd_signal"])?; Self::null_ptr_extern_statics(this, &["bsd_signal"])?;
Self::weak_symbol_extern_statics(this, &["signal"])?; Self::weak_symbol_extern_statics(this, &["signal", "getrandom"])?;
}
"solaris" | "illumos" => {
let environ = this.machine.env_vars.unix().environ();
Self::add_extern_static(this, "environ", environ);
} }
"windows" => { "windows" => {
// "_tls_used" // "_tls_used"

View File

@ -0,0 +1,32 @@
use rustc_span::Symbol;
use rustc_target::spec::abi::Abi;
use crate::*;
pub fn is_dyn_sym(_name: &str) -> bool {
false
}
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
fn emulate_foreign_item_inner(
&mut self,
link_name: Symbol,
abi: Abi,
args: &[OpTy<'tcx, Provenance>],
dest: &MPlaceTy<'tcx, Provenance>,
) -> InterpResult<'tcx, EmulateItemResult> {
let this = self.eval_context_mut();
match link_name.as_str() {
// Miscellaneous
"__errno" => {
let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let errno_place = this.last_error_place()?;
this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?;
}
_ => return Ok(EmulateItemResult::NotSupported),
}
Ok(EmulateItemResult::NeedsJumping)
}
}

View File

@ -0,0 +1 @@
pub mod foreign_items;

View File

@ -9,6 +9,7 @@
use crate::shims::unix::*; use crate::shims::unix::*;
use crate::*; use crate::*;
use shims::unix::android::foreign_items as android;
use shims::unix::freebsd::foreign_items as freebsd; use shims::unix::freebsd::foreign_items as freebsd;
use shims::unix::linux::foreign_items as linux; use shims::unix::linux::foreign_items as linux;
use shims::unix::macos::foreign_items as macos; use shims::unix::macos::foreign_items as macos;
@ -26,6 +27,7 @@ pub fn is_dyn_sym(name: &str, target_os: &str) -> bool {
// Give specific OSes a chance to allow their symbols. // Give specific OSes a chance to allow their symbols.
_ => _ =>
match target_os { match target_os {
"android" => android::is_dyn_sym(name),
"freebsd" => freebsd::is_dyn_sym(name), "freebsd" => freebsd::is_dyn_sym(name),
"linux" => linux::is_dyn_sym(name), "linux" => linux::is_dyn_sym(name),
"macos" => macos::is_dyn_sym(name), "macos" => macos::is_dyn_sym(name),
@ -267,7 +269,7 @@ fn emulate_foreign_item_inner(
"reallocarray" => { "reallocarray" => {
// Currently this function does not exist on all Unixes, e.g. on macOS. // Currently this function does not exist on all Unixes, e.g. on macOS.
if !matches!(&*this.tcx.sess.target.os, "linux" | "freebsd") { if !matches!(&*this.tcx.sess.target.os, "linux" | "freebsd" | "android") {
throw_unsup_format!( throw_unsup_format!(
"`reallocarray` is not supported on {}", "`reallocarray` is not supported on {}",
this.tcx.sess.target.os this.tcx.sess.target.os
@ -593,7 +595,7 @@ fn emulate_foreign_item_inner(
"getentropy" => { "getentropy" => {
// This function is non-standard but exists with the same signature and behavior on // This function is non-standard but exists with the same signature and behavior on
// Linux, macOS, FreeBSD and Solaris/Illumos. // Linux, macOS, FreeBSD and Solaris/Illumos.
if !matches!(&*this.tcx.sess.target.os, "linux" | "macos" | "freebsd" | "illumos" | "solaris") { if !matches!(&*this.tcx.sess.target.os, "linux" | "macos" | "freebsd" | "illumos" | "solaris" | "android") {
throw_unsup_format!( throw_unsup_format!(
"`getentropy` is not supported on {}", "`getentropy` is not supported on {}",
this.tcx.sess.target.os this.tcx.sess.target.os
@ -622,9 +624,9 @@ fn emulate_foreign_item_inner(
"getrandom" => { "getrandom" => {
// This function is non-standard but exists with the same signature and behavior on // This function is non-standard but exists with the same signature and behavior on
// Linux, FreeBSD and Solaris/Illumos. // Linux, FreeBSD and Solaris/Illumos.
if !matches!(&*this.tcx.sess.target.os, "linux" | "freebsd" | "illumos" | "solaris") { if !matches!(&*this.tcx.sess.target.os, "linux" | "freebsd" | "illumos" | "solaris" | "android") {
throw_unsup_format!( throw_unsup_format!(
"`getentropy` is not supported on {}", "`getrandom` is not supported on {}",
this.tcx.sess.target.os this.tcx.sess.target.os
); );
} }
@ -748,6 +750,7 @@ fn emulate_foreign_item_inner(
_ => { _ => {
let target_os = &*this.tcx.sess.target.os; let target_os = &*this.tcx.sess.target.os;
return match target_os { return match target_os {
"android" => android::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest),
"freebsd" => freebsd::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest), "freebsd" => freebsd::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest),
"linux" => linux::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest), "linux" => linux::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest),
"macos" => macos::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest), "macos" => macos::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest),

View File

@ -8,6 +8,7 @@
mod sync; mod sync;
mod thread; mod thread;
mod android;
mod freebsd; mod freebsd;
mod linux; mod linux;
mod macos; mod macos;

View File

@ -1,11 +1,5 @@
//@ignore-target-windows: Windows does not have a global environ list that the program can access directly //@ignore-target-windows: Windows does not have a global environ list that the program can access directly
#[cfg(any(
target_os = "linux",
target_os = "freebsd",
target_os = "solaris",
target_os = "illumos"
))]
fn get_environ() -> *const *const u8 { fn get_environ() -> *const *const u8 {
extern "C" { extern "C" {
static mut environ: *const *const u8; static mut environ: *const *const u8;
@ -13,14 +7,6 @@ fn get_environ() -> *const *const u8 {
unsafe { environ } unsafe { environ }
} }
#[cfg(target_os = "macos")]
fn get_environ() -> *const *const u8 {
extern "C" {
fn _NSGetEnviron() -> *mut *const *const u8;
}
unsafe { *_NSGetEnviron() }
}
fn main() { fn main() {
let pointer = get_environ(); let pointer = get_environ();
let _x = unsafe { *pointer }; let _x = unsafe { *pointer };

View File

@ -10,9 +10,11 @@
fn test_thread_local_errno() { fn test_thread_local_errno() {
#[cfg(any(target_os = "illumos", target_os = "solaris"))] #[cfg(any(target_os = "illumos", target_os = "solaris"))]
use libc::___errno as __errno_location; use libc::___errno as __errno_location;
#[cfg(target_os = "android")]
use libc::__errno as __errno_location;
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
use libc::__errno_location; use libc::__errno_location;
#[cfg(any(target_os = "macos", target_os = "freebsd"))] #[cfg(any(target_os = "freebsd", target_os = "macos"))]
use libc::__error as __errno_location; use libc::__error as __errno_location;
unsafe { unsafe {
@ -28,6 +30,21 @@ fn test_thread_local_errno() {
} }
} }
fn test_environ() {
// Just a smoke test for now, checking that the extern static exists.
extern "C" {
static mut environ: *const *const libc::c_char;
}
unsafe {
let mut e = environ;
// Iterate to the end.
while !(*e).is_null() {
e = e.add(1);
}
}
}
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
fn test_sigrt() { fn test_sigrt() {
let min = libc::SIGRTMIN(); let min = libc::SIGRTMIN();
@ -60,6 +77,7 @@ fn test_dlsym() {
fn main() { fn main() {
test_thread_local_errno(); test_thread_local_errno();
test_environ();
test_dlsym(); test_dlsym();

View File

@ -2,8 +2,12 @@
use std::env; use std::env;
fn main() { fn main() {
env::remove_var("HOME"); // make sure we enter the interesting codepath // Remove the env vars to hit the underlying shim -- except
env::remove_var("USERPROFILE"); // Windows also looks as this env var // on android where the env var is all we have.
#[cfg(not(target_os = "android"))]
env::remove_var("HOME");
env::remove_var("USERPROFILE");
#[allow(deprecated)] #[allow(deprecated)]
env::home_dir().unwrap(); env::home_dir().unwrap();
} }