From 6d314f3b11f50db58974746c1c68234c26259ca8 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 16 May 2024 10:43:38 +0200 Subject: [PATCH] alloc now works on wasi (and some formatting) --- src/tools/miri/ci/ci.sh | 15 ++++---- src/tools/miri/src/machine.rs | 15 ++++---- src/tools/miri/src/shims/alloc.rs | 26 ++++++++++++++ src/tools/miri/src/shims/foreign_items.rs | 5 +++ src/tools/miri/src/shims/mod.rs | 11 +++--- .../miri/src/shims/unix/foreign_items.rs | 22 ++---------- .../miri/src/shims/wasi/foreign_items.rs | 34 +++++++++++++++++++ src/tools/miri/src/shims/wasi/mod.rs | 1 + .../miri/tests/pass-dep/libc/libc-mem.rs | 6 ++-- src/tools/miri/tests/pass/empty_main.rs | 3 ++ 10 files changed, 97 insertions(+), 41 deletions(-) create mode 100644 src/tools/miri/src/shims/wasi/foreign_items.rs create mode 100644 src/tools/miri/src/shims/wasi/mod.rs create mode 100644 src/tools/miri/tests/pass/empty_main.rs diff --git a/src/tools/miri/ci/ci.sh b/src/tools/miri/ci/ci.sh index 6292d1033b68e..2a6ca8f478311 100755 --- a/src/tools/miri/ci/ci.sh +++ b/src/tools/miri/ci/ci.sh @@ -144,16 +144,15 @@ case $HOST_TARGET in TEST_TARGET=arm-unknown-linux-gnueabi run_tests TEST_TARGET=s390x-unknown-linux-gnu run_tests # big-endian architecture of choice # Partially supported targets (tier 2) - VERY_BASIC="integer vec string btreemap" # common things we test on all of them (if they have std), requires no target-specific shims - BASIC="$VERY_BASIC hello hashmap alloc align" # ensures we have the shims for stdout and basic data structures + BASIC="empty_main integer vec string btreemap hello hashmap heap_alloc align" # ensures we have the basics: stdout/stderr, system allocator, randomness (for HashMap initialization) TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal $BASIC panic/panic concurrency/simple atomic threadname libc-mem libc-misc libc-random libc-time fs env num_cpus TEST_TARGET=i686-unknown-freebsd run_tests_minimal $BASIC panic/panic concurrency/simple atomic threadname libc-mem libc-misc libc-random libc-time fs env num_cpus - TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $BASIC hello panic/panic concurrency/simple pthread-sync libc-mem libc-misc libc-random env - TEST_TARGET=x86_64-pc-solaris run_tests_minimal $BASIC hello panic/panic concurrency/simple pthread-sync libc-mem libc-misc libc-random env - TEST_TARGET=aarch64-linux-android run_tests_minimal $VERY_BASIC hello panic/panic - TEST_TARGET=wasm32-wasi run_tests_minimal $VERY_BASIC wasm - TEST_TARGET=wasm32-unknown-unknown run_tests_minimal $VERY_BASIC wasm - TEST_TARGET=thumbv7em-none-eabihf run_tests_minimal no_std + TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $BASIC panic/panic concurrency/simple pthread-sync libc-mem libc-misc libc-random env + TEST_TARGET=x86_64-pc-solaris run_tests_minimal $BASIC panic/panic concurrency/simple pthread-sync libc-mem libc-misc libc-random env + TEST_TARGET=aarch64-linux-android run_tests_minimal empty_main hello panic/panic + TEST_TARGET=wasm32-wasi run_tests_minimal empty_main wasm heap_alloc libc-mem + TEST_TARGET=wasm32-unknown-unknown run_tests_minimal empty_main wasm + TEST_TARGET=thumbv7em-none-eabihf run_tests_minimal no_std # Custom target JSON file TEST_TARGET=tests/avr.json MIRI_NO_STD=1 run_tests_minimal no_std ;; diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 8854b18528034..6fdd126ff24ea 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -30,14 +30,13 @@ use rustc_target::abi::{Align, Size}; use rustc_target::spec::abi::Abi; use crate::{ - concurrency::{data_race, weak_memory}, - shims::unix, + concurrency::{ + data_race::{self, NaReadType, NaWriteType}, + weak_memory, + }, *, }; -use self::concurrency::data_race::NaReadType; -use self::concurrency::data_race::NaWriteType; - /// First real-time signal. /// `signal(7)` says this must be between 32 and 64 and specifies 34 or 35 /// as typical values. @@ -464,9 +463,9 @@ pub struct MiriMachine<'mir, 'tcx> { pub(crate) validate: bool, /// The table of file descriptors. - pub(crate) fds: unix::FdTable, + pub(crate) fds: shims::FdTable, /// The table of directory descriptors. - pub(crate) dirs: unix::DirTable, + pub(crate) dirs: shims::DirTable, /// This machine's monotone clock. pub(crate) clock: Clock, @@ -641,7 +640,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { tls: TlsData::default(), isolated_op: config.isolated_op, validate: config.validate, - fds: unix::FdTable::new(config.mute_stdout_stderr), + fds: shims::FdTable::new(config.mute_stdout_stderr), dirs: Default::default(), layouts, threads: ThreadManager::default(), diff --git a/src/tools/miri/src/shims/alloc.rs b/src/tools/miri/src/shims/alloc.rs index 1deb9a5654edf..d0f36bd4757c0 100644 --- a/src/tools/miri/src/shims/alloc.rs +++ b/src/tools/miri/src/shims/alloc.rs @@ -111,6 +111,32 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { Ok(ptr.into()) } + fn posix_memalign( + &mut self, + memptr: &OpTy<'tcx, Provenance>, + align: &OpTy<'tcx, Provenance>, + size: &OpTy<'tcx, Provenance>, + ) -> InterpResult<'tcx, Scalar> { + let this = self.eval_context_mut(); + let memptr = this.deref_pointer(memptr)?; + let align = this.read_target_usize(align)?; + let size = this.read_target_usize(size)?; + + // Align must be power of 2, and also at least ptr-sized (POSIX rules). + // But failure to adhere to this is not UB, it's an error condition. + if !align.is_power_of_two() || align < this.pointer_size().bytes() { + Ok(this.eval_libc("EINVAL")) + } else { + let ptr = this.allocate_ptr( + Size::from_bytes(size), + Align::from_bytes(align).unwrap(), + MiriMemoryKind::C.into(), + )?; + this.write_pointer(ptr, &memptr)?; + Ok(Scalar::from_i32(0)) + } + } + fn free(&mut self, ptr: Pointer>) -> InterpResult<'tcx> { let this = self.eval_context_mut(); if !this.ptr_is_null(ptr)? { diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index d431c28d55a56..a65da823e24cd 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -108,6 +108,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let this = self.eval_context_ref(); match this.tcx.sess.target.os.as_ref() { os if this.target_os_is_unix() => shims::unix::foreign_items::is_dyn_sym(name, os), + "wasi" => shims::wasi::foreign_items::is_dyn_sym(name), "windows" => shims::windows::foreign_items::is_dyn_sym(name), _ => false, } @@ -947,6 +948,10 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { shims::unix::foreign_items::EvalContextExt::emulate_foreign_item_inner( this, link_name, abi, args, dest, ), + "wasi" => + shims::wasi::foreign_items::EvalContextExt::emulate_foreign_item_inner( + this, link_name, abi, args, dest, + ), "windows" => shims::windows::foreign_items::EvalContextExt::emulate_foreign_item_inner( this, link_name, abi, args, dest, diff --git a/src/tools/miri/src/shims/mod.rs b/src/tools/miri/src/shims/mod.rs index aaa3c69b92da7..d9c4a2282c1fc 100644 --- a/src/tools/miri/src/shims/mod.rs +++ b/src/tools/miri/src/shims/mod.rs @@ -2,20 +2,23 @@ mod alloc; mod backtrace; -pub mod foreign_items; #[cfg(target_os = "linux")] -pub mod native_lib; -pub mod unix; -pub mod windows; +mod native_lib; +mod unix; +mod wasi; +mod windows; mod x86; pub mod env; pub mod extern_static; +pub mod foreign_items; pub mod os_str; pub mod panic; pub mod time; pub mod tls; +pub use unix::{DirTable, FdTable}; + /// What needs to be done after emulating an item (a shim or an intrinsic) is done. pub enum EmulateItemResult { /// The caller is expected to jump to the return block. diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index 5434951d9e40f..78d297d4b040b 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -3,7 +3,6 @@ use std::str; use rustc_middle::ty::layout::LayoutOf; use rustc_span::Symbol; -use rustc_target::abi::{Align, Size}; use rustc_target::spec::abi::Abi; use crate::shims::alloc::EvalContextExt as _; @@ -249,24 +248,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // Allocation "posix_memalign" => { - let [ret, align, size] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let ret = this.deref_pointer(ret)?; - let align = this.read_target_usize(align)?; - let size = this.read_target_usize(size)?; - // Align must be power of 2, and also at least ptr-sized (POSIX rules). - // But failure to adhere to this is not UB, it's an error condition. - if !align.is_power_of_two() || align < this.pointer_size().bytes() { - let einval = this.eval_libc_i32("EINVAL"); - this.write_int(einval, dest)?; - } else { - let ptr = this.allocate_ptr( - Size::from_bytes(size), - Align::from_bytes(align).unwrap(), - MiriMemoryKind::C.into(), - )?; - this.write_pointer(ptr, &ret)?; - this.write_null(dest)?; - } + let [memptr, align, size] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let result = this.posix_memalign(memptr, align, size)?; + this.write_scalar(result, dest)?; } "mmap" => { diff --git a/src/tools/miri/src/shims/wasi/foreign_items.rs b/src/tools/miri/src/shims/wasi/foreign_items.rs new file mode 100644 index 0000000000000..12bf0490932d8 --- /dev/null +++ b/src/tools/miri/src/shims/wasi/foreign_items.rs @@ -0,0 +1,34 @@ +use rustc_span::Symbol; +use rustc_target::spec::abi::Abi; + +use crate::shims::alloc::EvalContextExt as _; +use crate::*; + +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_inner( + &mut self, + link_name: Symbol, + abi: Abi, + args: &[OpTy<'tcx, Provenance>], + dest: &MPlaceTy<'tcx, Provenance>, + ) -> InterpResult<'tcx, EmulateItemResult> { + let this = self.eval_context_mut(); + match link_name.as_str() { + // Allocation + "posix_memalign" => { + let [memptr, align, size] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let result = this.posix_memalign(memptr, align, size)?; + this.write_scalar(result, dest)?; + } + + _ => return Ok(EmulateItemResult::NotSupported), + } + Ok(EmulateItemResult::NeedsJumping) + } +} diff --git a/src/tools/miri/src/shims/wasi/mod.rs b/src/tools/miri/src/shims/wasi/mod.rs new file mode 100644 index 0000000000000..09c6507b24f84 --- /dev/null +++ b/src/tools/miri/src/shims/wasi/mod.rs @@ -0,0 +1 @@ +pub mod foreign_items; diff --git a/src/tools/miri/tests/pass-dep/libc/libc-mem.rs b/src/tools/miri/tests/pass-dep/libc/libc-mem.rs index b36fb436b572d..5bd205dd085d1 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-mem.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-mem.rs @@ -226,7 +226,8 @@ fn test_memalign() { target_os = "windows", target_os = "macos", target_os = "illumos", - target_os = "solaris" + target_os = "solaris", + target_os = "wasi", )))] fn test_reallocarray() { unsafe { @@ -249,7 +250,8 @@ fn main() { target_os = "windows", target_os = "macos", target_os = "illumos", - target_os = "solaris" + target_os = "solaris", + target_os = "wasi", )))] test_reallocarray(); diff --git a/src/tools/miri/tests/pass/empty_main.rs b/src/tools/miri/tests/pass/empty_main.rs new file mode 100644 index 0000000000000..d081b6db6702a --- /dev/null +++ b/src/tools/miri/tests/pass/empty_main.rs @@ -0,0 +1,3 @@ +// This may look trivial, but a bunch of code runs in std before +// `main` is called, so we are ensuring that that all works. +fn main() {}