echo
}
+function run_tests_minimal {
+ if [ -n "${MIRI_TEST_TARGET+exists}" ]; then
+ echo "Testing MINIMAL foreign architecture $MIRI_TEST_TARGET: only testing $@"
+ else
+ echo "Testing MINIMAL host architecture: only testing $@"
+ fi
+
+ ./miri test --locked -- "$@"
+}
+
# host
run_tests
MIRI_TEST_TARGET=i686-unknown-linux-gnu run_tests
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
;;
x86_64-apple-darwin)
MIRI_TEST_TARGET=mips64-unknown-linux-gnuabi64 run_tests # big-endian architecture
/// 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")
+ matches!(target_os, "linux" | "macos" | "freebsd")
}
use rustc_target::spec::abi::Abi;
use crate::*;
+use shims::unix::freebsd::dlsym as freebsd;
use shims::unix::linux::dlsym as linux;
use shims::unix::macos::dlsym as macos;
pub enum Dlsym {
Linux(linux::Dlsym),
MacOs(macos::Dlsym),
+ FreeBSD(freebsd::Dlsym),
}
impl Dlsym {
Ok(match target_os {
"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!(),
})
}
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::FreeBSD(dlsym) =>
+ freebsd::EvalContextExt::call_dlsym(this, dlsym, args, dest, ret),
}
}
}
this.write_null(dest)?;
}
+ // Querying system information
+ "pthread_attr_getstack" => {
+ // We don't support "pthread_attr_setstack", so we just pretend all stacks have the same values here. Hence we can mostly ignore the input `attr_place`.
+ let [attr_place, addr_place, size_place] =
+ this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+ let _attr_place = this.deref_operand(attr_place)?;
+ let addr_place = this.deref_operand(addr_place)?;
+ let size_place = this.deref_operand(size_place)?;
+
+ this.write_scalar(
+ Scalar::from_uint(STACK_ADDR, this.pointer_size()),
+ &addr_place.into(),
+ )?;
+ this.write_scalar(
+ Scalar::from_uint(STACK_SIZE, this.pointer_size()),
+ &size_place.into(),
+ )?;
+
+ // Return success (`0`).
+ this.write_null(dest)?;
+ }
+
| "signal"
| "sigaltstack"
if this.frame_in_std() => {
match this.tcx.sess.target.os.as_ref() {
"linux" => return shims::unix::linux::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest, ret),
"macos" => return shims::unix::macos::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest, ret),
+ "freebsd" => return shims::unix::freebsd::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest, ret),
_ => unreachable!(),
}
}
--- /dev/null
+use rustc_middle::mir;
+
+use crate::*;
+
+#[derive(Debug, Copy, Clone)]
+#[allow(non_camel_case_types)]
+pub enum Dlsym {}
+
+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>> {
+ throw_unsup_format!("unsupported FreeBSD 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, Tag>],
+ _dest: &PlaceTy<'tcx, Tag>,
+ 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 == "freebsd");
+
+ match dlsym {}
+ }
+}
--- /dev/null
+use rustc_middle::mir;
+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, Tag>],
+ dest: &PlaceTy<'tcx, Tag>,
+ _ret: mir::BasicBlock,
+ ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> {
+ let this = self.eval_context_mut();
+ match link_name.as_str() {
+ // Linux's `pthread_getattr_np` equivalent
+ "pthread_attr_get_np" if this.frame_in_std() => {
+ let [_thread, _attr] =
+ this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+ this.write_null(dest)?;
+ }
+ _ => return Ok(EmulateByNameResult::NotSupported),
+ }
+ Ok(EmulateByNameResult::NeedsJumping)
+ }
+}
--- /dev/null
+pub mod dlsym;
+pub mod foreign_items;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
- // Querying system information
- "pthread_attr_getstack" => {
- // We don't support "pthread_attr_setstack", so we just pretend all stacks have the same values here.
- let [attr_place, addr_place, size_place] =
- this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
- this.deref_operand(attr_place)?;
- let addr_place = this.deref_operand(addr_place)?;
- let size_place = this.deref_operand(size_place)?;
-
- this.write_scalar(
- Scalar::from_uint(STACK_ADDR, this.pointer_size()),
- &addr_place.into(),
- )?;
- this.write_scalar(
- Scalar::from_uint(STACK_SIZE, this.pointer_size()),
- &size_place.into(),
- )?;
-
- // Return success (`0`).
- this.write_null(dest)?;
- }
-
// Threading
"prctl" => {
// prctl is variadic. (It is not documented like that in the manpage, but defined like that in the libc crate.)
mod sync;
mod thread;
+mod freebsd;
mod linux;
mod macos;
extern crate libc;
-#[cfg(target_os = "linux")]
+#[cfg(any(target_os = "linux", target_os = "freebsd"))]
fn tmp() -> std::path::PathBuf {
std::env::var("MIRI_TEMP")
.map(std::path::PathBuf::from)
.unwrap_or_else(|_| std::env::temp_dir())
}
-#[cfg(target_os = "linux")]
+#[cfg(any(target_os = "linux", target_os = "freebsd"))]
fn test_posix_fadvise() {
use std::convert::TryInto;
use std::fs::{remove_file, File};
assert_eq!(result, 0);
}
-#[cfg(target_os = "linux")]
+#[cfg(any(target_os = "linux", target_os = "freebsd"))]
fn test_sync_file_range() {
use std::fs::{remove_file, File};
use std::io::Write;
/// Test whether the `prctl` shim correctly sets the thread name.
///
/// Note: `prctl` exists only on Linux.
-#[cfg(target_os = "linux")]
+#[cfg(any(target_os = "linux", target_os = "freebsd"))]
fn test_prctl_thread_name() {
use libc::c_long;
use std::ffi::CString;
}
/// Tests whether clock support exists at all
-#[cfg(target_os = "linux")]
+#[cfg(any(target_os = "linux", target_os = "freebsd"))]
fn test_clocks() {
let mut tp = std::mem::MaybeUninit::<libc::timespec>::uninit();
let is_error = unsafe { libc::clock_gettime(libc::CLOCK_REALTIME, tp.as_mut_ptr()) };
}
fn main() {
- #[cfg(target_os = "linux")]
+ #[cfg(any(target_os = "linux", target_os = "freebsd"))]
test_posix_fadvise();
- #[cfg(target_os = "linux")]
+ #[cfg(any(target_os = "linux", target_os = "freebsd"))]
test_sync_file_range();
test_mutex_libc_init_recursive();
test_mutex_libc_init_errorcheck();
test_rwlock_libc_static_initializer();
- #[cfg(target_os = "linux")]
+ #[cfg(any(target_os = "linux", target_os = "freebsd"))]
test_mutex_libc_static_initializer_recursive();
- #[cfg(target_os = "linux")]
+ #[cfg(any(target_os = "linux", target_os = "freebsd"))]
test_prctl_thread_name();
test_thread_local_errno();
- #[cfg(target_os = "linux")]
+ #[cfg(any(target_os = "linux", target_os = "freebsd"))]
test_clocks();
}