Skip to content

illumos support #3198

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 5, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -227,6 +227,7 @@ degree documented below):
- We have unofficial support (not maintained by the Miri team itself) for some further operating systems.
- `freebsd`: **maintainer wanted**. Supports `std::env` and parts of `std::{thread, fs}`, but not `std::sync`.
- `android`: **maintainer wanted**. Support very incomplete, but a basic "hello world" works.
- `illumos`: maintained by @devnexen. Support very incomplete, but a basic "hello world" works.
- `wasm`: **maintainer wanted**. Support very incomplete, not even standard output works, but an empty `main` function works.
- For targets on other operating systems, Miri might fail before even reaching the `main` function.

3 changes: 3 additions & 0 deletions ci/ci.sh
Original file line number Diff line number Diff line change
@@ -146,6 +146,9 @@ case $HOST_TARGET in
MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal $BASIC panic/panic concurrency/simple atomic threadname libc-getentropy libc-getrandom libc-misc fs env num_cpus
MIRI_TEST_TARGET=i686-unknown-freebsd run_tests_minimal $BASIC panic/panic concurrency/simple atomic threadname libc-getentropy libc-getrandom libc-misc fs env num_cpus
MIRI_TEST_TARGET=aarch64-linux-android run_tests_minimal $VERY_BASIC hello panic/panic
MIRI_TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $VERY_BASIC hello panic/panic pthread-sync
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also run tests with x86_64-pc-solaris? You've added two OSes everywhere but we're only testing one of them.

# TODO fix solaris stack guard
# MIRI_TEST_TARGET=x86_64-pc-solaris run_tests_minimal $VERY_BASIC hello panic/panic pthread-sync
MIRI_TEST_TARGET=wasm32-wasi run_tests_minimal $VERY_BASIC wasm
MIRI_TEST_TARGET=wasm32-unknown-unknown run_tests_minimal $VERY_BASIC wasm
MIRI_TEST_TARGET=thumbv7em-none-eabihf run_tests_minimal no_std
7 changes: 7 additions & 0 deletions src/concurrency/thread.rs
Original file line number Diff line number Diff line change
@@ -78,6 +78,13 @@ impl TryFrom<u64> for ThreadId {
}
}

impl TryFrom<i128> for ThreadId {
type Error = TryFromIntError;
fn try_from(id: i128) -> Result<Self, Self::Error> {
u32::try_from(id).map(Self)
}
}

impl From<u32> for ThreadId {
fn from(id: u32) -> Self {
Self(id)
8 changes: 6 additions & 2 deletions src/shims/unix/foreign_items.rs
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@ use crate::*;
use shims::unix::freebsd::foreign_items as freebsd;
use shims::unix::linux::foreign_items as linux;
use shims::unix::macos::foreign_items as macos;
use shims::unix::solarish::foreign_items as solarish;

pub fn is_dyn_sym(name: &str, target_os: &str) -> bool {
match name {
@@ -29,6 +30,7 @@ pub fn is_dyn_sym(name: &str, target_os: &str) -> bool {
"freebsd" => freebsd::is_dyn_sym(name),
"linux" => linux::is_dyn_sym(name),
"macos" => macos::is_dyn_sym(name),
"solaris" | "illumos" => solarish::is_dyn_sym(name),
_ => false,
},
}
@@ -591,8 +593,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
}
"getentropy" => {
// This function is non-standard but exists with the same signature and behavior on
// Linux, macOS, and FreeBSD.
if !matches!(&*this.tcx.sess.target.os, "linux" | "macos" | "freebsd") {
// Linux, macOS, FreeBSD and Solaris/Illumos.
if !matches!(&*this.tcx.sess.target.os, "linux" | "macos" | "freebsd" | "illumos" | "solaris") {
throw_unsup_format!(
"`getentropy` is not supported on {}",
this.tcx.sess.target.os
@@ -608,6 +610,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
// FreeBSD: https://man.freebsd.org/cgi/man.cgi?query=getentropy&sektion=3&format=html
// Linux: https://man7.org/linux/man-pages/man3/getentropy.3.html
// macOS: https://keith.github.io/xcode-man-pages/getentropy.2.html
// Solaris/Illumos: https://illumos.org/man/3C/getentropy
if bufsize > 256 {
let err = this.eval_libc("EIO");
this.set_last_error(err)?;
@@ -730,6 +733,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
"freebsd" => freebsd::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest),
"linux" => linux::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest),
"macos" => macos::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest),
"solaris" | "illumos" => solarish::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest),
_ => Ok(EmulateItemResult::NotSupported),
};
}
1 change: 1 addition & 0 deletions src/shims/unix/mod.rs
Original file line number Diff line number Diff line change
@@ -11,6 +11,7 @@ mod thread;
mod freebsd;
mod linux;
mod macos;
mod solarish;

pub use env::UnixEnvVars;
pub use fd::{FdTable, FileDescription};
41 changes: 41 additions & 0 deletions src/shims/unix/solarish/foreign_items.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use rustc_span::Symbol;
use rustc_target::spec::abi::Abi;

use crate::shims::unix::*;
use crate::*;
use shims::EmulateItemResult;

pub fn is_dyn_sym(_name: &str) -> bool {
false
}

impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
fn emulate_foreign_item_inner(
&mut self,
link_name: Symbol,
abi: Abi,
args: &[OpTy<'tcx, Provenance>],
dest: &MPlaceTy<'tcx, Provenance>,
) -> InterpResult<'tcx, EmulateItemResult> {
let this = self.eval_context_mut();
match link_name.as_str() {
// Threading
"pthread_condattr_setclock" => {
let [attr, clock_id] =
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let result = this.pthread_condattr_setclock(attr, clock_id)?;
this.write_scalar(result, dest)?;
}
"pthread_condattr_getclock" => {
let [attr, clock_id] =
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let result = this.pthread_condattr_getclock(attr, clock_id)?;
this.write_scalar(result, dest)?;
}

_ => return Ok(EmulateItemResult::NotSupported),
}
Ok(EmulateItemResult::NeedsJumping)
}
}
1 change: 1 addition & 0 deletions src/shims/unix/solarish/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod foreign_items;
62 changes: 41 additions & 21 deletions src/shims/unix/sync.rs
Original file line number Diff line number Diff line change
@@ -68,11 +68,20 @@ fn mutexattr_set_kind<'mir, 'tcx: 'mir>(
// (the kind has to be at this particular offset for compatibility with Linux's static initializer
// macros, e.g. PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP.)

#[inline]
fn mutex_id_offset<'mir, 'tcx: 'mir>(ecx: &MiriInterpCx<'mir, 'tcx>) -> u64 {
if matches!(&*ecx.tcx.sess.target.os, "macos") { 4 } else { 0 }
}

fn mutex_get_id<'mir, 'tcx: 'mir>(
ecx: &mut MiriInterpCx<'mir, 'tcx>,
mutex_op: &OpTy<'tcx, Provenance>,
) -> InterpResult<'tcx, MutexId> {
ecx.mutex_get_or_create_id(mutex_op, ecx.libc_ty_layout("pthread_mutex_t"), 4)
ecx.mutex_get_or_create_id(
mutex_op,
ecx.libc_ty_layout("pthread_mutex_t"),
mutex_id_offset(ecx),
)
}

fn mutex_reset_id<'mir, 'tcx: 'mir>(
@@ -81,7 +90,7 @@ fn mutex_reset_id<'mir, 'tcx: 'mir>(
) -> InterpResult<'tcx, ()> {
ecx.deref_pointer_and_write(
mutex_op,
4,
mutex_id_offset(ecx),
Scalar::from_i32(0),
ecx.libc_ty_layout("pthread_mutex_t"),
ecx.machine.layouts.u32,
@@ -124,13 +133,20 @@ fn mutex_set_kind<'mir, 'tcx: 'mir>(
// (need to avoid this because it is set by static initializer macros)
// bytes 4-7: rwlock id as u32 or 0 if id is not assigned yet.

const RWLOCK_ID_OFFSET: u64 = 4;
#[inline]
fn rwlock_id_offset<'mir, 'tcx: 'mir>(ecx: &MiriInterpCx<'mir, 'tcx>) -> u64 {
if matches!(&*ecx.tcx.sess.target.os, "macos") { 4 } else { 0 }
}

fn rwlock_get_id<'mir, 'tcx: 'mir>(
ecx: &mut MiriInterpCx<'mir, 'tcx>,
rwlock_op: &OpTy<'tcx, Provenance>,
) -> InterpResult<'tcx, RwLockId> {
ecx.rwlock_get_or_create_id(rwlock_op, ecx.libc_ty_layout("pthread_rwlock_t"), RWLOCK_ID_OFFSET)
ecx.rwlock_get_or_create_id(
rwlock_op,
ecx.libc_ty_layout("pthread_rwlock_t"),
rwlock_id_offset(ecx),
)
}

// pthread_condattr_t
@@ -177,14 +193,18 @@ fn condattr_set_clock_id<'mir, 'tcx: 'mir>(
// bytes 4-7: the conditional variable id as u32 or 0 if id is not assigned yet.
// bytes 8-11: the clock id constant as i32

const CONDVAR_ID_OFFSET: u64 = 4;
const CONDVAR_CLOCK_OFFSET: u64 = 8;

#[inline]
fn cond_id_offset<'mir, 'tcx: 'mir>(ecx: &MiriInterpCx<'mir, 'tcx>) -> u64 {
if matches!(&*ecx.tcx.sess.target.os, "macos") { 4 } else { 0 }
}

fn cond_get_id<'mir, 'tcx: 'mir>(
ecx: &mut MiriInterpCx<'mir, 'tcx>,
cond_op: &OpTy<'tcx, Provenance>,
) -> InterpResult<'tcx, CondvarId> {
ecx.condvar_get_or_create_id(cond_op, ecx.libc_ty_layout("pthread_cond_t"), CONDVAR_ID_OFFSET)
ecx.condvar_get_or_create_id(cond_op, ecx.libc_ty_layout("pthread_cond_t"), cond_id_offset(ecx))
}

fn cond_reset_id<'mir, 'tcx: 'mir>(
@@ -193,7 +213,7 @@ fn cond_reset_id<'mir, 'tcx: 'mir>(
) -> InterpResult<'tcx, ()> {
ecx.deref_pointer_and_write(
cond_op,
CONDVAR_ID_OFFSET,
cond_id_offset(ecx),
Scalar::from_i32(0),
ecx.libc_ty_layout("pthread_cond_t"),
ecx.machine.layouts.u32,
@@ -287,7 +307,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();

if !matches!(&*this.tcx.sess.target.os, "linux" | "macos") {
if !matches!(&*this.tcx.sess.target.os, "linux" | "macos" | "solaris" | "illumos") {
throw_unsup_format!(
"`pthread_mutexattr_init` is not supported on {}",
this.tcx.sess.target.os
@@ -376,7 +396,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();

if !matches!(&*this.tcx.sess.target.os, "linux" | "macos") {
if !matches!(&*this.tcx.sess.target.os, "linux" | "macos" | "solaris" | "illumos") {
throw_unsup_format!(
"`pthread_mutex_init` is not supported on {}",
this.tcx.sess.target.os
@@ -537,7 +557,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();

if !matches!(&*this.tcx.sess.target.os, "linux" | "macos") {
if !matches!(&*this.tcx.sess.target.os, "linux" | "macos" | "solaris" | "illumos") {
throw_unsup_format!(
"`pthread_rwlock_rdlock` is not supported on {}",
this.tcx.sess.target.os
@@ -562,7 +582,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();

if !matches!(&*this.tcx.sess.target.os, "linux" | "macos") {
if !matches!(&*this.tcx.sess.target.os, "linux" | "macos" | "solaris" | "illumos") {
throw_unsup_format!(
"`pthread_rwlock_tryrdlock` is not supported on {}",
this.tcx.sess.target.os
@@ -586,7 +606,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();

if !matches!(&*this.tcx.sess.target.os, "linux" | "macos") {
if !matches!(&*this.tcx.sess.target.os, "linux" | "macos" | "solaris" | "illumos") {
throw_unsup_format!(
"`pthread_rwlock_wrlock` is not supported on {}",
this.tcx.sess.target.os
@@ -623,7 +643,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();

if !matches!(&*this.tcx.sess.target.os, "linux" | "macos") {
if !matches!(&*this.tcx.sess.target.os, "linux" | "macos" | "solaris" | "illumos") {
throw_unsup_format!(
"`pthread_rwlock_trywrlock` is not supported on {}",
this.tcx.sess.target.os
@@ -647,7 +667,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();

if !matches!(&*this.tcx.sess.target.os, "linux" | "macos") {
if !matches!(&*this.tcx.sess.target.os, "linux" | "macos" | "solaris" | "illumos") {
throw_unsup_format!(
"`pthread_rwlock_unlock` is not supported on {}",
this.tcx.sess.target.os
@@ -673,7 +693,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();

if !matches!(&*this.tcx.sess.target.os, "linux" | "macos") {
if !matches!(&*this.tcx.sess.target.os, "linux" | "macos" | "solaris" | "illumos") {
throw_unsup_format!(
"`pthread_rwlock_destroy` is not supported on {}",
this.tcx.sess.target.os
@@ -704,7 +724,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();

if !matches!(&*this.tcx.sess.target.os, "linux" | "macos") {
if !matches!(&*this.tcx.sess.target.os, "linux" | "macos" | "solaris" | "illumos") {
throw_unsup_format!(
"`pthread_condattr_init` is not supported on {}",
this.tcx.sess.target.os
@@ -728,9 +748,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let this = self.eval_context_mut();

// Does not exist on macOS!
if !matches!(&*this.tcx.sess.target.os, "linux") {
if !matches!(&*this.tcx.sess.target.os, "linux" | "solaris" | "illumos") {
throw_unsup_format!(
"`pthread_condattr_init` is not supported on {}",
"`pthread_condattr_setclock` is not supported on {}",
this.tcx.sess.target.os
);
}
@@ -756,9 +776,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let this = self.eval_context_mut();

// Does not exist on macOS!
if !matches!(&*this.tcx.sess.target.os, "linux") {
if !matches!(&*this.tcx.sess.target.os, "linux" | "solaris" | "illumos") {
throw_unsup_format!(
"`pthread_condattr_init` is not supported on {}",
"`pthread_condattr_getclock` is not supported on {}",
this.tcx.sess.target.os
);
}
@@ -793,7 +813,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();

if !matches!(&*this.tcx.sess.target.os, "linux" | "macos") {
if !matches!(&*this.tcx.sess.target.os, "linux" | "macos" | "solaris" | "illumos") {
throw_unsup_format!(
"`pthread_cond_init` is not supported on {}",
this.tcx.sess.target.os
2 changes: 1 addition & 1 deletion src/shims/unix/thread.rs
Original file line number Diff line number Diff line change
@@ -42,7 +42,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
throw_unsup_format!("Miri supports pthread_join only with retval==NULL");
}

let thread_id = this.read_target_usize(thread)?;
let thread_id = this.read_scalar(thread)?.to_int(this.libc_ty_layout("pthread_t").size)?;
this.join_thread_exclusive(thread_id.try_into().expect("thread ID should fit in u32"))?;

Ok(0)