Skip to content

Commit a05a8eb

Browse files
committed
add very basic Android support
1 parent af033ea commit a05a8eb

File tree

13 files changed

+143
-21
lines changed

13 files changed

+143
-21
lines changed

ci.sh

+1
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ case $HOST_TARGET in
8484
MIRI_TEST_TARGET=aarch64-apple-darwin run_tests
8585
MIRI_TEST_TARGET=i686-pc-windows-msvc run_tests
8686
MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec data_race env/var
87+
MIRI_TEST_TARGET=aarch64-linux-android run_tests_minimal hello integer vec
8788
MIRI_TEST_TARGET=thumbv7em-none-eabihf MIRI_NO_STD=1 run_tests_minimal no_std # no_std embedded architecture
8889
;;
8990
x86_64-apple-darwin)

rust-version

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
8556e6620e4866526b3cea767ad8c20ae877a569
1+
9c20b2a8cc7588decb6de25ac6a7912dcef24d65

src/helpers.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -954,5 +954,5 @@ pub fn get_local_crates(tcx: TyCtxt<'_>) -> Vec<CrateNum> {
954954
/// Helper function used inside the shims of foreign functions to check that
955955
/// `target_os` is a supported UNIX OS.
956956
pub fn target_os_is_unix(target_os: &str) -> bool {
957-
matches!(target_os, "linux" | "macos" | "freebsd")
957+
matches!(target_os, "linux" | "macos" | "freebsd" | "android")
958958
}

src/machine.rs

+35-9
Original file line numberDiff line numberDiff line change
@@ -232,13 +232,15 @@ pub struct PrimitiveLayouts<'tcx> {
232232
pub u32: TyAndLayout<'tcx>,
233233
pub usize: TyAndLayout<'tcx>,
234234
pub bool: TyAndLayout<'tcx>,
235-
pub mut_raw_ptr: TyAndLayout<'tcx>,
235+
pub mut_raw_ptr: TyAndLayout<'tcx>, // *mut ()
236+
pub const_raw_ptr: TyAndLayout<'tcx>, // *const ()
236237
}
237238

238239
impl<'mir, 'tcx: 'mir> PrimitiveLayouts<'tcx> {
239240
fn new(layout_cx: LayoutCx<'tcx, TyCtxt<'tcx>>) -> Result<Self, LayoutError<'tcx>> {
240241
let tcx = layout_cx.tcx;
241242
let mut_raw_ptr = tcx.mk_ptr(TypeAndMut { ty: tcx.types.unit, mutbl: Mutability::Mut });
243+
let const_raw_ptr = tcx.mk_ptr(TypeAndMut { ty: tcx.types.unit, mutbl: Mutability::Not });
242244
Ok(Self {
243245
unit: layout_cx.layout_of(tcx.mk_unit())?,
244246
i8: layout_cx.layout_of(tcx.types.i8)?,
@@ -251,6 +253,7 @@ impl<'mir, 'tcx: 'mir> PrimitiveLayouts<'tcx> {
251253
usize: layout_cx.layout_of(tcx.types.usize)?,
252254
bool: layout_cx.layout_of(tcx.types.bool)?,
253255
mut_raw_ptr: layout_cx.layout_of(mut_raw_ptr)?,
256+
const_raw_ptr: layout_cx.layout_of(const_raw_ptr)?,
254257
})
255258
}
256259
}
@@ -431,6 +434,17 @@ impl<'mir, 'tcx> Evaluator<'mir, 'tcx> {
431434
this.machine.extern_statics.try_insert(Symbol::intern(name), ptr).unwrap();
432435
}
433436

437+
fn alloc_extern_static(
438+
this: &mut MiriEvalContext<'mir, 'tcx>,
439+
name: &str,
440+
val: ImmTy<'tcx, Provenance>,
441+
) -> InterpResult<'tcx> {
442+
let place = this.allocate(val.layout, MiriMemoryKind::ExternStatic.into())?;
443+
this.write_immediate(*val, &place.into())?;
444+
Self::add_extern_static(this, name, place.ptr);
445+
Ok(())
446+
}
447+
434448
/// Sets up the "extern statics" for this machine.
435449
fn init_extern_statics(this: &mut MiriEvalContext<'mir, 'tcx>) -> InterpResult<'tcx> {
436450
match this.tcx.sess.target.os.as_ref() {
@@ -447,10 +461,8 @@ impl<'mir, 'tcx> Evaluator<'mir, 'tcx> {
447461
// syscall that we do support).
448462
for name in &["__cxa_thread_atexit_impl", "getrandom", "statx", "__clock_gettime64"]
449463
{
450-
let layout = this.machine.layouts.usize;
451-
let place = this.allocate(layout, MiriMemoryKind::ExternStatic.into())?;
452-
this.write_scalar(Scalar::from_machine_usize(0, this), &place.into())?;
453-
Self::add_extern_static(this, name, place.ptr);
464+
let val = ImmTy::from_int(0, this.machine.layouts.usize);
465+
Self::alloc_extern_static(this, name, val)?;
454466
}
455467
}
456468
"freebsd" => {
@@ -461,13 +473,27 @@ impl<'mir, 'tcx> Evaluator<'mir, 'tcx> {
461473
this.machine.env_vars.environ.unwrap().ptr,
462474
);
463475
}
476+
"android" => {
477+
// "signal"
478+
let layout = this.machine.layouts.const_raw_ptr;
479+
let dlsym = Dlsym::from_str("signal".as_bytes(), &this.tcx.sess.target.os)?
480+
.expect("`signal` must be an actual dlsym on android");
481+
let ptr = this.create_fn_alloc_ptr(FnVal::Other(dlsym));
482+
let val = ImmTy::from_scalar(Scalar::from_pointer(ptr, this), layout);
483+
Self::alloc_extern_static(this, "signal", val)?;
484+
// A couple zero-initialized pointer-sized extern statics.
485+
// Most of them are for weak symbols, which we all set to null (indicating that the
486+
// symbol is not supported, and triggering fallback code.)
487+
for name in &["bsd_signal"] {
488+
let val = ImmTy::from_int(0, this.machine.layouts.usize);
489+
Self::alloc_extern_static(this, name, val)?;
490+
}
491+
}
464492
"windows" => {
465493
// "_tls_used"
466494
// This is some obscure hack that is part of the Windows TLS story. It's a `u8`.
467-
let layout = this.machine.layouts.u8;
468-
let place = this.allocate(layout, MiriMemoryKind::ExternStatic.into())?;
469-
this.write_scalar(Scalar::from_u8(0), &place.into())?;
470-
Self::add_extern_static(this, "_tls_used", place.ptr);
495+
let val = ImmTy::from_int(0, this.machine.layouts.u8);
496+
Self::alloc_extern_static(this, "_tls_used", val)?;
471497
}
472498
_ => {} // No "extern statics" supported on this target
473499
}

src/shims/unix/android/dlsym.rs

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
use rustc_middle::mir;
2+
3+
use crate::helpers::check_arg_count;
4+
use crate::*;
5+
6+
#[derive(Debug, Copy, Clone)]
7+
#[allow(non_camel_case_types)]
8+
pub enum Dlsym {
9+
signal,
10+
}
11+
12+
impl Dlsym {
13+
// Returns an error for unsupported symbols, and None if this symbol
14+
// should become a NULL pointer (pretend it does not exist).
15+
pub fn from_str<'tcx>(name: &str) -> InterpResult<'tcx, Option<Dlsym>> {
16+
Ok(match &*name {
17+
"signal" => Some(Dlsym::signal),
18+
_ => throw_unsup_format!("unsupported Android dlsym: {}", name),
19+
})
20+
}
21+
}
22+
23+
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
24+
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
25+
fn call_dlsym(
26+
&mut self,
27+
dlsym: Dlsym,
28+
args: &[OpTy<'tcx, Provenance>],
29+
dest: &PlaceTy<'tcx, Provenance>,
30+
ret: Option<mir::BasicBlock>,
31+
) -> InterpResult<'tcx> {
32+
let this = self.eval_context_mut();
33+
let ret = ret.expect("we don't support any diverging dlsym");
34+
assert!(this.tcx.sess.target.os == "android");
35+
36+
match dlsym {
37+
Dlsym::signal => {
38+
if !this.frame_in_std() {
39+
throw_unsup_format!(
40+
"`signal` support is crude and just enough for libstd to work"
41+
);
42+
}
43+
44+
let &[ref _sig, ref _func] = check_arg_count(args)?;
45+
this.write_null(dest)?;
46+
}
47+
}
48+
49+
log::trace!("{:?}", this.dump_place(**dest));
50+
this.go_to_block(ret);
51+
Ok(())
52+
}
53+
}
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
use rustc_span::Symbol;
2+
use rustc_target::spec::abi::Abi;
3+
4+
use crate::*;
5+
use shims::foreign_items::EmulateByNameResult;
6+
7+
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
8+
9+
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
10+
fn emulate_foreign_item_by_name(
11+
&mut self,
12+
link_name: Symbol,
13+
_abi: Abi,
14+
_args: &[OpTy<'tcx, Provenance>],
15+
_dest: &PlaceTy<'tcx, Provenance>,
16+
) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> {
17+
let _this = self.eval_context_mut();
18+
match link_name.as_str() {
19+
_ => return Ok(EmulateByNameResult::NotSupported),
20+
}
21+
//Ok(EmulateByNameResult::NeedsJumping)
22+
}
23+
}

src/shims/unix/android/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pub mod dlsym;
2+
pub mod foreign_items;

src/shims/unix/dlsym.rs

+10-5
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,29 @@ use rustc_middle::mir;
22
use rustc_target::spec::abi::Abi;
33

44
use crate::*;
5+
use shims::unix::android::dlsym as android;
56
use shims::unix::freebsd::dlsym as freebsd;
67
use shims::unix::linux::dlsym as linux;
78
use shims::unix::macos::dlsym as macos;
89

910
#[derive(Debug, Copy, Clone)]
1011
pub enum Dlsym {
12+
Android(android::Dlsym),
13+
FreeBsd(freebsd::Dlsym),
1114
Linux(linux::Dlsym),
1215
MacOs(macos::Dlsym),
13-
FreeBsd(freebsd::Dlsym),
1416
}
1517

1618
impl Dlsym {
1719
// Returns an error for unsupported symbols, and None if this symbol
1820
// should become a NULL pointer (pretend it does not exist).
1921
pub fn from_str<'tcx>(name: &str, target_os: &str) -> InterpResult<'tcx, Option<Dlsym>> {
2022
Ok(match target_os {
23+
"android" => android::Dlsym::from_str(name)?.map(Dlsym::Android),
24+
"freebsd" => freebsd::Dlsym::from_str(name)?.map(Dlsym::FreeBsd),
2125
"linux" => linux::Dlsym::from_str(name)?.map(Dlsym::Linux),
2226
"macos" => macos::Dlsym::from_str(name)?.map(Dlsym::MacOs),
23-
"freebsd" => freebsd::Dlsym::from_str(name)?.map(Dlsym::FreeBsd),
24-
_ => unreachable!(),
27+
_ => panic!("unsupported Unix OS {target_os}"),
2528
})
2629
}
2730
}
@@ -41,10 +44,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
4144
this.check_abi(abi, Abi::C { unwind: false })?;
4245

4346
match dlsym {
44-
Dlsym::Linux(dlsym) => linux::EvalContextExt::call_dlsym(this, dlsym, args, dest, ret),
45-
Dlsym::MacOs(dlsym) => macos::EvalContextExt::call_dlsym(this, dlsym, args, dest, ret),
47+
Dlsym::Android(dlsym) =>
48+
android::EvalContextExt::call_dlsym(this, dlsym, args, dest, ret),
4649
Dlsym::FreeBsd(dlsym) =>
4750
freebsd::EvalContextExt::call_dlsym(this, dlsym, args, dest, ret),
51+
Dlsym::Linux(dlsym) => linux::EvalContextExt::call_dlsym(this, dlsym, args, dest, ret),
52+
Dlsym::MacOs(dlsym) => macos::EvalContextExt::call_dlsym(this, dlsym, args, dest, ret),
4853
}
4954
}
5055
}

src/shims/unix/foreign_items.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
2424
) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> {
2525
let this = self.eval_context_mut();
2626

27+
#[rustfmt::skip]
2728
match link_name.as_str() {
2829
// Environment related shims
2930
"getenv" => {
@@ -588,11 +589,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
588589

589590
// Platform-specific shims
590591
_ => {
591-
match this.tcx.sess.target.os.as_ref() {
592+
let target_os = &*this.tcx.sess.target.os;
593+
match target_os {
594+
"android" => return shims::unix::android::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest),
595+
"freebsd" => return shims::unix::freebsd::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest),
592596
"linux" => return shims::unix::linux::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest),
593597
"macos" => return shims::unix::macos::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest),
594-
"freebsd" => return shims::unix::freebsd::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest),
595-
_ => unreachable!(),
598+
_ => panic!("unsupported Unix OS {target_os}"),
596599
}
597600
}
598601
};

src/shims/unix/freebsd/dlsym.rs

+4
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
2828
assert!(this.tcx.sess.target.os == "freebsd");
2929

3030
match dlsym {}
31+
32+
//trace!("{:?}", this.dump_place(**dest));
33+
//this.go_to_block(ret);
34+
//Ok(())
3135
}
3236
}

src/shims/unix/linux/dlsym.rs

+4
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
3232
assert!(this.tcx.sess.target.os == "linux");
3333

3434
match dlsym {}
35+
36+
//trace!("{:?}", this.dump_place(**dest));
37+
//this.go_to_block(ret);
38+
//Ok(())
3539
}
3640
}

src/shims/unix/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ mod fs;
55
mod sync;
66
mod thread;
77

8+
mod android;
89
mod freebsd;
910
mod linux;
1011
mod macos;

src/shims/windows/dlsym.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
4545
Dlsym::NtWriteFile => {
4646
if !this.frame_in_std() {
4747
throw_unsup_format!(
48-
"NtWriteFile support is crude and just enough for stdout to work"
48+
"`NtWriteFile` support is crude and just enough for stdout to work"
4949
);
5050
}
5151

@@ -68,7 +68,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
6868

6969
if byte_offset != 0 {
7070
throw_unsup_format!(
71-
"NtWriteFile ByteOffset paremeter is non-null, which is unsupported"
71+
"`NtWriteFile` `ByteOffset` paremeter is non-null, which is unsupported"
7272
);
7373
}
7474

0 commit comments

Comments
 (0)