From bc8d4dfa95ae10c3f7229c01710a9e8f838baaec Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 6 Oct 2023 09:15:48 +0200 Subject: [PATCH] refactor dlsym: dispatch symbols via the normal shim mechanism --- src/tools/miri/src/helpers.rs | 2 +- src/tools/miri/src/lib.rs | 4 +- src/tools/miri/src/machine.rs | 12 +-- src/tools/miri/src/shims/dlsym.rs | 48 ---------- src/tools/miri/src/shims/foreign_items.rs | 42 ++++++-- src/tools/miri/src/shims/mod.rs | 4 +- .../miri/src/shims/unix/android/dlsym.rs | 54 ----------- .../src/shims/unix/android/foreign_items.rs | 21 ++-- src/tools/miri/src/shims/unix/android/mod.rs | 1 - src/tools/miri/src/shims/unix/dlsym.rs | 55 ----------- .../miri/src/shims/unix/foreign_items.rs | 31 ++++-- .../miri/src/shims/unix/freebsd/dlsym.rs | 36 ------- .../src/shims/unix/freebsd/foreign_items.rs | 7 +- src/tools/miri/src/shims/unix/freebsd/mod.rs | 1 - src/tools/miri/src/shims/unix/linux/dlsym.rs | 40 -------- .../src/shims/unix/linux/foreign_items.rs | 8 +- src/tools/miri/src/shims/unix/linux/mod.rs | 1 - src/tools/miri/src/shims/unix/macos/dlsym.rs | 51 ---------- .../src/shims/unix/macos/foreign_items.rs | 31 +++--- src/tools/miri/src/shims/unix/macos/mod.rs | 1 - src/tools/miri/src/shims/unix/mod.rs | 1 - src/tools/miri/src/shims/windows/dlsym.rs | 82 ---------------- .../miri/src/shims/windows/foreign_items.rs | 95 +++++++++++++------ src/tools/miri/src/shims/windows/mod.rs | 1 - 24 files changed, 168 insertions(+), 461 deletions(-) delete mode 100644 src/tools/miri/src/shims/dlsym.rs delete mode 100644 src/tools/miri/src/shims/unix/android/dlsym.rs delete mode 100644 src/tools/miri/src/shims/unix/dlsym.rs delete mode 100644 src/tools/miri/src/shims/unix/freebsd/dlsym.rs delete mode 100644 src/tools/miri/src/shims/unix/linux/dlsym.rs delete mode 100644 src/tools/miri/src/shims/unix/macos/dlsym.rs delete mode 100644 src/tools/miri/src/shims/windows/dlsym.rs diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index fd9d57c487c0..4146a9b41ae1 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -960,7 +960,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { self.check_abi(abi, exp_abi)?; if let Some((body, instance)) = self.eval_context_mut().lookup_exported_symbol(link_name)? { // If compiler-builtins is providing the symbol, then don't treat it as a clash. - // We'll use our built-in implementation in `emulate_foreign_item_by_name` for increased + // We'll use our built-in implementation in `emulate_foreign_item_inner` for increased // performance. Note that this means we won't catch any undefined behavior in // compiler-builtins when running other crates, but Miri can still be run on // compiler-builtins itself (or any crate that uses it as a normal dependency) diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 816055cc4fe9..f1d8ce01bc24 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -8,6 +8,7 @@ #![feature(yeet_expr)] #![feature(nonzero_ops)] #![feature(round_ties_even)] +#![feature(let_chains)] #![feature(lint_reasons)] #![feature(trait_upcasting)] // Configure clippy and other lints @@ -86,9 +87,8 @@ pub use rustc_const_eval::interpret::*; // Resolve ambiguity. pub use rustc_const_eval::interpret::{self, AllocMap, PlaceTy, Provenance as _}; -pub use crate::shims::dlsym::{Dlsym, EvalContextExt as _}; pub use crate::shims::env::{EnvVars, EvalContextExt as _}; -pub use crate::shims::foreign_items::EvalContextExt as _; +pub use crate::shims::foreign_items::{DynSym, EvalContextExt as _}; pub use crate::shims::intrinsics::EvalContextExt as _; pub use crate::shims::os_str::EvalContextExt as _; pub use crate::shims::panic::{CatchUnwindData, EvalContextExt as _}; diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index fb56e0135b4c..54f90b2c0399 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -709,9 +709,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { "android" => { // "signal" let layout = this.machine.layouts.const_raw_ptr; - let dlsym = Dlsym::from_str("signal".as_bytes(), &this.tcx.sess.target.os)? - .expect("`signal` must be an actual dlsym on android"); - let ptr = this.fn_ptr(FnVal::Other(dlsym)); + 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. @@ -867,7 +865,7 @@ impl<'mir, 'tcx> MiriInterpCxExt<'mir, 'tcx> for MiriInterpCx<'mir, 'tcx> { /// Machine hook implementations. impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { type MemoryKind = MiriMemoryKind; - type ExtraFnVal = Dlsym; + type ExtraFnVal = DynSym; type FrameExtra = FrameExtra<'tcx>; type AllocExtra = AllocExtra<'tcx>; @@ -939,15 +937,15 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { #[inline(always)] fn call_extra_fn( ecx: &mut MiriInterpCx<'mir, 'tcx>, - fn_val: Dlsym, + fn_val: DynSym, abi: Abi, args: &[FnArg<'tcx, Provenance>], dest: &PlaceTy<'tcx, Provenance>, ret: Option, - _unwind: mir::UnwindAction, + unwind: mir::UnwindAction, ) -> InterpResult<'tcx> { let args = ecx.copy_fn_args(args)?; // FIXME: Should `InPlace` arguments be reset to uninit? - ecx.call_dlsym(fn_val, abi, &args, dest, ret) + ecx.emulate_dyn_sym(fn_val, abi, &args, dest, ret, unwind) } #[inline(always)] diff --git a/src/tools/miri/src/shims/dlsym.rs b/src/tools/miri/src/shims/dlsym.rs deleted file mode 100644 index 8bf6d24f85f3..000000000000 --- a/src/tools/miri/src/shims/dlsym.rs +++ /dev/null @@ -1,48 +0,0 @@ -use rustc_middle::mir; -use rustc_target::spec::abi::Abi; - -use crate::helpers::target_os_is_unix; -use crate::*; -use shims::unix::dlsym as unix; -use shims::windows::dlsym as windows; - -#[derive(Debug, Copy, Clone)] -#[allow(non_camel_case_types)] -pub enum Dlsym { - Posix(unix::Dlsym), - Windows(windows::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: &[u8], target_os: &str) -> InterpResult<'tcx, Option> { - let name = &*String::from_utf8_lossy(name); - Ok(match target_os { - target if target_os_is_unix(target) => - unix::Dlsym::from_str(name, target)?.map(Dlsym::Posix), - "windows" => windows::Dlsym::from_str(name)?.map(Dlsym::Windows), - os => bug!("dlsym not implemented for target_os {}", os), - }) - } -} - -impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} -pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn call_dlsym( - &mut self, - dlsym: Dlsym, - abi: Abi, - args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, - ret: Option, - ) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); - match dlsym { - Dlsym::Posix(dlsym) => - unix::EvalContextExt::call_dlsym(this, dlsym, abi, args, dest, ret), - Dlsym::Windows(dlsym) => - windows::EvalContextExt::call_dlsym(this, dlsym, abi, args, dest, ret), - } - } -} diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 0c92ede40fd8..e93521ac774c 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -6,7 +6,7 @@ use rustc_apfloat::Float; use rustc_ast::expand::allocator::AllocatorKind; use rustc_hir::{ def::DefKind, - def_id::{CrateNum, DefId, LOCAL_CRATE}, + def_id::{CrateNum, LOCAL_CRATE}, }; use rustc_middle::middle::{ codegen_fn_attrs::CodegenFnAttrFlags, dependency_format::Linkage, @@ -25,7 +25,18 @@ use super::backtrace::EvalContextExt as _; use crate::helpers::target_os_is_unix; use crate::*; -/// Returned by `emulate_foreign_item_by_name`. +/// Type of dynamic symbols (for `dlsym` et al) +#[derive(Debug, Copy, Clone)] +pub struct DynSym(Symbol); + +#[allow(clippy::should_implement_trait)] +impl DynSym { + pub fn from_str(name: &str) -> Self { + DynSym(Symbol::intern(name)) + } +} + +/// Returned by `emulate_foreign_item_inner`. pub enum EmulateByNameResult<'mir, 'tcx> { /// The caller is expected to jump to the return block. NeedsJumping, @@ -254,7 +265,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { /// is delegated to another function. fn emulate_foreign_item( &mut self, - def_id: DefId, + link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &PlaceTy<'tcx, Provenance>, @@ -262,7 +273,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { unwind: mir::UnwindAction, ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> { let this = self.eval_context_mut(); - let link_name = this.item_link_name(def_id); let tcx = this.tcx.tcx; // First: functions that diverge. @@ -322,7 +332,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { }; // Second: functions that return immediately. - match this.emulate_foreign_item_by_name(link_name, abi, args, dest)? { + match this.emulate_foreign_item_inner(link_name, abi, args, dest)? { EmulateByNameResult::NeedsJumping => { trace!("{:?}", this.dump_place(dest)); this.go_to_block(ret); @@ -345,6 +355,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { Ok(None) } + /// Emulates a call to a `DynSym`. + fn emulate_dyn_sym( + &mut self, + sym: DynSym, + abi: Abi, + args: &[OpTy<'tcx, Provenance>], + dest: &PlaceTy<'tcx, Provenance>, + ret: Option, + unwind: mir::UnwindAction, + ) -> InterpResult<'tcx> { + let res = self.emulate_foreign_item(sym.0, abi, args, dest, ret, unwind)?; + assert!(res.is_none(), "DynSyms that delegate are not supported"); + Ok(()) + } + /// Emulates calling the internal __rust_* allocator functions fn emulate_allocator( &mut self, @@ -373,8 +398,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } - /// Emulates calling a foreign item using its name. - fn emulate_foreign_item_by_name( + fn emulate_foreign_item_inner( &mut self, link_name: Symbol, abi: Abi, @@ -1045,11 +1069,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { _ => return match this.tcx.sess.target.os.as_ref() { target_os if target_os_is_unix(target_os) => - shims::unix::foreign_items::EvalContextExt::emulate_foreign_item_by_name( + shims::unix::foreign_items::EvalContextExt::emulate_foreign_item_inner( this, link_name, abi, args, dest, ), "windows" => - shims::windows::foreign_items::EvalContextExt::emulate_foreign_item_by_name( + shims::windows::foreign_items::EvalContextExt::emulate_foreign_item_inner( this, link_name, abi, args, dest, ), _ => Ok(EmulateByNameResult::NotSupported), diff --git a/src/tools/miri/src/shims/mod.rs b/src/tools/miri/src/shims/mod.rs index 5a9574766f3d..a031a2a25c96 100644 --- a/src/tools/miri/src/shims/mod.rs +++ b/src/tools/miri/src/shims/mod.rs @@ -9,7 +9,6 @@ pub mod unix; pub mod windows; mod x86; -pub mod dlsym; pub mod env; pub mod os_str; pub mod panic; @@ -58,7 +57,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // 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? - return this.emulate_foreign_item(instance.def_id(), abi, &args, dest, ret, unwind); + 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. diff --git a/src/tools/miri/src/shims/unix/android/dlsym.rs b/src/tools/miri/src/shims/unix/android/dlsym.rs deleted file mode 100644 index 451bc0bd5e15..000000000000 --- a/src/tools/miri/src/shims/unix/android/dlsym.rs +++ /dev/null @@ -1,54 +0,0 @@ -use rustc_middle::mir; - -use crate::helpers::check_arg_count; -use crate::*; - -#[derive(Debug, Copy, Clone)] -#[allow(non_camel_case_types)] -pub enum Dlsym { - signal, -} - -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 { - "signal" => Some(Dlsym::signal), - "android_set_abort_message" => None, - _ => throw_unsup_format!("unsupported Android dlsym: {}", name), - }) - } -} - -impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} -pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn call_dlsym( - &mut self, - dlsym: Dlsym, - args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, - 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 == "android"); - - match dlsym { - Dlsym::signal => { - if !this.frame_in_std() { - throw_unsup_format!( - "`signal` support is crude and just enough for libstd to work" - ); - } - - let [_sig, _func] = check_arg_count(args)?; - this.write_null(dest)?; - } - } - - log::trace!("{:?}", this.dump_place(dest)); - this.go_to_block(ret); - Ok(()) - } -} diff --git a/src/tools/miri/src/shims/unix/android/foreign_items.rs b/src/tools/miri/src/shims/unix/android/foreign_items.rs index 756aed369f15..b610cf97750f 100644 --- a/src/tools/miri/src/shims/unix/android/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/android/foreign_items.rs @@ -6,17 +6,26 @@ use shims::foreign_items::EmulateByNameResult; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} +pub fn is_dyn_sym(name: &str) -> bool { + matches!(name, "signal") +} + pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn emulate_foreign_item_by_name( + fn emulate_foreign_item_inner( &mut self, link_name: Symbol, - _abi: Abi, - _args: &[OpTy<'tcx, Provenance>], - _dest: &PlaceTy<'tcx, Provenance>, + abi: Abi, + args: &[OpTy<'tcx, Provenance>], + dest: &PlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> { - let _this = self.eval_context_mut(); - #[allow(clippy::match_single_binding)] + let this = self.eval_context_mut(); + match link_name.as_str() { + "signal" if this.frame_in_std() => { + let [_sig, _func] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + this.write_null(dest)?; + } _ => return Ok(EmulateByNameResult::NotSupported), } diff --git a/src/tools/miri/src/shims/unix/android/mod.rs b/src/tools/miri/src/shims/unix/android/mod.rs index 434f5f30b5a5..09c6507b24f8 100644 --- a/src/tools/miri/src/shims/unix/android/mod.rs +++ b/src/tools/miri/src/shims/unix/android/mod.rs @@ -1,2 +1 @@ -pub mod dlsym; pub mod foreign_items; diff --git a/src/tools/miri/src/shims/unix/dlsym.rs b/src/tools/miri/src/shims/unix/dlsym.rs deleted file mode 100644 index 8bc19d18f2b2..000000000000 --- a/src/tools/miri/src/shims/unix/dlsym.rs +++ /dev/null @@ -1,55 +0,0 @@ -use rustc_middle::mir; -use rustc_target::spec::abi::Abi; - -use crate::*; -use shims::unix::android::dlsym as android; -use shims::unix::freebsd::dlsym as freebsd; -use shims::unix::linux::dlsym as linux; -use shims::unix::macos::dlsym as macos; - -#[derive(Debug, Copy, Clone)] -pub enum Dlsym { - Android(android::Dlsym), - FreeBsd(freebsd::Dlsym), - Linux(linux::Dlsym), - MacOs(macos::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, target_os: &str) -> InterpResult<'tcx, Option> { - Ok(match target_os { - "android" => android::Dlsym::from_str(name)?.map(Dlsym::Android), - "freebsd" => freebsd::Dlsym::from_str(name)?.map(Dlsym::FreeBsd), - "linux" => linux::Dlsym::from_str(name)?.map(Dlsym::Linux), - "macos" => macos::Dlsym::from_str(name)?.map(Dlsym::MacOs), - _ => panic!("unsupported Unix OS {target_os}"), - }) - } -} - -impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} -pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn call_dlsym( - &mut self, - dlsym: Dlsym, - abi: Abi, - args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, - ret: Option, - ) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); - - this.check_abi(abi, Abi::C { unwind: false })?; - - match dlsym { - Dlsym::Android(dlsym) => - android::EvalContextExt::call_dlsym(this, dlsym, args, dest, ret), - Dlsym::FreeBsd(dlsym) => - freebsd::EvalContextExt::call_dlsym(this, dlsym, args, dest, ret), - Dlsym::Linux(dlsym) => linux::EvalContextExt::call_dlsym(this, dlsym, args, dest, ret), - Dlsym::MacOs(dlsym) => macos::EvalContextExt::call_dlsym(this, dlsym, args, dest, ret), - } - } -} diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index 4bcca5076cac..06ffdbff4e6d 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -1,4 +1,5 @@ use std::ffi::OsStr; +use std::str; use log::trace; @@ -14,9 +15,14 @@ use shims::unix::mem::EvalContextExt as _; use shims::unix::sync::EvalContextExt as _; use shims::unix::thread::EvalContextExt as _; +use shims::unix::android::foreign_items as android; +use shims::unix::freebsd::foreign_items as freebsd; +use shims::unix::linux::foreign_items as linux; +use shims::unix::macos::foreign_items as macos; + 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_by_name( + fn emulate_foreign_item_inner( &mut self, link_name: Symbol, abi: Abi, @@ -25,7 +31,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> { let this = self.eval_context_mut(); - // See `fn emulate_foreign_item_by_name` in `shims/foreign_items.rs` for the general pattern. + // See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern. #[rustfmt::skip] match link_name.as_str() { // Environment related shims @@ -230,9 +236,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let [handle, symbol] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; this.read_target_usize(handle)?; let symbol = this.read_pointer(symbol)?; - let symbol_name = this.read_c_str(symbol)?; - if let Some(dlsym) = Dlsym::from_str(symbol_name, &this.tcx.sess.target.os)? { - let ptr = this.fn_ptr(FnVal::Other(dlsym)); + let name = this.read_c_str(symbol)?; + let is_dyn_sym = |name| match &*this.tcx.sess.target.os { + "android" => android::is_dyn_sym(name), + "freebsd" => freebsd::is_dyn_sym(name), + "linux" => linux::is_dyn_sym(name), + "macos" => macos::is_dyn_sym(name), + target_os => panic!("unsupported Unix OS {target_os}"), + }; + if let Ok(name) = str::from_utf8(name) && is_dyn_sym(name) { + let ptr = this.fn_ptr(FnVal::Other(DynSym::from_str(name))); this.write_pointer(ptr, dest)?; } else { this.write_null(dest)?; @@ -609,10 +622,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { _ => { let target_os = &*this.tcx.sess.target.os; return match target_os { - "android" => shims::unix::android::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest), - "freebsd" => shims::unix::freebsd::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest), - "linux" => shims::unix::linux::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest), - "macos" => shims::unix::macos::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest), + "android" => android::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest), + "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), _ => Ok(EmulateByNameResult::NotSupported), }; } diff --git a/src/tools/miri/src/shims/unix/freebsd/dlsym.rs b/src/tools/miri/src/shims/unix/freebsd/dlsym.rs deleted file mode 100644 index d759ffb8994b..000000000000 --- a/src/tools/miri/src/shims/unix/freebsd/dlsym.rs +++ /dev/null @@ -1,36 +0,0 @@ -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> { - throw_unsup_format!("unsupported FreeBSD dlsym: {}", name) - } -} - -impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} -pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn call_dlsym( - &mut self, - dlsym: Dlsym, - _args: &[OpTy<'tcx, Provenance>], - _dest: &PlaceTy<'tcx, Provenance>, - 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 == "freebsd"); - - match dlsym {} - - //trace!("{:?}", this.dump_place(**dest)); - //this.go_to_block(ret); - //Ok(()) - } -} diff --git a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs index d755e5f10bae..388b20526795 100644 --- a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs @@ -5,10 +5,13 @@ use crate::*; use shims::foreign_items::EmulateByNameResult; use shims::unix::thread::EvalContextExt as _; -impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} +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_by_name( + fn emulate_foreign_item_inner( &mut self, link_name: Symbol, abi: Abi, diff --git a/src/tools/miri/src/shims/unix/freebsd/mod.rs b/src/tools/miri/src/shims/unix/freebsd/mod.rs index 434f5f30b5a5..09c6507b24f8 100644 --- a/src/tools/miri/src/shims/unix/freebsd/mod.rs +++ b/src/tools/miri/src/shims/unix/freebsd/mod.rs @@ -1,2 +1 @@ -pub mod dlsym; pub mod foreign_items; diff --git a/src/tools/miri/src/shims/unix/linux/dlsym.rs b/src/tools/miri/src/shims/unix/linux/dlsym.rs deleted file mode 100644 index a96c14c142b2..000000000000 --- a/src/tools/miri/src/shims/unix/linux/dlsym.rs +++ /dev/null @@ -1,40 +0,0 @@ -use rustc_middle::mir; - -use crate::*; - -#[derive(Debug, Copy, Clone)] -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> { - Ok(match name { - "__pthread_get_minstack" => None, - "getrandom" => None, // std falls back to syscall(SYS_getrandom, ...) when this is NULL. - "statx" => None, // std falls back to syscall(SYS_statx, ...) when this is NULL. - _ => throw_unsup_format!("unsupported Linux dlsym: {}", name), - }) - } -} - -impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} -pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn call_dlsym( - &mut self, - dlsym: Dlsym, - _args: &[OpTy<'tcx, Provenance>], - _dest: &PlaceTy<'tcx, Provenance>, - 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 == "linux"); - - match dlsym {} - - //trace!("{:?}", this.dump_place(**dest)); - //this.go_to_block(ret); - //Ok(()) - } -} diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs index 1bd751c59811..9f5f6ea9bd09 100644 --- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs @@ -12,9 +12,13 @@ use shims::unix::linux::sync::futex; use shims::unix::sync::EvalContextExt as _; use shims::unix::thread::EvalContextExt as _; +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_by_name( + fn emulate_foreign_item_inner( &mut self, link_name: Symbol, abi: Abi, @@ -23,7 +27,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> { let this = self.eval_context_mut(); - // See `fn emulate_foreign_item_by_name` in `shims/foreign_items.rs` for the general pattern. + // See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern. match link_name.as_str() { // errno diff --git a/src/tools/miri/src/shims/unix/linux/mod.rs b/src/tools/miri/src/shims/unix/linux/mod.rs index 856ec226de8f..fe18f1a32fd4 100644 --- a/src/tools/miri/src/shims/unix/linux/mod.rs +++ b/src/tools/miri/src/shims/unix/linux/mod.rs @@ -1,4 +1,3 @@ -pub mod dlsym; pub mod fd; pub mod foreign_items; pub mod mem; diff --git a/src/tools/miri/src/shims/unix/macos/dlsym.rs b/src/tools/miri/src/shims/unix/macos/dlsym.rs deleted file mode 100644 index fa8094528757..000000000000 --- a/src/tools/miri/src/shims/unix/macos/dlsym.rs +++ /dev/null @@ -1,51 +0,0 @@ -use rustc_middle::mir; - -use log::trace; - -use super::foreign_items::EvalContextExt as _; -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::MiriInterpCx<'mir, 'tcx> {} -pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn call_dlsym( - &mut self, - dlsym: Dlsym, - args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, - 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 result = this.getentropy(ptr, len)?; - this.write_scalar(result, dest)?; - } - } - - trace!("{:?}", this.dump_place(dest)); - this.go_to_block(ret); - Ok(()) - } -} diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs index b514097c5df0..cb0af4c82791 100644 --- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs @@ -6,9 +6,13 @@ use shims::foreign_items::EmulateByNameResult; use shims::unix::fs::EvalContextExt as _; use shims::unix::thread::EvalContextExt as _; +pub fn is_dyn_sym(name: &str) -> bool { + matches!(name, "getentropy") +} + 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_by_name( + fn emulate_foreign_item_inner( &mut self, link_name: Symbol, abi: Abi, @@ -17,7 +21,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> { let this = self.eval_context_mut(); - // See `fn emulate_foreign_item_by_name` in `shims/foreign_items.rs` for the general pattern. + // See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern. match link_name.as_str() { // errno @@ -113,8 +117,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "getentropy" => { let [buf, bufsize] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.getentropy(buf, bufsize)?; - this.write_scalar(result, dest)?; + let buf = this.read_pointer(buf)?; + let bufsize = this.read_target_usize(bufsize)?; + + this.gen_random(buf, bufsize)?; + + this.write_scalar(Scalar::from_i32(0), dest)?; // KERN_SUCCESS } // Access to command-line arguments @@ -206,19 +214,4 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { Ok(EmulateByNameResult::NeedsJumping) } - - fn getentropy( - &mut self, - buffer_op: &OpTy<'tcx, Provenance>, - length_op: &OpTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, Scalar> { - let this = self.eval_context_mut(); - this.assert_target_os("macos", "getentropy"); - - let ptr = this.read_pointer(buffer_op)?; - let len = this.read_target_usize(length_op)?; - this.gen_random(ptr, len)?; - - Ok(Scalar::from_i32(0)) // KERN_SUCCESS - } } diff --git a/src/tools/miri/src/shims/unix/macos/mod.rs b/src/tools/miri/src/shims/unix/macos/mod.rs index 434f5f30b5a5..09c6507b24f8 100644 --- a/src/tools/miri/src/shims/unix/macos/mod.rs +++ b/src/tools/miri/src/shims/unix/macos/mod.rs @@ -1,2 +1 @@ -pub mod dlsym; pub mod foreign_items; diff --git a/src/tools/miri/src/shims/unix/mod.rs b/src/tools/miri/src/shims/unix/mod.rs index a8ebd369abaa..2f8014933521 100644 --- a/src/tools/miri/src/shims/unix/mod.rs +++ b/src/tools/miri/src/shims/unix/mod.rs @@ -1,4 +1,3 @@ -pub mod dlsym; pub mod foreign_items; mod fs; diff --git a/src/tools/miri/src/shims/windows/dlsym.rs b/src/tools/miri/src/shims/windows/dlsym.rs deleted file mode 100644 index e5afee35905d..000000000000 --- a/src/tools/miri/src/shims/windows/dlsym.rs +++ /dev/null @@ -1,82 +0,0 @@ -use rustc_middle::mir; -use rustc_target::spec::abi::Abi; - -use log::trace; - -use crate::helpers::check_arg_count; -use crate::shims::windows::handle::{EvalContextExt as _, Handle, PseudoHandle}; -use crate::shims::windows::sync::EvalContextExt as _; -use crate::*; - -#[derive(Debug, Copy, Clone)] -pub enum Dlsym { - SetThreadDescription, - WaitOnAddress, - WakeByAddressSingle, -} - -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 { - "GetSystemTimePreciseAsFileTime" => None, - "SetThreadDescription" => Some(Dlsym::SetThreadDescription), - "WaitOnAddress" => Some(Dlsym::WaitOnAddress), - "WakeByAddressSingle" => Some(Dlsym::WakeByAddressSingle), - _ => throw_unsup_format!("unsupported Windows dlsym: {}", name), - }) - } -} - -impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} -pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn call_dlsym( - &mut self, - dlsym: Dlsym, - abi: Abi, - args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, - 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 == "windows"); - - this.check_abi(abi, Abi::System { unwind: false })?; - - match dlsym { - Dlsym::SetThreadDescription => { - let [handle, name] = check_arg_count(args)?; - - let handle = this.read_scalar(handle)?; - - let name = this.read_wide_str(this.read_pointer(name)?)?; - - let thread = match Handle::from_scalar(handle, this)? { - Some(Handle::Thread(thread)) => thread, - Some(Handle::Pseudo(PseudoHandle::CurrentThread)) => this.get_active_thread(), - _ => this.invalid_handle("SetThreadDescription")?, - }; - - this.set_thread_name_wide(thread, &name); - - this.write_null(dest)?; - } - Dlsym::WaitOnAddress => { - let [ptr_op, compare_op, size_op, timeout_op] = check_arg_count(args)?; - - this.WaitOnAddress(ptr_op, compare_op, size_op, timeout_op, dest)?; - } - Dlsym::WakeByAddressSingle => { - let [ptr_op] = check_arg_count(args)?; - - this.WakeByAddressSingle(ptr_op)?; - } - } - - trace!("{:?}", this.dump_place(dest)); - this.go_to_block(ret); - Ok(()) - } -} diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs index d76d01b07891..fe2f48638b8f 100644 --- a/src/tools/miri/src/shims/windows/foreign_items.rs +++ b/src/tools/miri/src/shims/windows/foreign_items.rs @@ -1,4 +1,5 @@ use std::iter; +use std::str; use rustc_span::Symbol; use rustc_target::abi::Size; @@ -10,9 +11,13 @@ use shims::windows::handle::{EvalContextExt as _, Handle, PseudoHandle}; use shims::windows::sync::EvalContextExt as _; use shims::windows::thread::EvalContextExt as _; +fn is_dyn_sym(name: &str) -> bool { + matches!(name, "SetThreadDescription" | "WaitOnAddress" | "WakeByAddressSingle") +} + 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_by_name( + fn emulate_foreign_item_inner( &mut self, link_name: Symbol, abi: Abi, @@ -21,7 +26,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> { let this = self.eval_context_mut(); - // See `fn emulate_foreign_item_by_name` in `shims/foreign_items.rs` for the general pattern. + // See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern. // Windows API stubs. // HANDLE = isize @@ -326,6 +331,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.WakeAllConditionVariable(condvar)?; } + "WaitOnAddress" => { + let [ptr_op, compare_op, size_op, timeout_op] = + this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; + + this.WaitOnAddress(ptr_op, compare_op, size_op, timeout_op, dest)?; + } + "WakeByAddressSingle" => { + let [ptr_op] = + this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; + + this.WakeByAddressSingle(ptr_op)?; + } // Dynamic symbol loading "GetProcAddress" => { @@ -334,14 +351,58 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; this.read_target_isize(hModule)?; let name = this.read_c_str(this.read_pointer(lpProcName)?)?; - if let Some(dlsym) = Dlsym::from_str(name, &this.tcx.sess.target.os)? { - let ptr = this.fn_ptr(FnVal::Other(dlsym)); + if let Ok(name) = str::from_utf8(name) && is_dyn_sym(name) { + let ptr = this.fn_ptr(FnVal::Other(DynSym::from_str(name))); this.write_pointer(ptr, dest)?; } else { this.write_null(dest)?; } } + // Threading + "CreateThread" => { + let [security, stacksize, start, arg, flags, thread] = + this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; + + let thread_id = + this.CreateThread(security, stacksize, start, arg, flags, thread)?; + + this.write_scalar(Handle::Thread(thread_id).to_scalar(this), dest)?; + } + "WaitForSingleObject" => { + let [handle, timeout] = + this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; + + let ret = this.WaitForSingleObject(handle, timeout)?; + this.write_scalar(Scalar::from_u32(ret), dest)?; + } + "GetCurrentThread" => { + let [] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; + + this.write_scalar( + Handle::Pseudo(PseudoHandle::CurrentThread).to_scalar(this), + dest, + )?; + } + "SetThreadDescription" => { + let [handle, name] = + this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; + + let handle = this.read_scalar(handle)?; + + let name = this.read_wide_str(this.read_pointer(name)?)?; + + let thread = match Handle::from_scalar(handle, this)? { + Some(Handle::Thread(thread)) => thread, + Some(Handle::Pseudo(PseudoHandle::CurrentThread)) => this.get_active_thread(), + _ => this.invalid_handle("SetThreadDescription")?, + }; + + this.set_thread_name_wide(thread, &name); + + this.write_null(dest)?; + } + // Miscellaneous "SystemFunction036" => { // This is really 'RtlGenRandom'. @@ -456,32 +517,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } - // Threading - "CreateThread" => { - let [security, stacksize, start, arg, flags, thread] = - this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; - - let thread_id = - this.CreateThread(security, stacksize, start, arg, flags, thread)?; - - this.write_scalar(Handle::Thread(thread_id).to_scalar(this), dest)?; - } - "WaitForSingleObject" => { - let [handle, timeout] = - this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; - - let ret = this.WaitForSingleObject(handle, timeout)?; - this.write_scalar(Scalar::from_u32(ret), dest)?; - } - "GetCurrentThread" => { - let [] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; - - this.write_scalar( - Handle::Pseudo(PseudoHandle::CurrentThread).to_scalar(this), - dest, - )?; - } - // Incomplete shims that we "stub out" just to get pre-main initialization code to work. // These shims are enabled only when the caller is in the standard library. "GetProcessHeap" if this.frame_in_std() => { diff --git a/src/tools/miri/src/shims/windows/mod.rs b/src/tools/miri/src/shims/windows/mod.rs index 40fe71b2dbd0..7688abe412b9 100644 --- a/src/tools/miri/src/shims/windows/mod.rs +++ b/src/tools/miri/src/shims/windows/mod.rs @@ -1,4 +1,3 @@ -pub mod dlsym; pub mod foreign_items; mod handle;