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=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=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
|
||||
;;
|
||||
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
|
||||
/// `target_os` is a supported UNIX OS.
|
||||
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 usize: 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> {
|
||||
fn new(layout_cx: LayoutCx<'tcx, TyCtxt<'tcx>>) -> Result<Self, LayoutError<'tcx>> {
|
||||
let tcx = layout_cx.tcx;
|
||||
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 {
|
||||
unit: layout_cx.layout_of(tcx.mk_unit())?,
|
||||
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)?,
|
||||
bool: layout_cx.layout_of(tcx.types.bool)?,
|
||||
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();
|
||||
}
|
||||
|
||||
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.
|
||||
fn init_extern_statics(this: &mut MiriEvalContext<'mir, 'tcx>) -> InterpResult<'tcx> {
|
||||
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).
|
||||
for name in &["__cxa_thread_atexit_impl", "getrandom", "statx", "__clock_gettime64"]
|
||||
{
|
||||
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);
|
||||
let val = ImmTy::from_int(0, this.machine.layouts.usize);
|
||||
Self::alloc_extern_static(this, name, val)?;
|
||||
}
|
||||
}
|
||||
"freebsd" => {
|
||||
@ -461,13 +473,27 @@ fn init_extern_statics(this: &mut MiriEvalContext<'mir, 'tcx>) -> InterpResult<'
|
||||
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" => {
|
||||
// "_tls_used"
|
||||
// This is some obscure hack that is part of the Windows TLS story. It's a `u8`.
|
||||
let layout = this.machine.layouts.u8;
|
||||
let place = this.allocate(layout, MiriMemoryKind::ExternStatic.into())?;
|
||||
this.write_scalar(Scalar::from_u8(0), &place.into())?;
|
||||
Self::add_extern_static(this, "_tls_used", place.ptr);
|
||||
let val = ImmTy::from_int(0, this.machine.layouts.u8);
|
||||
Self::alloc_extern_static(this, "_tls_used", val)?;
|
||||
}
|
||||
_ => {} // 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 crate::*;
|
||||
use shims::unix::android::dlsym as android;
|
||||
use shims::unix::freebsd::dlsym as freebsd;
|
||||
use shims::unix::linux::dlsym as linux;
|
||||
use shims::unix::macos::dlsym as macos;
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum Dlsym {
|
||||
Android(android::Dlsym),
|
||||
FreeBsd(freebsd::Dlsym),
|
||||
Linux(linux::Dlsym),
|
||||
MacOs(macos::Dlsym),
|
||||
FreeBsd(freebsd::Dlsym),
|
||||
}
|
||||
|
||||
impl Dlsym {
|
||||
@ -18,10 +20,11 @@ impl Dlsym {
|
||||
// should become a NULL pointer (pretend it does not exist).
|
||||
pub fn from_str<'tcx>(name: &str, target_os: &str) -> InterpResult<'tcx, Option<Dlsym>> {
|
||||
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),
|
||||
"macos" => macos::Dlsym::from_str(name)?.map(Dlsym::MacOs),
|
||||
"freebsd" => freebsd::Dlsym::from_str(name)?.map(Dlsym::FreeBsd),
|
||||
_ => unreachable!(),
|
||||
_ => panic!("unsupported Unix OS {target_os}"),
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -41,10 +44,12 @@ fn call_dlsym(
|
||||
this.check_abi(abi, Abi::C { unwind: false })?;
|
||||
|
||||
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::FreeBsd(dlsym) =>
|
||||
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>> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
#[rustfmt::skip]
|
||||
match link_name.as_str() {
|
||||
// Environment related shims
|
||||
"getenv" => {
|
||||
@ -588,11 +589,13 @@ fn emulate_foreign_item_by_name(
|
||||
|
||||
// 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),
|
||||
"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),
|
||||
_ => unreachable!(),
|
||||
_ => panic!("unsupported Unix OS {target_os}"),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -28,5 +28,9 @@ fn call_dlsym(
|
||||
assert!(this.tcx.sess.target.os == "freebsd");
|
||||
|
||||
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");
|
||||
|
||||
match dlsym {}
|
||||
|
||||
//trace!("{:?}", this.dump_place(**dest));
|
||||
//this.go_to_block(ret);
|
||||
//Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
mod sync;
|
||||
mod thread;
|
||||
|
||||
mod android;
|
||||
mod freebsd;
|
||||
mod linux;
|
||||
mod macos;
|
||||
|
@ -45,7 +45,7 @@ fn call_dlsym(
|
||||
Dlsym::NtWriteFile => {
|
||||
if !this.frame_in_std() {
|
||||
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 {
|
||||
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