add very basic Android support
This commit is contained in:
parent
af033ea428
commit
a05a8eb805
1
ci.sh
1
ci.sh
@ -84,6 +84,7 @@ case $HOST_TARGET in
|
|||||||
MIRI_TEST_TARGET=aarch64-apple-darwin run_tests
|
MIRI_TEST_TARGET=aarch64-apple-darwin run_tests
|
||||||
MIRI_TEST_TARGET=i686-pc-windows-msvc run_tests
|
MIRI_TEST_TARGET=i686-pc-windows-msvc run_tests
|
||||||
MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec data_race env/var
|
MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec data_race env/var
|
||||||
|
MIRI_TEST_TARGET=aarch64-linux-android run_tests_minimal hello integer vec
|
||||||
MIRI_TEST_TARGET=thumbv7em-none-eabihf MIRI_NO_STD=1 run_tests_minimal no_std # no_std embedded architecture
|
MIRI_TEST_TARGET=thumbv7em-none-eabihf MIRI_NO_STD=1 run_tests_minimal no_std # no_std embedded architecture
|
||||||
;;
|
;;
|
||||||
x86_64-apple-darwin)
|
x86_64-apple-darwin)
|
||||||
|
@ -1 +1 @@
|
|||||||
8556e6620e4866526b3cea767ad8c20ae877a569
|
9c20b2a8cc7588decb6de25ac6a7912dcef24d65
|
||||||
|
@ -954,5 +954,5 @@ pub fn get_local_crates(tcx: TyCtxt<'_>) -> Vec<CrateNum> {
|
|||||||
/// Helper function used inside the shims of foreign functions to check that
|
/// Helper function used inside the shims of foreign functions to check that
|
||||||
/// `target_os` is a supported UNIX OS.
|
/// `target_os` is a supported UNIX OS.
|
||||||
pub fn target_os_is_unix(target_os: &str) -> bool {
|
pub fn target_os_is_unix(target_os: &str) -> bool {
|
||||||
matches!(target_os, "linux" | "macos" | "freebsd")
|
matches!(target_os, "linux" | "macos" | "freebsd" | "android")
|
||||||
}
|
}
|
||||||
|
@ -232,13 +232,15 @@ pub struct PrimitiveLayouts<'tcx> {
|
|||||||
pub u32: TyAndLayout<'tcx>,
|
pub u32: TyAndLayout<'tcx>,
|
||||||
pub usize: TyAndLayout<'tcx>,
|
pub usize: TyAndLayout<'tcx>,
|
||||||
pub bool: TyAndLayout<'tcx>,
|
pub bool: TyAndLayout<'tcx>,
|
||||||
pub mut_raw_ptr: TyAndLayout<'tcx>,
|
pub mut_raw_ptr: TyAndLayout<'tcx>, // *mut ()
|
||||||
|
pub const_raw_ptr: TyAndLayout<'tcx>, // *const ()
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'mir, 'tcx: 'mir> PrimitiveLayouts<'tcx> {
|
impl<'mir, 'tcx: 'mir> PrimitiveLayouts<'tcx> {
|
||||||
fn new(layout_cx: LayoutCx<'tcx, TyCtxt<'tcx>>) -> Result<Self, LayoutError<'tcx>> {
|
fn new(layout_cx: LayoutCx<'tcx, TyCtxt<'tcx>>) -> Result<Self, LayoutError<'tcx>> {
|
||||||
let tcx = layout_cx.tcx;
|
let tcx = layout_cx.tcx;
|
||||||
let mut_raw_ptr = tcx.mk_ptr(TypeAndMut { ty: tcx.types.unit, mutbl: Mutability::Mut });
|
let mut_raw_ptr = tcx.mk_ptr(TypeAndMut { ty: tcx.types.unit, mutbl: Mutability::Mut });
|
||||||
|
let const_raw_ptr = tcx.mk_ptr(TypeAndMut { ty: tcx.types.unit, mutbl: Mutability::Not });
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
unit: layout_cx.layout_of(tcx.mk_unit())?,
|
unit: layout_cx.layout_of(tcx.mk_unit())?,
|
||||||
i8: layout_cx.layout_of(tcx.types.i8)?,
|
i8: layout_cx.layout_of(tcx.types.i8)?,
|
||||||
@ -251,6 +253,7 @@ fn new(layout_cx: LayoutCx<'tcx, TyCtxt<'tcx>>) -> Result<Self, LayoutError<'tcx
|
|||||||
usize: layout_cx.layout_of(tcx.types.usize)?,
|
usize: layout_cx.layout_of(tcx.types.usize)?,
|
||||||
bool: layout_cx.layout_of(tcx.types.bool)?,
|
bool: layout_cx.layout_of(tcx.types.bool)?,
|
||||||
mut_raw_ptr: layout_cx.layout_of(mut_raw_ptr)?,
|
mut_raw_ptr: layout_cx.layout_of(mut_raw_ptr)?,
|
||||||
|
const_raw_ptr: layout_cx.layout_of(const_raw_ptr)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -431,6 +434,17 @@ fn add_extern_static(
|
|||||||
this.machine.extern_statics.try_insert(Symbol::intern(name), ptr).unwrap();
|
this.machine.extern_statics.try_insert(Symbol::intern(name), ptr).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn alloc_extern_static(
|
||||||
|
this: &mut MiriEvalContext<'mir, 'tcx>,
|
||||||
|
name: &str,
|
||||||
|
val: ImmTy<'tcx, Provenance>,
|
||||||
|
) -> InterpResult<'tcx> {
|
||||||
|
let place = this.allocate(val.layout, MiriMemoryKind::ExternStatic.into())?;
|
||||||
|
this.write_immediate(*val, &place.into())?;
|
||||||
|
Self::add_extern_static(this, name, place.ptr);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Sets up the "extern statics" for this machine.
|
/// Sets up the "extern statics" for this machine.
|
||||||
fn init_extern_statics(this: &mut MiriEvalContext<'mir, 'tcx>) -> InterpResult<'tcx> {
|
fn init_extern_statics(this: &mut MiriEvalContext<'mir, 'tcx>) -> InterpResult<'tcx> {
|
||||||
match this.tcx.sess.target.os.as_ref() {
|
match this.tcx.sess.target.os.as_ref() {
|
||||||
@ -447,10 +461,8 @@ fn init_extern_statics(this: &mut MiriEvalContext<'mir, 'tcx>) -> InterpResult<'
|
|||||||
// syscall that we do support).
|
// syscall that we do support).
|
||||||
for name in &["__cxa_thread_atexit_impl", "getrandom", "statx", "__clock_gettime64"]
|
for name in &["__cxa_thread_atexit_impl", "getrandom", "statx", "__clock_gettime64"]
|
||||||
{
|
{
|
||||||
let layout = this.machine.layouts.usize;
|
let val = ImmTy::from_int(0, this.machine.layouts.usize);
|
||||||
let place = this.allocate(layout, MiriMemoryKind::ExternStatic.into())?;
|
Self::alloc_extern_static(this, name, val)?;
|
||||||
this.write_scalar(Scalar::from_machine_usize(0, this), &place.into())?;
|
|
||||||
Self::add_extern_static(this, name, place.ptr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"freebsd" => {
|
"freebsd" => {
|
||||||
@ -461,13 +473,27 @@ fn init_extern_statics(this: &mut MiriEvalContext<'mir, 'tcx>) -> InterpResult<'
|
|||||||
this.machine.env_vars.environ.unwrap().ptr,
|
this.machine.env_vars.environ.unwrap().ptr,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
"android" => {
|
||||||
|
// "signal"
|
||||||
|
let layout = this.machine.layouts.const_raw_ptr;
|
||||||
|
let dlsym = Dlsym::from_str("signal".as_bytes(), &this.tcx.sess.target.os)?
|
||||||
|
.expect("`signal` must be an actual dlsym on android");
|
||||||
|
let ptr = this.create_fn_alloc_ptr(FnVal::Other(dlsym));
|
||||||
|
let val = ImmTy::from_scalar(Scalar::from_pointer(ptr, this), layout);
|
||||||
|
Self::alloc_extern_static(this, "signal", val)?;
|
||||||
|
// 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.)
|
||||||
|
for name in &["bsd_signal"] {
|
||||||
|
let val = ImmTy::from_int(0, this.machine.layouts.usize);
|
||||||
|
Self::alloc_extern_static(this, name, val)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
"windows" => {
|
"windows" => {
|
||||||
// "_tls_used"
|
// "_tls_used"
|
||||||
// This is some obscure hack that is part of the Windows TLS story. It's a `u8`.
|
// This is some obscure hack that is part of the Windows TLS story. It's a `u8`.
|
||||||
let layout = this.machine.layouts.u8;
|
let val = ImmTy::from_int(0, this.machine.layouts.u8);
|
||||||
let place = this.allocate(layout, MiriMemoryKind::ExternStatic.into())?;
|
Self::alloc_extern_static(this, "_tls_used", val)?;
|
||||||
this.write_scalar(Scalar::from_u8(0), &place.into())?;
|
|
||||||
Self::add_extern_static(this, "_tls_used", place.ptr);
|
|
||||||
}
|
}
|
||||||
_ => {} // No "extern statics" supported on this target
|
_ => {} // No "extern statics" supported on this target
|
||||||
}
|
}
|
||||||
|
53
src/shims/unix/android/dlsym.rs
Normal file
53
src/shims/unix/android/dlsym.rs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
use rustc_middle::mir;
|
||||||
|
|
||||||
|
use crate::helpers::check_arg_count;
|
||||||
|
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<Dlsym>> {
|
||||||
|
Ok(match &*name {
|
||||||
|
"signal" => Some(Dlsym::signal),
|
||||||
|
_ => 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, Provenance>],
|
||||||
|
dest: &PlaceTy<'tcx, Provenance>,
|
||||||
|
ret: Option<mir::BasicBlock>,
|
||||||
|
) -> InterpResult<'tcx> {
|
||||||
|
let this = self.eval_context_mut();
|
||||||
|
let ret = ret.expect("we don't support any diverging dlsym");
|
||||||
|
assert!(this.tcx.sess.target.os == "android");
|
||||||
|
|
||||||
|
match dlsym {
|
||||||
|
Dlsym::signal => {
|
||||||
|
if !this.frame_in_std() {
|
||||||
|
throw_unsup_format!(
|
||||||
|
"`signal` support is crude and just enough for libstd to work"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let &[ref _sig, ref _func] = check_arg_count(args)?;
|
||||||
|
this.write_null(dest)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log::trace!("{:?}", this.dump_place(**dest));
|
||||||
|
this.go_to_block(ret);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
23
src/shims/unix/android/foreign_items.rs
Normal file
23
src/shims/unix/android/foreign_items.rs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
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, Provenance>],
|
||||||
|
_dest: &PlaceTy<'tcx, Provenance>,
|
||||||
|
) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> {
|
||||||
|
let _this = self.eval_context_mut();
|
||||||
|
match link_name.as_str() {
|
||||||
|
_ => return Ok(EmulateByNameResult::NotSupported),
|
||||||
|
}
|
||||||
|
//Ok(EmulateByNameResult::NeedsJumping)
|
||||||
|
}
|
||||||
|
}
|
2
src/shims/unix/android/mod.rs
Normal file
2
src/shims/unix/android/mod.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
pub mod dlsym;
|
||||||
|
pub mod foreign_items;
|
@ -2,15 +2,17 @@
|
|||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
|
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
use shims::unix::android::dlsym as android;
|
||||||
use shims::unix::freebsd::dlsym as freebsd;
|
use shims::unix::freebsd::dlsym as freebsd;
|
||||||
use shims::unix::linux::dlsym as linux;
|
use shims::unix::linux::dlsym as linux;
|
||||||
use shims::unix::macos::dlsym as macos;
|
use shims::unix::macos::dlsym as macos;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub enum Dlsym {
|
pub enum Dlsym {
|
||||||
|
Android(android::Dlsym),
|
||||||
|
FreeBsd(freebsd::Dlsym),
|
||||||
Linux(linux::Dlsym),
|
Linux(linux::Dlsym),
|
||||||
MacOs(macos::Dlsym),
|
MacOs(macos::Dlsym),
|
||||||
FreeBsd(freebsd::Dlsym),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Dlsym {
|
impl Dlsym {
|
||||||
@ -18,10 +20,11 @@ impl Dlsym {
|
|||||||
// should become a NULL pointer (pretend it does not exist).
|
// should become a NULL pointer (pretend it does not exist).
|
||||||
pub fn from_str<'tcx>(name: &str, target_os: &str) -> InterpResult<'tcx, Option<Dlsym>> {
|
pub fn from_str<'tcx>(name: &str, target_os: &str) -> InterpResult<'tcx, Option<Dlsym>> {
|
||||||
Ok(match target_os {
|
Ok(match target_os {
|
||||||
|
"android" => android::Dlsym::from_str(name)?.map(Dlsym::Android),
|
||||||
|
"freebsd" => freebsd::Dlsym::from_str(name)?.map(Dlsym::FreeBsd),
|
||||||
"linux" => linux::Dlsym::from_str(name)?.map(Dlsym::Linux),
|
"linux" => linux::Dlsym::from_str(name)?.map(Dlsym::Linux),
|
||||||
"macos" => macos::Dlsym::from_str(name)?.map(Dlsym::MacOs),
|
"macos" => macos::Dlsym::from_str(name)?.map(Dlsym::MacOs),
|
||||||
"freebsd" => freebsd::Dlsym::from_str(name)?.map(Dlsym::FreeBsd),
|
_ => panic!("unsupported Unix OS {target_os}"),
|
||||||
_ => unreachable!(),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -41,10 +44,12 @@ fn call_dlsym(
|
|||||||
this.check_abi(abi, Abi::C { unwind: false })?;
|
this.check_abi(abi, Abi::C { unwind: false })?;
|
||||||
|
|
||||||
match dlsym {
|
match dlsym {
|
||||||
Dlsym::Linux(dlsym) => linux::EvalContextExt::call_dlsym(this, dlsym, args, dest, ret),
|
Dlsym::Android(dlsym) =>
|
||||||
Dlsym::MacOs(dlsym) => macos::EvalContextExt::call_dlsym(this, dlsym, args, dest, ret),
|
android::EvalContextExt::call_dlsym(this, dlsym, args, dest, ret),
|
||||||
Dlsym::FreeBsd(dlsym) =>
|
Dlsym::FreeBsd(dlsym) =>
|
||||||
freebsd::EvalContextExt::call_dlsym(this, dlsym, args, dest, ret),
|
freebsd::EvalContextExt::call_dlsym(this, dlsym, args, dest, ret),
|
||||||
|
Dlsym::Linux(dlsym) => linux::EvalContextExt::call_dlsym(this, dlsym, args, dest, ret),
|
||||||
|
Dlsym::MacOs(dlsym) => macos::EvalContextExt::call_dlsym(this, dlsym, args, dest, ret),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ fn emulate_foreign_item_by_name(
|
|||||||
) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> {
|
) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> {
|
||||||
let this = self.eval_context_mut();
|
let this = self.eval_context_mut();
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
match link_name.as_str() {
|
match link_name.as_str() {
|
||||||
// Environment related shims
|
// Environment related shims
|
||||||
"getenv" => {
|
"getenv" => {
|
||||||
@ -588,11 +589,13 @@ fn emulate_foreign_item_by_name(
|
|||||||
|
|
||||||
// Platform-specific shims
|
// Platform-specific shims
|
||||||
_ => {
|
_ => {
|
||||||
match this.tcx.sess.target.os.as_ref() {
|
let target_os = &*this.tcx.sess.target.os;
|
||||||
|
match target_os {
|
||||||
|
"android" => return shims::unix::android::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest),
|
||||||
|
"freebsd" => return shims::unix::freebsd::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest),
|
||||||
"linux" => return shims::unix::linux::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest),
|
"linux" => return shims::unix::linux::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest),
|
||||||
"macos" => return shims::unix::macos::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest),
|
"macos" => return shims::unix::macos::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest),
|
||||||
"freebsd" => return shims::unix::freebsd::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest),
|
_ => panic!("unsupported Unix OS {target_os}"),
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -28,5 +28,9 @@ fn call_dlsym(
|
|||||||
assert!(this.tcx.sess.target.os == "freebsd");
|
assert!(this.tcx.sess.target.os == "freebsd");
|
||||||
|
|
||||||
match dlsym {}
|
match dlsym {}
|
||||||
|
|
||||||
|
//trace!("{:?}", this.dump_place(**dest));
|
||||||
|
//this.go_to_block(ret);
|
||||||
|
//Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,5 +32,9 @@ fn call_dlsym(
|
|||||||
assert!(this.tcx.sess.target.os == "linux");
|
assert!(this.tcx.sess.target.os == "linux");
|
||||||
|
|
||||||
match dlsym {}
|
match dlsym {}
|
||||||
|
|
||||||
|
//trace!("{:?}", this.dump_place(**dest));
|
||||||
|
//this.go_to_block(ret);
|
||||||
|
//Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
mod sync;
|
mod sync;
|
||||||
mod thread;
|
mod thread;
|
||||||
|
|
||||||
|
mod android;
|
||||||
mod freebsd;
|
mod freebsd;
|
||||||
mod linux;
|
mod linux;
|
||||||
mod macos;
|
mod macos;
|
||||||
|
@ -45,7 +45,7 @@ fn call_dlsym(
|
|||||||
Dlsym::NtWriteFile => {
|
Dlsym::NtWriteFile => {
|
||||||
if !this.frame_in_std() {
|
if !this.frame_in_std() {
|
||||||
throw_unsup_format!(
|
throw_unsup_format!(
|
||||||
"NtWriteFile support is crude and just enough for stdout to work"
|
"`NtWriteFile` support is crude and just enough for stdout to work"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ fn call_dlsym(
|
|||||||
|
|
||||||
if byte_offset != 0 {
|
if byte_offset != 0 {
|
||||||
throw_unsup_format!(
|
throw_unsup_format!(
|
||||||
"NtWriteFile ByteOffset paremeter is non-null, which is unsupported"
|
"`NtWriteFile` `ByteOffset` paremeter is non-null, which is unsupported"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user