From 5f1ef760ebd08229d6c6a8c44a81d282b5c2af26 Mon Sep 17 00:00:00 2001 From: infrandomness Date: Thu, 9 Jun 2022 16:06:07 +0200 Subject: [PATCH] Initial freebsd work --- ci.sh | 1 + diff | 104 ++++++++++++++++++++++++ src/shims/foreign_items.rs | 2 +- src/shims/unix/dlsym.rs | 4 + src/shims/unix/foreign_items.rs | 1 + src/shims/unix/freebsd/dlsym.rs | 52 ++++++++++++ src/shims/unix/freebsd/foreign_items.rs | 23 ++++++ src/shims/unix/freebsd/mod.rs | 2 + src/shims/unix/macos/dlsym.rs | 15 +--- src/shims/unix/mod.rs | 1 + tests/pass/libc.rs | 27 +++--- 11 files changed, 209 insertions(+), 23 deletions(-) create mode 100644 diff create mode 100644 src/shims/unix/freebsd/dlsym.rs create mode 100644 src/shims/unix/freebsd/foreign_items.rs create mode 100644 src/shims/unix/freebsd/mod.rs diff --git a/ci.sh b/ci.sh index 01b86ff2f9..f436e0179a 100755 --- a/ci.sh +++ b/ci.sh @@ -50,6 +50,7 @@ case $HOST_TARGET in 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 ;; x86_64-apple-darwin) MIRI_TEST_TARGET=mips64-unknown-linux-gnuabi64 run_tests # big-endian architecture diff --git a/diff b/diff new file mode 100644 index 0000000000..db5fce9cb6 --- /dev/null +++ b/diff @@ -0,0 +1,104 @@ +diff --git a/src/shims/unix/freebsd/mod.rs b/src/shims/unix/freebsd/mod.rs +new file mode 100644 +index 00000000..329f2217 +--- /dev/null ++++ b/src/shims/unix/freebsd/mod.rs +@@ -0,0 +1 @@ ++// placeholder +\ No newline at end of file +diff --git a/src/shims/unix/mod.rs b/src/shims/unix/mod.rs +index f40dfaef..4002b056 100644 +--- a/src/shims/unix/mod.rs ++++ b/src/shims/unix/mod.rs +@@ -7,5 +7,6 @@ mod thread; + + mod linux; + mod macos; ++mod freebsd; + + pub use fs::{DirHandler, FileHandler}; +diff --git a/tests/pass/libc.rs b/tests/pass/libc.rs +index bf5ae982..20a06ffb 100644 +--- a/tests/pass/libc.rs ++++ b/tests/pass/libc.rs +@@ -5,12 +5,12 @@ + + extern crate libc; + +-#[cfg(target_os = "linux")] ++#[cfg(target_os = "linux, 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(target_os = "linux, freebsd")] + fn test_posix_fadvise() { + use std::convert::TryInto; + use std::fs::{remove_file, File}; +@@ -40,7 +40,7 @@ fn test_posix_fadvise() { + assert_eq!(result, 0); + } + +-#[cfg(target_os = "linux")] ++#[cfg(target_os = "linux, freebsd")] + fn test_sync_file_range() { + use std::fs::{remove_file, File}; + use std::io::Write; +@@ -191,7 +191,7 @@ fn test_rwlock_libc_static_initializer() { + /// Test whether the `prctl` shim correctly sets the thread name. + /// + /// Note: `prctl` exists only on Linux. +-#[cfg(target_os = "linux")] ++#[cfg(target_os = "linux,freebsd")] + fn test_prctl_thread_name() { + use std::ffi::CString; + use libc::c_long; +@@ -231,7 +231,7 @@ fn test_thread_local_errno() { + } + + /// Tests whether clock support exists at all +-#[cfg(target_os = "linux")] ++#[cfg(target_os = "linux,freebsd")] + fn test_clocks() { + let mut tp = std::mem::MaybeUninit::::uninit(); + let is_error = unsafe { +@@ -252,11 +252,18 @@ fn test_clocks() { + assert_eq!(is_error, 0); + } + ++#[cfg(target_os = "linux,freebsd,macos")] ++fn test_getpid() { ++ unsafe { ++ assert_eq!(libc::getpid(), std::process::id()); ++ } ++} ++ + fn main() { +- #[cfg(target_os = "linux")] ++ #[cfg(target_os = "linux,freebsd")] + test_posix_fadvise(); + +- #[cfg(target_os = "linux")] ++ #[cfg(target_os = "linux,freebsd")] + test_sync_file_range(); + + test_mutex_libc_init_recursive(); +@@ -264,14 +271,14 @@ fn main() { + test_mutex_libc_init_errorcheck(); + test_rwlock_libc_static_initializer(); + +- #[cfg(target_os = "linux")] ++ #[cfg(target_os = "linux,freebsd")] + test_mutex_libc_static_initializer_recursive(); + +- #[cfg(target_os = "linux")] ++ #[cfg(target_os = "linux,freebsd")] + test_prctl_thread_name(); + + test_thread_local_errno(); + +- #[cfg(target_os = "linux")] ++ #[cfg(target_os = "linux,freebsd")] + test_clocks(); + } diff --git a/src/shims/foreign_items.rs b/src/shims/foreign_items.rs index a81dcdc110..81f655054a 100644 --- a/src/shims/foreign_items.rs +++ b/src/shims/foreign_items.rs @@ -702,7 +702,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // Platform-specific shims _ => match this.tcx.sess.target.os.as_ref() { - "linux" | "macos" => return shims::unix::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest, ret), + "linux" | "macos" | "freebsd" => return shims::unix::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest, ret), "windows" => return shims::windows::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest, ret), target => throw_unsup_format!("the target `{}` is not supported", target), } diff --git a/src/shims/unix/dlsym.rs b/src/shims/unix/dlsym.rs index 578ae488a9..f183971b59 100644 --- a/src/shims/unix/dlsym.rs +++ b/src/shims/unix/dlsym.rs @@ -4,11 +4,13 @@ use rustc_target::spec::abi::Abi; use crate::*; use shims::unix::linux::dlsym as linux; use shims::unix::macos::dlsym as macos; +use shims::unix::freebsd::dlsym as freebsd; #[derive(Debug, Copy, Clone)] pub enum Dlsym { Linux(linux::Dlsym), MacOs(macos::Dlsym), + FreeBSD(freebsd::Dlsym) } impl Dlsym { @@ -18,6 +20,7 @@ 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!(), }) } @@ -40,6 +43,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx 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) } } } diff --git a/src/shims/unix/foreign_items.rs b/src/shims/unix/foreign_items.rs index 5f59426bc5..1764575c8b 100644 --- a/src/shims/unix/foreign_items.rs +++ b/src/shims/unix/foreign_items.rs @@ -479,6 +479,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx 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!(), } } diff --git a/src/shims/unix/freebsd/dlsym.rs b/src/shims/unix/freebsd/dlsym.rs new file mode 100644 index 0000000000..2e97b7918e --- /dev/null +++ b/src/shims/unix/freebsd/dlsym.rs @@ -0,0 +1,52 @@ +use rustc_middle::mir; + +use log::trace; + +use crate::*; +use helpers::check_arg_count; + +#[derive(Debug, Copy, Clone)] +#[allow(non_camel_case_types)] +pub enum Dlsym { + getentropy, +} + +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> { + Ok(match name { + "getentropy" => Some(Dlsym::getentropy), + _ => throw_unsup_format!("unsupported macOS 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, + ) -> 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 == "macos"); + + match dlsym { + Dlsym::getentropy => { + let [ptr, len] = check_arg_count(args)?; + let ptr = this.read_pointer(ptr)?; + let len = this.read_scalar(len)?.to_machine_usize(this)?; + this.gen_random(ptr, len)?; + this.write_null(dest)?; + } + } + + trace!("{:?}", this.dump_place(**dest)); + this.go_to_block(ret); + Ok(()) + } +} diff --git a/src/shims/unix/freebsd/foreign_items.rs b/src/shims/unix/freebsd/foreign_items.rs new file mode 100644 index 0000000000..ac261cecc2 --- /dev/null +++ b/src/shims/unix/freebsd/foreign_items.rs @@ -0,0 +1,23 @@ +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 + Ok(EmulateByNameResult::NeedsJumping) + } +} \ No newline at end of file diff --git a/src/shims/unix/freebsd/mod.rs b/src/shims/unix/freebsd/mod.rs new file mode 100644 index 0000000000..428d997d78 --- /dev/null +++ b/src/shims/unix/freebsd/mod.rs @@ -0,0 +1,2 @@ +pub mod foreign_items; +pub mod dlsym; \ No newline at end of file diff --git a/src/shims/unix/macos/dlsym.rs b/src/shims/unix/macos/dlsym.rs index 2e97b7918e..2b478a4df2 100644 --- a/src/shims/unix/macos/dlsym.rs +++ b/src/shims/unix/macos/dlsym.rs @@ -3,12 +3,10 @@ use rustc_middle::mir; use log::trace; use crate::*; -use helpers::check_arg_count; #[derive(Debug, Copy, Clone)] #[allow(non_camel_case_types)] pub enum Dlsym { - getentropy, } impl Dlsym { @@ -16,8 +14,7 @@ impl Dlsym { // should become a NULL pointer (pretend it does not exist). pub fn from_str<'tcx>(name: &str) -> InterpResult<'tcx, Option> { Ok(match name { - "getentropy" => Some(Dlsym::getentropy), - _ => throw_unsup_format!("unsupported macOS dlsym: {}", name), + _ => throw_unsup_format!("unsupported freebsd dlsym: {}", name), }) } } @@ -33,16 +30,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx ) -> 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 == "macos"); + assert!(this.tcx.sess.target.os == "freebsd"); match dlsym { - Dlsym::getentropy => { - let [ptr, len] = check_arg_count(args)?; - let ptr = this.read_pointer(ptr)?; - let len = this.read_scalar(len)?.to_machine_usize(this)?; - this.gen_random(ptr, len)?; - this.write_null(dest)?; - } + _ => {} } trace!("{:?}", this.dump_place(**dest)); diff --git a/src/shims/unix/mod.rs b/src/shims/unix/mod.rs index f40dfaefb9..4002b056b4 100644 --- a/src/shims/unix/mod.rs +++ b/src/shims/unix/mod.rs @@ -7,5 +7,6 @@ mod thread; mod linux; mod macos; +mod freebsd; pub use fs::{DirHandler, FileHandler}; diff --git a/tests/pass/libc.rs b/tests/pass/libc.rs index bf5ae98290..20a06ffb2f 100644 --- a/tests/pass/libc.rs +++ b/tests/pass/libc.rs @@ -5,12 +5,12 @@ extern crate libc; -#[cfg(target_os = "linux")] +#[cfg(target_os = "linux, 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(target_os = "linux, freebsd")] fn test_posix_fadvise() { use std::convert::TryInto; use std::fs::{remove_file, File}; @@ -40,7 +40,7 @@ fn test_posix_fadvise() { assert_eq!(result, 0); } -#[cfg(target_os = "linux")] +#[cfg(target_os = "linux, freebsd")] fn test_sync_file_range() { use std::fs::{remove_file, File}; use std::io::Write; @@ -191,7 +191,7 @@ fn test_rwlock_libc_static_initializer() { /// Test whether the `prctl` shim correctly sets the thread name. /// /// Note: `prctl` exists only on Linux. -#[cfg(target_os = "linux")] +#[cfg(target_os = "linux,freebsd")] fn test_prctl_thread_name() { use std::ffi::CString; use libc::c_long; @@ -231,7 +231,7 @@ fn test_thread_local_errno() { } /// Tests whether clock support exists at all -#[cfg(target_os = "linux")] +#[cfg(target_os = "linux,freebsd")] fn test_clocks() { let mut tp = std::mem::MaybeUninit::::uninit(); let is_error = unsafe { @@ -252,11 +252,18 @@ fn test_clocks() { assert_eq!(is_error, 0); } +#[cfg(target_os = "linux,freebsd,macos")] +fn test_getpid() { + unsafe { + assert_eq!(libc::getpid(), std::process::id()); + } +} + fn main() { - #[cfg(target_os = "linux")] + #[cfg(target_os = "linux,freebsd")] test_posix_fadvise(); - #[cfg(target_os = "linux")] + #[cfg(target_os = "linux,freebsd")] test_sync_file_range(); test_mutex_libc_init_recursive(); @@ -264,14 +271,14 @@ fn main() { test_mutex_libc_init_errorcheck(); test_rwlock_libc_static_initializer(); - #[cfg(target_os = "linux")] + #[cfg(target_os = "linux,freebsd")] test_mutex_libc_static_initializer_recursive(); - #[cfg(target_os = "linux")] + #[cfg(target_os = "linux,freebsd")] test_prctl_thread_name(); test_thread_local_errno(); - #[cfg(target_os = "linux")] + #[cfg(target_os = "linux,freebsd")] test_clocks(); }