Auto merge of #3277 - RalfJung:freebsd, r=RalfJung
add __cxa_thread_atexit_impl on freebsd Fixes https://github.com/rust-lang/miri/issues/3276
This commit is contained in:
commit
4e8ad10843
@ -121,9 +121,8 @@ case $HOST_TARGET in
|
|||||||
MIRI_TEST_TARGET=aarch64-apple-darwin run_tests
|
MIRI_TEST_TARGET=aarch64-apple-darwin run_tests
|
||||||
MIRI_TEST_TARGET=i686-pc-windows-gnu run_tests
|
MIRI_TEST_TARGET=i686-pc-windows-gnu run_tests
|
||||||
# Some targets are only partially supported.
|
# Some targets are only partially supported.
|
||||||
# FIXME: freeBSD disabled due to https://github.com/rust-lang/miri/issues/3276
|
MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple pthread-threadname libc-getentropy libc-getrandom libc-misc libc-fs atomic env align
|
||||||
#MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple pthread-threadname libc-getentropy libc-getrandom libc-misc libc-fs atomic env align
|
MIRI_TEST_TARGET=i686-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple pthread-threadname libc-getentropy libc-getrandom libc-misc libc-fs atomic env align
|
||||||
#MIRI_TEST_TARGET=i686-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple pthread-threadname libc-getentropy libc-getrandom libc-misc libc-fs atomic env align
|
|
||||||
MIRI_TEST_TARGET=aarch64-linux-android run_tests_minimal hello integer vec panic/panic
|
MIRI_TEST_TARGET=aarch64-linux-android run_tests_minimal hello integer vec panic/panic
|
||||||
MIRI_TEST_TARGET=wasm32-wasi run_tests_minimal no_std integer strings wasm
|
MIRI_TEST_TARGET=wasm32-wasi run_tests_minimal no_std integer strings wasm
|
||||||
MIRI_TEST_TARGET=wasm32-unknown-unknown run_tests_minimal no_std integer strings wasm
|
MIRI_TEST_TARGET=wasm32-unknown-unknown run_tests_minimal no_std integer strings wasm
|
||||||
|
@ -94,7 +94,6 @@ pub use crate::shims::os_str::EvalContextExt as _;
|
|||||||
pub use crate::shims::panic::{CatchUnwindData, EvalContextExt as _};
|
pub use crate::shims::panic::{CatchUnwindData, EvalContextExt as _};
|
||||||
pub use crate::shims::time::EvalContextExt as _;
|
pub use crate::shims::time::EvalContextExt as _;
|
||||||
pub use crate::shims::tls::TlsData;
|
pub use crate::shims::tls::TlsData;
|
||||||
pub use crate::shims::EvalContextExt as _;
|
|
||||||
|
|
||||||
pub use crate::borrow_tracker::stacked_borrows::{
|
pub use crate::borrow_tracker::stacked_borrows::{
|
||||||
EvalContextExt as _, Item, Permission, Stack, Stacks,
|
EvalContextExt as _, Item, Permission, Stack, Stacks,
|
||||||
|
@ -691,7 +691,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_extern_static(
|
pub(crate) fn add_extern_static(
|
||||||
this: &mut MiriInterpCx<'mir, 'tcx>,
|
this: &mut MiriInterpCx<'mir, 'tcx>,
|
||||||
name: &str,
|
name: &str,
|
||||||
ptr: Pointer<Option<Provenance>>,
|
ptr: Pointer<Option<Provenance>>,
|
||||||
@ -701,75 +701,6 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
|
|||||||
this.machine.extern_statics.try_insert(Symbol::intern(name), ptr).unwrap();
|
this.machine.extern_statics.try_insert(Symbol::intern(name), ptr).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alloc_extern_static(
|
|
||||||
this: &mut MiriInterpCx<'mir, 'tcx>,
|
|
||||||
name: &str,
|
|
||||||
val: ImmTy<'tcx, Provenance>,
|
|
||||||
) -> InterpResult<'tcx> {
|
|
||||||
let place = this.allocate(val.layout, MiriMemoryKind::ExternStatic.into())?;
|
|
||||||
this.write_immediate(*val, &place)?;
|
|
||||||
Self::add_extern_static(this, name, place.ptr());
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets up the "extern statics" for this machine.
|
|
||||||
fn init_extern_statics(this: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> {
|
|
||||||
// "__rust_no_alloc_shim_is_unstable"
|
|
||||||
let val = ImmTy::from_int(0, this.machine.layouts.u8);
|
|
||||||
Self::alloc_extern_static(this, "__rust_no_alloc_shim_is_unstable", val)?;
|
|
||||||
|
|
||||||
match this.tcx.sess.target.os.as_ref() {
|
|
||||||
"linux" => {
|
|
||||||
// "environ"
|
|
||||||
Self::add_extern_static(
|
|
||||||
this,
|
|
||||||
"environ",
|
|
||||||
this.machine.env_vars.environ.as_ref().unwrap().ptr(),
|
|
||||||
);
|
|
||||||
// A couple zero-initialized pointer-sized extern statics.
|
|
||||||
// Most of them are for weak symbols, which we all set to null (indicating that the
|
|
||||||
// symbol is not supported, and triggering fallback code which ends up calling a
|
|
||||||
// syscall that we do support).
|
|
||||||
for name in &["__cxa_thread_atexit_impl", "getrandom", "statx", "__clock_gettime64"]
|
|
||||||
{
|
|
||||||
let val = ImmTy::from_int(0, this.machine.layouts.usize);
|
|
||||||
Self::alloc_extern_static(this, name, val)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"freebsd" => {
|
|
||||||
// "environ"
|
|
||||||
Self::add_extern_static(
|
|
||||||
this,
|
|
||||||
"environ",
|
|
||||||
this.machine.env_vars.environ.as_ref().unwrap().ptr(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
"android" => {
|
|
||||||
// "signal" -- just needs a non-zero pointer value (function does not even get called),
|
|
||||||
// but we arrange for this to be callable anyway (it will then do nothing).
|
|
||||||
let layout = this.machine.layouts.const_raw_ptr;
|
|
||||||
let ptr = this.fn_ptr(FnVal::Other(DynSym::from_str("signal")));
|
|
||||||
let val = ImmTy::from_scalar(Scalar::from_pointer(ptr, this), layout);
|
|
||||||
Self::alloc_extern_static(this, "signal", val)?;
|
|
||||||
// A couple zero-initialized pointer-sized extern statics.
|
|
||||||
// Most of them are for weak symbols, which we all set to null (indicating that the
|
|
||||||
// symbol is not supported, and triggering fallback code.)
|
|
||||||
for name in &["bsd_signal"] {
|
|
||||||
let val = ImmTy::from_int(0, this.machine.layouts.usize);
|
|
||||||
Self::alloc_extern_static(this, name, val)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"windows" => {
|
|
||||||
// "_tls_used"
|
|
||||||
// This is some obscure hack that is part of the Windows TLS story. It's a `u8`.
|
|
||||||
let val = ImmTy::from_int(0, this.machine.layouts.u8);
|
|
||||||
Self::alloc_extern_static(this, "_tls_used", val)?;
|
|
||||||
}
|
|
||||||
_ => {} // No "extern statics" supported on this target
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn communicate(&self) -> bool {
|
pub(crate) fn communicate(&self) -> bool {
|
||||||
self.isolated_op == IsolatedOp::Allow
|
self.isolated_op == IsolatedOp::Allow
|
||||||
}
|
}
|
||||||
@ -989,7 +920,21 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
|
|||||||
ret: Option<mir::BasicBlock>,
|
ret: Option<mir::BasicBlock>,
|
||||||
unwind: mir::UnwindAction,
|
unwind: mir::UnwindAction,
|
||||||
) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
|
) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
|
||||||
ecx.find_mir_or_eval_fn(instance, abi, args, dest, ret, unwind)
|
// For foreign items, try to see if we can emulate them.
|
||||||
|
if ecx.tcx.is_foreign_item(instance.def_id()) {
|
||||||
|
// An external function call that does not have a MIR body. We either find MIR elsewhere
|
||||||
|
// or emulate its effect.
|
||||||
|
// This will be Ok(None) if we're emulating the intrinsic entirely within Miri (no need
|
||||||
|
// to run extra MIR), and Ok(Some(body)) if we found MIR to run for the
|
||||||
|
// foreign function
|
||||||
|
// Any needed call to `goto_block` will be performed by `emulate_foreign_item`.
|
||||||
|
let args = ecx.copy_fn_args(args)?; // FIXME: Should `InPlace` arguments be reset to uninit?
|
||||||
|
let link_name = ecx.item_link_name(instance.def_id());
|
||||||
|
return ecx.emulate_foreign_item(link_name, abi, &args, dest, ret, unwind);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, load the MIR.
|
||||||
|
Ok(Some((ecx.load_mir(instance.def, None)?, instance)))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
79
src/tools/miri/src/shims/extern_static.rs
Normal file
79
src/tools/miri/src/shims/extern_static.rs
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
//! Provides the `extern static` that this platform expects.
|
||||||
|
|
||||||
|
use crate::*;
|
||||||
|
|
||||||
|
impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
|
||||||
|
fn alloc_extern_static(
|
||||||
|
this: &mut MiriInterpCx<'mir, 'tcx>,
|
||||||
|
name: &str,
|
||||||
|
val: ImmTy<'tcx, Provenance>,
|
||||||
|
) -> InterpResult<'tcx> {
|
||||||
|
let place = this.allocate(val.layout, MiriMemoryKind::ExternStatic.into())?;
|
||||||
|
this.write_immediate(*val, &place)?;
|
||||||
|
Self::add_extern_static(this, name, place.ptr());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Zero-initialized pointer-sized extern statics are pretty common.
|
||||||
|
/// Most of them are for weak symbols, which we all set to null (indicating that the
|
||||||
|
/// symbol is not supported, and triggering fallback code which ends up calling a
|
||||||
|
/// syscall that we do support).
|
||||||
|
fn null_ptr_extern_statics(
|
||||||
|
this: &mut MiriInterpCx<'mir, 'tcx>,
|
||||||
|
names: &[&str],
|
||||||
|
) -> InterpResult<'tcx> {
|
||||||
|
for name in names {
|
||||||
|
let val = ImmTy::from_int(0, this.machine.layouts.usize);
|
||||||
|
Self::alloc_extern_static(this, name, val)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets up the "extern statics" for this machine.
|
||||||
|
pub fn init_extern_statics(this: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> {
|
||||||
|
// "__rust_no_alloc_shim_is_unstable"
|
||||||
|
let val = ImmTy::from_int(0, this.machine.layouts.u8);
|
||||||
|
Self::alloc_extern_static(this, "__rust_no_alloc_shim_is_unstable", val)?;
|
||||||
|
|
||||||
|
match this.tcx.sess.target.os.as_ref() {
|
||||||
|
"linux" => {
|
||||||
|
Self::null_ptr_extern_statics(
|
||||||
|
this,
|
||||||
|
&["__cxa_thread_atexit_impl", "getrandom", "statx", "__clock_gettime64"],
|
||||||
|
)?;
|
||||||
|
// "environ"
|
||||||
|
Self::add_extern_static(
|
||||||
|
this,
|
||||||
|
"environ",
|
||||||
|
this.machine.env_vars.environ.as_ref().unwrap().ptr(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
"freebsd" => {
|
||||||
|
Self::null_ptr_extern_statics(this, &["__cxa_thread_atexit_impl"])?;
|
||||||
|
// "environ"
|
||||||
|
Self::add_extern_static(
|
||||||
|
this,
|
||||||
|
"environ",
|
||||||
|
this.machine.env_vars.environ.as_ref().unwrap().ptr(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
"android" => {
|
||||||
|
Self::null_ptr_extern_statics(this, &["bsd_signal"])?;
|
||||||
|
// "signal" -- just needs a non-zero pointer value (function does not even get called),
|
||||||
|
// but we arrange for this to call the `signal` function anyway.
|
||||||
|
let layout = this.machine.layouts.const_raw_ptr;
|
||||||
|
let ptr = this.fn_ptr(FnVal::Other(DynSym::from_str("signal")));
|
||||||
|
let val = ImmTy::from_scalar(Scalar::from_pointer(ptr, this), layout);
|
||||||
|
Self::alloc_extern_static(this, "signal", val)?;
|
||||||
|
}
|
||||||
|
"windows" => {
|
||||||
|
// "_tls_used"
|
||||||
|
// This is some obscure hack that is part of the Windows TLS story. It's a `u8`.
|
||||||
|
let val = ImmTy::from_int(0, this.machine.layouts.u8);
|
||||||
|
Self::alloc_extern_static(this, "_tls_used", val)?;
|
||||||
|
}
|
||||||
|
_ => {} // No "extern statics" supported on this target
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
@ -10,48 +10,8 @@ pub mod windows;
|
|||||||
mod x86;
|
mod x86;
|
||||||
|
|
||||||
pub mod env;
|
pub mod env;
|
||||||
|
pub mod extern_static;
|
||||||
pub mod os_str;
|
pub mod os_str;
|
||||||
pub mod panic;
|
pub mod panic;
|
||||||
pub mod time;
|
pub mod time;
|
||||||
pub mod tls;
|
pub mod tls;
|
||||||
|
|
||||||
// End module management, begin local code
|
|
||||||
|
|
||||||
use log::trace;
|
|
||||||
|
|
||||||
use rustc_middle::{mir, ty};
|
|
||||||
use rustc_target::spec::abi::Abi;
|
|
||||||
|
|
||||||
use crate::*;
|
|
||||||
|
|
||||||
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
|
|
||||||
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|
||||||
fn find_mir_or_eval_fn(
|
|
||||||
&mut self,
|
|
||||||
instance: ty::Instance<'tcx>,
|
|
||||||
abi: Abi,
|
|
||||||
args: &[FnArg<'tcx, Provenance>],
|
|
||||||
dest: &PlaceTy<'tcx, Provenance>,
|
|
||||||
ret: Option<mir::BasicBlock>,
|
|
||||||
unwind: mir::UnwindAction,
|
|
||||||
) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
|
|
||||||
let this = self.eval_context_mut();
|
|
||||||
trace!("eval_fn_call: {:#?}, {:?}", instance, dest);
|
|
||||||
|
|
||||||
// For foreign items, try to see if we can emulate them.
|
|
||||||
if this.tcx.is_foreign_item(instance.def_id()) {
|
|
||||||
// An external function call that does not have a MIR body. We either find MIR elsewhere
|
|
||||||
// or emulate its effect.
|
|
||||||
// This will be Ok(None) if we're emulating the intrinsic entirely within Miri (no need
|
|
||||||
// to run extra MIR), and Ok(Some(body)) if we found MIR to run for the
|
|
||||||
// foreign function
|
|
||||||
// Any needed call to `goto_block` will be performed by `emulate_foreign_item`.
|
|
||||||
let args = this.copy_fn_args(args)?; // FIXME: Should `InPlace` arguments be reset to uninit?
|
|
||||||
let link_name = this.item_link_name(instance.def_id());
|
|
||||||
return this.emulate_foreign_item(link_name, abi, &args, dest, ret, unwind);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, load the MIR.
|
|
||||||
Ok(Some((this.load_mir(instance.def, None)?, instance)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user