From 71f41405500cec42be22f0080bf3f83f97bfa768 Mon Sep 17 00:00:00 2001 From: hyd-dev Date: Sun, 30 May 2021 01:36:06 +0800 Subject: [PATCH] Add `-Zmiri-disable-abi-check` --- README.md | 4 + src/bin/miri.rs | 3 + src/eval.rs | 3 + src/helpers.rs | 13 +- src/machine.rs | 9 ++ src/shims/foreign_items.rs | 54 ++++---- src/shims/posix/dlsym.rs | 2 +- src/shims/posix/foreign_items.rs | 122 +++++++++--------- src/shims/posix/linux/foreign_items.rs | 32 ++--- src/shims/posix/macos/foreign_items.rs | 38 +++--- src/shims/windows/dlsym.rs | 2 +- src/shims/windows/foreign_items.rs | 80 ++++++------ tests/compile-fail/check_callback_abi.rs | 15 +++ .../concurrency/unwind_top_of_stack.rs | 6 +- tests/compile-fail/panic/bad_unwind.rs | 2 + tests/run-pass/disable_abi_check.rs | 24 ++++ 16 files changed, 235 insertions(+), 174 deletions(-) create mode 100644 tests/compile-fail/check_callback_abi.rs create mode 100644 tests/run-pass/disable_abi_check.rs diff --git a/README.md b/README.md index b214ab6d09c..f87a7e989d9 100644 --- a/README.md +++ b/README.md @@ -214,6 +214,8 @@ environment variable: as out-of-bounds accesses) first. Setting this flag means Miri can miss bugs in your program. However, this can also help to make Miri run faster. Using this flag is **unsound**. +* `-Zmiri-disable-abi-check` disables checking [function ABI]. Using this flag + is **unsound**. * `-Zmiri-disable-isolation` disables host isolation. As a consequence, the program has access to host resources such as environment variables, file systems, and randomness. @@ -263,6 +265,8 @@ environment variable: with `-Zmiri-track-raw-pointers` also works without `-Zmiri-track-raw-pointers`, but for the vast majority of code, this will be the case. +[function ABI]: https://doc.rust-lang.org/reference/items/functions.html#extern-function-qualifier + Some native rustc `-Z` flags are also very relevant for Miri: * `-Zmir-opt-level` controls how many MIR optimizations are performed. Miri diff --git a/src/bin/miri.rs b/src/bin/miri.rs index 47cde5c353e..e921407f63f 100644 --- a/src/bin/miri.rs +++ b/src/bin/miri.rs @@ -227,6 +227,9 @@ fn main() { "-Zmiri-symbolic-alignment-check" => { miri_config.check_alignment = miri::AlignmentCheck::Symbolic; } + "-Zmiri-disable-abi-check" => { + miri_config.check_abi = false; + } "-Zmiri-disable-isolation" => { miri_config.communicate = true; } diff --git a/src/eval.rs b/src/eval.rs index 52e554f57d7..6646783d349 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -31,6 +31,8 @@ pub struct MiriConfig { pub stacked_borrows: bool, /// Controls alignment checking. pub check_alignment: AlignmentCheck, + /// Controls function [ABI](Abi) checking. + pub check_abi: bool, /// Determines if communication with the host environment is enabled. pub communicate: bool, /// Determines if memory leaks should be ignored. @@ -65,6 +67,7 @@ fn default() -> MiriConfig { validate: true, stacked_borrows: true, check_alignment: AlignmentCheck::Int, + check_abi: true, communicate: false, ignore_leaks: false, excluded_env_vars: vec![], diff --git a/src/helpers.rs b/src/helpers.rs index 45a5a8d4170..af6985ccebd 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -165,7 +165,7 @@ fn call_function( let this = self.eval_context_mut(); let param_env = ty::ParamEnv::reveal_all(); // in Miri this is always the param_env we use... and this.param_env is private. let callee_abi = f.ty(*this.tcx, param_env).fn_sig(*this.tcx).abi(); - if callee_abi != caller_abi { + if this.machine.enforce_abi && callee_abi != caller_abi { throw_ub_format!( "calling a function with ABI {} using caller ABI {}", callee_abi.name(), @@ -632,16 +632,19 @@ pub fn check_arg_count<'a, 'tcx, const N: usize>( } /// Check that the ABI is what we expect. -pub fn check_abi<'a>(abi: Abi, exp_abi: Abi) -> InterpResult<'a, ()> { - if abi == exp_abi { - Ok(()) - } else { +pub fn check_abi<'a>( + this: &MiriEvalContext<'_, '_>, + abi: Abi, + exp_abi: Abi, +) -> InterpResult<'a, ()> { + if this.machine.enforce_abi && abi != exp_abi { throw_ub_format!( "calling a function with ABI {} using caller ABI {}", exp_abi.name(), abi.name() ) } + Ok(()) } pub fn isolation_error(name: &str) -> InterpResult<'static> { diff --git a/src/machine.rs b/src/machine.rs index 4f643e7f509..175396ed119 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -270,6 +270,9 @@ pub struct Evaluator<'mir, 'tcx> { /// Whether to enforce the validity invariant. pub(crate) validate: bool, + /// Whether to enforce [ABI](Abi) of function calls. + pub(crate) enforce_abi: bool, + pub(crate) file_handler: shims::posix::FileHandler, pub(crate) dir_handler: shims::posix::DirHandler, @@ -310,6 +313,7 @@ pub(crate) fn new(config: &MiriConfig, layout_cx: LayoutCx<'tcx, TyCtxt<'tcx>>) tls: TlsData::default(), communicate: config.communicate, validate: config.validate, + enforce_abi: config.check_abi, file_handler: Default::default(), dir_handler: Default::default(), time_anchor: Instant::now(), @@ -371,6 +375,11 @@ fn enforce_validity(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool { ecx.machine.validate } + #[inline(always)] + fn enforce_abi(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool { + ecx.machine.enforce_abi + } + #[inline(always)] fn find_mir_or_eval_fn( ecx: &mut InterpCx<'mir, 'tcx, Self>, diff --git a/src/shims/foreign_items.rs b/src/shims/foreign_items.rs index 4c96c99eeea..2afa1a86712 100644 --- a/src/shims/foreign_items.rs +++ b/src/shims/foreign_items.rs @@ -136,14 +136,14 @@ fn emulate_foreign_item( let (dest, ret) = match ret { None => match link_name { "miri_start_panic" => { - check_abi(abi, Abi::Rust)?; + check_abi(this, abi, Abi::Rust)?; this.handle_miri_start_panic(args, unwind)?; return Ok(None); } // This matches calls to the foreign item `panic_impl`. // The implementation is provided by the function with the `#[panic_handler]` attribute. "panic_impl" => { - check_abi(abi, Abi::Rust)?; + check_abi(this, abi, Abi::Rust)?; let panic_impl_id = tcx.lang_items().panic_impl().unwrap(); let panic_impl_instance = ty::Instance::mono(tcx, panic_impl_id); return Ok(Some(&*this.load_mir(panic_impl_instance.def, None)?)); @@ -152,14 +152,14 @@ fn emulate_foreign_item( | "exit" | "ExitProcess" => { - check_abi(abi, if link_name == "exit" { Abi::C { unwind: false } } else { Abi::System { unwind: false } })?; + check_abi(this, abi, if link_name == "exit" { Abi::C { unwind: false } } else { Abi::System { unwind: false } })?; let &[ref code] = check_arg_count(args)?; // it's really u32 for ExitProcess, but we have to put it into the `Exit` variant anyway let code = this.read_scalar(code)?.to_i32()?; throw_machine_stop!(TerminationInfo::Exit(code.into())); } "abort" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; throw_machine_stop!(TerminationInfo::Abort( "the program aborted execution".to_owned() )) @@ -180,7 +180,7 @@ fn emulate_foreign_item( #[rustfmt::skip] "__rust_start_panic" | "__rust_panic_cleanup" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; // This replicates some of the logic in `inject_panic_runtime`. // FIXME: is there a way to reuse that logic? let panic_runtime = match this.tcx.sess.panic_strategy() { @@ -221,7 +221,7 @@ fn emulate_foreign_item_by_name( match link_name { // Miri-specific extern functions "miri_static_root" => { - check_abi(abi, Abi::Rust)?; + check_abi(this, abi, Abi::Rust)?; let &[ref ptr] = check_arg_count(args)?; let ptr = this.read_scalar(ptr)?.check_init()?; let ptr = this.force_ptr(ptr)?; @@ -233,27 +233,27 @@ fn emulate_foreign_item_by_name( // Obtains a Miri backtrace. See the README for details. "miri_get_backtrace" => { - check_abi(abi, Abi::Rust)?; + check_abi(this, abi, Abi::Rust)?; this.handle_miri_get_backtrace(args, dest)?; } // Resolves a Miri backtrace frame. See the README for details. "miri_resolve_frame" => { - check_abi(abi, Abi::Rust)?; + check_abi(this, abi, Abi::Rust)?; this.handle_miri_resolve_frame(args, dest)?; } // Standard C allocation "malloc" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref size] = check_arg_count(args)?; let size = this.read_scalar(size)?.to_machine_usize(this)?; let res = this.malloc(size, /*zero_init:*/ false, MiriMemoryKind::C); this.write_scalar(res, dest)?; } "calloc" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref items, ref len] = check_arg_count(args)?; let items = this.read_scalar(items)?.to_machine_usize(this)?; let len = this.read_scalar(len)?.to_machine_usize(this)?; @@ -263,13 +263,13 @@ fn emulate_foreign_item_by_name( this.write_scalar(res, dest)?; } "free" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref ptr] = check_arg_count(args)?; let ptr = this.read_scalar(ptr)?.check_init()?; this.free(ptr, MiriMemoryKind::C)?; } "realloc" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref old_ptr, ref new_size] = check_arg_count(args)?; let old_ptr = this.read_scalar(old_ptr)?.check_init()?; let new_size = this.read_scalar(new_size)?.to_machine_usize(this)?; @@ -281,7 +281,7 @@ fn emulate_foreign_item_by_name( // (Usually these would be forwarded to to `#[global_allocator]`; we instead implement a generic // allocation that also checks that all conditions are met, such as not permitting zero-sized allocations.) "__rust_alloc" => { - check_abi(abi, Abi::Rust)?; + check_abi(this, abi, Abi::Rust)?; let &[ref size, ref align] = check_arg_count(args)?; let size = this.read_scalar(size)?.to_machine_usize(this)?; let align = this.read_scalar(align)?.to_machine_usize(this)?; @@ -294,7 +294,7 @@ fn emulate_foreign_item_by_name( this.write_scalar(ptr, dest)?; } "__rust_alloc_zeroed" => { - check_abi(abi, Abi::Rust)?; + check_abi(this, abi, Abi::Rust)?; let &[ref size, ref align] = check_arg_count(args)?; let size = this.read_scalar(size)?.to_machine_usize(this)?; let align = this.read_scalar(align)?.to_machine_usize(this)?; @@ -309,7 +309,7 @@ fn emulate_foreign_item_by_name( this.write_scalar(ptr, dest)?; } "__rust_dealloc" => { - check_abi(abi, Abi::Rust)?; + check_abi(this, abi, Abi::Rust)?; let &[ref ptr, ref old_size, ref align] = check_arg_count(args)?; let ptr = this.read_scalar(ptr)?.check_init()?; let old_size = this.read_scalar(old_size)?.to_machine_usize(this)?; @@ -323,7 +323,7 @@ fn emulate_foreign_item_by_name( )?; } "__rust_realloc" => { - check_abi(abi, Abi::Rust)?; + check_abi(this, abi, Abi::Rust)?; let &[ref ptr, ref old_size, ref align, ref new_size] = check_arg_count(args)?; let ptr = this.force_ptr(this.read_scalar(ptr)?.check_init()?)?; let old_size = this.read_scalar(old_size)?.to_machine_usize(this)?; @@ -344,7 +344,7 @@ fn emulate_foreign_item_by_name( // C memory handling functions "memcmp" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref left, ref right, ref n] = check_arg_count(args)?; let left = this.read_scalar(left)?.check_init()?; let right = this.read_scalar(right)?.check_init()?; @@ -365,7 +365,7 @@ fn emulate_foreign_item_by_name( this.write_scalar(Scalar::from_i32(result), dest)?; } "memrchr" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref ptr, ref val, ref num] = check_arg_count(args)?; let ptr = this.read_scalar(ptr)?.check_init()?; let val = this.read_scalar(val)?.to_i32()? as u8; @@ -384,7 +384,7 @@ fn emulate_foreign_item_by_name( } } "memchr" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref ptr, ref val, ref num] = check_arg_count(args)?; let ptr = this.read_scalar(ptr)?.check_init()?; let val = this.read_scalar(val)?.to_i32()? as u8; @@ -402,7 +402,7 @@ fn emulate_foreign_item_by_name( } } "strlen" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref ptr] = check_arg_count(args)?; let ptr = this.read_scalar(ptr)?.check_init()?; let n = this.read_c_str(ptr)?.len(); @@ -419,7 +419,7 @@ fn emulate_foreign_item_by_name( | "asinf" | "atanf" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref f] = check_arg_count(args)?; // FIXME: Using host floats. let f = f32::from_bits(this.read_scalar(f)?.to_u32()?); @@ -440,7 +440,7 @@ fn emulate_foreign_item_by_name( | "hypotf" | "atan2f" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref f1, ref f2] = check_arg_count(args)?; // underscore case for windows, here and below // (see https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/floating-point-primitives?view=vs-2019) @@ -463,7 +463,7 @@ fn emulate_foreign_item_by_name( | "asin" | "atan" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref f] = check_arg_count(args)?; // FIXME: Using host floats. let f = f64::from_bits(this.read_scalar(f)?.to_u64()?); @@ -484,7 +484,7 @@ fn emulate_foreign_item_by_name( | "hypot" | "atan2" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref f1, ref f2] = check_arg_count(args)?; // FIXME: Using host floats. let f1 = f64::from_bits(this.read_scalar(f1)?.to_u64()?); @@ -501,7 +501,7 @@ fn emulate_foreign_item_by_name( | "ldexp" | "scalbn" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref x, ref exp] = check_arg_count(args)?; // For radix-2 (binary) systems, `ldexp` and `scalbn` are the same. let x = this.read_scalar(x)?.to_f64()?; @@ -523,12 +523,12 @@ fn emulate_foreign_item_by_name( // Architecture-specific shims "llvm.x86.sse2.pause" if this.tcx.sess.target.arch == "x86" || this.tcx.sess.target.arch == "x86_64" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[] = check_arg_count(args)?; this.yield_active_thread(); } "llvm.aarch64.isb" if this.tcx.sess.target.arch == "aarch64" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref arg] = check_arg_count(args)?; let arg = this.read_scalar(arg)?.to_i32()?; match arg { diff --git a/src/shims/posix/dlsym.rs b/src/shims/posix/dlsym.rs index df9e945f29f..5f420ac5363 100644 --- a/src/shims/posix/dlsym.rs +++ b/src/shims/posix/dlsym.rs @@ -35,7 +35,7 @@ fn call_dlsym( ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; match dlsym { Dlsym::Linux(dlsym) => linux::EvalContextExt::call_dlsym(this, dlsym, args, ret), diff --git a/src/shims/posix/foreign_items.rs b/src/shims/posix/foreign_items.rs index 52b41b49bd5..5eb731d09c8 100644 --- a/src/shims/posix/foreign_items.rs +++ b/src/shims/posix/foreign_items.rs @@ -25,32 +25,32 @@ fn emulate_foreign_item_by_name( match link_name { // Environment related shims "getenv" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref name] = check_arg_count(args)?; let result = this.getenv(name)?; this.write_scalar(result, dest)?; } "unsetenv" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref name] = check_arg_count(args)?; let result = this.unsetenv(name)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "setenv" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref name, ref value, ref overwrite] = check_arg_count(args)?; this.read_scalar(overwrite)?.to_i32()?; let result = this.setenv(name, value)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "getcwd" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref buf, ref size] = check_arg_count(args)?; let result = this.getcwd(buf, size)?; this.write_scalar(result, dest)?; } "chdir" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref path] = check_arg_count(args)?; let result = this.chdir(path)?; this.write_scalar(Scalar::from_i32(result), dest)?; @@ -58,18 +58,18 @@ fn emulate_foreign_item_by_name( // File related shims "open" | "open64" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref path, ref flag, ref mode] = check_arg_count(args)?; let result = this.open(path, flag, mode)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "fcntl" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let result = this.fcntl(args)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "read" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref fd, ref buf, ref count] = check_arg_count(args)?; let fd = this.read_scalar(fd)?.to_i32()?; let buf = this.read_scalar(buf)?.check_init()?; @@ -78,7 +78,7 @@ fn emulate_foreign_item_by_name( this.write_scalar(Scalar::from_machine_isize(result, this), dest)?; } "write" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref fd, ref buf, ref n] = check_arg_count(args)?; let fd = this.read_scalar(fd)?.to_i32()?; let buf = this.read_scalar(buf)?.check_init()?; @@ -89,62 +89,62 @@ fn emulate_foreign_item_by_name( this.write_scalar(Scalar::from_machine_isize(result, this), dest)?; } "unlink" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref path] = check_arg_count(args)?; let result = this.unlink(path)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "symlink" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref target, ref linkpath] = check_arg_count(args)?; let result = this.symlink(target, linkpath)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "rename" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref oldpath, ref newpath] = check_arg_count(args)?; let result = this.rename(oldpath, newpath)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "mkdir" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref path, ref mode] = check_arg_count(args)?; let result = this.mkdir(path, mode)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "rmdir" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref path] = check_arg_count(args)?; let result = this.rmdir(path)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "closedir" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref dirp] = check_arg_count(args)?; let result = this.closedir(dirp)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "lseek" | "lseek64" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref fd, ref offset, ref whence] = check_arg_count(args)?; let result = this.lseek64(fd, offset, whence)?; // "lseek" is only used on macOS which is 64bit-only, so `i64` always works. this.write_scalar(Scalar::from_i64(result), dest)?; } "fsync" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref fd] = check_arg_count(args)?; let result = this.fsync(fd)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "fdatasync" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref fd] = check_arg_count(args)?; let result = this.fdatasync(fd)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "readlink" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref pathname, ref buf, ref bufsize] = check_arg_count(args)?; let result = this.readlink(pathname, buf, bufsize)?; this.write_scalar(Scalar::from_machine_isize(result, this), dest)?; @@ -152,7 +152,7 @@ fn emulate_foreign_item_by_name( // Allocation "posix_memalign" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref ret, ref align, ref size] = check_arg_count(args)?; let ret = this.deref_operand(ret)?; let align = this.read_scalar(align)?.to_machine_usize(this)?; @@ -183,7 +183,7 @@ fn emulate_foreign_item_by_name( // Dynamic symbol loading "dlsym" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref handle, ref symbol] = check_arg_count(args)?; this.read_scalar(handle)?.to_machine_usize(this)?; let symbol = this.read_scalar(symbol)?.check_init()?; @@ -198,7 +198,7 @@ fn emulate_foreign_item_by_name( // Querying system information "sysconf" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref name] = check_arg_count(args)?; let name = this.read_scalar(name)?.to_i32()?; @@ -224,7 +224,7 @@ fn emulate_foreign_item_by_name( // Thread-local storage "pthread_key_create" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref key, ref dtor] = check_arg_count(args)?; let key_place = this.deref_operand(key)?; let dtor = this.read_scalar(dtor)?.check_init()?; @@ -253,7 +253,7 @@ fn emulate_foreign_item_by_name( this.write_null(dest)?; } "pthread_key_delete" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref key] = check_arg_count(args)?; let key = this.force_bits(this.read_scalar(key)?.check_init()?, key.layout.size)?; this.machine.tls.delete_tls_key(key)?; @@ -261,7 +261,7 @@ fn emulate_foreign_item_by_name( this.write_null(dest)?; } "pthread_getspecific" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref key] = check_arg_count(args)?; let key = this.force_bits(this.read_scalar(key)?.check_init()?, key.layout.size)?; let active_thread = this.get_active_thread(); @@ -269,7 +269,7 @@ fn emulate_foreign_item_by_name( this.write_scalar(ptr, dest)?; } "pthread_setspecific" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref key, ref new_ptr] = check_arg_count(args)?; let key = this.force_bits(this.read_scalar(key)?.check_init()?, key.layout.size)?; let active_thread = this.get_active_thread(); @@ -282,132 +282,132 @@ fn emulate_foreign_item_by_name( // Synchronization primitives "pthread_mutexattr_init" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref attr] = check_arg_count(args)?; let result = this.pthread_mutexattr_init(attr)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_mutexattr_settype" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref attr, ref kind] = check_arg_count(args)?; let result = this.pthread_mutexattr_settype(attr, kind)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_mutexattr_destroy" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref attr] = check_arg_count(args)?; let result = this.pthread_mutexattr_destroy(attr)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_mutex_init" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref mutex, ref attr] = check_arg_count(args)?; let result = this.pthread_mutex_init(mutex, attr)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_mutex_lock" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref mutex] = check_arg_count(args)?; let result = this.pthread_mutex_lock(mutex)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_mutex_trylock" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref mutex] = check_arg_count(args)?; let result = this.pthread_mutex_trylock(mutex)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_mutex_unlock" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref mutex] = check_arg_count(args)?; let result = this.pthread_mutex_unlock(mutex)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_mutex_destroy" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref mutex] = check_arg_count(args)?; let result = this.pthread_mutex_destroy(mutex)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_rwlock_rdlock" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref rwlock] = check_arg_count(args)?; let result = this.pthread_rwlock_rdlock(rwlock)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_rwlock_tryrdlock" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref rwlock] = check_arg_count(args)?; let result = this.pthread_rwlock_tryrdlock(rwlock)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_rwlock_wrlock" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref rwlock] = check_arg_count(args)?; let result = this.pthread_rwlock_wrlock(rwlock)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_rwlock_trywrlock" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref rwlock] = check_arg_count(args)?; let result = this.pthread_rwlock_trywrlock(rwlock)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_rwlock_unlock" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref rwlock] = check_arg_count(args)?; let result = this.pthread_rwlock_unlock(rwlock)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_rwlock_destroy" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref rwlock] = check_arg_count(args)?; let result = this.pthread_rwlock_destroy(rwlock)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_condattr_init" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref attr] = check_arg_count(args)?; let result = this.pthread_condattr_init(attr)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_condattr_destroy" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref attr] = check_arg_count(args)?; let result = this.pthread_condattr_destroy(attr)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_cond_init" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref cond, ref attr] = check_arg_count(args)?; let result = this.pthread_cond_init(cond, attr)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_cond_signal" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref cond] = check_arg_count(args)?; let result = this.pthread_cond_signal(cond)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_cond_broadcast" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref cond] = check_arg_count(args)?; let result = this.pthread_cond_broadcast(cond)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_cond_wait" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref cond, ref mutex] = check_arg_count(args)?; let result = this.pthread_cond_wait(cond, mutex)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_cond_timedwait" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref cond, ref mutex, ref abstime] = check_arg_count(args)?; this.pthread_cond_timedwait(cond, mutex, abstime, dest)?; } "pthread_cond_destroy" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref cond] = check_arg_count(args)?; let result = this.pthread_cond_destroy(cond)?; this.write_scalar(Scalar::from_i32(result), dest)?; @@ -415,36 +415,36 @@ fn emulate_foreign_item_by_name( // Threading "pthread_create" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref thread, ref attr, ref start, ref arg] = check_arg_count(args)?; let result = this.pthread_create(thread, attr, start, arg)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_join" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref thread, ref retval] = check_arg_count(args)?; let result = this.pthread_join(thread, retval)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_detach" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref thread] = check_arg_count(args)?; let result = this.pthread_detach(thread)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_self" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[] = check_arg_count(args)?; this.pthread_self(dest)?; } "sched_yield" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[] = check_arg_count(args)?; let result = this.sched_yield()?; this.write_scalar(Scalar::from_i32(result), dest)?; } "nanosleep" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref req, ref rem] = check_arg_count(args)?; let result = this.nanosleep(req, rem)?; this.write_scalar(Scalar::from_i32(result), dest)?; @@ -452,7 +452,7 @@ fn emulate_foreign_item_by_name( // Miscellaneous "isatty" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref fd] = check_arg_count(args)?; this.read_scalar(fd)?.to_i32()?; // "returns 1 if fd is an open file descriptor referring to a terminal; otherwise 0 is returned, and errno is set to indicate the error" @@ -462,7 +462,7 @@ fn emulate_foreign_item_by_name( this.write_null(dest)?; } "pthread_atfork" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref prepare, ref parent, ref child] = check_arg_count(args)?; this.force_bits(this.read_scalar(prepare)?.check_init()?, this.memory.pointer_size())?; this.force_bits(this.read_scalar(parent)?.check_init()?, this.memory.pointer_size())?; @@ -475,7 +475,7 @@ fn emulate_foreign_item_by_name( // These shims are enabled only when the caller is in the standard library. "pthread_attr_getguardsize" if this.frame().instance.to_string().starts_with("std::sys::unix::") => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref _attr, ref guard_size] = check_arg_count(args)?; let guard_size = this.deref_operand(guard_size)?; let guard_size_layout = this.libc_ty_layout("size_t")?; @@ -488,13 +488,13 @@ fn emulate_foreign_item_by_name( | "pthread_attr_init" | "pthread_attr_destroy" if this.frame().instance.to_string().starts_with("std::sys::unix::") => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[_] = check_arg_count(args)?; this.write_null(dest)?; } | "pthread_attr_setstacksize" if this.frame().instance.to_string().starts_with("std::sys::unix::") => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[_, _] = check_arg_count(args)?; this.write_null(dest)?; } @@ -502,14 +502,14 @@ fn emulate_foreign_item_by_name( | "signal" | "sigaltstack" if this.frame().instance.to_string().starts_with("std::sys::unix::") => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[_, _] = check_arg_count(args)?; this.write_null(dest)?; } | "sigaction" | "mprotect" if this.frame().instance.to_string().starts_with("std::sys::unix::") => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[_, _, _] = check_arg_count(args)?; this.write_null(dest)?; } diff --git a/src/shims/posix/linux/foreign_items.rs b/src/shims/posix/linux/foreign_items.rs index f7d7706e3f5..d16c740ffc5 100644 --- a/src/shims/posix/linux/foreign_items.rs +++ b/src/shims/posix/linux/foreign_items.rs @@ -23,7 +23,7 @@ fn emulate_foreign_item_by_name( match link_name { // errno "__errno_location" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[] = check_arg_count(args)?; let errno_place = this.last_error_place()?; this.write_scalar(errno_place.to_ref().to_scalar()?, dest)?; @@ -33,32 +33,32 @@ fn emulate_foreign_item_by_name( // These symbols have different names on Linux and macOS, which is the only reason they are not // in the `posix` module. "close" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref fd] = check_arg_count(args)?; let result = this.close(fd)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "opendir" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref name] = check_arg_count(args)?; let result = this.opendir(name)?; this.write_scalar(result, dest)?; } "readdir64_r" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref dirp, ref entry, ref result] = check_arg_count(args)?; let result = this.linux_readdir64_r(dirp, entry, result)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "ftruncate64" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref fd, ref length] = check_arg_count(args)?; let result = this.ftruncate64(fd, length)?; this.write_scalar(Scalar::from_i32(result), dest)?; } // Linux-only "posix_fadvise" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref fd, ref offset, ref len, ref advice] = check_arg_count(args)?; this.read_scalar(fd)?.to_i32()?; this.read_scalar(offset)?.to_machine_isize(this)?; @@ -68,7 +68,7 @@ fn emulate_foreign_item_by_name( this.write_null(dest)?; } "sync_file_range" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref fd, ref offset, ref nbytes, ref flags] = check_arg_count(args)?; let result = this.sync_file_range(fd, offset, nbytes, flags)?; this.write_scalar(Scalar::from_i32(result), dest)?; @@ -76,7 +76,7 @@ fn emulate_foreign_item_by_name( // Time related shims "clock_gettime" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; // This is a POSIX function but it has only been tested on linux. let &[ref clk_id, ref tp] = check_arg_count(args)?; let result = this.clock_gettime(clk_id, tp)?; @@ -85,7 +85,7 @@ fn emulate_foreign_item_by_name( // Querying system information "pthread_attr_getstack" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; // We don't support "pthread_attr_setstack", so we just pretend all stacks have the same values here. let &[ref attr_place, ref addr_place, ref size_place] = check_arg_count(args)?; this.deref_operand(attr_place)?; @@ -107,19 +107,19 @@ fn emulate_foreign_item_by_name( // Threading "prctl" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref option, ref arg2, ref arg3, ref arg4, ref arg5] = check_arg_count(args)?; let result = this.prctl(option, arg2, arg3, arg4, arg5)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_condattr_setclock" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref attr, ref clock_id] = check_arg_count(args)?; let result = this.pthread_condattr_setclock(attr, clock_id)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_condattr_getclock" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref attr, ref clock_id] = check_arg_count(args)?; let result = this.pthread_condattr_getclock(attr, clock_id)?; this.write_scalar(Scalar::from_i32(result), dest)?; @@ -127,7 +127,7 @@ fn emulate_foreign_item_by_name( // Dynamically invoked syscalls "syscall" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; // The syscall variadic function is legal to call with more arguments than needed, // extra arguments are simply ignored. However, all arguments need to be scalars; // other types might be treated differently by the calling convention. @@ -188,12 +188,12 @@ fn emulate_foreign_item_by_name( // Miscelanneous "getrandom" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref ptr, ref len, ref flags] = check_arg_count(args)?; getrandom(this, ptr, len, flags, dest)?; } "sched_getaffinity" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref pid, ref cpusetsize, ref mask] = check_arg_count(args)?; this.read_scalar(pid)?.to_i32()?; this.read_scalar(cpusetsize)?.to_machine_usize(this)?; @@ -209,7 +209,7 @@ fn emulate_foreign_item_by_name( "pthread_getattr_np" if this.frame().instance.to_string().starts_with("std::sys::unix::") => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref _thread, ref _attr] = check_arg_count(args)?; this.write_null(dest)?; } diff --git a/src/shims/posix/macos/foreign_items.rs b/src/shims/posix/macos/foreign_items.rs index 9a7d3be1eb9..de4ed56633c 100644 --- a/src/shims/posix/macos/foreign_items.rs +++ b/src/shims/posix/macos/foreign_items.rs @@ -21,7 +21,7 @@ fn emulate_foreign_item_by_name( match link_name { // errno "__error" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[] = check_arg_count(args)?; let errno_place = this.last_error_place()?; this.write_scalar(errno_place.to_ref().to_scalar()?, dest)?; @@ -29,43 +29,43 @@ fn emulate_foreign_item_by_name( // File related shims "close" | "close$NOCANCEL" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref result] = check_arg_count(args)?; let result = this.close(result)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "stat" | "stat$INODE64" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref path, ref buf] = check_arg_count(args)?; let result = this.macos_stat(path, buf)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "lstat" | "lstat$INODE64" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref path, ref buf] = check_arg_count(args)?; let result = this.macos_lstat(path, buf)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "fstat" | "fstat$INODE64" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref fd, ref buf] = check_arg_count(args)?; let result = this.macos_fstat(fd, buf)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "opendir" | "opendir$INODE64" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref name] = check_arg_count(args)?; let result = this.opendir(name)?; this.write_scalar(result, dest)?; } "readdir_r" | "readdir_r$INODE64" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref dirp, ref entry, ref result] = check_arg_count(args)?; let result = this.macos_readdir_r(dirp, entry, result)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "ftruncate" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref fd, ref length] = check_arg_count(args)?; let result = this.ftruncate64(fd, length)?; this.write_scalar(Scalar::from_i32(result), dest)?; @@ -73,27 +73,27 @@ fn emulate_foreign_item_by_name( // Environment related shims "_NSGetEnviron" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[] = check_arg_count(args)?; this.write_scalar(this.machine.env_vars.environ.unwrap().ptr, dest)?; } // Time related shims "gettimeofday" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref tv, ref tz] = check_arg_count(args)?; let result = this.gettimeofday(tv, tz)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "mach_absolute_time" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[] = check_arg_count(args)?; let result = this.mach_absolute_time()?; this.write_scalar(Scalar::from_u64(result), dest)?; } "mach_timebase_info" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref info] = check_arg_count(args)?; let result = this.mach_timebase_info(info)?; this.write_scalar(Scalar::from_i32(result), dest)?; @@ -101,19 +101,19 @@ fn emulate_foreign_item_by_name( // Access to command-line arguments "_NSGetArgc" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[] = check_arg_count(args)?; this.write_scalar(this.machine.argc.expect("machine must be initialized"), dest)?; } "_NSGetArgv" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[] = check_arg_count(args)?; this.write_scalar(this.machine.argv.expect("machine must be initialized"), dest)?; } // Thread-local storage "_tlv_atexit" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref dtor, ref data] = check_arg_count(args)?; let dtor = this.read_scalar(dtor)?.check_init()?; let dtor = this.memory.get_fn(dtor)?.as_instance()?; @@ -124,14 +124,14 @@ fn emulate_foreign_item_by_name( // Querying system information "pthread_get_stackaddr_np" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref thread] = check_arg_count(args)?; this.read_scalar(thread)?.to_machine_usize(this)?; let stack_addr = Scalar::from_uint(STACK_ADDR, this.pointer_size()); this.write_scalar(stack_addr, dest)?; } "pthread_get_stacksize_np" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref thread] = check_arg_count(args)?; this.read_scalar(thread)?.to_machine_usize(this)?; let stack_size = Scalar::from_uint(STACK_SIZE, this.pointer_size()); @@ -140,7 +140,7 @@ fn emulate_foreign_item_by_name( // Threading "pthread_setname_np" => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; let &[ref name] = check_arg_count(args)?; let name = this.read_scalar(name)?.check_init()?; this.pthread_setname_np(name)?; @@ -149,7 +149,7 @@ fn emulate_foreign_item_by_name( // 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. "mmap" if this.frame().instance.to_string().starts_with("std::sys::unix::") => { - check_abi(abi, Abi::C { unwind: false })?; + check_abi(this, abi, Abi::C { unwind: false })?; // This is a horrible hack, but since the guard page mechanism calls mmap and expects a particular return value, we just give it that value. let &[ref addr, _, _, _, _, _] = check_arg_count(args)?; let addr = this.read_scalar(addr)?.check_init()?; diff --git a/src/shims/windows/dlsym.rs b/src/shims/windows/dlsym.rs index ace6c4674ae..18e2ed3db59 100644 --- a/src/shims/windows/dlsym.rs +++ b/src/shims/windows/dlsym.rs @@ -31,7 +31,7 @@ fn call_dlsym( let (_dest, _ret) = ret.expect("we don't support any diverging dlsym"); assert!(this.tcx.sess.target.os == "windows"); - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; match dlsym {} } diff --git a/src/shims/windows/foreign_items.rs b/src/shims/windows/foreign_items.rs index b246ccc33cf..d7b86fff732 100644 --- a/src/shims/windows/foreign_items.rs +++ b/src/shims/windows/foreign_items.rs @@ -28,37 +28,37 @@ fn emulate_foreign_item_by_name( match link_name { // Environment related shims "GetEnvironmentVariableW" => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; let &[ref name, ref buf, ref size] = check_arg_count(args)?; let result = this.GetEnvironmentVariableW(name, buf, size)?; this.write_scalar(Scalar::from_u32(result), dest)?; } "SetEnvironmentVariableW" => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; let &[ref name, ref value] = check_arg_count(args)?; let result = this.SetEnvironmentVariableW(name, value)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "GetEnvironmentStringsW" => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; let &[] = check_arg_count(args)?; let result = this.GetEnvironmentStringsW()?; this.write_scalar(result, dest)?; } "FreeEnvironmentStringsW" => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; let &[ref env_block] = check_arg_count(args)?; let result = this.FreeEnvironmentStringsW(env_block)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "GetCurrentDirectoryW" => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; let &[ref size, ref buf] = check_arg_count(args)?; let result = this.GetCurrentDirectoryW(size, buf)?; this.write_scalar(Scalar::from_u32(result), dest)?; } "SetCurrentDirectoryW" => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; let &[ref path] = check_arg_count(args)?; let result = this.SetCurrentDirectoryW(path)?; this.write_scalar(Scalar::from_i32(result), dest)?; @@ -66,7 +66,7 @@ fn emulate_foreign_item_by_name( // File related shims "GetStdHandle" => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; let &[ref which] = check_arg_count(args)?; let which = this.read_scalar(which)?.to_i32()?; // We just make this the identity function, so we know later in `WriteFile` @@ -74,7 +74,7 @@ fn emulate_foreign_item_by_name( this.write_scalar(Scalar::from_machine_isize(which.into(), this), dest)?; } "WriteFile" => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; let &[ref handle, ref buf, ref n, ref written_ptr, ref overlapped] = check_arg_count(args)?; this.read_scalar(overlapped)?.to_machine_usize(this)?; // this is a poiner, that we ignore @@ -110,7 +110,7 @@ fn emulate_foreign_item_by_name( // Allocation "HeapAlloc" => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; let &[ref handle, ref flags, ref size] = check_arg_count(args)?; this.read_scalar(handle)?.to_machine_isize(this)?; let flags = this.read_scalar(flags)?.to_u32()?; @@ -120,7 +120,7 @@ fn emulate_foreign_item_by_name( this.write_scalar(res, dest)?; } "HeapFree" => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; let &[ref handle, ref flags, ref ptr] = check_arg_count(args)?; this.read_scalar(handle)?.to_machine_isize(this)?; this.read_scalar(flags)?.to_u32()?; @@ -129,7 +129,7 @@ fn emulate_foreign_item_by_name( this.write_scalar(Scalar::from_i32(1), dest)?; } "HeapReAlloc" => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; let &[ref handle, ref flags, ref ptr, ref size] = check_arg_count(args)?; this.read_scalar(handle)?.to_machine_isize(this)?; this.read_scalar(flags)?.to_u32()?; @@ -141,13 +141,13 @@ fn emulate_foreign_item_by_name( // errno "SetLastError" => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; let &[ref error] = check_arg_count(args)?; let error = this.read_scalar(error)?.check_init()?; this.set_last_error(error)?; } "GetLastError" => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; let &[] = check_arg_count(args)?; let last_error = this.get_last_error()?; this.write_scalar(last_error, dest)?; @@ -155,7 +155,7 @@ fn emulate_foreign_item_by_name( // Querying system information "GetSystemInfo" => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; let &[ref system_info] = check_arg_count(args)?; let system_info = this.deref_operand(system_info)?; // Initialize with `0`. @@ -171,7 +171,7 @@ fn emulate_foreign_item_by_name( // Thread-local storage "TlsAlloc" => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; // This just creates a key; Windows does not natively support TLS destructors. // Create key and return it. @@ -180,7 +180,7 @@ fn emulate_foreign_item_by_name( this.write_scalar(Scalar::from_uint(key, dest.layout.size), dest)?; } "TlsGetValue" => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; let &[ref key] = check_arg_count(args)?; let key = u128::from(this.read_scalar(key)?.to_u32()?); let active_thread = this.get_active_thread(); @@ -188,7 +188,7 @@ fn emulate_foreign_item_by_name( this.write_scalar(ptr, dest)?; } "TlsSetValue" => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; let &[ref key, ref new_ptr] = check_arg_count(args)?; let key = u128::from(this.read_scalar(key)?.to_u32()?); let active_thread = this.get_active_thread(); @@ -201,7 +201,7 @@ fn emulate_foreign_item_by_name( // Access to command-line arguments "GetCommandLineW" => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; let &[] = check_arg_count(args)?; this.write_scalar( this.machine.cmd_line.expect("machine must be initialized"), @@ -211,20 +211,20 @@ fn emulate_foreign_item_by_name( // Time related shims "GetSystemTimeAsFileTime" => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; #[allow(non_snake_case)] let &[ref LPFILETIME] = check_arg_count(args)?; this.GetSystemTimeAsFileTime(LPFILETIME)?; } "QueryPerformanceCounter" => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; #[allow(non_snake_case)] let &[ref lpPerformanceCount] = check_arg_count(args)?; let result = this.QueryPerformanceCounter(lpPerformanceCount)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "QueryPerformanceFrequency" => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; #[allow(non_snake_case)] let &[ref lpFrequency] = check_arg_count(args)?; let result = this.QueryPerformanceFrequency(lpFrequency)?; @@ -233,33 +233,33 @@ fn emulate_foreign_item_by_name( // Synchronization primitives "AcquireSRWLockExclusive" => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; let &[ref ptr] = check_arg_count(args)?; this.AcquireSRWLockExclusive(ptr)?; } "ReleaseSRWLockExclusive" => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; let &[ref ptr] = check_arg_count(args)?; this.ReleaseSRWLockExclusive(ptr)?; } "TryAcquireSRWLockExclusive" => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; let &[ref ptr] = check_arg_count(args)?; let ret = this.TryAcquireSRWLockExclusive(ptr)?; this.write_scalar(Scalar::from_u8(ret), dest)?; } "AcquireSRWLockShared" => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; let &[ref ptr] = check_arg_count(args)?; this.AcquireSRWLockShared(ptr)?; } "ReleaseSRWLockShared" => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; let &[ref ptr] = check_arg_count(args)?; this.ReleaseSRWLockShared(ptr)?; } "TryAcquireSRWLockShared" => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; let &[ref ptr] = check_arg_count(args)?; let ret = this.TryAcquireSRWLockShared(ptr)?; this.write_scalar(Scalar::from_u8(ret), dest)?; @@ -267,7 +267,7 @@ fn emulate_foreign_item_by_name( // Dynamic symbol loading "GetProcAddress" => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; #[allow(non_snake_case)] let &[ref hModule, ref lpProcName] = check_arg_count(args)?; this.read_scalar(hModule)?.to_machine_isize(this)?; @@ -283,7 +283,7 @@ fn emulate_foreign_item_by_name( // Miscellaneous "SystemFunction036" => { // This is really 'RtlGenRandom'. - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; let &[ref ptr, ref len] = check_arg_count(args)?; let ptr = this.read_scalar(ptr)?.check_init()?; let len = this.read_scalar(len)?.to_u32()?; @@ -291,7 +291,7 @@ fn emulate_foreign_item_by_name( this.write_scalar(Scalar::from_bool(true), dest)?; } "BCryptGenRandom" => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; let &[ref algorithm, ref ptr, ref len, ref flags] = check_arg_count(args)?; let algorithm = this.read_scalar(algorithm)?; let ptr = this.read_scalar(ptr)?.check_init()?; @@ -312,7 +312,7 @@ fn emulate_foreign_item_by_name( this.write_null(dest)?; // STATUS_SUCCESS } "GetConsoleScreenBufferInfo" => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; // `term` needs this, so we fake it. let &[ref console, ref buffer_info] = check_arg_count(args)?; this.read_scalar(console)?.to_machine_isize(this)?; @@ -322,7 +322,7 @@ fn emulate_foreign_item_by_name( this.write_null(dest)?; } "GetConsoleMode" => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; // Windows "isatty" (in libtest) needs this, so we fake it. let &[ref console, ref mode] = check_arg_count(args)?; this.read_scalar(console)?.to_machine_isize(this)?; @@ -332,7 +332,7 @@ fn emulate_foreign_item_by_name( this.write_null(dest)?; } "SwitchToThread" => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; let &[] = check_arg_count(args)?; // Note that once Miri supports concurrency, this will need to return a nonzero // value if this call does result in switching to another thread. @@ -341,7 +341,7 @@ fn emulate_foreign_item_by_name( // Better error for attempts to create a thread "CreateThread" => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; throw_unsup_format!("Miri does not support concurrency on Windows"); } @@ -350,7 +350,7 @@ fn emulate_foreign_item_by_name( "GetProcessHeap" if this.frame().instance.to_string().starts_with("std::sys::windows::") => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; let &[] = check_arg_count(args)?; // Just fake a HANDLE this.write_scalar(Scalar::from_machine_isize(1, this), dest)?; @@ -358,7 +358,7 @@ fn emulate_foreign_item_by_name( "SetConsoleTextAttribute" if this.frame().instance.to_string().starts_with("std::sys::windows::") => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; #[allow(non_snake_case)] let &[ref _hConsoleOutput, ref _wAttribute] = check_arg_count(args)?; // Pretend these does not exist / nothing happened, by returning zero. @@ -367,7 +367,7 @@ fn emulate_foreign_item_by_name( "AddVectoredExceptionHandler" if this.frame().instance.to_string().starts_with("std::sys::windows::") => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; #[allow(non_snake_case)] let &[ref _First, ref _Handler] = check_arg_count(args)?; // Any non zero value works for the stdlib. This is just used for stack overflows anyway. @@ -376,7 +376,7 @@ fn emulate_foreign_item_by_name( "SetThreadStackGuarantee" if this.frame().instance.to_string().starts_with("std::sys::windows::") => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; #[allow(non_snake_case)] let &[_StackSizeInBytes] = check_arg_count(args)?; // Any non zero value works for the stdlib. This is just used for stack overflows anyway. @@ -388,7 +388,7 @@ fn emulate_foreign_item_by_name( | "DeleteCriticalSection" if this.frame().instance.to_string().starts_with("std::sys::windows::") => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; #[allow(non_snake_case)] let &[ref _lpCriticalSection] = check_arg_count(args)?; assert_eq!( @@ -403,7 +403,7 @@ fn emulate_foreign_item_by_name( "TryEnterCriticalSection" if this.frame().instance.to_string().starts_with("std::sys::windows::") => { - check_abi(abi, Abi::System { unwind: false })?; + check_abi(this, abi, Abi::System { unwind: false })?; #[allow(non_snake_case)] let &[ref _lpCriticalSection] = check_arg_count(args)?; assert_eq!( diff --git a/tests/compile-fail/check_callback_abi.rs b/tests/compile-fail/check_callback_abi.rs new file mode 100644 index 00000000000..69dfc035983 --- /dev/null +++ b/tests/compile-fail/check_callback_abi.rs @@ -0,0 +1,15 @@ +#![feature(core_intrinsics)] + +extern "C" fn try_fn(_: *mut u8) { + unreachable!(); +} + +fn main() { + unsafe { + std::intrinsics::r#try( //~ ERROR calling a function with ABI C using caller ABI Rust + std::mem::transmute::(try_fn), + std::ptr::null_mut(), + |_, _| unreachable!(), + ); + } +} diff --git a/tests/compile-fail/concurrency/unwind_top_of_stack.rs b/tests/compile-fail/concurrency/unwind_top_of_stack.rs index 8f3bb17470b..138a43d9d73 100644 --- a/tests/compile-fail/concurrency/unwind_top_of_stack.rs +++ b/tests/compile-fail/concurrency/unwind_top_of_stack.rs @@ -1,10 +1,8 @@ // ignore-windows: Concurrency on Windows is not supported yet. -// error-pattern: calling a function with ABI C-unwind using caller ABI C +// compile-flags: -Zmiri-disable-abi-check +// error-pattern: unwinding past the topmost frame of the stack //! Unwinding past the top frame of a stack is Undefined Behavior. -//! However, it is impossible to do that in pure Rust since one cannot write an unwinding -//! function with `C` ABI... so let's instead test that we are indeed correctly checking -//! the callee ABI in `pthread_create`. #![feature(rustc_private, c_unwind)] diff --git a/tests/compile-fail/panic/bad_unwind.rs b/tests/compile-fail/panic/bad_unwind.rs index fde2c19af07..cfb109cb8b5 100644 --- a/tests/compile-fail/panic/bad_unwind.rs +++ b/tests/compile-fail/panic/bad_unwind.rs @@ -4,6 +4,8 @@ //! Unwinding when the caller ABI is "C" (without "-unwind") is UB. //! Currently we detect the ABI mismatch; we could probably allow such calls in principle one day //! but then we have to detect the unexpected unwinding. +//! FIXME: `-Zmiri-disable-abi-check` does not work for this test because function pointers are +//! always allowed to unwind. extern "C-unwind" fn unwind() { panic!(); diff --git a/tests/run-pass/disable_abi_check.rs b/tests/run-pass/disable_abi_check.rs new file mode 100644 index 00000000000..1f855474137 --- /dev/null +++ b/tests/run-pass/disable_abi_check.rs @@ -0,0 +1,24 @@ +// compile-flags: -Zmiri-disable-abi-check +#![feature(core_intrinsics)] + +fn main() { + fn foo() {} + + extern "C" fn try_fn(ptr: *mut u8) { + assert!(ptr.is_null()); + } + + extern "Rust" { + fn malloc(size: usize) -> *mut std::ffi::c_void; + } + + unsafe { + let _ = malloc(0); + std::mem::transmute::(foo)(); + std::intrinsics::r#try( + std::mem::transmute::(try_fn), + std::ptr::null_mut(), + |_, _| unreachable!(), + ); + } +} -- 2.44.0