Skip to content

Commit 339500f

Browse files
committed
Auto merge of rust-lang#2493 - RalfJung:android, r=RalfJung
add very basic Android support This is just enough to print to stdout. I won't push this any further, but having these basics should hopefully make it easier for others to do so. Also slightly improve threading support on FreeBSD while we are at it. Partially based on rust-lang/miri#2011. Fixes rust-lang/miri#2010.
2 parents af033ea + 5e10f14 commit 339500f

File tree

15 files changed

+160
-23
lines changed

15 files changed

+160
-23
lines changed

ci.sh

+2-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,8 @@ case $HOST_TARGET in
8383
MIRI_TEST_TARGET=i686-unknown-linux-gnu run_tests
8484
MIRI_TEST_TARGET=aarch64-apple-darwin run_tests
8585
MIRI_TEST_TARGET=i686-pc-windows-msvc run_tests
86-
MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec data_race env/var
86+
MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple atomic data_race env/var
87+
MIRI_TEST_TARGET=aarch64-linux-android run_tests_minimal hello integer vec panic/panic
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/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
clippy::derive_hash_xor_eq,
2525
clippy::too_many_arguments,
2626
clippy::type_complexity,
27+
clippy::single_element_loop,
2728
// We are not implementing queries here so it's fine
2829
rustc::potential_query_instability
2930
)]

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

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
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+
"android_set_abort_message" => None,
19+
_ => throw_unsup_format!("unsupported Android dlsym: {}", name),
20+
})
21+
}
22+
}
23+
24+
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
25+
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
26+
fn call_dlsym(
27+
&mut self,
28+
dlsym: Dlsym,
29+
args: &[OpTy<'tcx, Provenance>],
30+
dest: &PlaceTy<'tcx, Provenance>,
31+
ret: Option<mir::BasicBlock>,
32+
) -> InterpResult<'tcx> {
33+
let this = self.eval_context_mut();
34+
let ret = ret.expect("we don't support any diverging dlsym");
35+
assert!(this.tcx.sess.target.os == "android");
36+
37+
match dlsym {
38+
Dlsym::signal => {
39+
if !this.frame_in_std() {
40+
throw_unsup_format!(
41+
"`signal` support is crude and just enough for libstd to work"
42+
);
43+
}
44+
45+
let &[ref _sig, ref _func] = check_arg_count(args)?;
46+
this.write_null(dest)?;
47+
}
48+
}
49+
50+
log::trace!("{:?}", this.dump_place(**dest));
51+
this.go_to_block(ret);
52+
Ok(())
53+
}
54+
}
+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
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+
#[allow(clippy::match_single_binding)]
19+
match link_name.as_str() {
20+
_ => return Ok(EmulateByNameResult::NotSupported),
21+
}
22+
23+
#[allow(unreachable_code)]
24+
Ok(EmulateByNameResult::NeedsJumping)
25+
}
26+
}

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/freebsd/foreign_items.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use rustc_target::spec::abi::Abi;
33

44
use crate::*;
55
use shims::foreign_items::EmulateByNameResult;
6+
use shims::unix::thread::EvalContextExt as _;
67

78
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
89

@@ -16,12 +17,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
1617
) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> {
1718
let this = self.eval_context_mut();
1819
match link_name.as_str() {
19-
// Linux's `pthread_getattr_np` equivalent
20+
// Threading
2021
"pthread_attr_get_np" if this.frame_in_std() => {
2122
let [_thread, _attr] =
2223
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
2324
this.write_null(dest)?;
2425
}
26+
"pthread_set_name_np" => {
27+
let [thread, name] =
28+
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
29+
let res = this.pthread_setname_np(
30+
this.read_scalar(thread)?.check_init()?,
31+
this.read_scalar(name)?.check_init()?,
32+
)?;
33+
this.write_scalar(res, dest)?;
34+
}
2535

2636
// errno
2737
"__error" => {

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)