]> git.lizzy.rs Git - rust.git/commitdiff
handle unknown targets more gracefully
authorRalf Jung <post@ralfj.de>
Tue, 27 Dec 2022 22:27:16 +0000 (23:27 +0100)
committerRalf Jung <post@ralfj.de>
Wed, 28 Dec 2022 09:51:13 +0000 (10:51 +0100)
15 files changed:
src/tools/miri/src/shims/foreign_items.rs
src/tools/miri/src/shims/tls.rs
src/tools/miri/src/shims/unix/foreign_items.rs
src/tools/miri/tests/extern-so/fail/function_not_in_so.rs
src/tools/miri/tests/extern-so/fail/function_not_in_so.stderr
src/tools/miri/tests/fail/alloc/no_global_allocator.rs
src/tools/miri/tests/fail/alloc/no_global_allocator.stderr
src/tools/miri/tests/fail/unsupported_foreign_function.rs
src/tools/miri/tests/fail/unsupported_foreign_function.stderr
src/tools/miri/tests/fail/unsupported_incomplete_function.rs [new file with mode: 0644]
src/tools/miri/tests/fail/unsupported_incomplete_function.stderr [new file with mode: 0644]
src/tools/miri/tests/fail/unsupported_signal.rs [deleted file]
src/tools/miri/tests/fail/unsupported_signal.stderr [deleted file]
src/tools/miri/tests/panic/unsupported_foreign_function.rs
src/tools/miri/tests/panic/unsupported_foreign_function.stderr

index 4321bdf9aae67e5f18b4044d7f58e0a7acd797dd..c792a27ab4ca29b93f5a0d0ce9961a3589d696be 100644 (file)
@@ -47,7 +47,7 @@ fn min_align(&self, size: u64, kind: MiriMemoryKind) -> Align {
         let min_align = match this.tcx.sess.target.arch.as_ref() {
             "x86" | "arm" | "mips" | "powerpc" | "powerpc64" | "asmjs" | "wasm32" => 8,
             "x86_64" | "aarch64" | "mips64" | "s390x" | "sparc64" => 16,
-            arch => bug!("Unsupported target architecture: {}", arch),
+            arch => bug!("unsupported target architecture for malloc: `{}`", arch),
         };
         // Windows always aligns, even small allocations.
         // Source: <https://support.microsoft.com/en-us/help/286470/how-to-use-pageheap-exe-in-windows-xp-windows-2000-and-windows-server>
@@ -320,7 +320,10 @@ fn emulate_foreign_item(
                     return Ok(Some(body));
                 }
 
-                this.handle_unsupported(format!("can't call foreign function: {link_name}"))?;
+                this.handle_unsupported(format!(
+                    "can't call foreign function `{link_name}` on OS `{os}`",
+                    os = this.tcx.sess.target.os,
+                ))?;
                 return Ok(None);
             }
         }
@@ -336,9 +339,7 @@ fn emulate_allocator(
     ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> {
         let this = self.eval_context_mut();
 
-        let allocator_kind = if let Some(allocator_kind) = this.tcx.allocator_kind(()) {
-            allocator_kind
-        } else {
+        let Some(allocator_kind) = this.tcx.allocator_kind(()) else {
             // in real code, this symbol does not exist without an allocator
             return Ok(EmulateByNameResult::NotSupported);
         };
@@ -420,9 +421,9 @@ fn emulate_foreign_item_by_name(
                 let [ptr] = this.check_shim(abi, Abi::Rust, link_name, args)?;
                 let ptr = this.read_pointer(ptr)?;
                 let (alloc_id, _, _) = this.ptr_get_alloc_id(ptr).map_err(|_e| {
-                    err_machine_stop!(TerminationInfo::Abort(
-                        format!("pointer passed to miri_get_alloc_id must not be dangling, got {ptr:?}")
-                    ))
+                    err_machine_stop!(TerminationInfo::Abort(format!(
+                        "pointer passed to miri_get_alloc_id must not be dangling, got {ptr:?}"
+                    )))
                 })?;
                 this.write_scalar(Scalar::from_u64(alloc_id.0.get()), dest)?;
             }
@@ -438,7 +439,9 @@ fn emulate_foreign_item_by_name(
                 let ptr = this.read_pointer(ptr)?;
                 let (alloc_id, offset, _) = this.ptr_get_alloc_id(ptr)?;
                 if offset != Size::ZERO {
-                    throw_unsup_format!("pointer passed to miri_static_root must point to beginning of an allocated block");
+                    throw_unsup_format!(
+                        "pointer passed to miri_static_root must point to beginning of an allocated block"
+                    );
                 }
                 this.machine.static_roots.push(alloc_id);
             }
@@ -453,7 +456,8 @@ fn emulate_foreign_item_by_name(
 
                 // We read this as a plain OsStr and write it as a path, which will convert it to the target.
                 let path = this.read_os_str_from_c_str(ptr)?.to_owned();
-                let (success, needed_size) = this.write_path_to_c_str(Path::new(&path), out, out_size)?;
+                let (success, needed_size) =
+                    this.write_path_to_c_str(Path::new(&path), out, out_size)?;
                 // Return value: 0 on success, otherwise the size it would have needed.
                 this.write_int(if success { 0 } else { needed_size }, dest)?;
             }
@@ -505,11 +509,13 @@ fn emulate_foreign_item_by_name(
                 this.write_pointer(res, dest)?;
             }
             "calloc" => {
-                let [items, len] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+                let [items, len] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let items = this.read_machine_usize(items)?;
                 let len = this.read_machine_usize(len)?;
-                let size =
-                    items.checked_mul(len).ok_or_else(|| err_ub_format!("overflow during calloc size computation"))?;
+                let size = items
+                    .checked_mul(len)
+                    .ok_or_else(|| err_ub_format!("overflow during calloc size computation"))?;
                 let res = this.malloc(size, /*zero_init:*/ true, MiriMemoryKind::C)?;
                 this.write_pointer(res, dest)?;
             }
@@ -519,7 +525,8 @@ fn emulate_foreign_item_by_name(
                 this.free(ptr, MiriMemoryKind::C)?;
             }
             "realloc" => {
-                let [old_ptr, new_size] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+                let [old_ptr, new_size] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let old_ptr = this.read_pointer(old_ptr)?;
                 let new_size = this.read_machine_usize(new_size)?;
                 let res = this.realloc(old_ptr, new_size, MiriMemoryKind::C)?;
@@ -551,11 +558,12 @@ fn emulate_foreign_item_by_name(
                 };
 
                 match link_name.as_str() {
-                    "__rust_alloc" => return this.emulate_allocator(Symbol::intern("__rg_alloc"), default),
+                    "__rust_alloc" =>
+                        return this.emulate_allocator(Symbol::intern("__rg_alloc"), default),
                     "miri_alloc" => {
                         default(this)?;
                         return Ok(EmulateByNameResult::NeedsJumping);
-                    },
+                    }
                     _ => unreachable!(),
                 }
             }
@@ -574,7 +582,11 @@ fn emulate_foreign_item_by_name(
                     )?;
 
                     // We just allocated this, the access is definitely in-bounds.
-                    this.write_bytes_ptr(ptr.into(), iter::repeat(0u8).take(usize::try_from(size).unwrap())).unwrap();
+                    this.write_bytes_ptr(
+                        ptr.into(),
+                        iter::repeat(0u8).take(usize::try_from(size).unwrap()),
+                    )
+                    .unwrap();
                     this.write_pointer(ptr, dest)
                 });
             }
@@ -600,7 +612,8 @@ fn emulate_foreign_item_by_name(
                 };
 
                 match link_name.as_str() {
-                    "__rust_dealloc" => return this.emulate_allocator(Symbol::intern("__rg_dealloc"), default),
+                    "__rust_dealloc" =>
+                        return this.emulate_allocator(Symbol::intern("__rg_dealloc"), default),
                     "miri_dealloc" => {
                         default(this)?;
                         return Ok(EmulateByNameResult::NeedsJumping);
@@ -609,7 +622,8 @@ fn emulate_foreign_item_by_name(
                 }
             }
             "__rust_realloc" => {
-                let [ptr, old_size, align, new_size] = this.check_shim(abi, Abi::Rust, link_name, args)?;
+                let [ptr, old_size, align, new_size] =
+                    this.check_shim(abi, Abi::Rust, link_name, args)?;
                 let ptr = this.read_pointer(ptr)?;
                 let old_size = this.read_machine_usize(old_size)?;
                 let align = this.read_machine_usize(align)?;
@@ -633,7 +647,8 @@ fn emulate_foreign_item_by_name(
 
             // C memory handling functions
             "memcmp" => {
-                let [left, right, n] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+                let [left, right, n] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let left = this.read_pointer(left)?;
                 let right = this.read_pointer(right)?;
                 let n = Size::from_bytes(this.read_machine_usize(n)?);
@@ -653,7 +668,8 @@ fn emulate_foreign_item_by_name(
                 this.write_scalar(Scalar::from_i32(result), dest)?;
             }
             "memrchr" => {
-                let [ptr, val, num] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+                let [ptr, val, num] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let ptr = this.read_pointer(ptr)?;
                 let val = this.read_scalar(val)?.to_i32()?;
                 let num = this.read_machine_usize(num)?;
@@ -676,7 +692,8 @@ fn emulate_foreign_item_by_name(
                 }
             }
             "memchr" => {
-                let [ptr, val, num] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+                let [ptr, val, num] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let ptr = this.read_pointer(ptr)?;
                 let val = this.read_scalar(val)?.to_i32()?;
                 let num = this.read_machine_usize(num)?;
@@ -699,7 +716,10 @@ fn emulate_foreign_item_by_name(
                 let [ptr] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let ptr = this.read_pointer(ptr)?;
                 let n = this.read_c_str(ptr)?.len();
-                this.write_scalar(Scalar::from_machine_usize(u64::try_from(n).unwrap(), this), dest)?;
+                this.write_scalar(
+                    Scalar::from_machine_usize(u64::try_from(n).unwrap(), this),
+                    dest,
+                )?;
             }
 
             // math functions (note that there are also intrinsics for some other functions)
@@ -835,7 +855,8 @@ fn emulate_foreign_item_by_name(
                 let a = this.read_scalar(a)?.to_u64()?;
                 let b = this.read_scalar(b)?.to_u64()?;
 
-                #[allow(clippy::integer_arithmetic)] // adding two u64 and a u8 cannot wrap in a u128
+                #[allow(clippy::integer_arithmetic)]
+                // adding two u64 and a u8 cannot wrap in a u128
                 let wide_sum = u128::from(c_in) + u128::from(a) + u128::from(b);
                 #[allow(clippy::integer_arithmetic)] // it's a u128, we can shift by 64
                 let (c_out, sum) = ((wide_sum >> 64).truncate::<u8>(), wide_sum.truncate::<u64>());
@@ -845,7 +866,9 @@ fn emulate_foreign_item_by_name(
                 let sum_field = this.place_field(dest, 1)?;
                 this.write_scalar(Scalar::from_u64(sum), &sum_field)?;
             }
-            "llvm.x86.sse2.pause" if this.tcx.sess.target.arch == "x86" || this.tcx.sess.target.arch == "x86_64" => {
+            "llvm.x86.sse2.pause"
+                if this.tcx.sess.target.arch == "x86" || this.tcx.sess.target.arch == "x86_64" =>
+            {
                 let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 this.yield_active_thread();
             }
@@ -853,7 +876,8 @@ fn emulate_foreign_item_by_name(
                 let [arg] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?;
                 let arg = this.read_scalar(arg)?.to_i32()?;
                 match arg {
-                    15 => { // SY ("full system scope")
+                    // SY ("full system scope")
+                    15 => {
                         this.yield_active_thread();
                     }
                     _ => {
@@ -863,11 +887,18 @@ fn emulate_foreign_item_by_name(
             }
 
             // Platform-specific shims
-            _ => match this.tcx.sess.target.os.as_ref() {
-                target if target_os_is_unix(target) => return shims::unix::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest),
-                "windows" => return shims::windows::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest),
-                target => throw_unsup_format!("the target `{}` is not supported", target),
-            }
+            _ =>
+                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(
+                            this, link_name, abi, args, dest,
+                        ),
+                    "windows" =>
+                        shims::windows::foreign_items::EvalContextExt::emulate_foreign_item_by_name(
+                            this, link_name, abi, args, dest,
+                        ),
+                    _ => Ok(EmulateByNameResult::NotSupported),
+                },
         };
         // We only fall through to here if we did *not* hit the `_` arm above,
         // i.e., if we actually emulated the function with one of the shims.
index 7768772338a777b73d709b1dbd68985435ee1643..ca31efa486c2717d03795f227ae6530988b7bfc1 100644 (file)
@@ -257,16 +257,11 @@ pub fn on_stack_empty<'tcx>(
                         // And move to the final state.
                         self.0 = Done;
                     }
-                    "wasi" | "none" => {
-                        // No OS, no TLS dtors.
+                    _ => {
+                        // No TLS dtor support.
                         // FIXME: should we do something on wasi?
                         self.0 = Done;
                     }
-                    os => {
-                        throw_unsup_format!(
-                            "the TLS machinery does not know how to handle OS `{os}`"
-                        );
-                    }
                 }
             }
             PthreadDtors(state) => {
index 7f43afb7820b5858367962cb2f3d79ba461cb3f1..d018a7ea252b7ec10e539b4ca4338213a26eab63 100644 (file)
@@ -596,13 +596,13 @@ fn emulate_foreign_item_by_name(
             // Platform-specific shims
             _ => {
                 let target_os = &*this.tcx.sess.target.os;
-                match target_os {
-                    "android" => return shims::unix::android::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest),
-                    "freebsd" => return shims::unix::freebsd::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest),
-                    "linux" => return shims::unix::linux::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest),
-                    "macos" => return shims::unix::macos::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest),
-                    _ => panic!("unsupported Unix OS {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),
+                    _ => Ok(EmulateByNameResult::NotSupported),
+                };
             }
         };
 
index 3aaeb632cad7b66412891a372fbd92068cbe7d2c..3540c75b73a12ceacef1485eeb3d4b4d2818bf5d 100644 (file)
@@ -1,5 +1,6 @@
 //@only-target-linux
 //@only-on-host
+//@normalize-stderr-test: "OS `.*`" -> "$$OS"
 
 extern "C" {
     fn foo();
@@ -7,6 +8,6 @@
 
 fn main() {
     unsafe {
-        foo(); //~ ERROR: unsupported operation: can't call foreign function: foo
+        foo(); //~ ERROR: unsupported operation: can't call foreign function `foo`
     }
 }
index f649f0ae43e30992634235fd3f6b160d6e857ec1..e9bc322047195ff89879969e76ba05a95b7a91de 100644 (file)
@@ -1,8 +1,8 @@
-error: unsupported operation: can't call foreign function: foo
+error: unsupported operation: can't call foreign function `foo` on $OS
   --> $DIR/function_not_in_so.rs:LL:CC
    |
 LL |         foo();
-   |         ^^^^^ can't call foreign function: foo
+   |         ^^^^^ can't call foreign function `foo` on $OS
    |
    = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
    = note: BACKTRACE:
index fb0e7986bb5e6042caebb2a7508e4f0a0e348cf3..624ad1bda582f21f00e0330287eb744ece22711f 100644 (file)
@@ -1,3 +1,4 @@
+//@normalize-stderr-test: "OS `.*`" -> "$$OS"
 // Make sure we pretend the allocation symbols don't exist when there is no allocator
 
 #![feature(lang_items, start)]
@@ -10,7 +11,7 @@
 #[start]
 fn start(_: isize, _: *const *const u8) -> isize {
     unsafe {
-        __rust_alloc(1, 1); //~ERROR: unsupported operation: can't call foreign function: __rust_alloc
+        __rust_alloc(1, 1); //~ERROR: unsupported operation: can't call foreign function `__rust_alloc`
     }
 
     0
index ea70970ae0fefbf499318cf12de8a12d68fb35dc..fe6a22fadc9e2ea85f1f3ce058ae340fb90bee3d 100644 (file)
@@ -1,8 +1,8 @@
-error: unsupported operation: can't call foreign function: __rust_alloc
+error: unsupported operation: can't call foreign function `__rust_alloc` on $OS
   --> $DIR/no_global_allocator.rs:LL:CC
    |
 LL |         __rust_alloc(1, 1);
-   |         ^^^^^^^^^^^^^^^^^^ can't call foreign function: __rust_alloc
+   |         ^^^^^^^^^^^^^^^^^^ can't call foreign function `__rust_alloc` on $OS
    |
    = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
    = note: BACKTRACE:
index dfd099e734b99a6b619135bc89905fa81c26dcbb..44f032fbabe0f57f548727b9c503ef9c95cfa912 100644 (file)
@@ -1,9 +1,11 @@
+//@normalize-stderr-test: "OS `.*`" -> "$$OS"
+
 fn main() {
     extern "Rust" {
         fn foo();
     }
 
     unsafe {
-        foo(); //~ ERROR: unsupported operation: can't call foreign function: foo
+        foo(); //~ ERROR: unsupported operation: can't call foreign function `foo`
     }
 }
index fde5fb78ac08a2c50d0f0de01c013900fc91538f..519f6d182d7d8b3d63fe2748b6a24fbc31287a2d 100644 (file)
@@ -1,8 +1,8 @@
-error: unsupported operation: can't call foreign function: foo
+error: unsupported operation: can't call foreign function `foo` on $OS
   --> $DIR/unsupported_foreign_function.rs:LL:CC
    |
 LL |         foo();
-   |         ^^^^^ can't call foreign function: foo
+   |         ^^^^^ can't call foreign function `foo` on $OS
    |
    = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
    = note: BACKTRACE:
diff --git a/src/tools/miri/tests/fail/unsupported_incomplete_function.rs b/src/tools/miri/tests/fail/unsupported_incomplete_function.rs
new file mode 100644 (file)
index 0000000..6ef842c
--- /dev/null
@@ -0,0 +1,11 @@
+//! `signal()` is special on Linux and macOS that it's only supported within libstd.
+//! The implementation is not complete enough to permit user code to call it.
+//@ignore-target-windows: No libc on Windows
+//@normalize-stderr-test: "OS `.*`" -> "$$OS"
+
+fn main() {
+    unsafe {
+        libc::signal(libc::SIGPIPE, libc::SIG_IGN);
+        //~^ ERROR: unsupported operation: can't call foreign function `signal`
+    }
+}
diff --git a/src/tools/miri/tests/fail/unsupported_incomplete_function.stderr b/src/tools/miri/tests/fail/unsupported_incomplete_function.stderr
new file mode 100644 (file)
index 0000000..ec2bba6
--- /dev/null
@@ -0,0 +1,14 @@
+error: unsupported operation: can't call foreign function `signal` on $OS
+  --> $DIR/unsupported_incomplete_function.rs:LL:CC
+   |
+LL |         libc::signal(libc::SIGPIPE, libc::SIG_IGN);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't call foreign function `signal` on $OS
+   |
+   = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/unsupported_incomplete_function.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to previous error
+
diff --git a/src/tools/miri/tests/fail/unsupported_signal.rs b/src/tools/miri/tests/fail/unsupported_signal.rs
deleted file mode 100644 (file)
index d50041f..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-//! `signal()` is special on Linux and macOS that it's only supported within libstd.
-//! The implementation is not complete enough to permit user code to call it.
-//@ignore-target-windows: No libc on Windows
-
-fn main() {
-    unsafe {
-        libc::signal(libc::SIGPIPE, libc::SIG_IGN);
-        //~^ ERROR: unsupported operation: can't call foreign function: signal
-    }
-}
diff --git a/src/tools/miri/tests/fail/unsupported_signal.stderr b/src/tools/miri/tests/fail/unsupported_signal.stderr
deleted file mode 100644 (file)
index d22ecbc..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error: unsupported operation: can't call foreign function: signal
-  --> $DIR/unsupported_signal.rs:LL:CC
-   |
-LL |         libc::signal(libc::SIGPIPE, libc::SIG_IGN);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't call foreign function: signal
-   |
-   = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
-   = note: BACKTRACE:
-   = note: inside `main` at $DIR/unsupported_signal.rs:LL:CC
-
-note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
-
-error: aborting due to previous error
-
index a78646528fb125b810f7c7893dd140c1a62d9949..b8301c507724cb7909f089f0529a114ce6e65c04 100644 (file)
@@ -1,4 +1,5 @@
 //@compile-flags: -Zmiri-panic-on-unsupported
+//@normalize-stderr-test: "OS `.*`" -> "$$OS"
 
 fn main() {
     extern "Rust" {
index 9af3e48655f38be504960982400d1d666f74b777..a49dbdae58a6fd873c45218d447f428a23a9b08d 100644 (file)
@@ -1,2 +1,2 @@
-thread 'main' panicked at 'unsupported Miri functionality: can't call foreign function: foo', $DIR/unsupported_foreign_function.rs:LL:CC
+thread 'main' panicked at 'unsupported Miri functionality: can't call foreign function `foo` on $OS', $DIR/unsupported_foreign_function.rs:LL:CC
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace