Skip to content

Commit a5820cd

Browse files
author
Lander Brandt
committed
add basic support for android targets
1 parent 5aeff5d commit a5820cd

File tree

11 files changed

+125
-27
lines changed

11 files changed

+125
-27
lines changed

src/helpers.rs

+14
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,20 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
437437
)
438438
}
439439

440+
/// Helper function used inside the shims of foreign functions to assert that the target OS
441+
/// is `target_os`. It panics showing a message with the `name` of the foreign function
442+
/// if this is not the case.
443+
fn assert_target_os_is_unix(&self, name: &str) {
444+
assert!(
445+
matches!(
446+
self.eval_context_ref().tcx.sess.target.os.as_str(),
447+
"linux" | "macos" | "android"
448+
),
449+
"`{}` is only available for the UNIX target family",
450+
name,
451+
);
452+
}
453+
440454
/// Get last error variable as a place, lazily allocating thread-local storage for it if
441455
/// necessary.
442456
fn last_error_place(&mut self) -> InterpResult<'tcx, MPlaceTy<'tcx, Tag>> {

src/machine.rs

+17
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,23 @@ impl MemoryExtra {
253253
this.write_scalar(Scalar::from_u8(0), &place.into())?;
254254
Self::add_extern_static(this, "_tls_used", place.ptr);
255255
}
256+
"android" =>
257+
for symbol_name in &["signal", "bsd_signal"] {
258+
let layout = this.machine.layouts.usize;
259+
let dlsym = Dlsym::from_str(symbol_name.as_bytes(), &this.tcx.sess.target.os)?
260+
.unwrap_or_else(|| {
261+
panic!(
262+
"hardcoded `extern static` symbol {} has no dlsym handler",
263+
symbol_name
264+
)
265+
});
266+
let (provenance, offset) =
267+
this.memory.create_fn_alloc(FnVal::Other(dlsym)).into_parts();
268+
let ptr = Pointer::new(Some(provenance), offset);
269+
let place = this.allocate(layout, MiriMemoryKind::ExternStatic.into())?;
270+
this.write_pointer(ptr, &place.into())?;
271+
Self::add_extern_static(this, symbol_name, place.ptr);
272+
},
256273
_ => {} // No "extern statics" supported on this target
257274
}
258275
Ok(())

src/shims/dlsym.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ impl Dlsym {
1818
pub fn from_str(name: &[u8], target_os: &str) -> InterpResult<'static, Option<Dlsym>> {
1919
let name = &*String::from_utf8_lossy(name);
2020
Ok(match target_os {
21-
"linux" | "macos" => posix::Dlsym::from_str(name, target_os)?.map(Dlsym::Posix),
21+
"linux" | "macos" | "android" =>
22+
posix::Dlsym::from_str(name, target_os)?.map(Dlsym::Posix),
2223
"windows" => windows::Dlsym::from_str(name)?.map(Dlsym::Windows),
2324
os => bug!("dlsym not implemented for target_os {}", os),
2425
})

src/shims/env.rs

+5-25
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,7 @@ impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mi
114114
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
115115
fn getenv(&mut self, name_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, Pointer<Option<Tag>>> {
116116
let this = self.eval_context_mut();
117-
let target_os = &this.tcx.sess.target.os;
118-
assert!(
119-
target_os == "linux" || target_os == "macos",
120-
"`getenv` is only available for the UNIX target family"
121-
);
117+
this.assert_target_os_is_unix("getenv");
122118

123119
let name_ptr = this.read_pointer(name_op)?;
124120
let name = this.read_os_str_from_c_str(name_ptr)?;
@@ -212,11 +208,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
212208
value_op: &OpTy<'tcx, Tag>,
213209
) -> InterpResult<'tcx, i32> {
214210
let mut this = self.eval_context_mut();
215-
let target_os = &this.tcx.sess.target.os;
216-
assert!(
217-
target_os == "linux" || target_os == "macos",
218-
"`setenv` is only available for the UNIX target family"
219-
);
211+
this.assert_target_os_is_unix("setenv");
220212

221213
let name_ptr = this.read_pointer(name_op)?;
222214
let value_ptr = this.read_pointer(value_op)?;
@@ -286,11 +278,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
286278

287279
fn unsetenv(&mut self, name_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
288280
let this = self.eval_context_mut();
289-
let target_os = &this.tcx.sess.target.os;
290-
assert!(
291-
target_os == "linux" || target_os == "macos",
292-
"`unsetenv` is only available for the UNIX target family"
293-
);
281+
this.assert_target_os_is_unix("unsetenv");
294282

295283
let name_ptr = this.read_pointer(name_op)?;
296284
let mut success = None;
@@ -320,11 +308,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
320308
size_op: &OpTy<'tcx, Tag>,
321309
) -> InterpResult<'tcx, Pointer<Option<Tag>>> {
322310
let this = self.eval_context_mut();
323-
let target_os = &this.tcx.sess.target.os;
324-
assert!(
325-
target_os == "linux" || target_os == "macos",
326-
"`getcwd` is only available for the UNIX target family"
327-
);
311+
this.assert_target_os_is_unix("getcwd");
328312

329313
let buf = this.read_pointer(&buf_op)?;
330314
let size = this.read_scalar(&size_op)?.to_machine_usize(&*this.tcx)?;
@@ -379,11 +363,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
379363

380364
fn chdir(&mut self, path_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
381365
let this = self.eval_context_mut();
382-
let target_os = &this.tcx.sess.target.os;
383-
assert!(
384-
target_os == "linux" || target_os == "macos",
385-
"`getcwd` is only available for the UNIX target family"
386-
);
366+
this.assert_target_os_is_unix("chdir");
387367

388368
let path = this.read_path_from_c_str(this.read_pointer(path_op)?)?;
389369

src/shims/foreign_items.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -687,7 +687,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
687687

688688
// Platform-specific shims
689689
_ => match this.tcx.sess.target.os.as_str() {
690-
"linux" | "macos" => return shims::posix::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest, ret),
690+
"linux" | "macos" | "android" => return shims::posix::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest, ret),
691691
"windows" => return shims::windows::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest, ret),
692692
target => throw_unsup_format!("the target `{}` is not supported", target),
693693
}

src/shims/posix/android/dlsym.rs

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
use helpers::check_arg_count;
2+
use log::trace;
3+
use rustc_middle::mir;
4+
5+
use crate::*;
6+
7+
#[derive(Debug, Copy, Clone)]
8+
#[allow(non_camel_case_types)]
9+
pub enum Dlsym {
10+
signal,
11+
}
12+
13+
impl Dlsym {
14+
// Returns an error for unsupported symbols, and None if this symbol
15+
// should become a NULL pointer (pretend it does not exist).
16+
pub fn from_str(name: &str) -> InterpResult<'static, Option<Dlsym>> {
17+
Ok(match &*name {
18+
"__pthread_get_minstack" => None,
19+
"getrandom" => None, // std falls back to syscall(SYS_getrandom, ...) when this is NULL.
20+
"statx" => None, // std falls back to syscall(SYS_statx, ...) when this is NULL.
21+
"signal" | "bsd_signal" => Some(Dlsym::signal), // these have the same signature/implementation
22+
_ => throw_unsup_format!("unsupported Android dlsym: {}", name),
23+
})
24+
}
25+
}
26+
27+
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
28+
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
29+
fn call_dlsym(
30+
&mut self,
31+
dlsym: Dlsym,
32+
args: &[OpTy<'tcx, Tag>],
33+
ret: Option<(&PlaceTy<'tcx, Tag>, mir::BasicBlock)>,
34+
) -> InterpResult<'tcx> {
35+
let this = self.eval_context_mut();
36+
let (dest, ret) = ret.expect("we don't support any diverging dlsym");
37+
assert!(this.tcx.sess.target.os == "android");
38+
39+
match dlsym {
40+
Dlsym::signal => {
41+
let &[ref _sig, ref _func] = check_arg_count(args)?;
42+
this.write_null(dest)?;
43+
}
44+
}
45+
46+
trace!("{:?}", this.dump_place(**dest));
47+
this.go_to_block(ret);
48+
Ok(())
49+
}
50+
}
+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
use rustc_middle::mir;
2+
use rustc_span::Symbol;
3+
use rustc_target::spec::abi::Abi;
4+
5+
use crate::*;
6+
use shims::foreign_items::EmulateByNameResult;
7+
8+
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
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, Tag>],
15+
dest: &PlaceTy<'tcx, Tag>,
16+
ret: mir::BasicBlock,
17+
) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> {
18+
let this = self.eval_context_mut();
19+
20+
match &*link_name.as_str() {
21+
_ => {
22+
// By default we piggyback off the items emulated for Linux. For now this functions
23+
// serves to make adding android-specific syscalls easy
24+
return shims::posix::linux::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest, ret);
25+
}
26+
}
27+
}
28+
}

src/shims/posix/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/posix/dlsym.rs

+4
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ use rustc_middle::mir;
22
use rustc_target::spec::abi::Abi;
33

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

89
#[derive(Debug, Copy, Clone)]
910
pub enum Dlsym {
1011
Linux(linux::Dlsym),
1112
MacOs(macos::Dlsym),
13+
Android(android::Dlsym),
1214
}
1315

1416
impl Dlsym {
@@ -18,6 +20,7 @@ impl Dlsym {
1820
Ok(match target_os {
1921
"linux" => linux::Dlsym::from_str(name)?.map(Dlsym::Linux),
2022
"macos" => macos::Dlsym::from_str(name)?.map(Dlsym::MacOs),
23+
"android" => android::Dlsym::from_str(name)?.map(Dlsym::Android),
2124
_ => unreachable!(),
2225
})
2326
}
@@ -39,6 +42,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
3942
match dlsym {
4043
Dlsym::Linux(dlsym) => linux::EvalContextExt::call_dlsym(this, dlsym, args, ret),
4144
Dlsym::MacOs(dlsym) => macos::EvalContextExt::call_dlsym(this, dlsym, args, ret),
45+
Dlsym::Android(dlsym) => android::EvalContextExt::call_dlsym(this, dlsym, args, ret),
4246
}
4347
}
4448
}

src/shims/posix/foreign_items.rs

+1
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
465465
match this.tcx.sess.target.os.as_str() {
466466
"linux" => return shims::posix::linux::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest, ret),
467467
"macos" => return shims::posix::macos::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest, ret),
468+
"android" => return shims::posix::android::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest, ret),
468469
_ => unreachable!(),
469470
}
470471
}

src/shims/posix/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 linux;
910
mod macos;
1011

0 commit comments

Comments
 (0)