about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock94
-rw-r--r--src/tools/miri/.github/workflows/ci.yml14
-rw-r--r--src/tools/miri/Cargo.lock442
-rw-r--r--src/tools/miri/Cargo.toml3
-rw-r--r--src/tools/miri/README.md10
-rw-r--r--src/tools/miri/bench-cargo-miri/mse/src/main.rs3
-rw-r--r--src/tools/miri/cargo-miri/Cargo.lock187
-rw-r--r--src/tools/miri/cargo-miri/src/phases.rs5
-rw-r--r--src/tools/miri/cargo-miri/src/setup.rs8
-rwxr-xr-xsrc/tools/miri/ci/ci.sh55
-rw-r--r--src/tools/miri/miri-script/Cargo.lock8
-rw-r--r--src/tools/miri/miri-script/Cargo.toml2
-rw-r--r--src/tools/miri/miri-script/src/commands.rs111
-rw-r--r--src/tools/miri/miri-script/src/main.rs67
-rw-r--r--src/tools/miri/miri-script/src/util.rs53
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs4
-rw-r--r--src/tools/miri/src/concurrency/sync.rs9
-rw-r--r--src/tools/miri/src/concurrency/thread.rs7
-rw-r--r--src/tools/miri/src/diagnostics.rs16
-rw-r--r--src/tools/miri/src/helpers.rs19
-rw-r--r--src/tools/miri/src/intrinsics/atomic.rs (renamed from src/tools/miri/src/shims/intrinsics/atomic.rs)0
-rw-r--r--src/tools/miri/src/intrinsics/mod.rs (renamed from src/tools/miri/src/shims/intrinsics/mod.rs)19
-rw-r--r--src/tools/miri/src/intrinsics/simd.rs (renamed from src/tools/miri/src/shims/intrinsics/simd.rs)4
-rw-r--r--src/tools/miri/src/lib.rs5
-rw-r--r--src/tools/miri/src/shims/env.rs15
-rw-r--r--src/tools/miri/src/shims/extern_static.rs29
-rw-r--r--src/tools/miri/src/shims/foreign_items.rs93
-rw-r--r--src/tools/miri/src/shims/mod.rs1
-rw-r--r--src/tools/miri/src/shims/time.rs26
-rw-r--r--src/tools/miri/src/shims/tls.rs12
-rw-r--r--src/tools/miri/src/shims/unix/env.rs50
-rw-r--r--src/tools/miri/src/shims/unix/fd.rs188
-rw-r--r--src/tools/miri/src/shims/unix/foreign_items.rs61
-rw-r--r--src/tools/miri/src/shims/unix/freebsd/foreign_items.rs30
-rw-r--r--src/tools/miri/src/shims/unix/fs.rs124
-rw-r--r--src/tools/miri/src/shims/unix/linux/epoll.rs69
-rw-r--r--src/tools/miri/src/shims/unix/linux/eventfd.rs25
-rw-r--r--src/tools/miri/src/shims/unix/linux/foreign_items.rs61
-rw-r--r--src/tools/miri/src/shims/unix/mod.rs3
-rw-r--r--src/tools/miri/src/shims/unix/socket.rs16
-rw-r--r--src/tools/miri/src/shims/unix/solarish/foreign_items.rs33
-rw-r--r--src/tools/miri/src/shims/unix/solarish/mod.rs1
-rw-r--r--src/tools/miri/src/shims/unix/sync.rs364
-rw-r--r--src/tools/miri/src/shims/unix/thread.rs12
-rw-r--r--src/tools/miri/src/shims/windows/env.rs9
-rw-r--r--src/tools/miri/src/shims/windows/foreign_items.rs8
-rw-r--r--src/tools/miri/src/shims/x86/avx2.rs2
-rw-r--r--src/tools/miri/src/shims/x86/mod.rs21
-rwxr-xr-xsrc/tools/miri/test-cargo-miri/run-test.py6
-rw-r--r--src/tools/miri/test_dependencies/Cargo.lock213
-rw-r--r--src/tools/miri/tests/extern-so/fail/function_not_in_so.stderr3
-rw-r--r--src/tools/miri/tests/fail-dep/shims/fs/close_stdout.stderr2
-rw-r--r--src/tools/miri/tests/fail-dep/shims/fs/read_from_stdout.stderr2
-rw-r--r--src/tools/miri/tests/fail-dep/shims/fs/write_to_stdin.stderr2
-rw-r--r--src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_condattr_double_destroy.rs1
-rw-r--r--src/tools/miri/tests/fail-dep/tokio/sleep.stderr2
-rw-r--r--src/tools/miri/tests/fail-dep/unsupported_incomplete_function.stderr3
-rw-r--r--src/tools/miri/tests/fail/alloc/no_global_allocator.stderr3
-rw-r--r--src/tools/miri/tests/fail/extern-type-field-offset.stderr2
-rw-r--r--src/tools/miri/tests/fail/extern_static.stderr2
-rw-r--r--src/tools/miri/tests/fail/extern_static_in_const.stderr2
-rw-r--r--src/tools/miri/tests/fail/extern_static_wrong_size.stderr2
-rw-r--r--src/tools/miri/tests/fail/function_pointers/abi_mismatch_array_vs_struct.stderr2
-rw-r--r--src/tools/miri/tests/fail/function_pointers/abi_mismatch_int_vs_float.stderr2
-rw-r--r--src/tools/miri/tests/fail/function_pointers/abi_mismatch_raw_pointer.stderr2
-rw-r--r--src/tools/miri/tests/fail/function_pointers/abi_mismatch_repr_C.stderr2
-rw-r--r--src/tools/miri/tests/fail/function_pointers/abi_mismatch_return_type.stderr2
-rw-r--r--src/tools/miri/tests/fail/function_pointers/abi_mismatch_simple.stderr2
-rw-r--r--src/tools/miri/tests/fail/function_pointers/abi_mismatch_vector.stderr2
-rw-r--r--src/tools/miri/tests/fail/intrinsic_fallback_checks_ub.stderr2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/intrinsic_target_feature.rs (renamed from src/tools/miri/tests/fail/shims/intrinsic_target_feature.rs)0
-rw-r--r--src/tools/miri/tests/fail/intrinsics/intrinsic_target_feature.stderr (renamed from src/tools/miri/tests/fail/shims/intrinsic_target_feature.stderr)0
-rw-r--r--src/tools/miri/tests/fail/issue-miri-3288-ice-symbolic-alignment-extern-static.stderr2
-rw-r--r--src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-flags.stderr2
-rw-r--r--src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-resolve-flags.stderr2
-rw-r--r--src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-resolve-names-flags.stderr2
-rw-r--r--src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-size-flags.stderr2
-rw-r--r--src/tools/miri/tests/fail/unaligned_pointers/promise_alignment.call_unaligned_ptr.stderr2
-rw-r--r--src/tools/miri/tests/fail/unaligned_pointers/promise_alignment_zero.stderr2
-rw-r--r--src/tools/miri/tests/fail/unsized-local.stderr2
-rw-r--r--src/tools/miri/tests/fail/unsupported_foreign_function.stderr3
-rw-r--r--src/tools/miri/tests/pass-dep/shims/libc-fs.rs174
-rw-r--r--src/tools/miri/tests/pass-dep/shims/libc-getentropy.rs20
-rw-r--r--src/tools/miri/tests/pass-dep/shims/libc-getrandom-without-isolation.rs41
-rw-r--r--src/tools/miri/tests/pass-dep/shims/libc-misc.rs365
-rw-r--r--src/tools/miri/tests/pass-dep/shims/libc-random.rs (renamed from src/tools/miri/tests/pass-dep/shims/libc-getrandom.rs)26
-rw-r--r--src/tools/miri/tests/pass-dep/shims/libc-rsfs.stdout1
-rw-r--r--src/tools/miri/tests/pass-dep/shims/libc-time.rs93
-rw-r--r--src/tools/miri/tests/pass-dep/shims/posix_memalign.rs82
-rw-r--r--src/tools/miri/tests/pass-dep/shims/pthread-sync.rs26
-rw-r--r--src/tools/miri/tests/pass/align_offset_symbolic.rs5
-rw-r--r--src/tools/miri/tests/pass/align_offset_symbolic.stdout1
-rw-r--r--src/tools/miri/tests/pass/alloc-access-tracking.rs5
-rw-r--r--src/tools/miri/tests/pass/alloc-access-tracking.stderr8
-rw-r--r--src/tools/miri/tests/pass/concurrency/threadname.rs (renamed from src/tools/miri/tests/pass/concurrency/thread_name.rs)0
-rw-r--r--src/tools/miri/tests/pass/hello.rs1
-rw-r--r--src/tools/miri/tests/pass/hello.stderr1
-rw-r--r--src/tools/miri/tests/pass/integers.rs (renamed from src/tools/miri/tests/pass/ints.rs)0
-rw-r--r--src/tools/miri/tests/pass/intrinsics/integer.rs (renamed from src/tools/miri/tests/pass/intrinsics-integer.rs)0
-rw-r--r--src/tools/miri/tests/pass/intrinsics/intrinsics.rs (renamed from src/tools/miri/tests/pass/intrinsics.rs)0
-rw-r--r--src/tools/miri/tests/pass/intrinsics/portable-simd-ptrs.rs (renamed from src/tools/miri/tests/pass/portable-simd-ptrs.rs)0
-rw-r--r--src/tools/miri/tests/pass/intrinsics/portable-simd.rs (renamed from src/tools/miri/tests/pass/portable-simd.rs)0
-rw-r--r--src/tools/miri/tests/pass/intrinsics/volatile.rs (renamed from src/tools/miri/tests/pass/volatile.rs)0
-rw-r--r--src/tools/miri/tests/pass/shims/available-parallelism-miri-num-cpus.rs (renamed from src/tools/miri/tests/pass/available-parallelism-miri-num-cpus.rs)0
-rw-r--r--src/tools/miri/tests/pass/shims/available-parallelism.rs (renamed from src/tools/miri/tests/pass/available-parallelism.rs)0
-rw-r--r--src/tools/miri/tests/pass/shims/x86/intrinsics-x86-aes-vaes.rs (renamed from src/tools/miri/tests/pass/intrinsics-x86-aes-vaes.rs)0
-rw-r--r--src/tools/miri/tests/pass/shims/x86/intrinsics-x86-avx.rs (renamed from src/tools/miri/tests/pass/intrinsics-x86-avx.rs)0
-rw-r--r--src/tools/miri/tests/pass/shims/x86/intrinsics-x86-avx2.rs (renamed from src/tools/miri/tests/pass/intrinsics-x86-avx2.rs)0
-rw-r--r--src/tools/miri/tests/pass/shims/x86/intrinsics-x86-avx512.rs (renamed from src/tools/miri/tests/pass/intrinsics-x86-avx512.rs)0
-rw-r--r--src/tools/miri/tests/pass/shims/x86/intrinsics-x86-pause-without-sse2.rs (renamed from src/tools/miri/tests/pass/intrinsics-x86-pause-without-sse2.rs)0
-rw-r--r--src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse.rs (renamed from src/tools/miri/tests/pass/intrinsics-x86-sse.rs)0
-rw-r--r--src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse2.rs (renamed from src/tools/miri/tests/pass/intrinsics-x86-sse2.rs)0
-rw-r--r--src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse3-ssse3.rs (renamed from src/tools/miri/tests/pass/intrinsics-x86-sse3-ssse3.rs)0
-rw-r--r--src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse41.rs (renamed from src/tools/miri/tests/pass/intrinsics-x86-sse41.rs)0
-rw-r--r--src/tools/miri/tests/pass/shims/x86/intrinsics-x86.rs (renamed from src/tools/miri/tests/pass/intrinsics-x86.rs)0
-rw-r--r--src/tools/miri/tests/pass/vecdeque.rs4
-rw-r--r--src/tools/miri/tests/pass/vecdeque.stack.stdout2
-rw-r--r--src/tools/miri/tests/pass/vecdeque.tree.stdout2
-rw-r--r--src/tools/miri/tests/pass/vecdeque.tree_uniq.stdout2
-rw-r--r--src/tools/miri/triagebot.toml5
121 files changed, 1910 insertions, 1634 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 40d810815b1..a6b6f3340dc 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -513,6 +513,28 @@ dependencies = [
 ]
 
 [[package]]
+name = "chrono-tz"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93698b29de5e97ad0ae26447b344c482a7284c737d9ddc5f9e52b74a336671bb"
+dependencies = [
+ "chrono",
+ "chrono-tz-build",
+ "phf 0.11.2",
+]
+
+[[package]]
+name = "chrono-tz-build"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c088aee841df9c3041febbb73934cfc39708749bf96dc827e3359cd39ef11b1"
+dependencies = [
+ "parse-zoneinfo",
+ "phf 0.11.2",
+ "phf_codegen 0.11.2",
+]
+
+[[package]]
 name = "cipher"
 version = "0.4.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2197,7 +2219,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19"
 dependencies = [
  "cfg-if",
- "windows-targets 0.52.4",
+ "windows-targets 0.48.5",
 ]
 
 [[package]]
@@ -2318,8 +2340,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016"
 dependencies = [
  "log",
- "phf",
- "phf_codegen",
+ "phf 0.10.1",
+ "phf_codegen 0.10.0",
  "string_cache",
  "string_cache_codegen",
  "tendril",
@@ -2480,6 +2502,7 @@ version = "0.1.0"
 dependencies = [
  "aes",
  "chrono",
+ "chrono-tz",
  "colored",
  "ctrlc",
  "directories",
@@ -2836,6 +2859,15 @@ dependencies = [
 ]
 
 [[package]]
+name = "parse-zoneinfo"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f2a05b18d44e2957b88f96ba460715e295bc1d7510468a2f3d3b44535d26c24"
+dependencies = [
+ "regex",
+]
+
+[[package]]
 name = "pathdiff"
 version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2907,7 +2939,16 @@ version = "0.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259"
 dependencies = [
- "phf_shared",
+ "phf_shared 0.10.0",
+]
+
+[[package]]
+name = "phf"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
+dependencies = [
+ "phf_shared 0.11.2",
 ]
 
 [[package]]
@@ -2916,8 +2957,18 @@ version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd"
 dependencies = [
- "phf_generator",
- "phf_shared",
+ "phf_generator 0.10.0",
+ "phf_shared 0.10.0",
+]
+
+[[package]]
+name = "phf_codegen"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a"
+dependencies = [
+ "phf_generator 0.11.2",
+ "phf_shared 0.11.2",
 ]
 
 [[package]]
@@ -2926,7 +2977,17 @@ version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6"
 dependencies = [
- "phf_shared",
+ "phf_shared 0.10.0",
+ "rand",
+]
+
+[[package]]
+name = "phf_generator"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0"
+dependencies = [
+ "phf_shared 0.11.2",
  "rand",
 ]
 
@@ -2940,6 +3001,15 @@ dependencies = [
 ]
 
 [[package]]
+name = "phf_shared"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b"
+dependencies = [
+ "siphasher",
+]
+
+[[package]]
 name = "pin-project-lite"
 version = "0.2.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3354,9 +3424,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-build-sysroot"
-version = "0.4.6"
+version = "0.4.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a9bf37423495cd3a6a9ef8c75fc4566de0d26de0ab75f36f67a426e58df5768c"
+checksum = "ab1dbbd1bdf65fdac44c885f6cca147ba179108ce284b60a08ccc04b1f1dbac0"
 dependencies = [
  "anyhow",
  "rustc_version",
@@ -5285,7 +5355,7 @@ dependencies = [
  "new_debug_unreachable",
  "once_cell",
  "parking_lot",
- "phf_shared",
+ "phf_shared 0.10.0",
  "precomputed-hash",
  "serde",
 ]
@@ -5296,8 +5366,8 @@ version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988"
 dependencies = [
- "phf_generator",
- "phf_shared",
+ "phf_generator 0.10.0",
+ "phf_shared 0.10.0",
  "proc-macro2",
  "quote",
 ]
diff --git a/src/tools/miri/.github/workflows/ci.yml b/src/tools/miri/.github/workflows/ci.yml
index 0af334a654b..3bc4163ab52 100644
--- a/src/tools/miri/.github/workflows/ci.yml
+++ b/src/tools/miri/.github/workflows/ci.yml
@@ -45,7 +45,7 @@ jobs:
       # over time).
       - name: Add cache for cargo
         id: cache
-        uses: actions/cache@v3
+        uses: actions/cache@v4
         with:
           path: |
             # Taken from <https://doc.rust-lang.org/nightly/cargo/guide/cargo-home.html#caching-the-cargo-home-in-ci>.
@@ -61,7 +61,7 @@ jobs:
           restore-keys: cargo-${{ runner.os }}-reset20240425
 
       - name: Install tools
-        if: ${{ steps.cache.outputs.cache-hit != 'true' }}
+        if: steps.cache.outputs.cache-hit != 'true'
         run: cargo install -f rustup-toolchain-install-master hyperfine
 
       - name: Install miri toolchain
@@ -78,6 +78,12 @@ jobs:
           rustc -Vv
           cargo -V
 
+      # The `style` job only runs on Linux; this makes sure the Windows-host-specific
+      # code is also covered by clippy.
+      - name: Check clippy
+        if: matrix.os == 'windows-latest'
+        run: ./miri clippy -- -D warnings
+
       - name: Test Miri
         run: ./ci/ci.sh
 
@@ -95,7 +101,7 @@ jobs:
       # over time).
       - name: Add cache for cargo
         id: cache
-        uses: actions/cache@v3
+        uses: actions/cache@v4
         with:
           path: |
             # Taken from <https://doc.rust-lang.org/nightly/cargo/guide/cargo-home.html#caching-the-cargo-home-in-ci>.
@@ -111,7 +117,7 @@ jobs:
           restore-keys: cargo-${{ runner.os }}-reset20240331
 
       - name: Install rustup-toolchain-install-master
-        if: ${{ steps.cache.outputs.cache-hit != 'true' }}
+        if: steps.cache.outputs.cache-hit != 'true'
         run: cargo install -f rustup-toolchain-install-master
 
       - name: Install "master" toolchain
diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock
index 293b937a5e5..417ecb09b31 100644
--- a/src/tools/miri/Cargo.lock
+++ b/src/tools/miri/Cargo.lock
@@ -30,29 +30,14 @@ dependencies = [
 
 [[package]]
 name = "aho-corasick"
-version = "1.1.2"
+version = "1.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
+checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
 dependencies = [
  "memchr",
 ]
 
 [[package]]
-name = "android-tzdata"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
-
-[[package]]
-name = "android_system_properties"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
-dependencies = [
- "libc",
-]
-
-[[package]]
 name = "annotate-snippets"
 version = "0.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -73,21 +58,21 @@ dependencies = [
 
 [[package]]
 name = "anyhow"
-version = "1.0.80"
+version = "1.0.82"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1"
+checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519"
 
 [[package]]
 name = "autocfg"
-version = "1.1.0"
+version = "1.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
 
 [[package]]
 name = "backtrace"
-version = "0.3.69"
+version = "0.3.71"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
+checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d"
 dependencies = [
  "addr2line",
  "cc",
@@ -100,21 +85,15 @@ dependencies = [
 
 [[package]]
 name = "bitflags"
-version = "1.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
-
-[[package]]
-name = "bitflags"
-version = "2.4.2"
+version = "2.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
+checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
 
 [[package]]
 name = "bstr"
-version = "1.9.0"
+version = "1.9.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c48f0051a4b4c5e0b6d365cd04af53aeaa209e3cc15ec2cdb69e73cc87fbd0dc"
+checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706"
 dependencies = [
  "memchr",
  "regex-automata",
@@ -122,12 +101,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "bumpalo"
-version = "3.16.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
-
-[[package]]
 name = "camino"
 version = "1.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -138,9 +111,9 @@ dependencies = [
 
 [[package]]
 name = "cargo-platform"
-version = "0.1.7"
+version = "0.1.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "694c8807f2ae16faecc43dc17d74b3eb042482789fd0eb64b39a2e04e087053f"
+checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc"
 dependencies = [
  "serde",
 ]
@@ -161,9 +134,9 @@ dependencies = [
 
 [[package]]
 name = "cc"
-version = "1.0.86"
+version = "1.0.96"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f9fa1897e4325be0d68d48df6aa1a71ac2ed4d27723887e7754192705350730"
+checksum = "065a29261d53ba54260972629f9ca6bffa69bac13cd1fed61420f7fa68b9f8bd"
 
 [[package]]
 name = "cfg-if"
@@ -172,15 +145,40 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
+name = "cfg_aliases"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
+
+[[package]]
 name = "chrono"
 version = "0.4.38"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
 dependencies = [
- "android-tzdata",
- "iana-time-zone",
  "num-traits",
- "windows-targets 0.52.3",
+]
+
+[[package]]
+name = "chrono-tz"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93698b29de5e97ad0ae26447b344c482a7284c737d9ddc5f9e52b74a336671bb"
+dependencies = [
+ "chrono",
+ "chrono-tz-build",
+ "phf",
+]
+
+[[package]]
+name = "chrono-tz-build"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c088aee841df9c3041febbb73934cfc39708749bf96dc827e3359cd39ef11b1"
+dependencies = [
+ "parse-zoneinfo",
+ "phf",
+ "phf_codegen",
 ]
 
 [[package]]
@@ -195,9 +193,9 @@ dependencies = [
 
 [[package]]
 name = "color-eyre"
-version = "0.6.2"
+version = "0.6.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a667583cca8c4f8436db8de46ea8233c42a7d9ae424a82d338f2e4675229204"
+checksum = "55146f5e46f237f7423d74111267d4597b59b0dad0ffaf7303bce9945d843ad5"
 dependencies = [
  "backtrace",
  "color-spantrace",
@@ -250,12 +248,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "core-foundation-sys"
-version = "0.8.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
-
-[[package]]
 name = "cpufeatures"
 version = "0.2.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -266,9 +258,9 @@ dependencies = [
 
 [[package]]
 name = "crossbeam-channel"
-version = "0.5.11"
+version = "0.5.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "176dc175b78f56c0f321911d9c8eb2b77a78a4860b9c19db83835fea1a46649b"
+checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95"
 dependencies = [
  "crossbeam-utils",
 ]
@@ -291,9 +283,9 @@ dependencies = [
 
 [[package]]
 name = "ctrlc"
-version = "3.4.2"
+version = "3.4.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b467862cc8610ca6fc9a1532d7777cee0804e678ab45410897b9396495994a0b"
+checksum = "672465ae37dc1bc6380a6547a8883d5dd397b0f1faaad4f265726cc7042a5345"
 dependencies = [
  "nix",
  "windows-sys 0.52.0",
@@ -348,9 +340,9 @@ dependencies = [
 
 [[package]]
 name = "fastrand"
-version = "2.0.1"
+version = "2.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
+checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a"
 
 [[package]]
 name = "generic-array"
@@ -364,9 +356,9 @@ dependencies = [
 
 [[package]]
 name = "getrandom"
-version = "0.2.12"
+version = "0.2.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5"
+checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c"
 dependencies = [
  "cfg-if",
  "libc",
@@ -380,29 +372,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
 
 [[package]]
-name = "iana-time-zone"
-version = "0.1.60"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
-dependencies = [
- "android_system_properties",
- "core-foundation-sys",
- "iana-time-zone-haiku",
- "js-sys",
- "wasm-bindgen",
- "windows-core",
-]
-
-[[package]]
-name = "iana-time-zone-haiku"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
-dependencies = [
- "cc",
-]
-
-[[package]]
 name = "indenter"
 version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -441,9 +410,9 @@ dependencies = [
 
 [[package]]
 name = "itoa"
-version = "1.0.10"
+version = "1.0.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
+checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
 
 [[package]]
 name = "jemalloc-sys"
@@ -456,15 +425,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "js-sys"
-version = "0.3.69"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
-dependencies = [
- "wasm-bindgen",
-]
-
-[[package]]
 name = "lazy_static"
 version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -478,9 +438,9 @@ checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760"
 
 [[package]]
 name = "libc"
-version = "0.2.153"
+version = "0.2.154"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
+checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346"
 
 [[package]]
 name = "libffi"
@@ -503,12 +463,12 @@ dependencies = [
 
 [[package]]
 name = "libloading"
-version = "0.8.1"
+version = "0.8.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161"
+checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19"
 dependencies = [
  "cfg-if",
- "windows-sys 0.48.0",
+ "windows-targets 0.52.5",
 ]
 
 [[package]]
@@ -517,7 +477,7 @@ version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
 dependencies = [
- "bitflags 2.4.2",
+ "bitflags",
  "libc",
 ]
 
@@ -529,9 +489,9 @@ checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
 
 [[package]]
 name = "lock_api"
-version = "0.4.11"
+version = "0.4.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
+checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
 dependencies = [
  "autocfg",
  "scopeguard",
@@ -539,9 +499,9 @@ dependencies = [
 
 [[package]]
 name = "log"
-version = "0.4.20"
+version = "0.4.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
+checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
 
 [[package]]
 name = "measureme"
@@ -559,9 +519,9 @@ dependencies = [
 
 [[package]]
 name = "memchr"
-version = "2.7.1"
+version = "2.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
+checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
 
 [[package]]
 name = "memmap2"
@@ -587,12 +547,12 @@ version = "0.1.0"
 dependencies = [
  "aes",
  "chrono",
+ "chrono-tz",
  "colored",
  "ctrlc",
  "directories",
  "getrandom",
  "jemalloc-sys",
- "lazy_static",
  "libc",
  "libffi",
  "libloading",
@@ -607,20 +567,21 @@ dependencies = [
 
 [[package]]
 name = "nix"
-version = "0.27.1"
+version = "0.28.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053"
+checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4"
 dependencies = [
- "bitflags 2.4.2",
+ "bitflags",
  "cfg-if",
+ "cfg_aliases",
  "libc",
 ]
 
 [[package]]
 name = "num-traits"
-version = "0.2.18"
+version = "0.2.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
+checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
 dependencies = [
  "autocfg",
 ]
@@ -669,9 +630,9 @@ dependencies = [
 
 [[package]]
 name = "parking_lot"
-version = "0.12.1"
+version = "0.12.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
+checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb"
 dependencies = [
  "lock_api",
  "parking_lot_core",
@@ -679,15 +640,24 @@ dependencies = [
 
 [[package]]
 name = "parking_lot_core"
-version = "0.9.9"
+version = "0.9.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
+checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
 dependencies = [
  "cfg-if",
  "libc",
  "redox_syscall",
  "smallvec",
- "windows-targets 0.48.5",
+ "windows-targets 0.52.5",
+]
+
+[[package]]
+name = "parse-zoneinfo"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f2a05b18d44e2957b88f96ba460715e295bc1d7510468a2f3d3b44535d26c24"
+dependencies = [
+ "regex",
 ]
 
 [[package]]
@@ -700,10 +670,48 @@ dependencies = [
 ]
 
 [[package]]
+name = "phf"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
+dependencies = [
+ "phf_shared",
+]
+
+[[package]]
+name = "phf_codegen"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a"
+dependencies = [
+ "phf_generator",
+ "phf_shared",
+]
+
+[[package]]
+name = "phf_generator"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0"
+dependencies = [
+ "phf_shared",
+ "rand",
+]
+
+[[package]]
+name = "phf_shared"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b"
+dependencies = [
+ "siphasher",
+]
+
+[[package]]
 name = "pin-project-lite"
-version = "0.2.13"
+version = "0.2.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
+checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
 
 [[package]]
 name = "portable-atomic"
@@ -729,18 +737,18 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.78"
+version = "1.0.81"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
+checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba"
 dependencies = [
  "unicode-ident",
 ]
 
 [[package]]
 name = "quote"
-version = "1.0.35"
+version = "1.0.36"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
+checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
 dependencies = [
  "proc-macro2",
 ]
@@ -777,11 +785,11 @@ dependencies = [
 
 [[package]]
 name = "redox_syscall"
-version = "0.4.1"
+version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
+checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e"
 dependencies = [
- "bitflags 1.3.2",
+ "bitflags",
 ]
 
 [[package]]
@@ -797,9 +805,9 @@ dependencies = [
 
 [[package]]
 name = "regex"
-version = "1.10.3"
+version = "1.10.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15"
+checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c"
 dependencies = [
  "aho-corasick",
  "memchr",
@@ -809,9 +817,9 @@ dependencies = [
 
 [[package]]
 name = "regex-automata"
-version = "0.4.5"
+version = "0.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd"
+checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
 dependencies = [
  "aho-corasick",
  "memchr",
@@ -820,9 +828,9 @@ dependencies = [
 
 [[package]]
 name = "regex-syntax"
-version = "0.8.2"
+version = "0.8.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
+checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
 
 [[package]]
 name = "rustc-demangle"
@@ -859,11 +867,11 @@ dependencies = [
 
 [[package]]
 name = "rustix"
-version = "0.38.31"
+version = "0.38.34"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949"
+checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
 dependencies = [
- "bitflags 2.4.2",
+ "bitflags",
  "errno",
  "libc",
  "linux-raw-sys",
@@ -893,18 +901,18 @@ dependencies = [
 
 [[package]]
 name = "serde"
-version = "1.0.197"
+version = "1.0.200"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
+checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.197"
+version = "1.0.200"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
+checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -913,9 +921,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.114"
+version = "1.0.116"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0"
+checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813"
 dependencies = [
  "itoa",
  "ryu",
@@ -932,16 +940,22 @@ dependencies = [
 ]
 
 [[package]]
+name = "siphasher"
+version = "0.3.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
+
+[[package]]
 name = "smallvec"
-version = "1.13.1"
+version = "1.13.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
+checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
 
 [[package]]
 name = "syn"
-version = "2.0.50"
+version = "2.0.60"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74f1bdc9872430ce9b75da68329d1c1746faf50ffac5f19e02b71e37ff881ffb"
+checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -950,9 +964,9 @@ dependencies = [
 
 [[package]]
 name = "tempfile"
-version = "3.10.0"
+version = "3.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a365e8cd18e44762ef95d87f284f4b5cd04107fec2ff3052bd6a3e6069669e67"
+checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1"
 dependencies = [
  "cfg-if",
  "fastrand",
@@ -962,18 +976,18 @@ dependencies = [
 
 [[package]]
 name = "thiserror"
-version = "1.0.57"
+version = "1.0.59"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b"
+checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa"
 dependencies = [
  "thiserror-impl",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.57"
+version = "1.0.59"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81"
+checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1072,9 +1086,9 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
 
 [[package]]
 name = "unicode-width"
-version = "0.1.11"
+version = "0.1.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
+checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6"
 
 [[package]]
 name = "valuable"
@@ -1095,60 +1109,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 
 [[package]]
-name = "wasm-bindgen"
-version = "0.2.92"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
-dependencies = [
- "cfg-if",
- "wasm-bindgen-macro",
-]
-
-[[package]]
-name = "wasm-bindgen-backend"
-version = "0.2.92"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
-dependencies = [
- "bumpalo",
- "log",
- "once_cell",
- "proc-macro2",
- "quote",
- "syn",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-macro"
-version = "0.2.92"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
-dependencies = [
- "quote",
- "wasm-bindgen-macro-support",
-]
-
-[[package]]
-name = "wasm-bindgen-macro-support"
-version = "0.2.92"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "wasm-bindgen-backend",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-shared"
-version = "0.2.92"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
-
-[[package]]
 name = "winapi"
 version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1171,15 +1131,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 
 [[package]]
-name = "windows-core"
-version = "0.52.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
-dependencies = [
- "windows-targets 0.52.3",
-]
-
-[[package]]
 name = "windows-sys"
 version = "0.48.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1194,7 +1145,7 @@ version = "0.52.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
 dependencies = [
- "windows-targets 0.52.3",
+ "windows-targets 0.52.5",
 ]
 
 [[package]]
@@ -1214,17 +1165,18 @@ dependencies = [
 
 [[package]]
 name = "windows-targets"
-version = "0.52.3"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d380ba1dc7187569a8a9e91ed34b8ccfc33123bbacb8c0aed2d1ad7f3ef2dc5f"
+checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
 dependencies = [
- "windows_aarch64_gnullvm 0.52.3",
- "windows_aarch64_msvc 0.52.3",
- "windows_i686_gnu 0.52.3",
- "windows_i686_msvc 0.52.3",
- "windows_x86_64_gnu 0.52.3",
- "windows_x86_64_gnullvm 0.52.3",
- "windows_x86_64_msvc 0.52.3",
+ "windows_aarch64_gnullvm 0.52.5",
+ "windows_aarch64_msvc 0.52.5",
+ "windows_i686_gnu 0.52.5",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc 0.52.5",
+ "windows_x86_64_gnu 0.52.5",
+ "windows_x86_64_gnullvm 0.52.5",
+ "windows_x86_64_msvc 0.52.5",
 ]
 
 [[package]]
@@ -1235,9 +1187,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
 
 [[package]]
 name = "windows_aarch64_gnullvm"
-version = "0.52.3"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68e5dcfb9413f53afd9c8f86e56a7b4d86d9a2fa26090ea2dc9e40fba56c6ec6"
+checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
 
 [[package]]
 name = "windows_aarch64_msvc"
@@ -1247,9 +1199,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
 
 [[package]]
 name = "windows_aarch64_msvc"
-version = "0.52.3"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8dab469ebbc45798319e69eebf92308e541ce46760b49b18c6b3fe5e8965b30f"
+checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
 
 [[package]]
 name = "windows_i686_gnu"
@@ -1259,9 +1211,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
 
 [[package]]
 name = "windows_i686_gnu"
-version = "0.52.3"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a4e9b6a7cac734a8b4138a4e1044eac3404d8326b6c0f939276560687a033fb"
+checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
 
 [[package]]
 name = "windows_i686_msvc"
@@ -1271,9 +1229,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
 
 [[package]]
 name = "windows_i686_msvc"
-version = "0.52.3"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28b0ec9c422ca95ff34a78755cfa6ad4a51371da2a5ace67500cf7ca5f232c58"
+checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
 
 [[package]]
 name = "windows_x86_64_gnu"
@@ -1283,9 +1241,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
 
 [[package]]
 name = "windows_x86_64_gnu"
-version = "0.52.3"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "704131571ba93e89d7cd43482277d6632589b18ecf4468f591fbae0a8b101614"
+checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
 
 [[package]]
 name = "windows_x86_64_gnullvm"
@@ -1295,9 +1253,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
 
 [[package]]
 name = "windows_x86_64_gnullvm"
-version = "0.52.3"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42079295511643151e98d61c38c0acc444e52dd42ab456f7ccfd5152e8ecf21c"
+checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
 
 [[package]]
 name = "windows_x86_64_msvc"
@@ -1307,9 +1265,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
 
 [[package]]
 name = "windows_x86_64_msvc"
-version = "0.52.3"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0770833d60a970638e989b3fa9fd2bb1aaadcf88963d1659fd7d9990196ed2d6"
+checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
 
 [[package]]
 name = "yansi-term"
diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml
index ac8b4b37e92..976bd080867 100644
--- a/src/tools/miri/Cargo.toml
+++ b/src/tools/miri/Cargo.toml
@@ -24,7 +24,8 @@ smallvec = "1.7"
 aes = { version = "0.8.3", features = ["hazmat"] }
 measureme = "11"
 ctrlc = "3.2.5"
-chrono = { version = "0.4.38", default-features = false, features = ["clock"] }
+chrono = { version = "0.4.38", default-features = false }
+chrono-tz = "0.9"
 directories = "5"
 
 # Copied from `compiler/rustc/Cargo.toml`.
diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md
index ef01ca25fb0..5b3e2a588b4 100644
--- a/src/tools/miri/README.md
+++ b/src/tools/miri/README.md
@@ -141,7 +141,7 @@ interpreter will explicitly tell you when it finds something unsupported:
 error: unsupported operation: can't call foreign function: bind
     ...
     = help: this is likely not a bug in the program; it indicates that the program \
-            performed an operation that the interpreter does not support
+            performed an operation that Miri does not support
 ```
 
 ### Cross-interpretation: running for different targets
@@ -224,8 +224,12 @@ degree documented below):
 - `s390x-unknown-linux-gnu` is supported as our "big-endian target of choice".
 - For every other target with OS `linux`, `macos`, or `windows`, Miri should generally work, but we
   make no promises and we don't run tests for such targets.
-- For targets on other operating systems, even basic operations such as printing to the standard
-  output might not work, and Miri might fail before even reaching the `main` function.
+- We have unofficial support (not maintained by the Miri team itself) for some further operating systems.
+  - `freebsd`: **maintainer wanted**. Supports `std::env` and parts of `std::{thread, fs}`, but not `std::sync`.
+  - `android`: **maintainer wanted**. Support very incomplete, but a basic "hello world" works.
+  - `illumos`: maintained by @devnexen. Support very incomplete, but a basic "hello world" works.
+  - `wasm`: **maintainer wanted**. Support very incomplete, not even standard output works, but an empty `main` function works.
+- For targets on other operating systems, Miri might fail before even reaching the `main` function.
 
 However, even for targets that we do support, the degree of support for accessing platform APIs
 (such as the file system) differs between targets: generally, Linux targets have the best support,
diff --git a/src/tools/miri/bench-cargo-miri/mse/src/main.rs b/src/tools/miri/bench-cargo-miri/mse/src/main.rs
index c09dc2484d3..e16ccd2c0d7 100644
--- a/src/tools/miri/bench-cargo-miri/mse/src/main.rs
+++ b/src/tools/miri/bench-cargo-miri/mse/src/main.rs
@@ -4,9 +4,6 @@ static EXPECTED: &[u8] = &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 static PCM: &[i16] = &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, -2, 0, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 1, 0, 1, 0, 0, -2, 0, -2, 0, -2, 0, -2, -2, -2, -3, -3, -3, -3, -4, -2, -5, -2, -5, -2, -4, 0, -4, 0, -4, 0, -4, 1, -4, 1, -4, 2, -4, 2, -4, 2, -4, 2, -4, 2, -3, 1, -4, 0, -4, 0, -5, 0, -5, 0, -5, 0, -4, 2, -4, 3, -4, 4, -3, 5, -2, 5, -3, 6, -3, 6, -3, 5, -3, 5, -2, 4, -2, 3, -5, 0, -6, 0, -3, -2, -4, -4, -9, -5, -9, -4, -4, -2, -4, -2, -4, 0, -2, 1, 1, 1, 4, 2, 8, 2, 12, 1, 13, 0, 12, 0, 11, 0, 8, -2, 7, 0, 7, -3, 11, -8, 15, -9, 17, -6, 17, -5, 13, -3, 7, 0, 3, 0, -2, 0, -4, 0, -4, -2, -6, 0, -14, -2, -17, -4, -8, 0, -7, 5, -17, 7, -18, 10, -7, 18, -2, 25, -3, 27, 0, 31, 4, 34, 4, 34, 8, 36, 8, 37, 2, 36, 4, 34, 8, 28, 3, 15, 0, 11, 0, 12, -5, 8, -4, 10, 0, 23, -4, 31, -8, 30, -2, 30, 0, 26, -6, 22, -6, 20, -12, 15, -19, 10, -10, 13, -14, 6, -43, -13, -43, -16, -9, -12, -10, -29, -42, -40, -37, -28, -5, -21, 1, -24, -8, -20, 4, -18, 26, -24, 44, -26, 66, -30, 86, -37, 88, -41, 72, -46, 50, -31, 28, 23, 14, 64, 16, 51, 26, 32, 34, 39, 42, 48, 35, 58, 0, 72, -36, 69, -59, 58, -98, 54, -124, 36, -103, 12, -110, 5, -173, -19, -146, -59, -4, -42, 51, 1, -23, -6, -30, -6, 45, 46, 47, 70, 6, 55, 19, 60, 38, 62, 42, 47, 61, 46, 40, 42, -19, 22, -34, 6, -35, -50, -61, -141, -37, -171, 17, -163, 26, -180, 46, -154, 80, -63, 48, -4, 18, 20, 50, 47, 58, 53, 44, 61, 57, 85, 37, 80, 0, 86, -8, 106, -95, 49, -213, -8, -131, 47, 49, 63, 40, -39, -69, -74, -37, -20, 63, -12, 58, -14, -12, 25, -31, 41, 11, 45, 76, 47, 167, 5, 261, -37, 277, -83, 183, -172, 35, -122, -79, 138, -70, 266, 69, 124, 228, 0, 391, -29, 594, -84, 702, -78, 627, -8, 551, -13, 509, 13, 372, 120, 352, 125, 622, 127, 691, 223, 362, 126, 386, -33, 915, 198, 958, 457, 456, 298, 500, 233, 1027, 469, 1096, 426, 918, 160, 1067, 141, 1220, 189, 1245, 164, 1375, 297, 1378, 503, 1299, 702, 1550, 929, 1799, 855, 1752, 547, 1830, 602, 1928, 832, 1736, 796, 1735, 933, 1961, 1385, 1935, 1562, 2105, 1485, 2716, 1449, 2948, 1305, 2768, 1205, 2716, 1346, 2531, 1450, 2470, 1653, 3117, 2111, 3370, 2176, 2696, 1947, 2925, 2305, 3846, 2658, 2425, 2184, -877, 1981, -2261, 2623, -1645, 2908, -1876, 2732, -2704, 2953, -2484, 3116, -2120, 2954, -2442, 3216, -2466, 3499, -2192, 3234, -2392, 3361, -2497, 3869, -2078, 3772, -1858, 3915, -2066, 4438, -2285, 2934, -2294, -280, -2066, -1762, -1992, -1412, -2298, -1535, -2399, -1789, -2223, -1419, -2244, -1334, -2092, -1476, -1777, -1396, -2014, -1571, -2199, -1574, -1843, -1167, -1910, -1446, -2007, -1818];
 
 fn main() {
-    #[cfg(increase_thread_usage)]
-    let thread = std::thread::spawn(|| 4);
-
     for _ in 0..2 {
         mse(PCM.len(), PCM, EXPECTED);
     }
diff --git a/src/tools/miri/cargo-miri/Cargo.lock b/src/tools/miri/cargo-miri/Cargo.lock
index a1dbc85605f..b8ead460249 100644
--- a/src/tools/miri/cargo-miri/Cargo.lock
+++ b/src/tools/miri/cargo-miri/Cargo.lock
@@ -4,21 +4,15 @@ version = 3
 
 [[package]]
 name = "anyhow"
-version = "1.0.80"
+version = "1.0.82"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1"
+checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519"
 
 [[package]]
 name = "bitflags"
-version = "1.3.2"
+version = "2.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
-
-[[package]]
-name = "bitflags"
-version = "2.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
+checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
 
 [[package]]
 name = "camino"
@@ -44,9 +38,9 @@ dependencies = [
 
 [[package]]
 name = "cargo-platform"
-version = "0.1.7"
+version = "0.1.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "694c8807f2ae16faecc43dc17d74b3eb042482789fd0eb64b39a2e04e087053f"
+checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc"
 dependencies = [
  "serde",
 ]
@@ -104,15 +98,15 @@ dependencies = [
 
 [[package]]
 name = "fastrand"
-version = "2.0.1"
+version = "2.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
+checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a"
 
 [[package]]
 name = "getrandom"
-version = "0.2.12"
+version = "0.2.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5"
+checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c"
 dependencies = [
  "cfg-if",
  "libc",
@@ -121,25 +115,24 @@ dependencies = [
 
 [[package]]
 name = "itoa"
-version = "1.0.10"
+version = "1.0.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
+checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
 
 [[package]]
 name = "libc"
-version = "0.2.153"
+version = "0.2.154"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
+checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346"
 
 [[package]]
 name = "libredox"
-version = "0.0.1"
+version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8"
+checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
 dependencies = [
- "bitflags 2.4.2",
+ "bitflags",
  "libc",
- "redox_syscall",
 ]
 
 [[package]]
@@ -156,36 +149,27 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.78"
+version = "1.0.81"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
+checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba"
 dependencies = [
  "unicode-ident",
 ]
 
 [[package]]
 name = "quote"
-version = "1.0.35"
+version = "1.0.36"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
+checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
 dependencies = [
  "proc-macro2",
 ]
 
 [[package]]
-name = "redox_syscall"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
-dependencies = [
- "bitflags 1.3.2",
-]
-
-[[package]]
 name = "redox_users"
-version = "0.4.4"
+version = "0.4.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4"
+checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891"
 dependencies = [
  "getrandom",
  "libredox",
@@ -194,9 +178,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-build-sysroot"
-version = "0.4.6"
+version = "0.4.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a9bf37423495cd3a6a9ef8c75fc4566de0d26de0ab75f36f67a426e58df5768c"
+checksum = "ab1dbbd1bdf65fdac44c885f6cca147ba179108ce284b60a08ccc04b1f1dbac0"
 dependencies = [
  "anyhow",
  "rustc_version",
@@ -221,11 +205,11 @@ dependencies = [
 
 [[package]]
 name = "rustix"
-version = "0.38.31"
+version = "0.38.34"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949"
+checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
 dependencies = [
- "bitflags 2.4.2",
+ "bitflags",
  "errno",
  "libc",
  "linux-raw-sys",
@@ -258,18 +242,18 @@ dependencies = [
 
 [[package]]
 name = "serde"
-version = "1.0.197"
+version = "1.0.200"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
+checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.197"
+version = "1.0.200"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
+checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -278,9 +262,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.114"
+version = "1.0.116"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0"
+checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813"
 dependencies = [
  "itoa",
  "ryu",
@@ -289,9 +273,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "2.0.50"
+version = "2.0.60"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74f1bdc9872430ce9b75da68329d1c1746faf50ffac5f19e02b71e37ff881ffb"
+checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -300,9 +284,9 @@ dependencies = [
 
 [[package]]
 name = "tempfile"
-version = "3.10.0"
+version = "3.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a365e8cd18e44762ef95d87f284f4b5cd04107fec2ff3052bd6a3e6069669e67"
+checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1"
 dependencies = [
  "cfg-if",
  "fastrand",
@@ -312,18 +296,18 @@ dependencies = [
 
 [[package]]
 name = "thiserror"
-version = "1.0.57"
+version = "1.0.59"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b"
+checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa"
 dependencies = [
  "thiserror-impl",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.57"
+version = "1.0.59"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81"
+checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -338,9 +322,9 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
 
 [[package]]
 name = "walkdir"
-version = "2.4.0"
+version = "2.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee"
+checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
 dependencies = [
  "same-file",
  "winapi-util",
@@ -353,37 +337,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 
 [[package]]
-name = "winapi"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
-dependencies = [
- "winapi-i686-pc-windows-gnu",
- "winapi-x86_64-pc-windows-gnu",
-]
-
-[[package]]
-name = "winapi-i686-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
-
-[[package]]
 name = "winapi-util"
-version = "0.1.6"
+version = "0.1.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
+checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b"
 dependencies = [
- "winapi",
+ "windows-sys 0.52.0",
 ]
 
 [[package]]
-name = "winapi-x86_64-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
-
-[[package]]
 name = "windows-sys"
 version = "0.48.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -398,7 +360,7 @@ version = "0.52.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
 dependencies = [
- "windows-targets 0.52.3",
+ "windows-targets 0.52.5",
 ]
 
 [[package]]
@@ -418,17 +380,18 @@ dependencies = [
 
 [[package]]
 name = "windows-targets"
-version = "0.52.3"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d380ba1dc7187569a8a9e91ed34b8ccfc33123bbacb8c0aed2d1ad7f3ef2dc5f"
+checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
 dependencies = [
- "windows_aarch64_gnullvm 0.52.3",
- "windows_aarch64_msvc 0.52.3",
- "windows_i686_gnu 0.52.3",
- "windows_i686_msvc 0.52.3",
- "windows_x86_64_gnu 0.52.3",
- "windows_x86_64_gnullvm 0.52.3",
- "windows_x86_64_msvc 0.52.3",
+ "windows_aarch64_gnullvm 0.52.5",
+ "windows_aarch64_msvc 0.52.5",
+ "windows_i686_gnu 0.52.5",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc 0.52.5",
+ "windows_x86_64_gnu 0.52.5",
+ "windows_x86_64_gnullvm 0.52.5",
+ "windows_x86_64_msvc 0.52.5",
 ]
 
 [[package]]
@@ -439,9 +402,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
 
 [[package]]
 name = "windows_aarch64_gnullvm"
-version = "0.52.3"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68e5dcfb9413f53afd9c8f86e56a7b4d86d9a2fa26090ea2dc9e40fba56c6ec6"
+checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
 
 [[package]]
 name = "windows_aarch64_msvc"
@@ -451,9 +414,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
 
 [[package]]
 name = "windows_aarch64_msvc"
-version = "0.52.3"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8dab469ebbc45798319e69eebf92308e541ce46760b49b18c6b3fe5e8965b30f"
+checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
 
 [[package]]
 name = "windows_i686_gnu"
@@ -463,9 +426,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
 
 [[package]]
 name = "windows_i686_gnu"
-version = "0.52.3"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a4e9b6a7cac734a8b4138a4e1044eac3404d8326b6c0f939276560687a033fb"
+checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
 
 [[package]]
 name = "windows_i686_msvc"
@@ -475,9 +444,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
 
 [[package]]
 name = "windows_i686_msvc"
-version = "0.52.3"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28b0ec9c422ca95ff34a78755cfa6ad4a51371da2a5ace67500cf7ca5f232c58"
+checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
 
 [[package]]
 name = "windows_x86_64_gnu"
@@ -487,9 +456,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
 
 [[package]]
 name = "windows_x86_64_gnu"
-version = "0.52.3"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "704131571ba93e89d7cd43482277d6632589b18ecf4468f591fbae0a8b101614"
+checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
 
 [[package]]
 name = "windows_x86_64_gnullvm"
@@ -499,9 +468,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
 
 [[package]]
 name = "windows_x86_64_gnullvm"
-version = "0.52.3"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42079295511643151e98d61c38c0acc444e52dd42ab456f7ccfd5152e8ecf21c"
+checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
 
 [[package]]
 name = "windows_x86_64_msvc"
@@ -511,6 +480,6 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
 
 [[package]]
 name = "windows_x86_64_msvc"
-version = "0.52.3"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0770833d60a970638e989b3fa9fd2bb1aaadcf88963d1659fd7d9990196ed2d6"
+checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
diff --git a/src/tools/miri/cargo-miri/src/phases.rs b/src/tools/miri/cargo-miri/src/phases.rs
index b774ca8fa72..e2fc2a0c277 100644
--- a/src/tools/miri/cargo-miri/src/phases.rs
+++ b/src/tools/miri/cargo-miri/src/phases.rs
@@ -28,7 +28,7 @@ Examples:
     cargo miri run
     cargo miri test -- test-suite-filter
 
-    cargo miri setup --print sysroot
+    cargo miri setup --print-sysroot
         This will print the path to the generated sysroot (and nothing else) on stdout.
         stderr will still contain progress information about how the build is doing.
 
@@ -87,6 +87,7 @@ pub fn phase_cargo_miri(mut args: impl Iterator<Item = String>) {
             ),
     };
     let verbose = num_arg_flag("-v");
+    let quiet = has_arg_flag("-q") || has_arg_flag("--quiet");
 
     // Determine the involved architectures.
     let rustc_version = VersionMeta::for_command(miri_for_host()).unwrap_or_else(|err| {
@@ -110,7 +111,7 @@ pub fn phase_cargo_miri(mut args: impl Iterator<Item = String>) {
     }
 
     // We always setup.
-    let miri_sysroot = setup(&subcommand, target, &rustc_version, verbose);
+    let miri_sysroot = setup(&subcommand, target, &rustc_version, verbose, quiet);
 
     // Invoke actual cargo for the job, but with different flags.
     // We re-use `cargo test` and `cargo run`, which makes target and binary handling very easy but
diff --git a/src/tools/miri/cargo-miri/src/setup.rs b/src/tools/miri/cargo-miri/src/setup.rs
index 401e9158fae..9a58e6fa018 100644
--- a/src/tools/miri/cargo-miri/src/setup.rs
+++ b/src/tools/miri/cargo-miri/src/setup.rs
@@ -19,6 +19,7 @@ pub fn setup(
     target: &str,
     rustc_version: &VersionMeta,
     verbose: usize,
+    quiet: bool,
 ) -> PathBuf {
     let only_setup = matches!(subcommand, MiriCommand::Setup);
     let ask_user = !only_setup;
@@ -119,6 +120,9 @@ pub fn setup(
             for _ in 0..verbose {
                 command.arg("-v");
             }
+            if quiet {
+                command.arg("--quiet");
+            }
         } else {
             // Suppress output.
             command.stdout(process::Stdio::null());
@@ -134,7 +138,7 @@ pub fn setup(
     let rustflags = &["-Cdebug-assertions=off", "-Coverflow-checks=on"];
 
     // Do the build.
-    if print_sysroot {
+    if print_sysroot || quiet {
         // Be silent.
     } else {
         let mut msg = String::new();
@@ -169,7 +173,7 @@ pub fn setup(
                 )
             }
         });
-    if print_sysroot {
+    if print_sysroot || quiet {
         // Be silent.
     } else if only_setup {
         eprintln!("A sysroot for Miri is now available in `{}`.", sysroot_dir.display());
diff --git a/src/tools/miri/ci/ci.sh b/src/tools/miri/ci/ci.sh
index c1ffb80783e..713c97830a5 100755
--- a/src/tools/miri/ci/ci.sh
+++ b/src/tools/miri/ci/ci.sh
@@ -13,15 +13,6 @@ function endgroup {
 
 begingroup "Building Miri"
 
-# Special Windows hacks
-if [ "$HOST_TARGET" = i686-pc-windows-msvc ]; then
-  # The $BASH variable is `/bin/bash` here, but that path does not actually work. There are some
-  # hacks in place somewhere to try to paper over this, but the hacks dont work either (see
-  # <https://github.com/rust-lang/miri/pull/3402>). So we hard-code the correct location for Github
-  # CI instead.
-  BASH="C:/Program Files/Git/usr/bin/bash"
-fi
-
 # Global configuration
 export RUSTFLAGS="-D warnings"
 export CARGO_INCREMENTAL=0
@@ -71,10 +62,9 @@ function run_tests {
     time MIRIFLAGS="${MIRIFLAGS-} -O -Zmir-opt-level=4 -Cdebug-assertions=yes" MIRI_SKIP_UI_CHECKS=1 ./miri test -- tests/{pass,panic}
   fi
   if [ -n "${MANY_SEEDS-}" ]; then
-    # Also run some many-seeds tests. 64 seeds means this takes around a minute per test.
-    # (Need to invoke via explicit `bash -c` for Windows.)
+    # Also run some many-seeds tests.
     time for FILE in tests/many-seeds/*.rs; do
-      MIRI_SEEDS=$MANY_SEEDS ./miri many-seeds "$BASH" -c "./miri run '$FILE'"
+      ./miri run "--many-seeds=0..$MANY_SEEDS" "$FILE"
     done
   fi
   if [ -n "${TEST_BENCH-}" ]; then
@@ -117,10 +107,10 @@ function run_tests_minimal {
     exit 1
   fi
 
-  ./miri test -- "$@"
+  time ./miri test -- "$@"
 
   # Ensure that a small smoke test of cargo-miri works.
-  cargo miri run --manifest-path test-cargo-miri/no-std-smoke/Cargo.toml --target ${MIRI_TEST_TARGET-$HOST_TARGET}
+  time cargo miri run --manifest-path test-cargo-miri/no-std-smoke/Cargo.toml --target ${MIRI_TEST_TARGET-$HOST_TARGET}
 
   endgroup
 }
@@ -135,23 +125,11 @@ case $HOST_TARGET in
     GC_STRESS=1 MIR_OPT=1 MANY_SEEDS=64 TEST_BENCH=1 CARGO_MIRI_ENV=1 run_tests
     # Extra tier 1
     # With reduced many-seed count to avoid spending too much time on that.
-    # (All OSes are run with 64 seeds at least once though via the macOS runner.)
+    # (All OSes and ABIs are run with 64 seeds at least once though via the macOS runner.)
     MANY_SEEDS=16 MIRI_TEST_TARGET=i686-unknown-linux-gnu run_tests
     MANY_SEEDS=16 MIRI_TEST_TARGET=aarch64-unknown-linux-gnu run_tests
     MANY_SEEDS=16 MIRI_TEST_TARGET=x86_64-apple-darwin run_tests
     MANY_SEEDS=16 MIRI_TEST_TARGET=x86_64-pc-windows-gnu run_tests
-    # Extra tier 2
-    MIRI_TEST_TARGET=aarch64-apple-darwin run_tests
-    MIRI_TEST_TARGET=arm-unknown-linux-gnueabi run_tests
-    # Partially supported targets (tier 2)
-    MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple pthread-threadname libc-getentropy libc-getrandom libc-misc libc-fs atomic env align num_cpus
-    MIRI_TEST_TARGET=i686-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple pthread-threadname libc-getentropy libc-getrandom libc-misc libc-fs atomic env align num_cpus
-    MIRI_TEST_TARGET=aarch64-linux-android run_tests_minimal hello integer vec panic/panic
-    MIRI_TEST_TARGET=wasm32-wasi run_tests_minimal no_std integer strings wasm
-    MIRI_TEST_TARGET=wasm32-unknown-unknown run_tests_minimal no_std integer strings wasm
-    MIRI_TEST_TARGET=thumbv7em-none-eabihf run_tests_minimal no_std
-    # Custom target JSON file
-    MIRI_TEST_TARGET=tests/avr.json MIRI_NO_STD=1 run_tests_minimal no_std
     ;;
   aarch64-apple-darwin)
     # Host (tier 2)
@@ -160,13 +138,28 @@ case $HOST_TARGET in
     MANY_SEEDS=64 MIRI_TEST_TARGET=i686-pc-windows-gnu run_tests
     MANY_SEEDS=64 MIRI_TEST_TARGET=x86_64-pc-windows-msvc CARGO_MIRI_ENV=1 run_tests
     # Extra tier 2
-    MIRI_TEST_TARGET=s390x-unknown-linux-gnu run_tests # big-endian architecture
+    MIRI_TEST_TARGET=arm-unknown-linux-gnueabi run_tests
+    MIRI_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
+    MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal $BASIC panic/panic concurrency/simple atomic threadname libc-misc libc-random libc-time fs env num_cpus
+    MIRI_TEST_TARGET=i686-unknown-freebsd   run_tests_minimal $BASIC panic/panic concurrency/simple atomic threadname libc-misc libc-random libc-time fs env num_cpus
+    MIRI_TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $VERY_BASIC hello panic/panic concurrency/simple pthread-sync libc-misc libc-random
+    # TODO fix solaris stack guard
+    # MIRI_TEST_TARGET=x86_64-pc-solaris run_tests_minimal $VERY_BASIC hello panic/panic pthread-sync
+    MIRI_TEST_TARGET=aarch64-linux-android  run_tests_minimal $VERY_BASIC hello panic/panic
+    MIRI_TEST_TARGET=wasm32-wasi run_tests_minimal $VERY_BASIC wasm
+    MIRI_TEST_TARGET=wasm32-unknown-unknown run_tests_minimal $VERY_BASIC wasm
+    MIRI_TEST_TARGET=thumbv7em-none-eabihf run_tests_minimal no_std
+    # Custom target JSON file
+    MIRI_TEST_TARGET=tests/avr.json MIRI_NO_STD=1 run_tests_minimal no_std
     ;;
   i686-pc-windows-msvc)
     # Host
-    # Only smoke-test `many-seeds`; 64 runs of just the scoped-thread-leak test take 15min here!
-    # See <https://github.com/rust-lang/miri/issues/3509>.
-    GC_STRESS=1 MIR_OPT=1 MANY_SEEDS=1 TEST_BENCH=1 run_tests
+    # Without GC_STRESS and with reduced many-seeds count as this is the slowest runner.
+    # (The macOS runner checks windows-msvc with full many-seeds count.)
+    MIR_OPT=1 MANY_SEEDS=16 TEST_BENCH=1 run_tests
     # Extra tier 1
     # We really want to ensure a Linux target works on a Windows host,
     # and a 64bit target works on a 32bit host.
diff --git a/src/tools/miri/miri-script/Cargo.lock b/src/tools/miri/miri-script/Cargo.lock
index a6f7467f0a2..5e792abac17 100644
--- a/src/tools/miri/miri-script/Cargo.lock
+++ b/src/tools/miri/miri-script/Cargo.lock
@@ -466,15 +466,15 @@ checksum = "0770833d60a970638e989b3fa9fd2bb1aaadcf88963d1659fd7d9990196ed2d6"
 
 [[package]]
 name = "xshell"
-version = "0.2.5"
+version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce2107fe03e558353b4c71ad7626d58ed82efaf56c54134228608893c77023ad"
+checksum = "6db0ab86eae739efd1b054a8d3d16041914030ac4e01cd1dca0cf252fd8b6437"
 dependencies = [
  "xshell-macros",
 ]
 
 [[package]]
 name = "xshell-macros"
-version = "0.2.5"
+version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e2c411759b501fb9501aac2b1b2d287a6e93e5bdcf13c25306b23e1b716dd0e"
+checksum = "9d422e8e38ec76e2f06ee439ccc765e9c6a9638b9e7c9f2e8255e4d41e8bd852"
diff --git a/src/tools/miri/miri-script/Cargo.toml b/src/tools/miri/miri-script/Cargo.toml
index 79d0b13600d..631d3a82102 100644
--- a/src/tools/miri/miri-script/Cargo.toml
+++ b/src/tools/miri/miri-script/Cargo.toml
@@ -19,7 +19,7 @@ itertools = "0.11"
 path_macro = "1.0"
 shell-words = "1.1"
 anyhow = "1.0"
-xshell = "0.2"
+xshell = "0.2.6"
 rustc_version = "0.4"
 dunce = "1.0.4"
 directories = "5"
diff --git a/src/tools/miri/miri-script/src/commands.rs b/src/tools/miri/miri-script/src/commands.rs
index 66707dee5e7..6d07455c0de 100644
--- a/src/tools/miri/miri-script/src/commands.rs
+++ b/src/tools/miri/miri-script/src/commands.rs
@@ -2,6 +2,7 @@ use std::env;
 use std::ffi::OsString;
 use std::io::Write;
 use std::ops::Not;
+use std::ops::Range;
 use std::path::PathBuf;
 use std::process;
 use std::thread;
@@ -150,7 +151,6 @@ impl Command {
             | Command::Fmt { .. }
             | Command::Clippy { .. }
             | Command::Cargo { .. } => Self::auto_actions()?,
-            | Command::ManySeeds { .. }
             | Command::Toolchain { .. }
             | Command::Bench { .. }
             | Command::RustcPull { .. }
@@ -162,11 +162,11 @@ impl Command {
             Command::Build { flags } => Self::build(flags),
             Command::Check { flags } => Self::check(flags),
             Command::Test { bless, flags } => Self::test(bless, flags),
-            Command::Run { dep, flags } => Self::run(dep, flags),
+            Command::Run { dep, verbose, many_seeds, flags } =>
+                Self::run(dep, verbose, many_seeds, flags),
             Command::Fmt { flags } => Self::fmt(flags),
             Command::Clippy { flags } => Self::clippy(flags),
             Command::Cargo { flags } => Self::cargo(flags),
-            Command::ManySeeds { command } => Self::many_seeds(command),
             Command::Bench { benches } => Self::bench(benches),
             Command::Toolchain { flags } => Self::toolchain(flags),
             Command::RustcPull { commit } => Self::rustc_pull(commit.clone()),
@@ -239,6 +239,8 @@ impl Command {
         // the merge has confused the heck out of josh in the past.
         // We pass `--no-verify` to avoid running git hooks like `./miri fmt` that could in turn
         // trigger auto-actions.
+        // We do this before the merge so that if there are merge conflicts, we have
+        // the right rust-version file while resolving them.
         sh.write_file("rust-version", format!("{commit}\n"))?;
         const PREPARING_COMMIT_MESSAGE: &str = "Preparing for merge from rustc";
         cmd!(sh, "git commit rust-version --no-verify -m {PREPARING_COMMIT_MESSAGE}")
@@ -257,12 +259,26 @@ impl Command {
             })
             .context("FAILED to fetch new commits, something went wrong (committing the rust-version file has been undone)")?;
 
+        // This should not add any new root commits. So count those before and after merging.
+        let num_roots = || -> Result<u32> {
+            Ok(cmd!(sh, "git rev-list HEAD --max-parents=0 --count")
+                .read()
+                .context("failed to determine the number of root commits")?
+                .parse::<u32>()?)
+        };
+        let num_roots_before = num_roots()?;
+
         // Merge the fetched commit.
         const MERGE_COMMIT_MESSAGE: &str = "Merge from rustc";
         cmd!(sh, "git merge FETCH_HEAD --no-verify --no-ff -m {MERGE_COMMIT_MESSAGE}")
             .run()
             .context("FAILED to merge new commits, something went wrong")?;
 
+        // Check that the number of roots did not increase.
+        if num_roots()? != num_roots_before {
+            bail!("Josh created a new root commit. This is probably not the history you want.");
+        }
+
         drop(josh);
         Ok(())
     }
@@ -353,43 +369,6 @@ impl Command {
         Ok(())
     }
 
-    fn many_seeds(command: Vec<OsString>) -> Result<()> {
-        let seed_start: u64 = env::var("MIRI_SEED_START")
-            .unwrap_or_else(|_| "0".into())
-            .parse()
-            .context("failed to parse MIRI_SEED_START")?;
-        let seed_end: u64 = match (env::var("MIRI_SEEDS"), env::var("MIRI_SEED_END")) {
-            (Ok(_), Ok(_)) => bail!("Only one of MIRI_SEEDS and MIRI_SEED_END may be set"),
-            (Ok(seeds), Err(_)) =>
-                seed_start + seeds.parse::<u64>().context("failed to parse MIRI_SEEDS")?,
-            (Err(_), Ok(seed_end)) => seed_end.parse().context("failed to parse MIRI_SEED_END")?,
-            (Err(_), Err(_)) => seed_start + 256,
-        };
-        if seed_end <= seed_start {
-            bail!("the end of the seed range must be larger than the start.");
-        }
-
-        let Some((command_name, trailing_args)) = command.split_first() else {
-            bail!("expected many-seeds command to be non-empty");
-        };
-        let sh = Shell::new()?;
-        sh.set_var("MIRI_AUTO_OPS", "no"); // just in case we get recursively invoked
-        for seed in seed_start..seed_end {
-            println!("Trying seed: {seed}");
-            let mut miriflags = env::var_os("MIRIFLAGS").unwrap_or_default();
-            miriflags.push(format!(" -Zlayout-seed={seed} -Zmiri-seed={seed}"));
-            let status = cmd!(sh, "{command_name} {trailing_args...}")
-                .env("MIRIFLAGS", miriflags)
-                .quiet()
-                .run();
-            if let Err(err) = status {
-                println!("Failing seed: {seed}");
-                return Err(err.into());
-            }
-        }
-        Ok(())
-    }
-
     fn bench(benches: Vec<OsString>) -> Result<()> {
         // The hyperfine to use
         let hyperfine = env::var("HYPERFINE");
@@ -481,7 +460,12 @@ impl Command {
         Ok(())
     }
 
-    fn run(dep: bool, mut flags: Vec<OsString>) -> Result<()> {
+    fn run(
+        dep: bool,
+        verbose: bool,
+        many_seeds: Option<Range<u32>>,
+        mut flags: Vec<OsString>,
+    ) -> Result<()> {
         let mut e = MiriEnv::new()?;
         // Scan for "--target" to overwrite the "MIRI_TEST_TARGET" env var so
         // that we set the MIRI_SYSROOT up the right way. We must make sure that
@@ -508,26 +492,49 @@ impl Command {
         }
 
         // Prepare a sysroot, and add it to the flags.
-        let miri_sysroot = e.build_miri_sysroot(/* quiet */ true)?;
+        let miri_sysroot = e.build_miri_sysroot(/* quiet */ !verbose)?;
         flags.push("--sysroot".into());
         flags.push(miri_sysroot.into());
 
-        // Then run the actual command. Also add MIRIFLAGS.
+        // Compute everything needed to run the actual command. Also add MIRIFLAGS.
         let miri_manifest = path!(e.miri_dir / "Cargo.toml");
         let miri_flags = e.sh.var("MIRIFLAGS").unwrap_or_default();
         let miri_flags = flagsplit(&miri_flags);
         let toolchain = &e.toolchain;
         let extra_flags = &e.cargo_extra_flags;
-        if dep {
-            cmd!(
-                e.sh,
-                "cargo +{toolchain} --quiet test {extra_flags...} --manifest-path {miri_manifest} --test ui -- --miri-run-dep-mode {miri_flags...} {flags...}"
-            ).quiet().run()?;
+        let quiet_flag = if verbose { None } else { Some("--quiet") };
+        // This closure runs the command with the given `seed_flag` added between the MIRIFLAGS and
+        // the `flags` given on the command-line.
+        let run_miri = |sh: &Shell, seed_flag: Option<String>| -> Result<()> {
+            // The basic command that executes the Miri driver.
+            let mut cmd = if dep {
+                cmd!(
+                    sh,
+                    "cargo +{toolchain} {quiet_flag...} test {extra_flags...} --manifest-path {miri_manifest} --test ui -- --miri-run-dep-mode"
+                )
+            } else {
+                cmd!(
+                    sh,
+                    "cargo +{toolchain} {quiet_flag...} run {extra_flags...} --manifest-path {miri_manifest} --"
+                )
+            };
+            cmd.set_quiet(!verbose);
+            // Add Miri flags
+            let cmd = cmd.args(&miri_flags).args(seed_flag).args(&flags);
+            // And run the thing.
+            Ok(cmd.run()?)
+        };
+        // Run the closure once or many times.
+        if let Some(seed_range) = many_seeds {
+            e.run_many_times(seed_range, |sh, seed| {
+                eprintln!("Trying seed: {seed}");
+                run_miri(sh, Some(format!("-Zmiri-seed={seed}"))).map_err(|err| {
+                    eprintln!("FAILING SEED: {seed}");
+                    err
+                })
+            })?;
         } else {
-            cmd!(
-                e.sh,
-                "cargo +{toolchain} --quiet run {extra_flags...} --manifest-path {miri_manifest} -- {miri_flags...} {flags...}"
-            ).quiet().run()?;
+            run_miri(&e.sh, None)?;
         }
         Ok(())
     }
diff --git a/src/tools/miri/miri-script/src/main.rs b/src/tools/miri/miri-script/src/main.rs
index 712180be282..f0ebbc84690 100644
--- a/src/tools/miri/miri-script/src/main.rs
+++ b/src/tools/miri/miri-script/src/main.rs
@@ -3,10 +3,10 @@
 mod commands;
 mod util;
 
-use std::env;
 use std::ffi::OsString;
+use std::{env, ops::Range};
 
-use anyhow::{anyhow, bail, Result};
+use anyhow::{anyhow, bail, Context, Result};
 
 #[derive(Clone, Debug)]
 pub enum Command {
@@ -38,6 +38,8 @@ pub enum Command {
     /// (Also respects MIRIFLAGS environment variable.)
     Run {
         dep: bool,
+        verbose: bool,
+        many_seeds: Option<Range<u32>>,
         /// Flags that are passed through to `miri`.
         flags: Vec<OsString>,
     },
@@ -54,10 +56,6 @@ pub enum Command {
     /// Runs just `cargo <flags>` with the Miri-specific environment variables.
     /// Mainly meant to be invoked by rust-analyzer.
     Cargo { flags: Vec<OsString> },
-    /// Runs <command> over and over again with different seeds for Miri. The MIRIFLAGS
-    /// variable is set to its original value appended with ` -Zmiri-seed=$SEED` for
-    /// many different seeds.
-    ManySeeds { command: Vec<OsString> },
     /// Runs the benchmarks from bench-cargo-miri in hyperfine. hyperfine needs to be installed.
     Bench {
         /// List of benchmarks to run. By default all benchmarks are run.
@@ -90,9 +88,11 @@ Just check miri. <flags> are passed to `cargo check`.
 Build miri, set up a sysroot and then run the test suite. <flags> are passed
 to the final `cargo test` invocation.
 
-./miri run [--dep] <flags>:
+./miri run [--dep] [-v|--verbose] [--many-seeds|--many-seeds=..to|--many-seeds=from..to] <flags>:
 Build miri, set up a sysroot and then run the driver with the given <flags>.
 (Also respects MIRIFLAGS environment variable.)
+If `--many-seeds` is present, Miri is run many times in parallel with different seeds.
+The range defaults to `0..256`.
 
 ./miri fmt <flags>:
 Format all sources and tests. <flags> are passed to `rustfmt`.
@@ -110,13 +110,6 @@ install`. Sets up the rpath such that the installed binary should work in any
 working directory. Note that the binaries are placed in the `miri` toolchain
 sysroot, to prevent conflicts with other toolchains.
 
-./miri many-seeds <command>:
-Runs <command> over and over again with different seeds for Miri. The MIRIFLAGS
-variable is set to its original value appended with ` -Zmiri-seed=$SEED` for
-many different seeds. MIRI_SEED_START controls the first seed to try (default: 0).
-MIRI_SEEDS controls how many seeds are being tried (default: 256);
-alternatively, MIRI_SEED_END controls the end of the (exclusive) seed range to try.
-
 ./miri bench <benches>:
 Runs the benchmarks from bench-cargo-miri in hyperfine. hyperfine needs to be installed.
 <benches> can explicitly list the benchmarks to run; by default, all of them are run.
@@ -132,10 +125,10 @@ Pull and merge Miri changes from the rustc repo. Defaults to fetching the latest
 rustc commit. The fetched commit is stored in the `rust-version` file, so the
 next `./miri toolchain` will install the rustc that just got pulled.
 
-./miri rustc-push <github user> <branch>:
+./miri rustc-push <github user> [<branch>]:
 Push Miri changes back to the rustc repo. This will pull a copy of the rustc
 history into the Miri repo, unless you set the RUSTC_GIT env var to an existing
-clone of the rustc repo.
+clone of the rustc repo. The branch defaults to `miri-sync`.
 
   ENVIRONMENT VARIABLES
 
@@ -162,18 +155,39 @@ fn main() -> Result<()> {
             Command::Test { bless, flags: args.collect() }
         }
         Some("run") => {
-            let dep = args.peek().is_some_and(|a| a.to_str() == Some("--dep"));
-            if dep {
-                // Consume the flag.
+            let mut dep = false;
+            let mut verbose = false;
+            let mut many_seeds = None;
+            while let Some(arg) = args.peek().and_then(|s| s.to_str()) {
+                if arg == "--dep" {
+                    dep = true;
+                } else if arg == "-v" || arg == "--verbose" {
+                    verbose = true;
+                } else if arg == "--many-seeds" {
+                    many_seeds = Some(0..256);
+                } else if let Some(val) = arg.strip_prefix("--many-seeds=") {
+                    let (from, to) = val.split_once("..").ok_or_else(|| {
+                        anyhow!("invalid format for `--many-seeds`: expected `from..to`")
+                    })?;
+                    let from: u32 = if from.is_empty() {
+                        0
+                    } else {
+                        from.parse().context("invalid `from` in `--many-seeds=from..to")?
+                    };
+                    let to: u32 = to.parse().context("invalid `to` in `--many-seeds=from..to")?;
+                    many_seeds = Some(from..to);
+                } else {
+                    break; // not for us
+                }
+                // Consume the flag, look at the next one.
                 args.next().unwrap();
             }
-            Command::Run { dep, flags: args.collect() }
+            Command::Run { dep, verbose, many_seeds, flags: args.collect() }
         }
         Some("fmt") => Command::Fmt { flags: args.collect() },
         Some("clippy") => Command::Clippy { flags: args.collect() },
         Some("cargo") => Command::Cargo { flags: args.collect() },
         Some("install") => Command::Install { flags: args.collect() },
-        Some("many-seeds") => Command::ManySeeds { command: args.collect() },
         Some("bench") => Command::Bench { benches: args.collect() },
         Some("toolchain") => Command::Toolchain { flags: args.collect() },
         Some("rustc-pull") => {
@@ -187,17 +201,12 @@ fn main() -> Result<()> {
             let github_user = args
                 .next()
                 .ok_or_else(|| {
-                    anyhow!("Missing first argument for `./miri rustc-push GITHUB_USER BRANCH`")
-                })?
-                .to_string_lossy()
-                .into_owned();
-            let branch = args
-                .next()
-                .ok_or_else(|| {
-                    anyhow!("Missing second argument for `./miri rustc-push GITHUB_USER BRANCH`")
+                    anyhow!("Missing first argument for `./miri rustc-push GITHUB_USER [BRANCH]`")
                 })?
                 .to_string_lossy()
                 .into_owned();
+            let branch =
+                args.next().unwrap_or_else(|| "miri-sync".into()).to_string_lossy().into_owned();
             if args.next().is_some() {
                 bail!("Too many arguments for `./miri rustc-push GITHUB_USER BRANCH`");
             }
diff --git a/src/tools/miri/miri-script/src/util.rs b/src/tools/miri/miri-script/src/util.rs
index 361a4ca0cf7..23b5e936edd 100644
--- a/src/tools/miri/miri-script/src/util.rs
+++ b/src/tools/miri/miri-script/src/util.rs
@@ -1,5 +1,8 @@
 use std::ffi::{OsStr, OsString};
+use std::ops::Range;
 use std::path::{Path, PathBuf};
+use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};
+use std::thread;
 
 use anyhow::{anyhow, Context, Result};
 use dunce::canonicalize;
@@ -189,4 +192,54 @@ impl MiriEnv {
 
         Ok(())
     }
+
+    /// Run the given closure many times in parallel with access to the shell, once for each value in the `range`.
+    pub fn run_many_times(
+        &self,
+        range: Range<u32>,
+        run: impl Fn(&Shell, u32) -> Result<()> + Sync,
+    ) -> Result<()> {
+        // `next` is atomic so threads can concurrently fetch their next value to run.
+        let next = AtomicU32::new(range.start);
+        let end = range.end; // exclusive!
+        let failed = AtomicBool::new(false);
+        thread::scope(|s| {
+            let mut handles = Vec::new();
+            // Spawn one worker per core.
+            for _ in 0..thread::available_parallelism()?.get() {
+                // Create a copy of the shell for this thread.
+                let local_shell = self.sh.clone();
+                let handle = s.spawn(|| -> Result<()> {
+                    let local_shell = local_shell; // move the copy into this thread.
+                    // Each worker thread keeps asking for numbers until we're all done.
+                    loop {
+                        let cur = next.fetch_add(1, Ordering::Relaxed);
+                        if cur >= end {
+                            // We hit the upper limit and are done.
+                            break;
+                        }
+                        // Run the command with this seed.
+                        run(&local_shell, cur).map_err(|err| {
+                            // If we failed, tell everyone about this.
+                            failed.store(true, Ordering::Relaxed);
+                            err
+                        })?;
+                        // Check if some other command failed (in which case we'll stop as well).
+                        if failed.load(Ordering::Relaxed) {
+                            return Ok(());
+                        }
+                    }
+                    Ok(())
+                });
+                handles.push(handle);
+            }
+            // Wait for all workers to be done.
+            for handle in handles {
+                handle.join().unwrap()?;
+            }
+            // If all workers succeeded, we can't have failed.
+            assert!(!failed.load(Ordering::Relaxed));
+            Ok(())
+        })
+    }
 }
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index a45ecda15c4..ca6f4d50917 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-6acb9e75ebc936df737381a9d0b7a7bccd6f0b2f
+d568423a7a4ddb4b49323d96078a22f94df55fbd
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs
index 2470624181e..ff4589657af 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs
@@ -106,6 +106,8 @@ impl LocationState {
         let old_perm = self.permission;
         let transition = Permission::perform_access(access_kind, rel_pos, old_perm, protected)
             .ok_or(TransitionError::ChildAccessForbidden(old_perm))?;
+        self.initialized |= !rel_pos.is_foreign();
+        self.permission = transition.applied(old_perm).unwrap();
         // Why do only initialized locations cause protector errors?
         // Consider two mutable references `x`, `y` into disjoint parts of
         // the same allocation. A priori, these may actually both be used to
@@ -123,8 +125,6 @@ impl LocationState {
         if protected && self.initialized && transition.produces_disabled() {
             return Err(TransitionError::ProtectedDisabled(old_perm));
         }
-        self.permission = transition.applied(old_perm).unwrap();
-        self.initialized |= !rel_pos.is_foreign();
         Ok(transition)
     }
 
diff --git a/src/tools/miri/src/concurrency/sync.rs b/src/tools/miri/src/concurrency/sync.rs
index d3cef8bf5f3..94676955999 100644
--- a/src/tools/miri/src/concurrency/sync.rs
+++ b/src/tools/miri/src/concurrency/sync.rs
@@ -305,6 +305,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let this = self.eval_context_mut();
         let next_index = this.machine.threads.sync.mutexes.next_index();
         if let Some(old) = existing(this, next_index)? {
+            if this.machine.threads.sync.mutexes.get(old).is_none() {
+                throw_ub_format!("mutex has invalid ID");
+            }
             Ok(old)
         } else {
             let new_index = this.machine.threads.sync.mutexes.push(Default::default());
@@ -399,6 +402,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let this = self.eval_context_mut();
         let next_index = this.machine.threads.sync.rwlocks.next_index();
         if let Some(old) = existing(this, next_index)? {
+            if this.machine.threads.sync.rwlocks.get(old).is_none() {
+                throw_ub_format!("rwlock has invalid ID");
+            }
             Ok(old)
         } else {
             let new_index = this.machine.threads.sync.rwlocks.push(Default::default());
@@ -563,6 +569,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let this = self.eval_context_mut();
         let next_index = this.machine.threads.sync.condvars.next_index();
         if let Some(old) = existing(this, next_index)? {
+            if this.machine.threads.sync.condvars.get(old).is_none() {
+                throw_ub_format!("condvar has invalid ID");
+            }
             Ok(old)
         } else {
             let new_index = this.machine.threads.sync.condvars.push(Default::default());
diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs
index 0116bd0281a..6953ce81c5e 100644
--- a/src/tools/miri/src/concurrency/thread.rs
+++ b/src/tools/miri/src/concurrency/thread.rs
@@ -78,6 +78,13 @@ impl TryFrom<u64> for ThreadId {
     }
 }
 
+impl TryFrom<i128> for ThreadId {
+    type Error = TryFromIntError;
+    fn try_from(id: i128) -> Result<Self, Self::Error> {
+        u32::try_from(id).map(Self)
+    }
+}
+
 impl From<u32> for ThreadId {
     fn from(id: u32) -> Self {
         Self(id)
diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs
index 9fa786332e3..cb5ed27b6cf 100644
--- a/src/tools/miri/src/diagnostics.rs
+++ b/src/tools/miri/src/diagnostics.rs
@@ -48,6 +48,7 @@ pub enum TerminationInfo {
         extra: Option<&'static str>,
         retag_explain: bool,
     },
+    UnsupportedForeignItem(String),
 }
 
 pub struct RacingOp {
@@ -85,6 +86,7 @@ impl fmt::Display for TerminationInfo {
                     op2.action,
                     op2.thread_info
                 ),
+            UnsupportedForeignItem(msg) => write!(f, "{msg}"),
         }
     }
 }
@@ -214,7 +216,7 @@ pub fn report_error<'tcx, 'mir>(
         let title = match info {
             Exit { code, leak_check } => return Some((*code, *leak_check)),
             Abort(_) => Some("abnormal termination"),
-            UnsupportedInIsolation(_) | Int2PtrWithStrictProvenance =>
+            UnsupportedInIsolation(_) | Int2PtrWithStrictProvenance | UnsupportedForeignItem(_) =>
                 Some("unsupported operation"),
             StackedBorrowsUb { .. } | TreeBorrowsUb { .. } | DataRace { .. } =>
                 Some("Undefined Behavior"),
@@ -228,6 +230,12 @@ pub fn report_error<'tcx, 'mir>(
                     (None, format!("pass the flag `-Zmiri-disable-isolation` to disable isolation;")),
                     (None, format!("or pass `-Zmiri-isolation-error=warn` to configure Miri to return an error code from isolated operations (if supported for that operation) and continue with a warning")),
                 ],
+            UnsupportedForeignItem(_) => {
+                vec![
+                    (None, format!("if this is a basic API commonly used on this target, please report an issue with Miri")),
+                    (None, format!("however, note that Miri does not aim to support every FFI function out there; for instance, we will not support APIs for things such as GUIs, scripting languages, or databases")),
+                ]
+            }
             StackedBorrowsUb { help, history, .. } => {
                 msg.extend(help.clone());
                 let mut helps = vec![
@@ -320,7 +328,9 @@ pub fn report_error<'tcx, 'mir>(
         #[rustfmt::skip]
         let helps = match e.kind() {
             Unsupported(_) =>
-                vec![(None, format!("this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support"))],
+                vec![
+                    (None, format!("this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support")),
+                ],
             UndefinedBehavior(AlignmentCheckFailed { .. })
                 if ecx.machine.check_alignment == AlignmentCheck::Symbolic
             =>
@@ -344,7 +354,7 @@ pub fn report_error<'tcx, 'mir>(
                     }
                     AbiMismatchArgument { .. } | AbiMismatchReturn { .. } => {
                         helps.push((None, format!("this means these two types are not *guaranteed* to be ABI-compatible across all targets")));
-                        helps.push((None, format!("if you think this code should be accepted anyway, please report an issue")));
+                        helps.push((None, format!("if you think this code should be accepted anyway, please report an issue with Miri")));
                     }
                     _ => {},
                 }
diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs
index 92bdaf30170..40c2008ac94 100644
--- a/src/tools/miri/src/helpers.rs
+++ b/src/tools/miri/src/helpers.rs
@@ -255,14 +255,19 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     }
 
     /// Evaluates the scalar at the specified path.
-    fn eval_path_scalar(&self, path: &[&str]) -> Scalar<Provenance> {
+    fn eval_path(&self, path: &[&str]) -> OpTy<'tcx, Provenance> {
         let this = self.eval_context_ref();
         let instance = this.resolve_path(path, Namespace::ValueNS);
         // We don't give a span -- this isn't actually used directly by the program anyway.
         let const_val = this.eval_global(instance).unwrap_or_else(|err| {
             panic!("failed to evaluate required Rust item: {path:?}\n{err:?}")
         });
-        this.read_scalar(&const_val)
+        const_val.into()
+    }
+    fn eval_path_scalar(&self, path: &[&str]) -> Scalar<Provenance> {
+        let this = self.eval_context_ref();
+        let val = this.eval_path(path);
+        this.read_scalar(&val)
             .unwrap_or_else(|err| panic!("failed to read required Rust item: {path:?}\n{err:?}"))
     }
 
@@ -1067,20 +1072,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         crate_name == "std" || crate_name == "std_miri_test"
     }
 
-    /// Handler that should be called when unsupported functionality is encountered.
+    /// Handler that should be called when an unsupported foreign item is encountered.
     /// This function will either panic within the context of the emulated application
     /// or return an error in the Miri process context
-    ///
-    /// Return value of `Ok(bool)` indicates whether execution should continue.
-    fn handle_unsupported<S: AsRef<str>>(&mut self, error_msg: S) -> InterpResult<'tcx, ()> {
+    fn handle_unsupported_foreign_item(&mut self, error_msg: String) -> InterpResult<'tcx, ()> {
         let this = self.eval_context_mut();
         if this.machine.panic_on_unsupported {
             // message is slightly different here to make automated analysis easier
-            let error_msg = format!("unsupported Miri functionality: {}", error_msg.as_ref());
+            let error_msg = format!("unsupported Miri functionality: {error_msg}");
             this.start_panic(error_msg.as_ref(), mir::UnwindAction::Continue)?;
             Ok(())
         } else {
-            throw_unsup_format!("{}", error_msg.as_ref());
+            throw_machine_stop!(TerminationInfo::UnsupportedForeignItem(error_msg));
         }
     }
 
diff --git a/src/tools/miri/src/shims/intrinsics/atomic.rs b/src/tools/miri/src/intrinsics/atomic.rs
index 40f6b8a64ef..40f6b8a64ef 100644
--- a/src/tools/miri/src/shims/intrinsics/atomic.rs
+++ b/src/tools/miri/src/intrinsics/atomic.rs
diff --git a/src/tools/miri/src/shims/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs
index 974943432aa..effd7f6d543 100644
--- a/src/tools/miri/src/shims/intrinsics/mod.rs
+++ b/src/tools/miri/src/intrinsics/mod.rs
@@ -91,6 +91,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         }
 
         match intrinsic_name {
+            // Basic control flow
             "abort" => {
                 throw_machine_stop!(TerminationInfo::Abort(
                     "the program aborted execution".to_owned()
@@ -98,7 +99,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             }
             "catch_unwind" => {
                 this.handle_catch_unwind(args, dest, ret)?;
-                // THis pushed a stack frame, don't jump to `ret`.
+                // This pushed a stack frame, don't jump to `ret`.
                 return Ok(EmulateItemResult::AlreadyJumped);
             }
 
@@ -193,12 +194,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             => {
                 let [f] = check_arg_count(args)?;
                 let f = this.read_scalar(f)?.to_f32()?;
-                // FIXME: Using host floats.
+                // Using host floats (but it's fine, these operations do not have guaranteed precision).
                 let f_host = f.to_host();
                 let res = match intrinsic_name {
                     "sinf32" => f_host.sin(),
                     "cosf32" => f_host.cos(),
-                    "sqrtf32" => f_host.sqrt(),
+                    "sqrtf32" => f_host.sqrt(), // FIXME Using host floats, this should use full-precision soft-floats
                     "expf32" => f_host.exp(),
                     "exp2f32" => f_host.exp2(),
                     "logf32" => f_host.ln(),
@@ -238,12 +239,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             => {
                 let [f] = check_arg_count(args)?;
                 let f = this.read_scalar(f)?.to_f64()?;
-                // FIXME: Using host floats.
+                // Using host floats (but it's fine, these operations do not have guaranteed precision).
                 let f_host = f.to_host();
                 let res = match intrinsic_name {
                     "sinf64" => f_host.sin(),
                     "cosf64" => f_host.cos(),
-                    "sqrtf64" => f_host.sqrt(),
+                    "sqrtf64" => f_host.sqrt(), // FIXME Using host floats, this should use full-precision soft-floats
                     "expf64" => f_host.exp(),
                     "exp2f64" => f_host.exp2(),
                     "logf64" => f_host.ln(),
@@ -366,7 +367,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let [f1, f2] = check_arg_count(args)?;
                 let f1 = this.read_scalar(f1)?.to_f32()?;
                 let f2 = this.read_scalar(f2)?.to_f32()?;
-                // FIXME: Using host floats.
+                // Using host floats (but it's fine, this operation does not have guaranteed precision).
                 let res = f1.to_host().powf(f2.to_host()).to_soft();
                 let res = this.adjust_nan(res, &[f1, f2]);
                 this.write_scalar(res, dest)?;
@@ -376,7 +377,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let [f1, f2] = check_arg_count(args)?;
                 let f1 = this.read_scalar(f1)?.to_f64()?;
                 let f2 = this.read_scalar(f2)?.to_f64()?;
-                // FIXME: Using host floats.
+                // Using host floats (but it's fine, this operation does not have guaranteed precision).
                 let res = f1.to_host().powf(f2.to_host()).to_soft();
                 let res = this.adjust_nan(res, &[f1, f2]);
                 this.write_scalar(res, dest)?;
@@ -386,7 +387,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let [f, i] = check_arg_count(args)?;
                 let f = this.read_scalar(f)?.to_f32()?;
                 let i = this.read_scalar(i)?.to_i32()?;
-                // FIXME: Using host floats.
+                // Using host floats (but it's fine, this operation does not have guaranteed precision).
                 let res = f.to_host().powi(i).to_soft();
                 let res = this.adjust_nan(res, &[f]);
                 this.write_scalar(res, dest)?;
@@ -396,7 +397,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let [f, i] = check_arg_count(args)?;
                 let f = this.read_scalar(f)?.to_f64()?;
                 let i = this.read_scalar(i)?.to_i32()?;
-                // FIXME: Using host floats.
+                // Using host floats (but it's fine, this operation does not have guaranteed precision).
                 let res = f.to_host().powi(i).to_soft();
                 let res = this.adjust_nan(res, &[f]);
                 this.write_scalar(res, dest)?;
diff --git a/src/tools/miri/src/shims/intrinsics/simd.rs b/src/tools/miri/src/intrinsics/simd.rs
index c7de587443a..3be98d7f5f8 100644
--- a/src/tools/miri/src/shims/intrinsics/simd.rs
+++ b/src/tools/miri/src/intrinsics/simd.rs
@@ -100,14 +100,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                             let ty::Float(float_ty) = op.layout.ty.kind() else {
                                 span_bug!(this.cur_span(), "{} operand is not a float", intrinsic_name)
                             };
-                            // FIXME using host floats
+                            // Using host floats (but it's fine, these operations do not have guaranteed precision).
                             match float_ty {
                                 FloatTy::F16 => unimplemented!("f16_f128"),
                                 FloatTy::F32 => {
                                     let f = op.to_scalar().to_f32()?;
                                     let f_host = f.to_host();
                                     let res = match host_op {
-                                        "fsqrt" => f_host.sqrt(),
+                                        "fsqrt" => f_host.sqrt(), // FIXME Using host floats, this should use full-precision soft-floats
                                         "fsin" => f_host.sin(),
                                         "fcos" => f_host.cos(),
                                         "fexp" => f_host.exp(),
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index 3b1d7687d02..1680b98eca3 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -79,6 +79,7 @@ mod concurrency;
 mod diagnostics;
 mod eval;
 mod helpers;
+mod intrinsics;
 mod machine;
 mod mono_hash_map;
 mod operator;
@@ -95,14 +96,14 @@ pub use rustc_const_eval::interpret::*;
 #[doc(no_inline)]
 pub use rustc_const_eval::interpret::{self, AllocMap, PlaceTy, Provenance as _};
 
-pub use crate::shims::EmulateItemResult;
+pub use crate::intrinsics::EvalContextExt as _;
 pub use crate::shims::env::{EnvVars, EvalContextExt as _};
 pub use crate::shims::foreign_items::{DynSym, EvalContextExt as _};
-pub use crate::shims::intrinsics::EvalContextExt as _;
 pub use crate::shims::os_str::EvalContextExt as _;
 pub use crate::shims::panic::{CatchUnwindData, EvalContextExt as _};
 pub use crate::shims::time::EvalContextExt as _;
 pub use crate::shims::tls::TlsData;
+pub use crate::shims::EmulateItemResult;
 
 pub use crate::alloc_addresses::{EvalContextExt as _, ProvenanceMode};
 pub use crate::borrow_tracker::stacked_borrows::{
diff --git a/src/tools/miri/src/shims/env.rs b/src/tools/miri/src/shims/env.rs
index fc0160fdf21..695d1138756 100644
--- a/src/tools/miri/src/shims/env.rs
+++ b/src/tools/miri/src/shims/env.rs
@@ -1,4 +1,4 @@
-use std::ffi::OsString;
+use std::ffi::{OsStr, OsString};
 
 use rustc_data_structures::fx::FxHashMap;
 
@@ -99,4 +99,15 @@ impl<'tcx> EnvVars<'tcx> {
 }
 
 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {}
+pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+    /// Try to get an environment variable from the interpreted program's environment. This is
+    /// useful for implementing shims which are documented to read from the environment.
+    fn get_env_var(&mut self, name: &OsStr) -> InterpResult<'tcx, Option<OsString>> {
+        let this = self.eval_context_ref();
+        match &this.machine.env_vars {
+            EnvVars::Uninit => return Ok(None),
+            EnvVars::Unix(vars) => vars.get(this, name),
+            EnvVars::Windows(vars) => vars.get(name),
+        }
+    }
+}
diff --git a/src/tools/miri/src/shims/extern_static.rs b/src/tools/miri/src/shims/extern_static.rs
index 442338a6117..c3c7ef7c1fd 100644
--- a/src/tools/miri/src/shims/extern_static.rs
+++ b/src/tools/miri/src/shims/extern_static.rs
@@ -16,8 +16,8 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
 
     /// Zero-initialized pointer-sized extern statics are pretty common.
     /// Most of them are for weak symbols, which we all set to null (indicating that the
-    /// symbol is not supported, and triggering fallback code which ends up calling a
-    /// syscall that we do support).
+    /// symbol is not supported, and triggering fallback code which ends up calling
+    /// some other shim that we do support).
     fn null_ptr_extern_statics(
         this: &mut MiriInterpCx<'mir, 'tcx>,
         names: &[&str],
@@ -29,6 +29,21 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
         Ok(())
     }
 
+    /// Extern statics that are initialized with function pointers to the symbols of the same name.
+    fn weak_symbol_extern_statics(
+        this: &mut MiriInterpCx<'mir, 'tcx>,
+        names: &[&str],
+    ) -> InterpResult<'tcx> {
+        for name in names {
+            assert!(this.is_dyn_sym(name), "{name} is not a dynamic symbol");
+            let layout = this.machine.layouts.const_raw_ptr;
+            let ptr = this.fn_ptr(FnVal::Other(DynSym::from_str(name)));
+            let val = ImmTy::from_scalar(Scalar::from_pointer(ptr, this), layout);
+            Self::alloc_extern_static(this, name, val)?;
+        }
+        Ok(())
+    }
+
     /// Sets up the "extern statics" for this machine.
     pub fn init_extern_statics(this: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> {
         // "__rust_no_alloc_shim_is_unstable"
@@ -44,8 +59,9 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
             "linux" => {
                 Self::null_ptr_extern_statics(
                     this,
-                    &["__cxa_thread_atexit_impl", "getrandom", "statx", "__clock_gettime64"],
+                    &["__cxa_thread_atexit_impl", "__clock_gettime64"],
                 )?;
+                Self::weak_symbol_extern_statics(this, &["getrandom", "statx"])?;
                 // "environ"
                 let environ = this.machine.env_vars.unix().environ();
                 Self::add_extern_static(this, "environ", environ);
@@ -58,12 +74,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
             }
             "android" => {
                 Self::null_ptr_extern_statics(this, &["bsd_signal"])?;
-                // "signal" -- just needs a non-zero pointer value (function does not even get called),
-                // but we arrange for this to call the `signal` function anyway.
-                let layout = this.machine.layouts.const_raw_ptr;
-                let ptr = this.fn_ptr(FnVal::Other(DynSym::from_str("signal")));
-                let val = ImmTy::from_scalar(Scalar::from_pointer(ptr, this), layout);
-                Self::alloc_extern_static(this, "signal", val)?;
+                Self::weak_symbol_extern_statics(this, &["signal"])?;
             }
             "windows" => {
                 // "_tls_used"
diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs
index 8a38c6c11a8..c51a27b7458 100644
--- a/src/tools/miri/src/shims/foreign_items.rs
+++ b/src/tools/miri/src/shims/foreign_items.rs
@@ -93,7 +93,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     return Ok(Some(body));
                 }
 
-                this.handle_unsupported(format!(
+                this.handle_unsupported_foreign_item(format!(
                     "can't call foreign function `{link_name}` on OS `{os}`",
                     os = this.tcx.sess.target.os,
                 ))?;
@@ -104,6 +104,15 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         Ok(None)
     }
 
+    fn is_dyn_sym(&self, name: &str) -> bool {
+        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),
+            "windows" => shims::windows::foreign_items::is_dyn_sym(name),
+            _ => false,
+        }
+    }
+
     /// Emulates a call to a `DynSym`.
     fn emulate_dyn_sym(
         &mut self,
@@ -396,14 +405,8 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             }
 
             // Aborting the process.
-            "exit" | "ExitProcess" => {
-                let exp_abi = if link_name.as_str() == "exit" {
-                    Abi::C { unwind: false }
-                } else {
-                    Abi::System { unwind: false }
-                };
-                let [code] = this.check_shim(abi, exp_abi, link_name, args)?;
-                // it's really u32 for ExitProcess, but we have to put it into the `Exit` variant anyway
+            "exit" => {
+                let [code] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let code = this.read_scalar(code)?.to_i32()?;
                 throw_machine_stop!(TerminationInfo::Exit { code: code.into(), leak_check: false });
             }
@@ -702,7 +705,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             => {
                 let [f] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let f = this.read_scalar(f)?.to_f32()?;
-                // FIXME: Using host floats.
+                // Using host floats (but it's fine, these operations do not have guaranteed precision).
                 let f_host = f.to_host();
                 let res = match link_name.as_str() {
                     "cbrtf" => f_host.cbrt(),
@@ -733,7 +736,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let f2 = this.read_scalar(f2)?.to_f32()?;
                 // 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)
-                // FIXME: Using host floats.
+                // Using host floats (but it's fine, these operations do not have guaranteed precision).
                 let res = match link_name.as_str() {
                     "_hypotf" | "hypotf" => f1.to_host().hypot(f2.to_host()).to_soft(),
                     "atan2f" => f1.to_host().atan2(f2.to_host()).to_soft(),
@@ -759,7 +762,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             => {
                 let [f] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let f = this.read_scalar(f)?.to_f64()?;
-                // FIXME: Using host floats.
+                // Using host floats (but it's fine, these operations do not have guaranteed precision).
                 let f_host = f.to_host();
                 let res = match link_name.as_str() {
                     "cbrt" => f_host.cbrt(),
@@ -790,7 +793,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let f2 = this.read_scalar(f2)?.to_f64()?;
                 // 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)
-                // FIXME: Using host floats.
+                // Using host floats (but it's fine, these operations do not have guaranteed precision).
                 let res = match link_name.as_str() {
                     "_hypot" | "hypot" => f1.to_host().hypot(f2.to_host()).to_soft(),
                     "atan2" => f1.to_host().atan2(f2.to_host()).to_soft(),
@@ -820,7 +823,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let x = this.read_scalar(x)?.to_f32()?;
                 let signp = this.deref_pointer(signp)?;
 
-                // FIXME: Using host floats.
+                // Using host floats (but it's fine, these operations do not have guaranteed precision).
                 let (res, sign) = x.to_host().ln_gamma();
                 this.write_int(sign, &signp)?;
                 let res = this.adjust_nan(res.to_soft(), &[x]);
@@ -831,7 +834,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let x = this.read_scalar(x)?.to_f64()?;
                 let signp = this.deref_pointer(signp)?;
 
-                // FIXME: Using host floats.
+                // Using host floats (but it's fine, these operations do not have guaranteed precision).
                 let (res, sign) = x.to_host().ln_gamma();
                 this.write_int(sign, &signp)?;
                 let res = this.adjust_nan(res.to_soft(), &[x]);
@@ -865,36 +868,6 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     throw_unsup_format!("unsupported `llvm.prefetch` type argument: {}", ty);
                 }
             }
-            // FIXME: Move these to an `arm` submodule.
-            "llvm.aarch64.isb" if this.tcx.sess.target.arch == "aarch64" => {
-                let [arg] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?;
-                let arg = this.read_scalar(arg)?.to_i32()?;
-                match arg {
-                    // SY ("full system scope")
-                    15 => {
-                        this.yield_active_thread();
-                    }
-                    _ => {
-                        throw_unsup_format!("unsupported llvm.aarch64.isb argument {}", arg);
-                    }
-                }
-            }
-            "llvm.arm.hint" if this.tcx.sess.target.arch == "arm" => {
-                let [arg] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?;
-                let arg = this.read_scalar(arg)?.to_i32()?;
-                // Note that different arguments might have different target feature requirements.
-                match arg {
-                    // YIELD
-                    1 => {
-                        this.expect_target_feature_for_intrinsic(link_name, "v6")?;
-                        this.yield_active_thread();
-                    }
-                    _ => {
-                        throw_unsup_format!("unsupported llvm.arm.hint argument {}", arg);
-                    }
-                }
-            }
-
             // Used to implement the x86 `_mm{,256,512}_popcnt_epi{8,16,32,64}` and wasm
             // `{i,u}8x16_popcnt` functions.
             name if name.starts_with("llvm.ctpop.v") => {
@@ -918,6 +891,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 }
             }
 
+            // Target-specific shims
             name if name.starts_with("llvm.x86.")
                 && (this.tcx.sess.target.arch == "x86"
                     || this.tcx.sess.target.arch == "x86_64") =>
@@ -926,6 +900,35 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     this, link_name, abi, args, dest,
                 );
             }
+            // FIXME: Move these to an `arm` submodule.
+            "llvm.aarch64.isb" if this.tcx.sess.target.arch == "aarch64" => {
+                let [arg] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?;
+                let arg = this.read_scalar(arg)?.to_i32()?;
+                match arg {
+                    // SY ("full system scope")
+                    15 => {
+                        this.yield_active_thread();
+                    }
+                    _ => {
+                        throw_unsup_format!("unsupported llvm.aarch64.isb argument {}", arg);
+                    }
+                }
+            }
+            "llvm.arm.hint" if this.tcx.sess.target.arch == "arm" => {
+                let [arg] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?;
+                let arg = this.read_scalar(arg)?.to_i32()?;
+                // Note that different arguments might have different target feature requirements.
+                match arg {
+                    // YIELD
+                    1 => {
+                        this.expect_target_feature_for_intrinsic(link_name, "v6")?;
+                        this.yield_active_thread();
+                    }
+                    _ => {
+                        throw_unsup_format!("unsupported llvm.arm.hint argument {}", arg);
+                    }
+                }
+            }
 
             // Platform-specific shims
             _ =>
diff --git a/src/tools/miri/src/shims/mod.rs b/src/tools/miri/src/shims/mod.rs
index 975efe29b4b..11048459206 100644
--- a/src/tools/miri/src/shims/mod.rs
+++ b/src/tools/miri/src/shims/mod.rs
@@ -5,7 +5,6 @@ mod backtrace;
 #[cfg(target_os = "linux")]
 pub mod ffi_support;
 pub mod foreign_items;
-pub mod intrinsics;
 pub mod unix;
 pub mod windows;
 mod x86;
diff --git a/src/tools/miri/src/shims/time.rs b/src/tools/miri/src/shims/time.rs
index dfdf58470d6..8d1f07f916c 100644
--- a/src/tools/miri/src/shims/time.rs
+++ b/src/tools/miri/src/shims/time.rs
@@ -1,8 +1,10 @@
-use std::ffi::OsString;
+use std::ffi::{OsStr, OsString};
 use std::fmt::Write;
+use std::str::FromStr;
 use std::time::{Duration, SystemTime};
 
-use chrono::{DateTime, Datelike, Local, Timelike, Utc};
+use chrono::{DateTime, Datelike, Offset, Timelike, Utc};
+use chrono_tz::Tz;
 
 use crate::concurrency::thread::MachineCallback;
 use crate::*;
@@ -136,8 +138,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             .unwrap();
         let dt_utc: DateTime<Utc> =
             DateTime::from_timestamp(sec_since_epoch, 0).expect("Invalid timestamp");
+
+        // Figure out what time zone is in use
+        let tz = this.get_env_var(OsStr::new("TZ"))?.unwrap_or_else(|| OsString::from("UTC"));
+        let tz = match tz.into_string() {
+            Ok(tz) => Tz::from_str(&tz).unwrap_or(Tz::UTC),
+            _ => Tz::UTC,
+        };
+
         // Convert that to local time, then return the broken-down time value.
-        let dt: DateTime<Local> = DateTime::from(dt_utc);
+        let dt: DateTime<Tz> = dt_utc.with_timezone(&tz);
 
         // This value is always set to -1, because there is no way to know if dst is in effect with
         // chrono crate yet.
@@ -146,17 +156,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         // tm_zone represents the timezone value in the form of: +0730, +08, -0730 or -08.
         // This may not be consistent with libc::localtime_r's result.
-        let offset_in_second = Local::now().offset().local_minus_utc();
-        let tm_gmtoff = offset_in_second;
+        let offset_in_seconds = dt.offset().fix().local_minus_utc();
+        let tm_gmtoff = offset_in_seconds;
         let mut tm_zone = String::new();
-        if offset_in_second < 0 {
+        if offset_in_seconds < 0 {
             tm_zone.push('-');
         } else {
             tm_zone.push('+');
         }
-        let offset_hour = offset_in_second.abs() / 3600;
+        let offset_hour = offset_in_seconds.abs() / 3600;
         write!(tm_zone, "{:02}", offset_hour).unwrap();
-        let offset_min = (offset_in_second.abs() % 3600) / 60;
+        let offset_min = (offset_in_seconds.abs() % 3600) / 60;
         if offset_min != 0 {
             write!(tm_zone, "{:02}", offset_min).unwrap();
         }
diff --git a/src/tools/miri/src/shims/tls.rs b/src/tools/miri/src/shims/tls.rs
index d25bae1cdc0..0dec12f0b65 100644
--- a/src/tools/miri/src/shims/tls.rs
+++ b/src/tools/miri/src/shims/tls.rs
@@ -242,21 +242,21 @@ impl<'tcx> TlsDtorsState<'tcx> {
             match &mut self.0 {
                 Init => {
                     match this.tcx.sess.target.os.as_ref() {
-                        "linux" | "freebsd" | "android" => {
-                            // Run the pthread dtors.
-                            break 'new_state PthreadDtors(Default::default());
-                        }
                         "macos" => {
                             // The macOS thread wide destructor runs "before any TLS slots get
                             // freed", so do that first.
                             this.schedule_macos_tls_dtor()?;
-                            // When the stack is empty again, go on with the pthread dtors.
+                            // When that destructor is done, go on with the pthread dtors.
+                            break 'new_state PthreadDtors(Default::default());
+                        }
+                        _ if this.target_os_is_unix() => {
+                            // All other Unixes directly jump to running the pthread dtors.
                             break 'new_state PthreadDtors(Default::default());
                         }
                         "windows" => {
                             // Determine which destructors to run.
                             let dtors = this.lookup_windows_tls_dtors()?;
-                            // And move to the final state.
+                            // And move to the next state, that runs them.
                             break 'new_state WindowsDtors(dtors);
                         }
                         _ => {
diff --git a/src/tools/miri/src/shims/unix/env.rs b/src/tools/miri/src/shims/unix/env.rs
index 128f0dcafa9..9082d13da84 100644
--- a/src/tools/miri/src/shims/unix/env.rs
+++ b/src/tools/miri/src/shims/unix/env.rs
@@ -70,6 +70,41 @@ impl<'tcx> UnixEnvVars<'tcx> {
     pub(crate) fn environ(&self) -> Pointer<Option<Provenance>> {
         self.environ.ptr()
     }
+
+    fn get_ptr<'mir>(
+        &self,
+        ecx: &InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>,
+        name: &OsStr,
+    ) -> InterpResult<'tcx, Option<Pointer<Option<Provenance>>>> {
+        // We don't care about the value as we have the `map` to keep track of everything,
+        // but we do want to do this read so it shows up as a data race.
+        let _vars_ptr = ecx.read_pointer(&self.environ)?;
+        let Some(var_ptr) = self.map.get(name) else {
+            return Ok(None);
+        };
+        // The offset is used to strip the "{name}=" part of the string.
+        let var_ptr = var_ptr.offset(
+            Size::from_bytes(u64::try_from(name.len()).unwrap().checked_add(1).unwrap()),
+            ecx,
+        )?;
+        Ok(Some(var_ptr))
+    }
+
+    /// Implementation detail for [`InterpCx::get_env_var`]. This basically does `getenv`, complete
+    /// with the reads of the environment, but returns an [`OsString`] instead of a pointer.
+    pub(crate) fn get<'mir>(
+        &self,
+        ecx: &InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>,
+        name: &OsStr,
+    ) -> InterpResult<'tcx, Option<OsString>> {
+        let var_ptr = self.get_ptr(ecx, name)?;
+        if let Some(ptr) = var_ptr {
+            let var = ecx.read_os_str_from_c_str(ptr)?;
+            Ok(Some(var.to_owned()))
+        } else {
+            Ok(None)
+        }
+    }
 }
 
 fn alloc_env_var<'mir, 'tcx>(
@@ -116,19 +151,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let name_ptr = this.read_pointer(name_op)?;
         let name = this.read_os_str_from_c_str(name_ptr)?;
 
-        // We don't care about the value as we have the `map` to keep track of everything,
-        // but we do want to do this read so it shows up as a data race.
-        let _vars_ptr = this.read_pointer(&this.machine.env_vars.unix().environ)?;
-        Ok(match this.machine.env_vars.unix().map.get(name) {
-            Some(var_ptr) => {
-                // The offset is used to strip the "{name}=" part of the string.
-                var_ptr.offset(
-                    Size::from_bytes(u64::try_from(name.len()).unwrap().checked_add(1).unwrap()),
-                    this,
-                )?
-            }
-            None => Pointer::null(),
-        })
+        let var_ptr = this.machine.env_vars.unix().get_ptr(this, name)?;
+        Ok(var_ptr.unwrap_or_else(Pointer::null))
     }
 
     fn setenv(
diff --git a/src/tools/miri/src/shims/unix/fd.rs b/src/tools/miri/src/shims/unix/fd.rs
index a5fe38b902d..e536b78d1c0 100644
--- a/src/tools/miri/src/shims/unix/fd.rs
+++ b/src/tools/miri/src/shims/unix/fd.rs
@@ -2,8 +2,10 @@
 //! standard file descriptors (stdin/stdout/stderr).
 
 use std::any::Any;
+use std::cell::{Ref, RefCell, RefMut};
 use std::collections::BTreeMap;
 use std::io::{self, ErrorKind, IsTerminal, Read, SeekFrom, Write};
+use std::rc::Rc;
 
 use rustc_middle::ty::TyCtxt;
 use rustc_target::abi::Size;
@@ -12,9 +14,10 @@ use crate::shims::unix::*;
 use crate::*;
 
 /// Represents an open file descriptor.
-pub trait FileDescriptor: std::fmt::Debug + Any {
+pub trait FileDescription: std::fmt::Debug + Any {
     fn name(&self) -> &'static str;
 
+    /// Reads as much as possible into the given buffer, and returns the number of bytes read.
     fn read<'tcx>(
         &mut self,
         _communicate_allowed: bool,
@@ -24,8 +27,9 @@ pub trait FileDescriptor: std::fmt::Debug + Any {
         throw_unsup_format!("cannot read from {}", self.name());
     }
 
+    /// Writes as much as possible from the given buffer, and returns the number of bytes written.
     fn write<'tcx>(
-        &self,
+        &mut self,
         _communicate_allowed: bool,
         _bytes: &[u8],
         _tcx: TyCtxt<'tcx>,
@@ -33,6 +37,8 @@ pub trait FileDescriptor: std::fmt::Debug + Any {
         throw_unsup_format!("cannot write to {}", self.name());
     }
 
+    /// Seeks to the given offset (which can be relative to the beginning, end, or current position).
+    /// Returns the new position from the start of the stream.
     fn seek<'tcx>(
         &mut self,
         _communicate_allowed: bool,
@@ -44,13 +50,10 @@ pub trait FileDescriptor: std::fmt::Debug + Any {
     fn close<'tcx>(
         self: Box<Self>,
         _communicate_allowed: bool,
-    ) -> InterpResult<'tcx, io::Result<i32>> {
+    ) -> InterpResult<'tcx, io::Result<()>> {
         throw_unsup_format!("cannot close {}", self.name());
     }
 
-    /// Return a new file descriptor *that refers to the same underlying object*.
-    fn dup(&mut self) -> io::Result<Box<dyn FileDescriptor>>;
-
     fn is_tty(&self, _communicate_allowed: bool) -> bool {
         // Most FDs are not tty's and the consequence of a wrong `false` are minor,
         // so we use a default impl here.
@@ -58,7 +61,7 @@ pub trait FileDescriptor: std::fmt::Debug + Any {
     }
 }
 
-impl dyn FileDescriptor {
+impl dyn FileDescription {
     #[inline(always)]
     pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
         (self as &dyn Any).downcast_ref()
@@ -70,7 +73,7 @@ impl dyn FileDescriptor {
     }
 }
 
-impl FileDescriptor for io::Stdin {
+impl FileDescription for io::Stdin {
     fn name(&self) -> &'static str {
         "stdin"
     }
@@ -88,28 +91,24 @@ impl FileDescriptor for io::Stdin {
         Ok(Read::read(self, bytes))
     }
 
-    fn dup(&mut self) -> io::Result<Box<dyn FileDescriptor>> {
-        Ok(Box::new(io::stdin()))
-    }
-
     fn is_tty(&self, communicate_allowed: bool) -> bool {
         communicate_allowed && self.is_terminal()
     }
 }
 
-impl FileDescriptor for io::Stdout {
+impl FileDescription for io::Stdout {
     fn name(&self) -> &'static str {
         "stdout"
     }
 
     fn write<'tcx>(
-        &self,
+        &mut self,
         _communicate_allowed: bool,
         bytes: &[u8],
         _tcx: TyCtxt<'tcx>,
     ) -> InterpResult<'tcx, io::Result<usize>> {
         // We allow writing to stderr even with isolation enabled.
-        let result = Write::write(&mut { self }, bytes);
+        let result = Write::write(self, bytes);
         // Stdout is buffered, flush to make sure it appears on the
         // screen.  This is the write() syscall of the interpreted
         // program, we want it to correspond to a write() syscall on
@@ -120,22 +119,18 @@ impl FileDescriptor for io::Stdout {
         Ok(result)
     }
 
-    fn dup(&mut self) -> io::Result<Box<dyn FileDescriptor>> {
-        Ok(Box::new(io::stdout()))
-    }
-
     fn is_tty(&self, communicate_allowed: bool) -> bool {
         communicate_allowed && self.is_terminal()
     }
 }
 
-impl FileDescriptor for io::Stderr {
+impl FileDescription for io::Stderr {
     fn name(&self) -> &'static str {
         "stderr"
     }
 
     fn write<'tcx>(
-        &self,
+        &mut self,
         _communicate_allowed: bool,
         bytes: &[u8],
         _tcx: TyCtxt<'tcx>,
@@ -145,10 +140,6 @@ impl FileDescriptor for io::Stderr {
         Ok(Write::write(&mut { self }, bytes))
     }
 
-    fn dup(&mut self) -> io::Result<Box<dyn FileDescriptor>> {
-        Ok(Box::new(io::stderr()))
-    }
-
     fn is_tty(&self, communicate_allowed: bool) -> bool {
         communicate_allowed && self.is_terminal()
     }
@@ -158,13 +149,13 @@ impl FileDescriptor for io::Stderr {
 #[derive(Debug)]
 pub struct NullOutput;
 
-impl FileDescriptor for NullOutput {
+impl FileDescription for NullOutput {
     fn name(&self) -> &'static str {
         "stderr and stdout"
     }
 
     fn write<'tcx>(
-        &self,
+        &mut self,
         _communicate_allowed: bool,
         bytes: &[u8],
         _tcx: TyCtxt<'tcx>,
@@ -172,16 +163,30 @@ impl FileDescriptor for NullOutput {
         // We just don't write anything, but report to the user that we did.
         Ok(Ok(bytes.len()))
     }
+}
+
+#[derive(Clone, Debug)]
+pub struct FileDescriptor(Rc<RefCell<Box<dyn FileDescription>>>);
+
+impl FileDescriptor {
+    pub fn new<T: FileDescription>(fd: T) -> Self {
+        FileDescriptor(Rc::new(RefCell::new(Box::new(fd))))
+    }
 
-    fn dup(&mut self) -> io::Result<Box<dyn FileDescriptor>> {
-        Ok(Box::new(NullOutput))
+    pub fn close<'ctx>(self, communicate_allowed: bool) -> InterpResult<'ctx, io::Result<()>> {
+        // Destroy this `Rc` using `into_inner` so we can call `close` instead of
+        // implicitly running the destructor of the file description.
+        match Rc::into_inner(self.0) {
+            Some(fd) => RefCell::into_inner(fd).close(communicate_allowed),
+            None => Ok(Ok(())),
+        }
     }
 }
 
 /// The file descriptor table
 #[derive(Debug)]
 pub struct FdTable {
-    pub fds: BTreeMap<i32, Box<dyn FileDescriptor>>,
+    pub fds: BTreeMap<i32, FileDescriptor>,
 }
 
 impl VisitProvenance for FdTable {
@@ -192,28 +197,24 @@ impl VisitProvenance for FdTable {
 
 impl FdTable {
     pub(crate) fn new(mute_stdout_stderr: bool) -> FdTable {
-        let mut fds: BTreeMap<_, Box<dyn FileDescriptor>> = BTreeMap::new();
-        fds.insert(0i32, Box::new(io::stdin()));
+        let mut fds: BTreeMap<_, FileDescriptor> = BTreeMap::new();
+        fds.insert(0i32, FileDescriptor::new(io::stdin()));
         if mute_stdout_stderr {
-            fds.insert(1i32, Box::new(NullOutput));
-            fds.insert(2i32, Box::new(NullOutput));
+            fds.insert(1i32, FileDescriptor::new(NullOutput));
+            fds.insert(2i32, FileDescriptor::new(NullOutput));
         } else {
-            fds.insert(1i32, Box::new(io::stdout()));
-            fds.insert(2i32, Box::new(io::stderr()));
+            fds.insert(1i32, FileDescriptor::new(io::stdout()));
+            fds.insert(2i32, FileDescriptor::new(io::stderr()));
         }
         FdTable { fds }
     }
 
-    pub fn insert_fd(&mut self, file_handle: Box<dyn FileDescriptor>) -> i32 {
+    pub fn insert_fd(&mut self, file_handle: FileDescriptor) -> i32 {
         self.insert_fd_with_min_fd(file_handle, 0)
     }
 
     /// Insert a new FD that is at least `min_fd`.
-    pub fn insert_fd_with_min_fd(
-        &mut self,
-        file_handle: Box<dyn FileDescriptor>,
-        min_fd: i32,
-    ) -> i32 {
+    pub fn insert_fd_with_min_fd(&mut self, file_handle: FileDescriptor, min_fd: i32) -> i32 {
         // Find the lowest unused FD, starting from min_fd. If the first such unused FD is in
         // between used FDs, the find_map combinator will return it. If the first such unused FD
         // is after all other used FDs, the find_map combinator will return None, and we will use
@@ -239,15 +240,22 @@ impl FdTable {
         new_fd
     }
 
-    pub fn get(&self, fd: i32) -> Option<&dyn FileDescriptor> {
-        Some(&**self.fds.get(&fd)?)
+    pub fn get(&self, fd: i32) -> Option<Ref<'_, dyn FileDescription>> {
+        let fd = self.fds.get(&fd)?;
+        Some(Ref::map(fd.0.borrow(), |fd| fd.as_ref()))
+    }
+
+    pub fn get_mut(&self, fd: i32) -> Option<RefMut<'_, dyn FileDescription>> {
+        let fd = self.fds.get(&fd)?;
+        Some(RefMut::map(fd.0.borrow_mut(), |fd| fd.as_mut()))
     }
 
-    pub fn get_mut(&mut self, fd: i32) -> Option<&mut dyn FileDescriptor> {
-        Some(&mut **self.fds.get_mut(&fd)?)
+    pub fn dup(&self, fd: i32) -> Option<FileDescriptor> {
+        let fd = self.fds.get(&fd)?;
+        Some(fd.clone())
     }
 
-    pub fn remove(&mut self, fd: i32) -> Option<Box<dyn FileDescriptor>> {
+    pub fn remove(&mut self, fd: i32) -> Option<FileDescriptor> {
         self.fds.remove(&fd)
     }
 
@@ -296,17 +304,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             }
             let start = this.read_scalar(&args[2])?.to_i32()?;
 
-            match this.machine.fds.get_mut(fd) {
-                Some(file_descriptor) => {
-                    let dup_result = file_descriptor.dup();
-                    match dup_result {
-                        Ok(dup_fd) => Ok(this.machine.fds.insert_fd_with_min_fd(dup_fd, start)),
-                        Err(e) => {
-                            this.set_last_error_from_io_error(e.kind())?;
-                            Ok(-1)
-                        }
-                    }
-                }
+            match this.machine.fds.dup(fd) {
+                Some(dup_fd) => Ok(this.machine.fds.insert_fd_with_min_fd(dup_fd, start)),
                 None => this.fd_not_found(),
             }
         } else if this.tcx.sess.target.os == "macos" && cmd == this.eval_libc_i32("F_FULLFSYNC") {
@@ -330,6 +329,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         Ok(Scalar::from_i32(if let Some(file_descriptor) = this.machine.fds.remove(fd) {
             let result = file_descriptor.close(this.machine.communicate())?;
+            // return `0` if close is successful
+            let result = result.map(|()| 0i32);
             this.try_unwrap_io_result(result)?
         } else {
             this.fd_not_found()?
@@ -369,32 +370,33 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             .min(u64::try_from(isize::MAX).unwrap());
         let communicate = this.machine.communicate();
 
-        if let Some(file_descriptor) = this.machine.fds.get_mut(fd) {
-            trace!("read: FD mapped to {:?}", file_descriptor);
-            // We want to read at most `count` bytes. We are sure that `count` is not negative
-            // because it was a target's `usize`. Also we are sure that its smaller than
-            // `usize::MAX` because it is bounded by the host's `isize`.
-            let mut bytes = vec![0; usize::try_from(count).unwrap()];
-            // `File::read` never returns a value larger than `count`,
-            // so this cannot fail.
-            let result = file_descriptor
-                .read(communicate, &mut bytes, *this.tcx)?
-                .map(|c| i64::try_from(c).unwrap());
-
-            match result {
-                Ok(read_bytes) => {
-                    // If reading to `bytes` did not fail, we write those bytes to the buffer.
-                    this.write_bytes_ptr(buf, bytes)?;
-                    Ok(read_bytes)
-                }
-                Err(e) => {
-                    this.set_last_error_from_io_error(e.kind())?;
-                    Ok(-1)
-                }
-            }
-        } else {
+        let Some(mut file_descriptor) = this.machine.fds.get_mut(fd) else {
             trace!("read: FD not found");
-            this.fd_not_found()
+            return this.fd_not_found();
+        };
+
+        trace!("read: FD mapped to {:?}", file_descriptor);
+        // We want to read at most `count` bytes. We are sure that `count` is not negative
+        // because it was a target's `usize`. Also we are sure that its smaller than
+        // `usize::MAX` because it is bounded by the host's `isize`.
+        let mut bytes = vec![0; usize::try_from(count).unwrap()];
+        // `File::read` never returns a value larger than `count`,
+        // so this cannot fail.
+        let result = file_descriptor
+            .read(communicate, &mut bytes, *this.tcx)?
+            .map(|c| i64::try_from(c).unwrap());
+        drop(file_descriptor);
+
+        match result {
+            Ok(read_bytes) => {
+                // If reading to `bytes` did not fail, we write those bytes to the buffer.
+                this.write_bytes_ptr(buf, bytes)?;
+                Ok(read_bytes)
+            }
+            Err(e) => {
+                this.set_last_error_from_io_error(e.kind())?;
+                Ok(-1)
+            }
         }
     }
 
@@ -418,14 +420,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             .min(u64::try_from(isize::MAX).unwrap());
         let communicate = this.machine.communicate();
 
-        if let Some(file_descriptor) = this.machine.fds.get(fd) {
-            let bytes = this.read_bytes_ptr_strip_provenance(buf, Size::from_bytes(count))?;
-            let result = file_descriptor
-                .write(communicate, bytes, *this.tcx)?
-                .map(|c| i64::try_from(c).unwrap());
-            this.try_unwrap_io_result(result)
-        } else {
-            this.fd_not_found()
-        }
+        let bytes = this.read_bytes_ptr_strip_provenance(buf, Size::from_bytes(count))?.to_owned();
+        let Some(mut file_descriptor) = this.machine.fds.get_mut(fd) else {
+            return this.fd_not_found();
+        };
+
+        let result = file_descriptor
+            .write(communicate, &bytes, *this.tcx)?
+            .map(|c| i64::try_from(c).unwrap());
+        drop(file_descriptor);
+
+        this.try_unwrap_io_result(result)
     }
 }
diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs
index 7f6a3ba0887..595cf64a4e4 100644
--- a/src/tools/miri/src/shims/unix/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/foreign_items.rs
@@ -13,8 +13,9 @@ use crate::*;
 use shims::unix::freebsd::foreign_items as freebsd;
 use shims::unix::linux::foreign_items as linux;
 use shims::unix::macos::foreign_items as macos;
+use shims::unix::solarish::foreign_items as solarish;
 
-fn is_dyn_sym(name: &str, target_os: &str) -> bool {
+pub fn is_dyn_sym(name: &str, target_os: &str) -> bool {
     match name {
         // Used for tests.
         "isatty" => true,
@@ -22,13 +23,14 @@ fn is_dyn_sym(name: &str, target_os: &str) -> bool {
         // well allow it in `dlsym`.
         "signal" => true,
         // needed at least on macOS to avoid file-based fallback in getrandom
-        "getentropy" => true,
+        "getentropy" | "getrandom" => true,
         // Give specific OSes a chance to allow their symbols.
         _ =>
             match target_os {
                 "freebsd" => freebsd::is_dyn_sym(name),
                 "linux" => linux::is_dyn_sym(name),
                 "macos" => macos::is_dyn_sym(name),
+                "solaris" | "illumos" => solarish::is_dyn_sym(name),
                 _ => false,
             },
     }
@@ -488,6 +490,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let result = this.pthread_condattr_init(attr)?;
                 this.write_scalar(Scalar::from_i32(result), dest)?;
             }
+            "pthread_condattr_setclock" => {
+                let [attr, clock_id] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+                let result = this.pthread_condattr_setclock(attr, clock_id)?;
+                this.write_scalar(result, dest)?;
+            }
+            "pthread_condattr_getclock" => {
+                let [attr, clock_id] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+                let result = this.pthread_condattr_getclock(attr, clock_id)?;
+                this.write_scalar(result, dest)?;
+            }
             "pthread_condattr_destroy" => {
                 let [attr] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let result = this.pthread_condattr_destroy(attr)?;
@@ -591,8 +605,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             }
             "getentropy" => {
                 // This function is non-standard but exists with the same signature and behavior on
-                // Linux, macOS, and FreeBSD.
-                if !matches!(&*this.tcx.sess.target.os, "linux" | "macos" | "freebsd") {
+                // Linux, macOS, FreeBSD and Solaris/Illumos.
+                if !matches!(&*this.tcx.sess.target.os, "linux" | "macos" | "freebsd" | "illumos" | "solaris") {
                     throw_unsup_format!(
                         "`getentropy` is not supported on {}",
                         this.tcx.sess.target.os
@@ -608,6 +622,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 // FreeBSD: https://man.freebsd.org/cgi/man.cgi?query=getentropy&sektion=3&format=html
                 // Linux: https://man7.org/linux/man-pages/man3/getentropy.3.html
                 // macOS: https://keith.github.io/xcode-man-pages/getentropy.2.html
+                // Solaris/Illumos: https://illumos.org/man/3C/getentropy
                 if bufsize > 256 {
                     let err = this.eval_libc("EIO");
                     this.set_last_error(err)?;
@@ -617,6 +632,24 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     this.write_scalar(Scalar::from_i32(0), dest)?;
                 }
             }
+            "getrandom" => {
+                // This function is non-standard but exists with the same signature and behavior on
+                // Linux, FreeBSD and Solaris/Illumos.
+                if !matches!(&*this.tcx.sess.target.os, "linux" | "freebsd" | "illumos" | "solaris") {
+                    throw_unsup_format!(
+                        "`getentropy` is not supported on {}",
+                        this.tcx.sess.target.os
+                    );
+                }
+                let [ptr, len, flags] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+                let ptr = this.read_pointer(ptr)?;
+                let len = this.read_target_usize(len)?;
+                let _flags = this.read_scalar(flags)?.to_i32()?;
+                // We ignore the flags, just always use the same PRNG / host RNG.
+                this.gen_random(ptr, len)?;
+                this.write_scalar(Scalar::from_target_usize(len, this), dest)?;
+            }
 
             // Incomplete shims that we "stub out" just to get pre-main initialization code to work.
             // These shims are enabled only when the caller is in the standard library.
@@ -723,25 +756,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 }
             }
 
-            "sched_getaffinity" => {
-                // FreeBSD supports it as well since 13.1 (as a wrapper of cpuset_getaffinity)
-                if !matches!(&*this.tcx.sess.target.os, "linux" | "freebsd") {
-                    throw_unsup_format!(
-                        "`sched_getaffinity` is not supported on {}",
-                        this.tcx.sess.target.os
-                    );
-                }
-                let [pid, cpusetsize, mask] =
-                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
-                this.read_scalar(pid)?.to_i32()?;
-                this.read_target_usize(cpusetsize)?;
-                this.deref_pointer_as(mask, this.libc_ty_layout("cpu_set_t"))?;
-                // FIXME: we just return an error; `num_cpus` then falls back to `sysconf`.
-                let einval = this.eval_libc("EINVAL");
-                this.set_last_error(einval)?;
-                this.write_scalar(Scalar::from_i32(-1), dest)?;
-            }
-
             // Platform-specific shims
             _ => {
                 let target_os = &*this.tcx.sess.target.os;
@@ -749,6 +763,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     "freebsd" => freebsd::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest),
                     "linux" => linux::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest),
                     "macos" => macos::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest),
+                    "solaris" | "illumos" => solarish::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest),
                     _ => Ok(EmulateItemResult::NotSupported),
                 };
             }
diff --git a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs
index 1e0e7d16320..e70cd35dda6 100644
--- a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs
@@ -20,11 +20,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let this = self.eval_context_mut();
         match link_name.as_str() {
             // Threading
-            "pthread_attr_get_np" if this.frame_in_std() => {
-                let [_thread, _attr] =
-                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
-                this.write_null(dest)?;
-            }
             "pthread_set_name_np" => {
                 let [thread, name] =
                     this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
@@ -46,21 +41,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     this.read_scalar(len)?,
                 )?;
             }
-            "getrandom" => {
-                let [ptr, len, flags] =
-                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
-                let ptr = this.read_pointer(ptr)?;
-                let len = this.read_target_usize(len)?;
-                let _flags = this.read_scalar(flags)?.to_i32()?;
-                // flags on freebsd does not really matter
-                // in practice, GRND_RANDOM does not particularly draw from /dev/random
-                // since it is the same as to /dev/urandom.
-                // GRND_INSECURE is only an alias of GRND_NONBLOCK, which
-                // does not affect the RNG.
-                // https://man.freebsd.org/cgi/man.cgi?query=getrandom&sektion=2&n=1
-                this.gen_random(ptr, len)?;
-                this.write_scalar(Scalar::from_target_usize(len, this), dest)?;
-            }
 
             // File related shims
             // For those, we both intercept `func` and `call@FBSD_1.0` symbols cases
@@ -89,13 +69,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 this.write_scalar(result, dest)?;
             }
 
-            // errno
+            // Miscellaneous
             "__error" => {
                 let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let errno_place = this.last_error_place()?;
                 this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?;
             }
 
+            // Incomplete shims that we "stub out" just to get pre-main initialization code to work.
+            // These shims are enabled only when the caller is in the standard library.
+            "pthread_attr_get_np" if this.frame_in_std() => {
+                let [_thread, _attr] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+                this.write_null(dest)?;
+            }
+
             _ => return Ok(EmulateItemResult::NotSupported),
         }
         Ok(EmulateItemResult::NeedsJumping)
diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs
index ebf9f43c19e..058747916c0 100644
--- a/src/tools/miri/src/shims/unix/fs.rs
+++ b/src/tools/miri/src/shims/unix/fs.rs
@@ -17,15 +17,17 @@ use crate::shims::unix::*;
 use crate::*;
 use shims::time::system_time_to_duration;
 
+use self::fd::FileDescriptor;
+
 #[derive(Debug)]
 struct FileHandle {
     file: File,
     writable: bool,
 }
 
-impl FileDescriptor for FileHandle {
+impl FileDescription for FileHandle {
     fn name(&self) -> &'static str {
-        "FILE"
+        "file"
     }
 
     fn read<'tcx>(
@@ -39,13 +41,13 @@ impl FileDescriptor for FileHandle {
     }
 
     fn write<'tcx>(
-        &self,
+        &mut self,
         communicate_allowed: bool,
         bytes: &[u8],
         _tcx: TyCtxt<'tcx>,
     ) -> InterpResult<'tcx, io::Result<usize>> {
         assert!(communicate_allowed, "isolation should have prevented even opening a file");
-        Ok((&mut &self.file).write(bytes))
+        Ok(self.file.write(bytes))
     }
 
     fn seek<'tcx>(
@@ -60,16 +62,14 @@ impl FileDescriptor for FileHandle {
     fn close<'tcx>(
         self: Box<Self>,
         communicate_allowed: bool,
-    ) -> InterpResult<'tcx, io::Result<i32>> {
+    ) -> InterpResult<'tcx, io::Result<()>> {
         assert!(communicate_allowed, "isolation should have prevented even opening a file");
         // We sync the file if it was opened in a mode different than read-only.
         if self.writable {
             // `File::sync_all` does the checks that are done when closing a file. We do this to
             // to handle possible errors correctly.
-            let result = self.file.sync_all().map(|_| 0i32);
-            // Now we actually close the file.
-            drop(self);
-            // And return the result.
+            let result = self.file.sync_all();
+            // Now we actually close the file and return the result.
             Ok(result)
         } else {
             // We drop the file, this closes it but ignores any errors
@@ -78,16 +78,10 @@ impl FileDescriptor for FileHandle {
             // `/dev/urandom` which are read-only. Check
             // https://github.com/rust-lang/miri/issues/999#issuecomment-568920439
             // for a deeper discussion.
-            drop(self);
-            Ok(Ok(0))
+            Ok(Ok(()))
         }
     }
 
-    fn dup(&mut self) -> io::Result<Box<dyn FileDescriptor>> {
-        let duplicated = self.file.try_clone()?;
-        Ok(Box::new(FileHandle { file: duplicated, writable: self.writable }))
-    }
-
     fn is_tty(&self, communicate_allowed: bool) -> bool {
         communicate_allowed && self.file.is_terminal()
     }
@@ -399,7 +393,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         let fd = options.open(path).map(|file| {
             let fh = &mut this.machine.fds;
-            fh.insert_fd(Box::new(FileHandle { file, writable }))
+            fh.insert_fd(FileDescriptor::new(FileHandle { file, writable }))
         });
 
         this.try_unwrap_io_result(fd)
@@ -428,14 +422,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         };
 
         let communicate = this.machine.communicate();
-        Ok(Scalar::from_i64(if let Some(file_descriptor) = this.machine.fds.get_mut(fd) {
-            let result = file_descriptor
-                .seek(communicate, seek_from)?
-                .map(|offset| i64::try_from(offset).unwrap());
-            this.try_unwrap_io_result(result)?
-        } else {
-            this.fd_not_found()?
-        }))
+
+        let Some(mut file_descriptor) = this.machine.fds.get_mut(fd) else {
+            return Ok(Scalar::from_i64(this.fd_not_found()?));
+        };
+        let result = file_descriptor
+            .seek(communicate, seek_from)?
+            .map(|offset| i64::try_from(offset).unwrap());
+        drop(file_descriptor);
+
+        let result = this.try_unwrap_io_result(result)?;
+        Ok(Scalar::from_i64(result))
     }
 
     fn unlink(&mut self, path_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> {
@@ -1131,32 +1128,35 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             return Ok(Scalar::from_i32(this.fd_not_found()?));
         }
 
-        Ok(Scalar::from_i32(if let Some(file_descriptor) = this.machine.fds.get_mut(fd) {
-            // FIXME: Support ftruncate64 for all FDs
-            let FileHandle { file, writable } =
-                file_descriptor.downcast_ref::<FileHandle>().ok_or_else(|| {
-                    err_unsup_format!(
-                        "`ftruncate64` is only supported on file-backed file descriptors"
-                    )
-                })?;
-            if *writable {
-                if let Ok(length) = length.try_into() {
-                    let result = file.set_len(length);
-                    this.try_unwrap_io_result(result.map(|_| 0i32))?
-                } else {
-                    let einval = this.eval_libc("EINVAL");
-                    this.set_last_error(einval)?;
-                    -1
-                }
+        let Some(file_descriptor) = this.machine.fds.get(fd) else {
+            return Ok(Scalar::from_i32(this.fd_not_found()?));
+        };
+
+        // FIXME: Support ftruncate64 for all FDs
+        let FileHandle { file, writable } =
+            file_descriptor.downcast_ref::<FileHandle>().ok_or_else(|| {
+                err_unsup_format!("`ftruncate64` is only supported on file-backed file descriptors")
+            })?;
+
+        if *writable {
+            if let Ok(length) = length.try_into() {
+                let result = file.set_len(length);
+                drop(file_descriptor);
+                let result = this.try_unwrap_io_result(result.map(|_| 0i32))?;
+                Ok(Scalar::from_i32(result))
             } else {
-                // The file is not writable
+                drop(file_descriptor);
                 let einval = this.eval_libc("EINVAL");
                 this.set_last_error(einval)?;
-                -1
+                Ok(Scalar::from_i32(-1))
             }
         } else {
-            this.fd_not_found()?
-        }))
+            drop(file_descriptor);
+            // The file is not writable
+            let einval = this.eval_libc("EINVAL");
+            this.set_last_error(einval)?;
+            Ok(Scalar::from_i32(-1))
+        }
     }
 
     fn fsync(&mut self, fd_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> {
@@ -1190,6 +1190,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 err_unsup_format!("`fsync` is only supported on file-backed file descriptors")
             })?;
         let io_result = maybe_sync_file(file, *writable, File::sync_all);
+        drop(file_descriptor);
         this.try_unwrap_io_result(io_result)
     }
 
@@ -1214,6 +1215,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 err_unsup_format!("`fdatasync` is only supported on file-backed file descriptors")
             })?;
         let io_result = maybe_sync_file(file, *writable, File::sync_data);
+        drop(file_descriptor);
         this.try_unwrap_io_result(io_result)
     }
 
@@ -1263,6 +1265,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 )
             })?;
         let io_result = maybe_sync_file(file, *writable, File::sync_data);
+        drop(file_descriptor);
         Ok(Scalar::from_i32(this.try_unwrap_io_result(io_result)?))
     }
 
@@ -1498,7 +1501,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             match file {
                 Ok(f) => {
                     let fh = &mut this.machine.fds;
-                    let fd = fh.insert_fd(Box::new(FileHandle { file: f, writable: true }));
+                    let fd =
+                        fh.insert_fd(FileDescriptor::new(FileHandle { file: f, writable: true }));
                     return Ok(fd);
                 }
                 Err(e) =>
@@ -1563,21 +1567,21 @@ impl FileMetadata {
         ecx: &mut MiriInterpCx<'_, 'tcx>,
         fd: i32,
     ) -> InterpResult<'tcx, Option<FileMetadata>> {
-        let option = ecx.machine.fds.get(fd);
-        let file = match option {
-            Some(file_descriptor) =>
-                &file_descriptor
-                    .downcast_ref::<FileHandle>()
-                    .ok_or_else(|| {
-                        err_unsup_format!(
-                            "obtaining metadata is only supported on file-backed file descriptors"
-                        )
-                    })?
-                    .file,
-            None => return ecx.fd_not_found().map(|_: i32| None),
+        let Some(file_descriptor) = ecx.machine.fds.get(fd) else {
+            return ecx.fd_not_found().map(|_: i32| None);
         };
-        let metadata = file.metadata();
 
+        let file = &file_descriptor
+            .downcast_ref::<FileHandle>()
+            .ok_or_else(|| {
+                err_unsup_format!(
+                    "obtaining metadata is only supported on file-backed file descriptors"
+                )
+            })?
+            .file;
+
+        let metadata = file.metadata();
+        drop(file_descriptor);
         FileMetadata::from_meta(ecx, metadata)
     }
 
diff --git a/src/tools/miri/src/shims/unix/linux/epoll.rs b/src/tools/miri/src/shims/unix/linux/epoll.rs
index 5161d91ca36..48a0ba01976 100644
--- a/src/tools/miri/src/shims/unix/linux/epoll.rs
+++ b/src/tools/miri/src/shims/unix/linux/epoll.rs
@@ -5,6 +5,8 @@ use rustc_data_structures::fx::FxHashMap;
 use crate::shims::unix::*;
 use crate::*;
 
+use self::shims::unix::fd::FileDescriptor;
+
 /// An `Epoll` file descriptor connects file handles and epoll events
 #[derive(Clone, Debug, Default)]
 struct Epoll {
@@ -29,22 +31,16 @@ struct EpollEvent {
     data: Scalar<Provenance>,
 }
 
-impl FileDescriptor for Epoll {
+impl FileDescription for Epoll {
     fn name(&self) -> &'static str {
         "epoll"
     }
 
-    fn dup(&mut self) -> io::Result<Box<dyn FileDescriptor>> {
-        // FIXME: this is probably wrong -- check if the `dup`ed descriptor truly uses an
-        // independent event set.
-        Ok(Box::new(self.clone()))
-    }
-
     fn close<'tcx>(
         self: Box<Self>,
         _communicate_allowed: bool,
-    ) -> InterpResult<'tcx, io::Result<i32>> {
-        Ok(Ok(0))
+    ) -> InterpResult<'tcx, io::Result<()>> {
+        Ok(Ok(()))
     }
 }
 
@@ -70,7 +66,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             throw_unsup_format!("epoll_create1 flags {flags} are not implemented");
         }
 
-        let fd = this.machine.fds.insert_fd(Box::new(Epoll::default()));
+        let fd = this.machine.fds.insert_fd(FileDescriptor::new(Epoll::default()));
         Ok(Scalar::from_i32(fd))
     }
 
@@ -114,27 +110,25 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             let data = this.read_scalar(&data)?;
             let event = EpollEvent { events, data };
 
-            if let Some(epfd) = this.machine.fds.get_mut(epfd) {
-                let epfd = epfd
-                    .downcast_mut::<Epoll>()
-                    .ok_or_else(|| err_unsup_format!("non-epoll FD passed to `epoll_ctl`"))?;
+            let Some(mut epfd) = this.machine.fds.get_mut(epfd) else {
+                return Ok(Scalar::from_i32(this.fd_not_found()?));
+            };
+            let epfd = epfd
+                .downcast_mut::<Epoll>()
+                .ok_or_else(|| err_unsup_format!("non-epoll FD passed to `epoll_ctl`"))?;
 
-                epfd.file_descriptors.insert(fd, event);
-                Ok(Scalar::from_i32(0))
-            } else {
-                Ok(Scalar::from_i32(this.fd_not_found()?))
-            }
+            epfd.file_descriptors.insert(fd, event);
+            Ok(Scalar::from_i32(0))
         } else if op == epoll_ctl_del {
-            if let Some(epfd) = this.machine.fds.get_mut(epfd) {
-                let epfd = epfd
-                    .downcast_mut::<Epoll>()
-                    .ok_or_else(|| err_unsup_format!("non-epoll FD passed to `epoll_ctl`"))?;
-
-                epfd.file_descriptors.remove(&fd);
-                Ok(Scalar::from_i32(0))
-            } else {
-                Ok(Scalar::from_i32(this.fd_not_found()?))
-            }
+            let Some(mut epfd) = this.machine.fds.get_mut(epfd) else {
+                return Ok(Scalar::from_i32(this.fd_not_found()?));
+            };
+            let epfd = epfd
+                .downcast_mut::<Epoll>()
+                .ok_or_else(|| err_unsup_format!("non-epoll FD passed to `epoll_ctl`"))?;
+
+            epfd.file_descriptors.remove(&fd);
+            Ok(Scalar::from_i32(0))
         } else {
             let einval = this.eval_libc("EINVAL");
             this.set_last_error(einval)?;
@@ -185,15 +179,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let _maxevents = this.read_scalar(maxevents)?.to_i32()?;
         let _timeout = this.read_scalar(timeout)?.to_i32()?;
 
-        if let Some(epfd) = this.machine.fds.get_mut(epfd) {
-            let _epfd = epfd
-                .downcast_mut::<Epoll>()
-                .ok_or_else(|| err_unsup_format!("non-epoll FD passed to `epoll_wait`"))?;
+        let Some(mut epfd) = this.machine.fds.get_mut(epfd) else {
+            return Ok(Scalar::from_i32(this.fd_not_found()?));
+        };
+        let _epfd = epfd
+            .downcast_mut::<Epoll>()
+            .ok_or_else(|| err_unsup_format!("non-epoll FD passed to `epoll_wait`"))?;
 
-            // FIXME return number of events ready when scheme for marking events ready exists
-            throw_unsup_format!("returning ready events from epoll_wait is not yet implemented");
-        } else {
-            Ok(Scalar::from_i32(this.fd_not_found()?))
-        }
+        // FIXME return number of events ready when scheme for marking events ready exists
+        throw_unsup_format!("returning ready events from epoll_wait is not yet implemented");
     }
 }
diff --git a/src/tools/miri/src/shims/unix/linux/eventfd.rs b/src/tools/miri/src/shims/unix/linux/eventfd.rs
index 0f28b69ac4a..a865f2efff9 100644
--- a/src/tools/miri/src/shims/unix/linux/eventfd.rs
+++ b/src/tools/miri/src/shims/unix/linux/eventfd.rs
@@ -1,6 +1,5 @@
 //! Linux `eventfd` implementation.
 //! Currently just a stub.
-use std::cell::Cell;
 use std::io;
 
 use rustc_middle::ty::TyCtxt;
@@ -9,6 +8,8 @@ use rustc_target::abi::Endian;
 use crate::shims::unix::*;
 use crate::*;
 
+use self::shims::unix::fd::FileDescriptor;
+
 /// A kind of file descriptor created by `eventfd`.
 /// The `Event` type isn't currently written to by `eventfd`.
 /// The interface is meant to keep track of objects associated
@@ -20,24 +21,19 @@ use crate::*;
 struct Event {
     /// The object contains an unsigned 64-bit integer (uint64_t) counter that is maintained by the
     /// kernel. This counter is initialized with the value specified in the argument initval.
-    val: Cell<u64>,
+    val: u64,
 }
 
-impl FileDescriptor for Event {
+impl FileDescription for Event {
     fn name(&self) -> &'static str {
         "event"
     }
 
-    fn dup(&mut self) -> io::Result<Box<dyn FileDescriptor>> {
-        // FIXME: this is wrong, the new and old FD should refer to the same event object!
-        Ok(Box::new(Event { val: self.val.clone() }))
-    }
-
     fn close<'tcx>(
         self: Box<Self>,
         _communicate_allowed: bool,
-    ) -> InterpResult<'tcx, io::Result<i32>> {
-        Ok(Ok(0))
+    ) -> InterpResult<'tcx, io::Result<()>> {
+        Ok(Ok(()))
     }
 
     /// A write call adds the 8-byte integer value supplied in
@@ -53,12 +49,11 @@ impl FileDescriptor for Event {
     /// supplied buffer is less than 8 bytes, or if an attempt is
     /// made to write the value 0xffffffffffffffff.
     fn write<'tcx>(
-        &self,
+        &mut self,
         _communicate_allowed: bool,
         bytes: &[u8],
         tcx: TyCtxt<'tcx>,
     ) -> InterpResult<'tcx, io::Result<usize>> {
-        let v1 = self.val.get();
         let bytes: [u8; 8] = bytes.try_into().unwrap(); // FIXME fail gracefully when this has the wrong size
         // Convert from target endianness to host endianness.
         let num = match tcx.sess.target.endian {
@@ -67,9 +62,7 @@ impl FileDescriptor for Event {
         };
         // FIXME handle blocking when addition results in exceeding the max u64 value
         // or fail with EAGAIN if the file descriptor is nonblocking.
-        let v2 = v1.checked_add(num).unwrap();
-        self.val.set(v2);
-        assert_eq!(8, bytes.len());
+        self.val = self.val.checked_add(num).unwrap();
         Ok(Ok(8))
     }
 }
@@ -119,7 +112,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             throw_unsup_format!("eventfd: EFD_SEMAPHORE is unsupported");
         }
 
-        let fd = this.machine.fds.insert_fd(Box::new(Event { val: Cell::new(val.into()) }));
+        let fd = this.machine.fds.insert_fd(FileDescriptor::new(Event { val: val.into() }));
         Ok(Scalar::from_i32(fd))
     }
 }
diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs
index dd4ec8cfaa7..ecf82f26a55 100644
--- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs
@@ -11,7 +11,7 @@ use shims::unix::linux::mem::EvalContextExt as _;
 use shims::unix::linux::sync::futex;
 
 pub fn is_dyn_sym(name: &str) -> bool {
-    matches!(name, "getrandom")
+    matches!(name, "statx")
 }
 
 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
@@ -28,7 +28,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         // See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern.
 
         match link_name.as_str() {
-            // File related shims (but also see "syscall" below for statx)
+            // File related shims
             "readdir64" => {
                 let [dirp] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let result = this.linux_readdir64(dirp)?;
@@ -40,6 +40,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let result = this.sync_file_range(fd, offset, nbytes, flags)?;
                 this.write_scalar(result, dest)?;
             }
+            "statx" => {
+                let [dirfd, pathname, flags, mask, statxbuf] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+                let result = this.linux_statx(dirfd, pathname, flags, mask, statxbuf)?;
+                this.write_scalar(Scalar::from_i32(result), dest)?;
+            }
 
             // epoll, eventfd
             "epoll_create1" => {
@@ -67,18 +73,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             }
 
             // Threading
-            "pthread_condattr_setclock" => {
-                let [attr, clock_id] =
-                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
-                let result = this.pthread_condattr_setclock(attr, clock_id)?;
-                this.write_scalar(result, dest)?;
-            }
-            "pthread_condattr_getclock" => {
-                let [attr, clock_id] =
-                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
-                let result = this.pthread_condattr_getclock(attr, clock_id)?;
-                this.write_scalar(result, dest)?;
-            }
             "pthread_setname_np" => {
                 let [thread, name] =
                     this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
@@ -112,9 +106,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 // have the right type.
 
                 let sys_getrandom = this.eval_libc("SYS_getrandom").to_target_usize(this)?;
-
-                let sys_statx = this.eval_libc("SYS_statx").to_target_usize(this)?;
-
                 let sys_futex = this.eval_libc("SYS_futex").to_target_usize(this)?;
 
                 if args.is_empty() {
@@ -135,37 +126,20 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                         }
                         getrandom(this, &args[1], &args[2], &args[3], dest)?;
                     }
-                    // `statx` is used by `libstd` to retrieve metadata information on `linux`
-                    // instead of using `stat`,`lstat` or `fstat` as on `macos`.
-                    id if id == sys_statx => {
-                        // The first argument is the syscall id, so skip over it.
-                        if args.len() < 6 {
-                            throw_ub_format!(
-                                "incorrect number of arguments for `statx` syscall: got {}, expected at least 6",
-                                args.len()
-                            );
-                        }
-                        let result =
-                            this.linux_statx(&args[1], &args[2], &args[3], &args[4], &args[5])?;
-                        this.write_scalar(Scalar::from_target_isize(result.into(), this), dest)?;
-                    }
                     // `futex` is used by some synchronization primitives.
                     id if id == sys_futex => {
                         futex(this, &args[1..], dest)?;
                     }
                     id => {
-                        this.handle_unsupported(format!("can't execute syscall with ID {id}"))?;
+                        this.handle_unsupported_foreign_item(format!(
+                            "can't execute syscall with ID {id}"
+                        ))?;
                         return Ok(EmulateItemResult::AlreadyJumped);
                     }
                 }
             }
 
             // Miscellaneous
-            "getrandom" => {
-                let [ptr, len, flags] =
-                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
-                getrandom(this, ptr, len, flags, dest)?;
-            }
             "mmap64" => {
                 let [addr, length, prot, flags, fd, offset] =
                     this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
@@ -194,6 +168,19 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
                 this.write_scalar(Scalar::from_i32(SIGRTMAX), dest)?;
             }
+            "sched_getaffinity" => {
+                // This shim isn't useful, aside from the fact that it makes `num_cpus`
+                // fall back to `sysconf` where it will successfully determine the number of CPUs.
+                let [pid, cpusetsize, mask] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+                this.read_scalar(pid)?.to_i32()?;
+                this.read_target_usize(cpusetsize)?;
+                this.deref_pointer_as(mask, this.libc_ty_layout("cpu_set_t"))?;
+                // FIXME: we just return an error.
+                let einval = this.eval_libc("EINVAL");
+                this.set_last_error(einval)?;
+                this.write_scalar(Scalar::from_i32(-1), dest)?;
+            }
 
             // Incomplete shims that we "stub out" just to get pre-main initialization code to work.
             // These shims are enabled only when the caller is in the standard library.
diff --git a/src/tools/miri/src/shims/unix/mod.rs b/src/tools/miri/src/shims/unix/mod.rs
index 144593aa2fc..6dee30d895c 100644
--- a/src/tools/miri/src/shims/unix/mod.rs
+++ b/src/tools/miri/src/shims/unix/mod.rs
@@ -11,9 +11,10 @@ mod thread;
 mod freebsd;
 mod linux;
 mod macos;
+mod solarish;
 
 pub use env::UnixEnvVars;
-pub use fd::{FdTable, FileDescriptor};
+pub use fd::{FdTable, FileDescription};
 pub use fs::DirTable;
 // All the Unix-specific extension traits
 pub use env::EvalContextExt as _;
diff --git a/src/tools/miri/src/shims/unix/socket.rs b/src/tools/miri/src/shims/unix/socket.rs
index 84ddd746fb5..11fd83f57e6 100644
--- a/src/tools/miri/src/shims/unix/socket.rs
+++ b/src/tools/miri/src/shims/unix/socket.rs
@@ -3,26 +3,24 @@ use std::io;
 use crate::shims::unix::*;
 use crate::*;
 
+use self::fd::FileDescriptor;
+
 /// Pair of connected sockets.
 ///
 /// We currently don't allow sending any data through this pair, so this can be just a dummy.
 #[derive(Debug)]
 struct SocketPair;
 
-impl FileDescriptor for SocketPair {
+impl FileDescription for SocketPair {
     fn name(&self) -> &'static str {
         "socketpair"
     }
 
-    fn dup(&mut self) -> io::Result<Box<dyn FileDescriptor>> {
-        Ok(Box::new(SocketPair))
-    }
-
     fn close<'tcx>(
         self: Box<Self>,
         _communicate_allowed: bool,
-    ) -> InterpResult<'tcx, io::Result<i32>> {
-        Ok(Ok(0))
+    ) -> InterpResult<'tcx, io::Result<()>> {
+        Ok(Ok(()))
     }
 }
 
@@ -52,9 +50,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         // FIXME: fail on unsupported inputs
 
         let fds = &mut this.machine.fds;
-        let sv0 = fds.insert_fd(Box::new(SocketPair));
+        let sv0 = fds.insert_fd(FileDescriptor::new(SocketPair));
         let sv0 = Scalar::try_from_int(sv0, sv.layout.size).unwrap();
-        let sv1 = fds.insert_fd(Box::new(SocketPair));
+        let sv1 = fds.insert_fd(FileDescriptor::new(SocketPair));
         let sv1 = Scalar::try_from_int(sv1, sv.layout.size).unwrap();
 
         this.write_scalar(sv0, &sv)?;
diff --git a/src/tools/miri/src/shims/unix/solarish/foreign_items.rs b/src/tools/miri/src/shims/unix/solarish/foreign_items.rs
new file mode 100644
index 00000000000..c01ae0ecb90
--- /dev/null
+++ b/src/tools/miri/src/shims/unix/solarish/foreign_items.rs
@@ -0,0 +1,33 @@
+use rustc_span::Symbol;
+use rustc_target::spec::abi::Abi;
+
+use crate::*;
+use shims::EmulateItemResult;
+
+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() {
+            // Miscellaneous
+            "___errno" => {
+                let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+                let errno_place = this.last_error_place()?;
+                this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?;
+            }
+
+            _ => return Ok(EmulateItemResult::NotSupported),
+        }
+        Ok(EmulateItemResult::NeedsJumping)
+    }
+}
diff --git a/src/tools/miri/src/shims/unix/solarish/mod.rs b/src/tools/miri/src/shims/unix/solarish/mod.rs
new file mode 100644
index 00000000000..09c6507b24f
--- /dev/null
+++ b/src/tools/miri/src/shims/unix/solarish/mod.rs
@@ -0,0 +1 @@
+pub mod foreign_items;
diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs
index e50a8934e09..f24f279ab0f 100644
--- a/src/tools/miri/src/shims/unix/sync.rs
+++ b/src/tools/miri/src/shims/unix/sync.rs
@@ -1,34 +1,23 @@
+use std::sync::atomic::{AtomicBool, Ordering};
 use std::time::SystemTime;
 
+use rustc_target::abi::Size;
+
 use crate::concurrency::thread::MachineCallback;
 use crate::*;
 
 // pthread_mutexattr_t is either 4 or 8 bytes, depending on the platform.
+// We ignore the platform layout and store our own fields:
+// - kind: i32
 
-// Our chosen memory layout for emulation (does not have to match the platform layout!):
-// store an i32 in the first four bytes equal to the corresponding libc mutex kind constant
-// (e.g. PTHREAD_MUTEX_NORMAL).
-
-/// A flag that allows to distinguish `PTHREAD_MUTEX_NORMAL` from
-/// `PTHREAD_MUTEX_DEFAULT`. Since in `glibc` they have the same numeric values,
-/// but different behaviour, we need a way to distinguish them. We do this by
-/// setting this bit flag to the `PTHREAD_MUTEX_NORMAL` mutexes. See the comment
-/// in `pthread_mutexattr_settype` function.
-const PTHREAD_MUTEX_NORMAL_FLAG: i32 = 0x8000000;
-
-fn is_mutex_kind_default<'mir, 'tcx: 'mir>(
+#[inline]
+fn mutexattr_kind_offset<'mir, 'tcx: 'mir>(
     ecx: &MiriInterpCx<'mir, 'tcx>,
-    kind: i32,
-) -> InterpResult<'tcx, bool> {
-    Ok(kind == ecx.eval_libc_i32("PTHREAD_MUTEX_DEFAULT"))
-}
-
-fn is_mutex_kind_normal<'mir, 'tcx: 'mir>(
-    ecx: &MiriInterpCx<'mir, 'tcx>,
-    kind: i32,
-) -> InterpResult<'tcx, bool> {
-    let mutex_normal_kind = ecx.eval_libc_i32("PTHREAD_MUTEX_NORMAL");
-    Ok(kind == (mutex_normal_kind | PTHREAD_MUTEX_NORMAL_FLAG))
+) -> InterpResult<'tcx, u64> {
+    Ok(match &*ecx.tcx.sess.target.os {
+        "linux" | "illumos" | "solaris" | "macos" => 0,
+        os => throw_unsup_format!("`pthread_mutexattr` is not supported on {os}"),
+    })
 }
 
 fn mutexattr_get_kind<'mir, 'tcx: 'mir>(
@@ -37,7 +26,7 @@ fn mutexattr_get_kind<'mir, 'tcx: 'mir>(
 ) -> InterpResult<'tcx, i32> {
     ecx.deref_pointer_and_read(
         attr_op,
-        0,
+        mutexattr_kind_offset(ecx)?,
         ecx.libc_ty_layout("pthread_mutexattr_t"),
         ecx.machine.layouts.i32,
     )?
@@ -51,27 +40,99 @@ fn mutexattr_set_kind<'mir, 'tcx: 'mir>(
 ) -> InterpResult<'tcx, ()> {
     ecx.deref_pointer_and_write(
         attr_op,
-        0,
+        mutexattr_kind_offset(ecx)?,
         Scalar::from_i32(kind),
         ecx.libc_ty_layout("pthread_mutexattr_t"),
         ecx.machine.layouts.i32,
     )
 }
 
+/// A flag that allows to distinguish `PTHREAD_MUTEX_NORMAL` from
+/// `PTHREAD_MUTEX_DEFAULT`. Since in `glibc` they have the same numeric values,
+/// but different behaviour, we need a way to distinguish them. We do this by
+/// setting this bit flag to the `PTHREAD_MUTEX_NORMAL` mutexes. See the comment
+/// in `pthread_mutexattr_settype` function.
+const PTHREAD_MUTEX_NORMAL_FLAG: i32 = 0x8000000;
+
+fn is_mutex_kind_default<'mir, 'tcx: 'mir>(
+    ecx: &MiriInterpCx<'mir, 'tcx>,
+    kind: i32,
+) -> InterpResult<'tcx, bool> {
+    Ok(kind == ecx.eval_libc_i32("PTHREAD_MUTEX_DEFAULT"))
+}
+
+fn is_mutex_kind_normal<'mir, 'tcx: 'mir>(
+    ecx: &MiriInterpCx<'mir, 'tcx>,
+    kind: i32,
+) -> InterpResult<'tcx, bool> {
+    let mutex_normal_kind = ecx.eval_libc_i32("PTHREAD_MUTEX_NORMAL");
+    Ok(kind == (mutex_normal_kind | PTHREAD_MUTEX_NORMAL_FLAG))
+}
+
 // pthread_mutex_t is between 24 and 48 bytes, depending on the platform.
+// We ignore the platform layout and store our own fields:
+// - id: u32
+// - kind: i32
+
+fn mutex_id_offset<'mir, 'tcx: 'mir>(ecx: &MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx, u64> {
+    let offset = match &*ecx.tcx.sess.target.os {
+        "linux" | "illumos" | "solaris" => 0,
+        // macOS stores a signature in the first bytes, so we have to move to offset 4.
+        "macos" => 4,
+        os => throw_unsup_format!("`pthread_mutex` is not supported on {os}"),
+    };
+
+    // Sanity-check this against PTHREAD_MUTEX_INITIALIZER (but only once):
+    // the id must start out as 0.
+    static SANITY: AtomicBool = AtomicBool::new(false);
+    if !SANITY.swap(true, Ordering::Relaxed) {
+        let static_initializer = ecx.eval_path(&["libc", "PTHREAD_MUTEX_INITIALIZER"]);
+        let id_field = static_initializer
+            .offset(Size::from_bytes(offset), ecx.machine.layouts.u32, ecx)
+            .unwrap();
+        let id = ecx.read_scalar(&id_field).unwrap().to_u32().unwrap();
+        assert_eq!(
+            id, 0,
+            "PTHREAD_MUTEX_INITIALIZER is incompatible with our pthread_mutex layout: id is not 0"
+        );
+    }
+
+    Ok(offset)
+}
 
-// Our chosen memory layout for the emulated mutex (does not have to match the platform layout!):
-// bytes 0-3: reserved for signature on macOS
-// (need to avoid this because it is set by static initializer macros)
-// bytes 4-7: mutex id as u32 or 0 if id is not assigned yet.
-// bytes 12-15 or 16-19 (depending on platform): mutex kind, as an i32
-// (the kind has to be at its offset for compatibility with static initializer macros)
+fn mutex_kind_offset<'mir, 'tcx: 'mir>(ecx: &MiriInterpCx<'mir, 'tcx>) -> u64 {
+    // These offsets are picked for compatibility with Linux's static initializer
+    // macros, e.g. PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP.)
+    let offset = if ecx.pointer_size().bytes() == 8 { 16 } else { 12 };
+
+    // Sanity-check this against PTHREAD_MUTEX_INITIALIZER (but only once):
+    // the kind must start out as PTHREAD_MUTEX_DEFAULT.
+    static SANITY: AtomicBool = AtomicBool::new(false);
+    if !SANITY.swap(true, Ordering::Relaxed) {
+        let static_initializer = ecx.eval_path(&["libc", "PTHREAD_MUTEX_INITIALIZER"]);
+        let kind_field = static_initializer
+            .offset(Size::from_bytes(mutex_kind_offset(ecx)), ecx.machine.layouts.i32, ecx)
+            .unwrap();
+        let kind = ecx.read_scalar(&kind_field).unwrap().to_i32().unwrap();
+        assert_eq!(
+            kind,
+            ecx.eval_libc_i32("PTHREAD_MUTEX_DEFAULT"),
+            "PTHREAD_MUTEX_INITIALIZER is incompatible with our pthread_mutex layout: kind is not PTHREAD_MUTEX_DEFAULT"
+        );
+    }
+
+    offset
+}
 
 fn mutex_get_id<'mir, 'tcx: 'mir>(
     ecx: &mut MiriInterpCx<'mir, 'tcx>,
     mutex_op: &OpTy<'tcx, Provenance>,
 ) -> InterpResult<'tcx, MutexId> {
-    ecx.mutex_get_or_create_id(mutex_op, ecx.libc_ty_layout("pthread_mutex_t"), 4)
+    ecx.mutex_get_or_create_id(
+        mutex_op,
+        ecx.libc_ty_layout("pthread_mutex_t"),
+        mutex_id_offset(ecx)?,
+    )
 }
 
 fn mutex_reset_id<'mir, 'tcx: 'mir>(
@@ -80,8 +141,8 @@ fn mutex_reset_id<'mir, 'tcx: 'mir>(
 ) -> InterpResult<'tcx, ()> {
     ecx.deref_pointer_and_write(
         mutex_op,
-        4,
-        Scalar::from_i32(0),
+        mutex_id_offset(ecx)?,
+        Scalar::from_u32(0),
         ecx.libc_ty_layout("pthread_mutex_t"),
         ecx.machine.layouts.u32,
     )
@@ -91,10 +152,9 @@ fn mutex_get_kind<'mir, 'tcx: 'mir>(
     ecx: &MiriInterpCx<'mir, 'tcx>,
     mutex_op: &OpTy<'tcx, Provenance>,
 ) -> InterpResult<'tcx, i32> {
-    let offset = if ecx.pointer_size().bytes() == 8 { 16 } else { 12 };
     ecx.deref_pointer_and_read(
         mutex_op,
-        offset,
+        mutex_kind_offset(ecx),
         ecx.libc_ty_layout("pthread_mutex_t"),
         ecx.machine.layouts.i32,
     )?
@@ -106,10 +166,9 @@ fn mutex_set_kind<'mir, 'tcx: 'mir>(
     mutex_op: &OpTy<'tcx, Provenance>,
     kind: i32,
 ) -> InterpResult<'tcx, ()> {
-    let offset = if ecx.pointer_size().bytes() == 8 { 16 } else { 12 };
     ecx.deref_pointer_and_write(
         mutex_op,
-        offset,
+        mutex_kind_offset(ecx),
         Scalar::from_i32(kind),
         ecx.libc_ty_layout("pthread_mutex_t"),
         ecx.machine.layouts.i32,
@@ -117,24 +176,60 @@ fn mutex_set_kind<'mir, 'tcx: 'mir>(
 }
 
 // pthread_rwlock_t is between 32 and 56 bytes, depending on the platform.
+// We ignore the platform layout and store our own fields:
+// - id: u32
+
+fn rwlock_id_offset<'mir, 'tcx: 'mir>(ecx: &MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx, u64> {
+    let offset = match &*ecx.tcx.sess.target.os {
+        "linux" | "illumos" | "solaris" => 0,
+        // macOS stores a signature in the first bytes, so we have to move to offset 4.
+        "macos" => 4,
+        os => throw_unsup_format!("`pthread_rwlock` is not supported on {os}"),
+    };
+
+    // Sanity-check this against PTHREAD_RWLOCK_INITIALIZER (but only once):
+    // the id must start out as 0.
+    static SANITY: AtomicBool = AtomicBool::new(false);
+    if !SANITY.swap(true, Ordering::Relaxed) {
+        let static_initializer = ecx.eval_path(&["libc", "PTHREAD_RWLOCK_INITIALIZER"]);
+        let id_field = static_initializer
+            .offset(Size::from_bytes(offset), ecx.machine.layouts.u32, ecx)
+            .unwrap();
+        let id = ecx.read_scalar(&id_field).unwrap().to_u32().unwrap();
+        assert_eq!(
+            id, 0,
+            "PTHREAD_RWLOCK_INITIALIZER is incompatible with our pthread_rwlock layout: id is not 0"
+        );
+    }
 
-// Our chosen memory layout for the emulated rwlock (does not have to match the platform layout!):
-// bytes 0-3: reserved for signature on macOS
-// (need to avoid this because it is set by static initializer macros)
-// bytes 4-7: rwlock id as u32 or 0 if id is not assigned yet.
+    Ok(offset)
+}
 
 fn rwlock_get_id<'mir, 'tcx: 'mir>(
     ecx: &mut MiriInterpCx<'mir, 'tcx>,
     rwlock_op: &OpTy<'tcx, Provenance>,
 ) -> InterpResult<'tcx, RwLockId> {
-    ecx.rwlock_get_or_create_id(rwlock_op, ecx.libc_ty_layout("pthread_rwlock_t"), 4)
+    ecx.rwlock_get_or_create_id(
+        rwlock_op,
+        ecx.libc_ty_layout("pthread_rwlock_t"),
+        rwlock_id_offset(ecx)?,
+    )
 }
 
-// pthread_condattr_t
+// pthread_condattr_t.
+// We ignore the platform layout and store our own fields:
+// - clock: i32
 
-// Our chosen memory layout for emulation (does not have to match the platform layout!):
-// store an i32 in the first four bytes equal to the corresponding libc clock id constant
-// (e.g. CLOCK_REALTIME).
+#[inline]
+fn condattr_clock_offset<'mir, 'tcx: 'mir>(
+    ecx: &MiriInterpCx<'mir, 'tcx>,
+) -> InterpResult<'tcx, u64> {
+    Ok(match &*ecx.tcx.sess.target.os {
+        "linux" | "illumos" | "solaris" => 0,
+        // macOS does not have a clock attribute.
+        os => throw_unsup_format!("`pthread_condattr` clock field is not supported on {os}"),
+    })
+}
 
 fn condattr_get_clock_id<'mir, 'tcx: 'mir>(
     ecx: &MiriInterpCx<'mir, 'tcx>,
@@ -142,7 +237,7 @@ fn condattr_get_clock_id<'mir, 'tcx: 'mir>(
 ) -> InterpResult<'tcx, i32> {
     ecx.deref_pointer_and_read(
         attr_op,
-        0,
+        condattr_clock_offset(ecx)?,
         ecx.libc_ty_layout("pthread_condattr_t"),
         ecx.machine.layouts.i32,
     )?
@@ -156,27 +251,86 @@ fn condattr_set_clock_id<'mir, 'tcx: 'mir>(
 ) -> InterpResult<'tcx, ()> {
     ecx.deref_pointer_and_write(
         attr_op,
-        0,
+        condattr_clock_offset(ecx)?,
         Scalar::from_i32(clock_id),
         ecx.libc_ty_layout("pthread_condattr_t"),
         ecx.machine.layouts.i32,
     )
 }
 
-// pthread_cond_t
+// pthread_cond_t.
+// We ignore the platform layout and store our own fields:
+// - id: u32
+// - clock: i32
+
+fn cond_id_offset<'mir, 'tcx: 'mir>(ecx: &MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx, u64> {
+    let offset = match &*ecx.tcx.sess.target.os {
+        "linux" | "illumos" | "solaris" => 0,
+        // macOS stores a signature in the first bytes, so we have to move to offset 4.
+        "macos" => 4,
+        os => throw_unsup_format!("`pthread_cond` is not supported on {os}"),
+    };
+
+    // Sanity-check this against PTHREAD_COND_INITIALIZER (but only once):
+    // the id must start out as 0.
+    static SANITY: AtomicBool = AtomicBool::new(false);
+    if !SANITY.swap(true, Ordering::Relaxed) {
+        let static_initializer = ecx.eval_path(&["libc", "PTHREAD_COND_INITIALIZER"]);
+        let id_field = static_initializer
+            .offset(Size::from_bytes(offset), ecx.machine.layouts.u32, ecx)
+            .unwrap();
+        let id = ecx.read_scalar(&id_field).unwrap().to_u32().unwrap();
+        assert_eq!(
+            id, 0,
+            "PTHREAD_COND_INITIALIZER is incompatible with our pthread_cond layout: id is not 0"
+        );
+    }
+
+    Ok(offset)
+}
+
+/// Determines whether this clock represents the real-time clock, CLOCK_REALTIME.
+fn is_cond_clock_realtime<'mir, 'tcx: 'mir>(ecx: &MiriInterpCx<'mir, 'tcx>, clock_id: i32) -> bool {
+    // To ensure compatibility with PTHREAD_COND_INITIALIZER on all platforms,
+    // we can't just compare with CLOCK_REALTIME: on Solarish, PTHREAD_COND_INITIALIZER
+    // makes the clock 0 but CLOCK_REALTIME is 3.
+    // However, we need to always be able to distinguish this from CLOCK_MONOTONIC.
+    clock_id == ecx.eval_libc_i32("CLOCK_REALTIME")
+        || (clock_id == 0 && clock_id != ecx.eval_libc_i32("CLOCK_MONOTONIC"))
+}
 
-// Our chosen memory layout for the emulated conditional variable (does not have
-// to match the platform layout!):
+fn cond_clock_offset<'mir, 'tcx: 'mir>(ecx: &MiriInterpCx<'mir, 'tcx>) -> u64 {
+    // macOS doesn't have a clock attribute, but to keep the code uniform we store
+    // a clock ID in the pthread_cond_t anyway. There's enough space.
+    let offset = 8;
+
+    // Sanity-check this against PTHREAD_COND_INITIALIZER (but only once):
+    // the clock must start out as CLOCK_REALTIME.
+    static SANITY: AtomicBool = AtomicBool::new(false);
+    if !SANITY.swap(true, Ordering::Relaxed) {
+        let static_initializer = ecx.eval_path(&["libc", "PTHREAD_COND_INITIALIZER"]);
+        let id_field = static_initializer
+            .offset(Size::from_bytes(offset), ecx.machine.layouts.i32, ecx)
+            .unwrap();
+        let id = ecx.read_scalar(&id_field).unwrap().to_i32().unwrap();
+        assert!(
+            is_cond_clock_realtime(ecx, id),
+            "PTHREAD_COND_INITIALIZER is incompatible with our pthread_cond layout: clock is not CLOCK_REALTIME"
+        );
+    }
 
-// bytes 0-3: reserved for signature on macOS
-// bytes 4-7: the conditional variable id as u32 or 0 if id is not assigned yet.
-// bytes 8-11: the clock id constant as i32
+    offset
+}
 
 fn cond_get_id<'mir, 'tcx: 'mir>(
     ecx: &mut MiriInterpCx<'mir, 'tcx>,
     cond_op: &OpTy<'tcx, Provenance>,
 ) -> InterpResult<'tcx, CondvarId> {
-    ecx.condvar_get_or_create_id(cond_op, ecx.libc_ty_layout("pthread_cond_t"), 4)
+    ecx.condvar_get_or_create_id(
+        cond_op,
+        ecx.libc_ty_layout("pthread_cond_t"),
+        cond_id_offset(ecx)?,
+    )
 }
 
 fn cond_reset_id<'mir, 'tcx: 'mir>(
@@ -185,7 +339,7 @@ fn cond_reset_id<'mir, 'tcx: 'mir>(
 ) -> InterpResult<'tcx, ()> {
     ecx.deref_pointer_and_write(
         cond_op,
-        4,
+        cond_id_offset(ecx)?,
         Scalar::from_i32(0),
         ecx.libc_ty_layout("pthread_cond_t"),
         ecx.machine.layouts.u32,
@@ -198,7 +352,7 @@ fn cond_get_clock_id<'mir, 'tcx: 'mir>(
 ) -> InterpResult<'tcx, i32> {
     ecx.deref_pointer_and_read(
         cond_op,
-        8,
+        cond_clock_offset(ecx),
         ecx.libc_ty_layout("pthread_cond_t"),
         ecx.machine.layouts.i32,
     )?
@@ -212,7 +366,7 @@ fn cond_set_clock_id<'mir, 'tcx: 'mir>(
 ) -> InterpResult<'tcx, ()> {
     ecx.deref_pointer_and_write(
         cond_op,
-        8,
+        cond_clock_offset(ecx),
         Scalar::from_i32(clock_id),
         ecx.libc_ty_layout("pthread_cond_t"),
         ecx.machine.layouts.i32,
@@ -279,13 +433,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     ) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
-        if !matches!(&*this.tcx.sess.target.os, "linux" | "macos") {
-            throw_unsup_format!(
-                "`pthread_mutexattr_init` is not supported on {}",
-                this.tcx.sess.target.os
-            );
-        }
-
         let default_kind = this.eval_libc_i32("PTHREAD_MUTEX_DEFAULT");
         mutexattr_set_kind(this, attr_op, default_kind)?;
 
@@ -368,13 +515,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     ) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
-        if !matches!(&*this.tcx.sess.target.os, "linux" | "macos") {
-            throw_unsup_format!(
-                "`pthread_mutex_init` is not supported on {}",
-                this.tcx.sess.target.os
-            );
-        }
-
         let attr = this.read_pointer(attr_op)?;
         let kind = if this.ptr_is_null(attr)? {
             this.eval_libc_i32("PTHREAD_MUTEX_DEFAULT")
@@ -529,13 +669,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     ) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
-        if !matches!(&*this.tcx.sess.target.os, "linux" | "macos") {
-            throw_unsup_format!(
-                "`pthread_rwlock_rdlock` is not supported on {}",
-                this.tcx.sess.target.os
-            );
-        }
-
         let id = rwlock_get_id(this, rwlock_op)?;
         let active_thread = this.get_active_thread();
 
@@ -554,13 +687,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     ) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
-        if !matches!(&*this.tcx.sess.target.os, "linux" | "macos") {
-            throw_unsup_format!(
-                "`pthread_rwlock_tryrdlock` is not supported on {}",
-                this.tcx.sess.target.os
-            );
-        }
-
         let id = rwlock_get_id(this, rwlock_op)?;
         let active_thread = this.get_active_thread();
 
@@ -578,13 +704,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     ) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
-        if !matches!(&*this.tcx.sess.target.os, "linux" | "macos") {
-            throw_unsup_format!(
-                "`pthread_rwlock_wrlock` is not supported on {}",
-                this.tcx.sess.target.os
-            );
-        }
-
         let id = rwlock_get_id(this, rwlock_op)?;
         let active_thread = this.get_active_thread();
 
@@ -615,13 +734,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     ) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
-        if !matches!(&*this.tcx.sess.target.os, "linux" | "macos") {
-            throw_unsup_format!(
-                "`pthread_rwlock_trywrlock` is not supported on {}",
-                this.tcx.sess.target.os
-            );
-        }
-
         let id = rwlock_get_id(this, rwlock_op)?;
         let active_thread = this.get_active_thread();
 
@@ -639,13 +751,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     ) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
-        if !matches!(&*this.tcx.sess.target.os, "linux" | "macos") {
-            throw_unsup_format!(
-                "`pthread_rwlock_unlock` is not supported on {}",
-                this.tcx.sess.target.os
-            );
-        }
-
         let id = rwlock_get_id(this, rwlock_op)?;
         let active_thread = this.get_active_thread();
 
@@ -665,13 +770,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     ) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
-        if !matches!(&*this.tcx.sess.target.os, "linux" | "macos") {
-            throw_unsup_format!(
-                "`pthread_rwlock_destroy` is not supported on {}",
-                this.tcx.sess.target.os
-            );
-        }
-
         let id = rwlock_get_id(this, rwlock_op)?;
 
         if this.rwlock_is_locked(id) {
@@ -696,19 +794,15 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     ) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
-        if !matches!(&*this.tcx.sess.target.os, "linux" | "macos") {
-            throw_unsup_format!(
-                "`pthread_condattr_init` is not supported on {}",
-                this.tcx.sess.target.os
-            );
+        // no clock attribute on macOS
+        if this.tcx.sess.target.os != "macos" {
+            // The default value of the clock attribute shall refer to the system
+            // clock.
+            // https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_condattr_setclock.html
+            let default_clock_id = this.eval_libc_i32("CLOCK_REALTIME");
+            condattr_set_clock_id(this, attr_op, default_clock_id)?;
         }
 
-        // The default value of the clock attribute shall refer to the system
-        // clock.
-        // https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_condattr_setclock.html
-        let default_clock_id = this.eval_libc_i32("CLOCK_REALTIME");
-        condattr_set_clock_id(this, attr_op, default_clock_id)?;
-
         Ok(0)
     }
 
@@ -752,8 +846,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let this = self.eval_context_mut();
 
         // Destroying an uninit pthread_condattr is UB, so check to make sure it's not uninit.
-        condattr_get_clock_id(this, attr_op)?;
+        // There's no clock attribute on macOS.
+        if this.tcx.sess.target.os != "macos" {
+            condattr_get_clock_id(this, attr_op)?;
+        }
 
+        // De-init the entire thing.
         // This might lead to false positives, see comment in pthread_mutexattr_destroy
         this.write_uninit(
             &this.deref_pointer_as(attr_op, this.libc_ty_layout("pthread_condattr_t"))?,
@@ -769,15 +867,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     ) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
-        if !matches!(&*this.tcx.sess.target.os, "linux" | "macos") {
-            throw_unsup_format!(
-                "`pthread_cond_init` is not supported on {}",
-                this.tcx.sess.target.os
-            );
-        }
-
         let attr = this.read_pointer(attr_op)?;
-        let clock_id = if this.ptr_is_null(attr)? {
+        // Default clock if `attr` is null, and on macOS where there is no clock attribute.
+        let clock_id = if this.ptr_is_null(attr)? || this.tcx.sess.target.os == "macos" {
             this.eval_libc_i32("CLOCK_REALTIME")
         } else {
             condattr_get_clock_id(this, attr_op)?
@@ -858,7 +950,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             }
         };
 
-        let timeout_time = if clock_id == this.eval_libc_i32("CLOCK_REALTIME") {
+        let timeout_time = if is_cond_clock_realtime(this, clock_id) {
             this.check_no_isolation("`pthread_cond_timedwait` with `CLOCK_REALTIME`")?;
             CallbackTime::RealTime(SystemTime::UNIX_EPOCH.checked_add(duration).unwrap())
         } else if clock_id == this.eval_libc_i32("CLOCK_MONOTONIC") {
diff --git a/src/tools/miri/src/shims/unix/thread.rs b/src/tools/miri/src/shims/unix/thread.rs
index 2a56cd35dcb..9e09401a815 100644
--- a/src/tools/miri/src/shims/unix/thread.rs
+++ b/src/tools/miri/src/shims/unix/thread.rs
@@ -42,7 +42,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             throw_unsup_format!("Miri supports pthread_join only with retval==NULL");
         }
 
-        let thread_id = this.read_target_usize(thread)?;
+        let thread_id = this.read_scalar(thread)?.to_int(this.libc_ty_layout("pthread_t").size)?;
         this.join_thread_exclusive(thread_id.try_into().expect("thread ID should fit in u32"))?;
 
         Ok(0)
@@ -51,7 +51,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     fn pthread_detach(&mut self, thread: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
-        let thread_id = this.read_target_usize(thread)?;
+        let thread_id = this.read_scalar(thread)?.to_int(this.libc_ty_layout("pthread_t").size)?;
         this.detach_thread(
             thread_id.try_into().expect("thread ID should fit in u32"),
             /*allow_terminated_joined*/ false,
@@ -64,7 +64,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let this = self.eval_context_mut();
 
         let thread_id = this.get_active_thread();
-        Ok(Scalar::from_target_usize(thread_id.into(), this))
+        Ok(Scalar::from_uint(thread_id.to_u32(), this.libc_ty_layout("pthread_t").size))
     }
 
     /// Set the name of the current thread. `max_name_len` is the maximal length of the name
@@ -77,7 +77,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     ) -> InterpResult<'tcx, Scalar<Provenance>> {
         let this = self.eval_context_mut();
 
-        let thread = ThreadId::try_from(thread.to_target_usize(this)?).unwrap();
+        let thread = thread.to_int(this.libc_ty_layout("pthread_t").size)?;
+        let thread = ThreadId::try_from(thread).unwrap();
         let name = name.to_pointer(this)?;
 
         let name = this.read_c_str(name)?.to_owned();
@@ -100,7 +101,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     ) -> InterpResult<'tcx, Scalar<Provenance>> {
         let this = self.eval_context_mut();
 
-        let thread = ThreadId::try_from(thread.to_target_usize(this)?).unwrap();
+        let thread = thread.to_int(this.libc_ty_layout("pthread_t").size)?;
+        let thread = ThreadId::try_from(thread).unwrap();
         let name_out = name_out.to_pointer(this)?;
         let len = len.to_target_usize(this)?;
 
diff --git a/src/tools/miri/src/shims/windows/env.rs b/src/tools/miri/src/shims/windows/env.rs
index e91623ac871..b3bc5d4d852 100644
--- a/src/tools/miri/src/shims/windows/env.rs
+++ b/src/tools/miri/src/shims/windows/env.rs
@@ -1,5 +1,5 @@
 use std::env;
-use std::ffi::OsString;
+use std::ffi::{OsStr, OsString};
 use std::io::ErrorKind;
 
 use rustc_data_structures::fx::FxHashMap;
@@ -9,7 +9,7 @@ use helpers::windows_check_buffer_size;
 
 #[derive(Default)]
 pub struct WindowsEnvVars {
-    /// Stores the environment varialbles.
+    /// Stores the environment variables.
     map: FxHashMap<OsString, OsString>,
 }
 
@@ -26,6 +26,11 @@ impl WindowsEnvVars {
     ) -> InterpResult<'tcx, Self> {
         Ok(Self { map: env_vars })
     }
+
+    /// Implementation detail for [`InterpCx::get_env_var`].
+    pub(crate) fn get<'tcx>(&self, name: &OsStr) -> InterpResult<'tcx, Option<OsString>> {
+        Ok(self.map.get(name).cloned())
+    }
 }
 
 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs
index 08aee04254b..dba5b7a906f 100644
--- a/src/tools/miri/src/shims/windows/foreign_items.rs
+++ b/src/tools/miri/src/shims/windows/foreign_items.rs
@@ -14,7 +14,7 @@ use crate::shims::windows::*;
 use crate::*;
 use shims::windows::handle::{Handle, PseudoHandle};
 
-fn is_dyn_sym(name: &str) -> bool {
+pub fn is_dyn_sym(name: &str) -> bool {
     // std does dynamic detection for these symbols
     matches!(
         name,
@@ -506,6 +506,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             }
 
             // Miscellaneous
+            "ExitProcess" => {
+                let [code] =
+                    this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
+                let code = this.read_scalar(code)?.to_u32()?;
+                throw_machine_stop!(TerminationInfo::Exit { code: code.into(), leak_check: false });
+            }
             "SystemFunction036" => {
                 // This is really 'RtlGenRandom'.
                 let [ptr, len] =
diff --git a/src/tools/miri/src/shims/x86/avx2.rs b/src/tools/miri/src/shims/x86/avx2.rs
index 6e3468c0189..783be802bb7 100644
--- a/src/tools/miri/src/shims/x86/avx2.rs
+++ b/src/tools/miri/src/shims/x86/avx2.rs
@@ -70,6 +70,8 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
                 let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
                 // There are cases like dest: i32x4, offsets: i64x2
+                // If dest has more elements than offset, extra dest elements are filled with zero.
+                // If offsets has more elements than dest, extra offsets are ignored.
                 let actual_len = dest_len.min(offsets_len);
 
                 assert_eq!(dest_len, mask_len);
diff --git a/src/tools/miri/src/shims/x86/mod.rs b/src/tools/miri/src/shims/x86/mod.rs
index 2ab2ae85905..e519fa5508d 100644
--- a/src/tools/miri/src/shims/x86/mod.rs
+++ b/src/tools/miri/src/shims/x86/mod.rs
@@ -738,14 +738,20 @@ fn int_abs<'tcx>(
 
     assert_eq!(op_len, dest_len);
 
+    let zero = ImmTy::from_int(0, op.layout.field(this, 0));
+
     for i in 0..dest_len {
-        let op = this.read_scalar(&this.project_index(&op, i)?)?;
+        let op = this.read_immediate(&this.project_index(&op, i)?)?;
         let dest = this.project_index(&dest, i)?;
 
-        // Converting to a host "i128" works since the input is always signed.
-        let res = op.to_int(dest.layout.size)?.unsigned_abs();
+        let lt_zero = this.wrapping_binary_op(mir::BinOp::Lt, &op, &zero)?;
+        let res = if lt_zero.to_scalar().to_bool()? {
+            this.wrapping_unary_op(mir::UnOp::Neg, &op)?
+        } else {
+            op
+        };
 
-        this.write_scalar(Scalar::from_uint(res, dest.layout.size), &dest)?;
+        this.write_immediate(*res, &dest)?;
     }
 
     Ok(())
@@ -1126,6 +1132,13 @@ fn pmulhrsw<'tcx>(
     Ok(())
 }
 
+/// Packs two N-bit integer vectors to a single N/2-bit integers.
+///
+/// The conversion from N-bit to N/2-bit should be provided by `f`.
+///
+/// Each 128-bit chunk is treated independently (i.e., the value for
+/// the is i-th 128-bit chunk of `dest` is calculated with the i-th
+/// 128-bit chunks of `left` and `right`).
 fn pack_generic<'tcx>(
     this: &mut crate::MiriInterpCx<'_, 'tcx>,
     left: &OpTy<'tcx, Provenance>,
diff --git a/src/tools/miri/test-cargo-miri/run-test.py b/src/tools/miri/test-cargo-miri/run-test.py
index cac11dff775..2639d29b73d 100755
--- a/src/tools/miri/test-cargo-miri/run-test.py
+++ b/src/tools/miri/test-cargo-miri/run-test.py
@@ -34,10 +34,6 @@ def normalize_stdout(str):
     str = re.sub("finished in \\d+\\.\\d\\ds", "finished in $TIME", str) # the time keeps changing, obviously
     return str
 
-def normalize_stderr(str):
-    str = re.sub("Preparing a sysroot for Miri \\(target: [a-z0-9_-]+\\)\\.\\.\\. done\n", "", str) # remove leading cargo-miri setup output
-    return str
-
 def check_output(actual, path, name):
     if os.environ.get("RUSTC_BLESS", "0") != "0":
         # Write the output only if bless is set
@@ -69,7 +65,7 @@ def test(name, cmd, stdout_ref, stderr_ref, stdin=b'', env=None):
     )
     (stdout, stderr) = p.communicate(input=stdin)
     stdout = normalize_stdout(stdout.decode("UTF-8"))
-    stderr = normalize_stderr(stderr.decode("UTF-8"))
+    stderr = stderr.decode("UTF-8")
 
     stdout_matches = check_output(stdout, stdout_ref, "stdout")
     stderr_matches = check_output(stderr, stderr_ref, "stderr")
diff --git a/src/tools/miri/test_dependencies/Cargo.lock b/src/tools/miri/test_dependencies/Cargo.lock
index 11d430bad15..3dd5eb9b91c 100644
--- a/src/tools/miri/test_dependencies/Cargo.lock
+++ b/src/tools/miri/test_dependencies/Cargo.lock
@@ -19,15 +19,15 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
 
 [[package]]
 name = "autocfg"
-version = "1.1.0"
+version = "1.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
 
 [[package]]
 name = "backtrace"
-version = "0.3.69"
+version = "0.3.71"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
+checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d"
 dependencies = [
  "addr2line",
  "cc",
@@ -40,36 +40,27 @@ dependencies = [
 
 [[package]]
 name = "bitflags"
-version = "1.3.2"
+version = "2.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
-
-[[package]]
-name = "bitflags"
-version = "2.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
+checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
 
 [[package]]
 name = "bumpalo"
-version = "3.14.0"
+version = "3.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
+checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
 
 [[package]]
 name = "bytes"
-version = "1.5.0"
+version = "1.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
+checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9"
 
 [[package]]
 name = "cc"
-version = "1.0.83"
+version = "1.0.96"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
-dependencies = [
- "libc",
-]
+checksum = "065a29261d53ba54260972629f9ca6bffa69bac13cd1fed61420f7fa68b9f8bd"
 
 [[package]]
 name = "cfg-if"
@@ -89,9 +80,9 @@ dependencies = [
 
 [[package]]
 name = "fastrand"
-version = "2.0.1"
+version = "2.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
+checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a"
 
 [[package]]
 name = "getrandom"
@@ -106,9 +97,9 @@ dependencies = [
 
 [[package]]
 name = "getrandom"
-version = "0.2.11"
+version = "0.2.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f"
+checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c"
 dependencies = [
  "cfg-if",
  "js-sys",
@@ -125,36 +116,36 @@ checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
 
 [[package]]
 name = "hermit-abi"
-version = "0.3.3"
+version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
+checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
 
 [[package]]
 name = "js-sys"
-version = "0.3.66"
+version = "0.3.69"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca"
+checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
 dependencies = [
  "wasm-bindgen",
 ]
 
 [[package]]
 name = "libc"
-version = "0.2.151"
+version = "0.2.154"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4"
+checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346"
 
 [[package]]
 name = "linux-raw-sys"
-version = "0.4.12"
+version = "0.4.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456"
+checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
 
 [[package]]
 name = "lock_api"
-version = "0.4.11"
+version = "0.4.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
+checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
 dependencies = [
  "autocfg",
  "scopeguard",
@@ -162,21 +153,21 @@ dependencies = [
 
 [[package]]
 name = "log"
-version = "0.4.20"
+version = "0.4.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
+checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
 
 [[package]]
 name = "memchr"
-version = "2.7.1"
+version = "2.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
+checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
 
 [[package]]
 name = "miniz_oxide"
-version = "0.7.1"
+version = "0.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
+checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7"
 dependencies = [
  "adler",
 ]
@@ -197,7 +188,7 @@ name = "miri-test-deps"
 version = "0.1.0"
 dependencies = [
  "getrandom 0.1.16",
- "getrandom 0.2.11",
+ "getrandom 0.2.14",
  "libc",
  "num_cpus",
  "page_size",
@@ -244,9 +235,9 @@ dependencies = [
 
 [[package]]
 name = "parking_lot"
-version = "0.12.1"
+version = "0.12.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
+checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb"
 dependencies = [
  "lock_api",
  "parking_lot_core",
@@ -254,22 +245,22 @@ dependencies = [
 
 [[package]]
 name = "parking_lot_core"
-version = "0.9.9"
+version = "0.9.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
+checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
 dependencies = [
  "cfg-if",
  "libc",
  "redox_syscall",
  "smallvec",
- "windows-targets 0.48.5",
+ "windows-targets 0.52.5",
 ]
 
 [[package]]
 name = "pin-project-lite"
-version = "0.2.13"
+version = "0.2.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
+checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
 
 [[package]]
 name = "ppv-lite86"
@@ -279,18 +270,18 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.76"
+version = "1.0.81"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c"
+checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba"
 dependencies = [
  "unicode-ident",
 ]
 
 [[package]]
 name = "quote"
-version = "1.0.35"
+version = "1.0.36"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
+checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
 dependencies = [
  "proc-macro2",
 ]
@@ -322,16 +313,16 @@ version = "0.6.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
 dependencies = [
- "getrandom 0.2.11",
+ "getrandom 0.2.14",
 ]
 
 [[package]]
 name = "redox_syscall"
-version = "0.4.1"
+version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
+checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e"
 dependencies = [
- "bitflags 1.3.2",
+ "bitflags",
 ]
 
 [[package]]
@@ -342,11 +333,11 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
 
 [[package]]
 name = "rustix"
-version = "0.38.28"
+version = "0.38.34"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316"
+checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
 dependencies = [
- "bitflags 2.4.1",
+ "bitflags",
  "errno",
  "libc",
  "linux-raw-sys",
@@ -361,34 +352,34 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
 
 [[package]]
 name = "signal-hook-registry"
-version = "1.4.1"
+version = "1.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
+checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
 dependencies = [
  "libc",
 ]
 
 [[package]]
 name = "smallvec"
-version = "1.11.2"
+version = "1.13.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
+checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
 
 [[package]]
 name = "socket2"
-version = "0.5.5"
+version = "0.5.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9"
+checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c"
 dependencies = [
  "libc",
- "windows-sys 0.48.0",
+ "windows-sys 0.52.0",
 ]
 
 [[package]]
 name = "syn"
-version = "2.0.48"
+version = "2.0.60"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
+checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -397,22 +388,21 @@ dependencies = [
 
 [[package]]
 name = "tempfile"
-version = "3.9.0"
+version = "3.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa"
+checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1"
 dependencies = [
  "cfg-if",
  "fastrand",
- "redox_syscall",
  "rustix",
  "windows-sys 0.52.0",
 ]
 
 [[package]]
 name = "tokio"
-version = "1.35.1"
+version = "1.37.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104"
+checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787"
 dependencies = [
  "backtrace",
  "bytes",
@@ -458,9 +448,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 
 [[package]]
 name = "wasm-bindgen"
-version = "0.2.89"
+version = "0.2.92"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e"
+checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
 dependencies = [
  "cfg-if",
  "wasm-bindgen-macro",
@@ -468,9 +458,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-backend"
-version = "0.2.89"
+version = "0.2.92"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826"
+checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
 dependencies = [
  "bumpalo",
  "log",
@@ -483,9 +473,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-macro"
-version = "0.2.89"
+version = "0.2.92"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2"
+checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
 dependencies = [
  "quote",
  "wasm-bindgen-macro-support",
@@ -493,9 +483,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-macro-support"
-version = "0.2.89"
+version = "0.2.92"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283"
+checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -506,9 +496,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-shared"
-version = "0.2.89"
+version = "0.2.92"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f"
+checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
 
 [[package]]
 name = "winapi"
@@ -547,7 +537,7 @@ version = "0.52.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
 dependencies = [
- "windows-targets 0.52.0",
+ "windows-targets 0.52.5",
 ]
 
 [[package]]
@@ -567,17 +557,18 @@ dependencies = [
 
 [[package]]
 name = "windows-targets"
-version = "0.52.0"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
+checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
 dependencies = [
- "windows_aarch64_gnullvm 0.52.0",
- "windows_aarch64_msvc 0.52.0",
- "windows_i686_gnu 0.52.0",
- "windows_i686_msvc 0.52.0",
- "windows_x86_64_gnu 0.52.0",
- "windows_x86_64_gnullvm 0.52.0",
- "windows_x86_64_msvc 0.52.0",
+ "windows_aarch64_gnullvm 0.52.5",
+ "windows_aarch64_msvc 0.52.5",
+ "windows_i686_gnu 0.52.5",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc 0.52.5",
+ "windows_x86_64_gnu 0.52.5",
+ "windows_x86_64_gnullvm 0.52.5",
+ "windows_x86_64_msvc 0.52.5",
 ]
 
 [[package]]
@@ -588,9 +579,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
 
 [[package]]
 name = "windows_aarch64_gnullvm"
-version = "0.52.0"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
+checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
 
 [[package]]
 name = "windows_aarch64_msvc"
@@ -600,9 +591,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
 
 [[package]]
 name = "windows_aarch64_msvc"
-version = "0.52.0"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
+checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
 
 [[package]]
 name = "windows_i686_gnu"
@@ -612,9 +603,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
 
 [[package]]
 name = "windows_i686_gnu"
-version = "0.52.0"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
+checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
 
 [[package]]
 name = "windows_i686_msvc"
@@ -624,9 +621,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
 
 [[package]]
 name = "windows_i686_msvc"
-version = "0.52.0"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
+checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
 
 [[package]]
 name = "windows_x86_64_gnu"
@@ -636,9 +633,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
 
 [[package]]
 name = "windows_x86_64_gnu"
-version = "0.52.0"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
+checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
 
 [[package]]
 name = "windows_x86_64_gnullvm"
@@ -648,9 +645,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
 
 [[package]]
 name = "windows_x86_64_gnullvm"
-version = "0.52.0"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
+checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
 
 [[package]]
 name = "windows_x86_64_msvc"
@@ -660,6 +657,6 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
 
 [[package]]
 name = "windows_x86_64_msvc"
-version = "0.52.0"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
+checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
diff --git a/src/tools/miri/tests/extern-so/fail/function_not_in_so.stderr b/src/tools/miri/tests/extern-so/fail/function_not_in_so.stderr
index c031cb0146a..e905d7d0391 100644
--- a/src/tools/miri/tests/extern-so/fail/function_not_in_so.stderr
+++ b/src/tools/miri/tests/extern-so/fail/function_not_in_so.stderr
@@ -4,7 +4,8 @@ error: unsupported operation: can't call foreign function `foo` on $OS
 LL |         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
+   = help: if this is a basic API commonly used on this target, please report an issue with Miri
+   = help: however, note that Miri does not aim to support every FFI function out there; for instance, we will not support APIs for things such as GUIs, scripting languages, or databases
    = note: BACKTRACE:
    = note: inside `main` at $DIR/function_not_in_so.rs:LL:CC
 
diff --git a/src/tools/miri/tests/fail-dep/shims/fs/close_stdout.stderr b/src/tools/miri/tests/fail-dep/shims/fs/close_stdout.stderr
index 7547ec41719..e1b1b053bbc 100644
--- a/src/tools/miri/tests/fail-dep/shims/fs/close_stdout.stderr
+++ b/src/tools/miri/tests/fail-dep/shims/fs/close_stdout.stderr
@@ -4,7 +4,7 @@ error: unsupported operation: cannot close stdout
 LL |         libc::close(1);
    |         ^^^^^^^^^^^^^^ cannot close stdout
    |
-   = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
+   = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support
    = note: BACKTRACE:
    = note: inside `main` at $DIR/close_stdout.rs:LL:CC
 
diff --git a/src/tools/miri/tests/fail-dep/shims/fs/read_from_stdout.stderr b/src/tools/miri/tests/fail-dep/shims/fs/read_from_stdout.stderr
index 355e16d5c34..baa6eb5ad6a 100644
--- a/src/tools/miri/tests/fail-dep/shims/fs/read_from_stdout.stderr
+++ b/src/tools/miri/tests/fail-dep/shims/fs/read_from_stdout.stderr
@@ -4,7 +4,7 @@ error: unsupported operation: cannot read from stdout
 LL |         libc::read(1, bytes.as_mut_ptr() as *mut libc::c_void, 512);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot read from stdout
    |
-   = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
+   = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support
    = note: BACKTRACE:
    = note: inside `main` at $DIR/read_from_stdout.rs:LL:CC
 
diff --git a/src/tools/miri/tests/fail-dep/shims/fs/write_to_stdin.stderr b/src/tools/miri/tests/fail-dep/shims/fs/write_to_stdin.stderr
index e2ebe234b0b..37323faf560 100644
--- a/src/tools/miri/tests/fail-dep/shims/fs/write_to_stdin.stderr
+++ b/src/tools/miri/tests/fail-dep/shims/fs/write_to_stdin.stderr
@@ -4,7 +4,7 @@ error: unsupported operation: cannot write to stdin
 LL |         libc::write(0, bytes.as_ptr() as *const libc::c_void, 5);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot write to stdin
    |
-   = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
+   = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support
    = note: BACKTRACE:
    = note: inside `main` at $DIR/write_to_stdin.rs:LL:CC
 
diff --git a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_condattr_double_destroy.rs b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_condattr_double_destroy.rs
index 13e639a867d..b5427d55eb0 100644
--- a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_condattr_double_destroy.rs
+++ b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_condattr_double_destroy.rs
@@ -1,4 +1,5 @@
 //@ignore-target-windows: No libc on Windows
+//@ignore-target-apple: Our macOS condattr don't have any fields so we do not notice this.
 
 /// Test that destroying a pthread_condattr twice fails, even without a check for number validity
 
diff --git a/src/tools/miri/tests/fail-dep/tokio/sleep.stderr b/src/tools/miri/tests/fail-dep/tokio/sleep.stderr
index 59179478c30..4b12729bbff 100644
--- a/src/tools/miri/tests/fail-dep/tokio/sleep.stderr
+++ b/src/tools/miri/tests/fail-dep/tokio/sleep.stderr
@@ -9,7 +9,7 @@ LL | |             timeout,
 LL | |         ))
    | |__________^ returning ready events from epoll_wait is not yet implemented
    |
-   = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
+   = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support
 
 error: aborting due to 1 previous error
 
diff --git a/src/tools/miri/tests/fail-dep/unsupported_incomplete_function.stderr b/src/tools/miri/tests/fail-dep/unsupported_incomplete_function.stderr
index fabe3bbf121..f62622e29bf 100644
--- a/src/tools/miri/tests/fail-dep/unsupported_incomplete_function.stderr
+++ b/src/tools/miri/tests/fail-dep/unsupported_incomplete_function.stderr
@@ -4,7 +4,8 @@ error: unsupported operation: can't call foreign function `signal` on $OS
 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
+   = help: if this is a basic API commonly used on this target, please report an issue with Miri
+   = help: however, note that Miri does not aim to support every FFI function out there; for instance, we will not support APIs for things such as GUIs, scripting languages, or databases
    = note: BACKTRACE:
    = note: inside `main` at $DIR/unsupported_incomplete_function.rs:LL:CC
 
diff --git a/src/tools/miri/tests/fail/alloc/no_global_allocator.stderr b/src/tools/miri/tests/fail/alloc/no_global_allocator.stderr
index bd2a6c628f9..82bcb48cbe6 100644
--- a/src/tools/miri/tests/fail/alloc/no_global_allocator.stderr
+++ b/src/tools/miri/tests/fail/alloc/no_global_allocator.stderr
@@ -4,7 +4,8 @@ error: unsupported operation: can't call foreign function `__rust_alloc` on $OS
 LL |         __rust_alloc(1, 1);
    |         ^^^^^^^^^^^^^^^^^^ 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
+   = help: if this is a basic API commonly used on this target, please report an issue with Miri
+   = help: however, note that Miri does not aim to support every FFI function out there; for instance, we will not support APIs for things such as GUIs, scripting languages, or databases
    = note: BACKTRACE:
    = note: inside `start` at $DIR/no_global_allocator.rs:LL:CC
 
diff --git a/src/tools/miri/tests/fail/extern-type-field-offset.stderr b/src/tools/miri/tests/fail/extern-type-field-offset.stderr
index cbbf1b38361..e0d6e9ebf1d 100644
--- a/src/tools/miri/tests/fail/extern-type-field-offset.stderr
+++ b/src/tools/miri/tests/fail/extern-type-field-offset.stderr
@@ -4,7 +4,7 @@ error: unsupported operation: `extern type` does not have a known offset
 LL |     let _field = &x.a;
    |                  ^^^^ `extern type` does not have a known offset
    |
-   = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
+   = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support
    = note: BACKTRACE:
    = note: inside `main` at $DIR/extern-type-field-offset.rs:LL:CC
 
diff --git a/src/tools/miri/tests/fail/extern_static.stderr b/src/tools/miri/tests/fail/extern_static.stderr
index 34bb273f04b..21759f96019 100644
--- a/src/tools/miri/tests/fail/extern_static.stderr
+++ b/src/tools/miri/tests/fail/extern_static.stderr
@@ -4,7 +4,7 @@ error: unsupported operation: extern static `FOO` is not supported by Miri
 LL |     let _val = unsafe { std::ptr::addr_of!(FOO) };
    |                                            ^^^ extern static `FOO` is not supported by Miri
    |
-   = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
+   = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support
    = note: BACKTRACE:
    = note: inside `main` at $DIR/extern_static.rs:LL:CC
 
diff --git a/src/tools/miri/tests/fail/extern_static_in_const.stderr b/src/tools/miri/tests/fail/extern_static_in_const.stderr
index 45d1632cce2..aa524c06469 100644
--- a/src/tools/miri/tests/fail/extern_static_in_const.stderr
+++ b/src/tools/miri/tests/fail/extern_static_in_const.stderr
@@ -4,7 +4,7 @@ error: unsupported operation: extern static `E` is not supported by Miri
 LL |     let _val = X;
    |                ^ extern static `E` is not supported by Miri
    |
-   = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
+   = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support
    = note: BACKTRACE:
    = note: inside `main` at $DIR/extern_static_in_const.rs:LL:CC
 
diff --git a/src/tools/miri/tests/fail/extern_static_wrong_size.stderr b/src/tools/miri/tests/fail/extern_static_wrong_size.stderr
index 27699d780c2..3c013a5d15d 100644
--- a/src/tools/miri/tests/fail/extern_static_wrong_size.stderr
+++ b/src/tools/miri/tests/fail/extern_static_wrong_size.stderr
@@ -4,7 +4,7 @@ error: unsupported operation: extern static `environ` has been declared as `exte
 LL |     let _val = unsafe { environ };
    |                         ^^^^^^^ extern static `environ` has been declared as `extern_static_wrong_size::environ` with a size of 1 bytes and alignment of 1 bytes, but Miri emulates it via an extern static shim with a size of N bytes and alignment of N bytes
    |
-   = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
+   = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support
    = note: BACKTRACE:
    = note: inside `main` at $DIR/extern_static_wrong_size.rs:LL:CC
 
diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_array_vs_struct.stderr b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_array_vs_struct.stderr
index 595235088f6..2b2a898ce73 100644
--- a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_array_vs_struct.stderr
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_array_vs_struct.stderr
@@ -7,7 +7,7 @@ LL |     g(Default::default())
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = help: this means these two types are not *guaranteed* to be ABI-compatible across all targets
-   = help: if you think this code should be accepted anyway, please report an issue
+   = help: if you think this code should be accepted anyway, please report an issue with Miri
    = note: BACKTRACE:
    = note: inside `main` at $DIR/abi_mismatch_array_vs_struct.rs:LL:CC
 
diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_int_vs_float.stderr b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_int_vs_float.stderr
index a8b1cf40c04..752e17116d1 100644
--- a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_int_vs_float.stderr
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_int_vs_float.stderr
@@ -7,7 +7,7 @@ LL |     g(42)
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = help: this means these two types are not *guaranteed* to be ABI-compatible across all targets
-   = help: if you think this code should be accepted anyway, please report an issue
+   = help: if you think this code should be accepted anyway, please report an issue with Miri
    = note: BACKTRACE:
    = note: inside `main` at $DIR/abi_mismatch_int_vs_float.rs:LL:CC
 
diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_raw_pointer.stderr b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_raw_pointer.stderr
index 60dd3814bf5..907a8e50c41 100644
--- a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_raw_pointer.stderr
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_raw_pointer.stderr
@@ -7,7 +7,7 @@ LL |     g(&42 as *const i32)
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = help: this means these two types are not *guaranteed* to be ABI-compatible across all targets
-   = help: if you think this code should be accepted anyway, please report an issue
+   = help: if you think this code should be accepted anyway, please report an issue with Miri
    = note: BACKTRACE:
    = note: inside `main` at $DIR/abi_mismatch_raw_pointer.rs:LL:CC
 
diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_repr_C.stderr b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_repr_C.stderr
index 6d42bea9da9..eaacc32bf68 100644
--- a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_repr_C.stderr
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_repr_C.stderr
@@ -7,7 +7,7 @@ LL |     fnptr(S1(NonZeroI32::new(1).unwrap()));
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = help: this means these two types are not *guaranteed* to be ABI-compatible across all targets
-   = help: if you think this code should be accepted anyway, please report an issue
+   = help: if you think this code should be accepted anyway, please report an issue with Miri
    = note: BACKTRACE:
    = note: inside `main` at $DIR/abi_mismatch_repr_C.rs:LL:CC
 
diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_return_type.stderr b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_return_type.stderr
index 198896b0dd7..3793590f842 100644
--- a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_return_type.stderr
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_return_type.stderr
@@ -7,7 +7,7 @@ LL |     g()
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = help: this means these two types are not *guaranteed* to be ABI-compatible across all targets
-   = help: if you think this code should be accepted anyway, please report an issue
+   = help: if you think this code should be accepted anyway, please report an issue with Miri
    = note: BACKTRACE:
    = note: inside `main` at $DIR/abi_mismatch_return_type.rs:LL:CC
 
diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_simple.stderr b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_simple.stderr
index daf216a142c..0c533c14173 100644
--- a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_simple.stderr
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_simple.stderr
@@ -7,7 +7,7 @@ LL |     g(42)
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = help: this means these two types are not *guaranteed* to be ABI-compatible across all targets
-   = help: if you think this code should be accepted anyway, please report an issue
+   = help: if you think this code should be accepted anyway, please report an issue with Miri
    = note: BACKTRACE:
    = note: inside `main` at $DIR/abi_mismatch_simple.rs:LL:CC
 
diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_vector.stderr b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_vector.stderr
index 50f4474cc0e..ef4b60b83b1 100644
--- a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_vector.stderr
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_vector.stderr
@@ -7,7 +7,7 @@ LL |     g(Default::default())
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = help: this means these two types are not *guaranteed* to be ABI-compatible across all targets
-   = help: if you think this code should be accepted anyway, please report an issue
+   = help: if you think this code should be accepted anyway, please report an issue with Miri
    = note: BACKTRACE:
    = note: inside `main` at $DIR/abi_mismatch_vector.rs:LL:CC
 
diff --git a/src/tools/miri/tests/fail/intrinsic_fallback_checks_ub.stderr b/src/tools/miri/tests/fail/intrinsic_fallback_checks_ub.stderr
index b37e05c62f9..699dda52096 100644
--- a/src/tools/miri/tests/fail/intrinsic_fallback_checks_ub.stderr
+++ b/src/tools/miri/tests/fail/intrinsic_fallback_checks_ub.stderr
@@ -4,7 +4,7 @@ error: unsupported operation: miri can only use intrinsic fallback bodies that c
 LL |     ptr_guaranteed_cmp::<()>(std::ptr::null(), std::ptr::null());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ miri can only use intrinsic fallback bodies that check UB. After verifying that `ptr_guaranteed_cmp` does so, add the `#[miri::intrinsic_fallback_checks_ub]` attribute to it; also ping @rust-lang/miri when you do that
    |
-   = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
+   = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support
    = note: BACKTRACE:
    = note: inside `main` at $DIR/intrinsic_fallback_checks_ub.rs:LL:CC
 
diff --git a/src/tools/miri/tests/fail/shims/intrinsic_target_feature.rs b/src/tools/miri/tests/fail/intrinsics/intrinsic_target_feature.rs
index 9263ad381d1..9263ad381d1 100644
--- a/src/tools/miri/tests/fail/shims/intrinsic_target_feature.rs
+++ b/src/tools/miri/tests/fail/intrinsics/intrinsic_target_feature.rs
diff --git a/src/tools/miri/tests/fail/shims/intrinsic_target_feature.stderr b/src/tools/miri/tests/fail/intrinsics/intrinsic_target_feature.stderr
index 8e83d20854f..8e83d20854f 100644
--- a/src/tools/miri/tests/fail/shims/intrinsic_target_feature.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/intrinsic_target_feature.stderr
diff --git a/src/tools/miri/tests/fail/issue-miri-3288-ice-symbolic-alignment-extern-static.stderr b/src/tools/miri/tests/fail/issue-miri-3288-ice-symbolic-alignment-extern-static.stderr
index e5dbe749884..4064d7fe4e9 100644
--- a/src/tools/miri/tests/fail/issue-miri-3288-ice-symbolic-alignment-extern-static.stderr
+++ b/src/tools/miri/tests/fail/issue-miri-3288-ice-symbolic-alignment-extern-static.stderr
@@ -4,7 +4,7 @@ error: unsupported operation: extern static `_dispatch_queue_attr_concurrent` is
 LL |     let _val = *DISPATCH_QUEUE_CONCURRENT;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ extern static `_dispatch_queue_attr_concurrent` is not supported by Miri
    |
-   = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
+   = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support
    = note: BACKTRACE:
    = note: inside `main` at $DIR/issue-miri-3288-ice-symbolic-alignment-extern-static.rs:LL:CC
 
diff --git a/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-flags.stderr b/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-flags.stderr
index 2523e5063e1..504485e3b3a 100644
--- a/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-flags.stderr
+++ b/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-flags.stderr
@@ -4,7 +4,7 @@ error: unsupported operation: unknown `miri_get_backtrace` flags 2
 LL |         miri_get_backtrace(2, std::ptr::null_mut());
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unknown `miri_get_backtrace` flags 2
    |
-   = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
+   = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support
    = note: BACKTRACE:
    = note: inside `main` at $DIR/bad-backtrace-flags.rs:LL:CC
 
diff --git a/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-resolve-flags.stderr b/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-resolve-flags.stderr
index 36446ae283b..c1f0ce3d1a8 100644
--- a/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-resolve-flags.stderr
+++ b/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-resolve-flags.stderr
@@ -4,7 +4,7 @@ error: unsupported operation: unknown `miri_resolve_frame` flags 2
 LL |         miri_resolve_frame(buf[0], 2);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unknown `miri_resolve_frame` flags 2
    |
-   = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
+   = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support
    = note: BACKTRACE:
    = note: inside `main` at $DIR/bad-backtrace-resolve-flags.rs:LL:CC
 
diff --git a/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-resolve-names-flags.stderr b/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-resolve-names-flags.stderr
index ff60ab09172..fc270593e63 100644
--- a/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-resolve-names-flags.stderr
+++ b/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-resolve-names-flags.stderr
@@ -4,7 +4,7 @@ error: unsupported operation: unknown `miri_resolve_frame_names` flags 2
 LL | ...   miri_resolve_frame_names(buf[0], 2, std::ptr::null_mut(), std::ptr::null_mut());
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unknown `miri_resolve_frame_names` flags 2
    |
-   = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
+   = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support
    = note: BACKTRACE:
    = note: inside `main` at $DIR/bad-backtrace-resolve-names-flags.rs:LL:CC
 
diff --git a/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-size-flags.stderr b/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-size-flags.stderr
index 6d4c370050f..2d70733334d 100644
--- a/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-size-flags.stderr
+++ b/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-size-flags.stderr
@@ -4,7 +4,7 @@ error: unsupported operation: unknown `miri_backtrace_size` flags 2
 LL |         miri_backtrace_size(2);
    |         ^^^^^^^^^^^^^^^^^^^^^^ unknown `miri_backtrace_size` flags 2
    |
-   = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
+   = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support
    = note: BACKTRACE:
    = note: inside `main` at $DIR/bad-backtrace-size-flags.rs:LL:CC
 
diff --git a/src/tools/miri/tests/fail/unaligned_pointers/promise_alignment.call_unaligned_ptr.stderr b/src/tools/miri/tests/fail/unaligned_pointers/promise_alignment.call_unaligned_ptr.stderr
index e23ac5ac2fc..6d62db4d3d5 100644
--- a/src/tools/miri/tests/fail/unaligned_pointers/promise_alignment.call_unaligned_ptr.stderr
+++ b/src/tools/miri/tests/fail/unaligned_pointers/promise_alignment.call_unaligned_ptr.stderr
@@ -4,7 +4,7 @@ error: unsupported operation: `miri_promise_symbolic_alignment`: pointer is not
 LL |         unsafe { utils::miri_promise_symbolic_alignment(align8.add(1).cast(), 8) };
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `miri_promise_symbolic_alignment`: pointer is not actually aligned
    |
-   = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
+   = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support
    = note: BACKTRACE:
    = note: inside `main` at $DIR/promise_alignment.rs:LL:CC
 
diff --git a/src/tools/miri/tests/fail/unaligned_pointers/promise_alignment_zero.stderr b/src/tools/miri/tests/fail/unaligned_pointers/promise_alignment_zero.stderr
index b3327e04933..3f7ced0b407 100644
--- a/src/tools/miri/tests/fail/unaligned_pointers/promise_alignment_zero.stderr
+++ b/src/tools/miri/tests/fail/unaligned_pointers/promise_alignment_zero.stderr
@@ -4,7 +4,7 @@ error: unsupported operation: `miri_promise_symbolic_alignment`: alignment must
 LL |     unsafe { utils::miri_promise_symbolic_alignment(buffer.as_ptr().cast(), 0) };
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `miri_promise_symbolic_alignment`: alignment must be a power of 2, got 0
    |
-   = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
+   = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support
    = note: BACKTRACE:
    = note: inside `main` at $DIR/promise_alignment_zero.rs:LL:CC
 
diff --git a/src/tools/miri/tests/fail/unsized-local.stderr b/src/tools/miri/tests/fail/unsized-local.stderr
index 0ffda9e6d63..df54c98bb0e 100644
--- a/src/tools/miri/tests/fail/unsized-local.stderr
+++ b/src/tools/miri/tests/fail/unsized-local.stderr
@@ -4,7 +4,7 @@ error: unsupported operation: unsized locals are not supported
 LL |     let x = *(Box::new(A) as Box<dyn Foo>);
    |         ^ unsized locals are not supported
    |
-   = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
+   = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support
    = note: BACKTRACE:
    = note: inside `main` at $DIR/unsized-local.rs:LL:CC
 
diff --git a/src/tools/miri/tests/fail/unsupported_foreign_function.stderr b/src/tools/miri/tests/fail/unsupported_foreign_function.stderr
index 5a2f415bb84..f392e9564c7 100644
--- a/src/tools/miri/tests/fail/unsupported_foreign_function.stderr
+++ b/src/tools/miri/tests/fail/unsupported_foreign_function.stderr
@@ -4,7 +4,8 @@ error: unsupported operation: can't call foreign function `foo` on $OS
 LL |         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
+   = help: if this is a basic API commonly used on this target, please report an issue with Miri
+   = help: however, note that Miri does not aim to support every FFI function out there; for instance, we will not support APIs for things such as GUIs, scripting languages, or databases
    = note: BACKTRACE:
    = note: inside `main` at $DIR/unsupported_foreign_function.rs:LL:CC
 
diff --git a/src/tools/miri/tests/pass-dep/shims/libc-fs.rs b/src/tools/miri/tests/pass-dep/shims/libc-fs.rs
index 4cfc1843a7a..0dd849a045d 100644
--- a/src/tools/miri/tests/pass-dep/shims/libc-fs.rs
+++ b/src/tools/miri/tests/pass-dep/shims/libc-fs.rs
@@ -4,10 +4,11 @@
 #![feature(io_error_more)]
 #![feature(io_error_uncategorized)]
 
-use std::ffi::CString;
+use std::ffi::{CStr, CString, OsString};
 use std::fs::{canonicalize, remove_dir_all, remove_file, File};
 use std::io::{Error, ErrorKind, Write};
 use std::os::unix::ffi::OsStrExt;
+use std::os::unix::io::AsRawFd;
 use std::path::PathBuf;
 
 #[path = "../../utils/mod.rs"]
@@ -27,6 +28,14 @@ fn main() {
     #[cfg(target_os = "linux")]
     test_o_tmpfile_flag();
     test_posix_mkstemp();
+    test_posix_realpath_alloc();
+    test_posix_realpath_noalloc();
+    test_posix_realpath_errors();
+    #[cfg(target_os = "linux")]
+    test_posix_fadvise();
+    #[cfg(target_os = "linux")]
+    test_sync_file_range();
+    test_isatty();
 }
 
 /// Prepare: compute filename and make sure the file does not exist.
@@ -256,3 +265,166 @@ fn test_posix_mkstemp() {
         assert_eq!(e.kind(), std::io::ErrorKind::InvalidInput);
     }
 }
+
+/// Test allocating variant of `realpath`.
+fn test_posix_realpath_alloc() {
+    use std::os::unix::ffi::OsStrExt;
+    use std::os::unix::ffi::OsStringExt;
+
+    let buf;
+    let path = utils::tmp().join("miri_test_libc_posix_realpath_alloc");
+    let c_path = CString::new(path.as_os_str().as_bytes()).expect("CString::new failed");
+
+    // Cleanup before test.
+    remove_file(&path).ok();
+    // Create file.
+    drop(File::create(&path).unwrap());
+    unsafe {
+        let r = libc::realpath(c_path.as_ptr(), std::ptr::null_mut());
+        assert!(!r.is_null());
+        buf = CStr::from_ptr(r).to_bytes().to_vec();
+        libc::free(r as *mut _);
+    }
+    let canonical = PathBuf::from(OsString::from_vec(buf));
+    assert_eq!(path.file_name(), canonical.file_name());
+
+    // Cleanup after test.
+    remove_file(&path).unwrap();
+}
+
+/// Test non-allocating variant of `realpath`.
+fn test_posix_realpath_noalloc() {
+    use std::ffi::{CStr, CString};
+    use std::os::unix::ffi::OsStrExt;
+
+    let path = utils::tmp().join("miri_test_libc_posix_realpath_noalloc");
+    let c_path = CString::new(path.as_os_str().as_bytes()).expect("CString::new failed");
+
+    let mut v = vec![0; libc::PATH_MAX as usize];
+
+    // Cleanup before test.
+    remove_file(&path).ok();
+    // Create file.
+    drop(File::create(&path).unwrap());
+    unsafe {
+        let r = libc::realpath(c_path.as_ptr(), v.as_mut_ptr());
+        assert!(!r.is_null());
+    }
+    let c = unsafe { CStr::from_ptr(v.as_ptr()) };
+    let canonical = PathBuf::from(c.to_str().expect("CStr to str"));
+
+    assert_eq!(path.file_name(), canonical.file_name());
+
+    // Cleanup after test.
+    remove_file(&path).unwrap();
+}
+
+/// Test failure cases for `realpath`.
+fn test_posix_realpath_errors() {
+    use std::ffi::CString;
+    use std::io::ErrorKind;
+
+    // Test nonexistent path returns an error.
+    let c_path = CString::new("./nothing_to_see_here").expect("CString::new failed");
+    let r = unsafe { libc::realpath(c_path.as_ptr(), std::ptr::null_mut()) };
+    assert!(r.is_null());
+    let e = std::io::Error::last_os_error();
+    assert_eq!(e.raw_os_error(), Some(libc::ENOENT));
+    assert_eq!(e.kind(), ErrorKind::NotFound);
+}
+
+#[cfg(target_os = "linux")]
+fn test_posix_fadvise() {
+    use std::io::Write;
+
+    let path = utils::tmp().join("miri_test_libc_posix_fadvise.txt");
+    // Cleanup before test
+    remove_file(&path).ok();
+
+    // Set up an open file
+    let mut file = File::create(&path).unwrap();
+    let bytes = b"Hello, World!\n";
+    file.write(bytes).unwrap();
+
+    // Test calling posix_fadvise on a file.
+    let result = unsafe {
+        libc::posix_fadvise(
+            file.as_raw_fd(),
+            0,
+            bytes.len().try_into().unwrap(),
+            libc::POSIX_FADV_DONTNEED,
+        )
+    };
+    drop(file);
+    remove_file(&path).unwrap();
+    assert_eq!(result, 0);
+}
+
+#[cfg(target_os = "linux")]
+fn test_sync_file_range() {
+    use std::io::Write;
+
+    let path = utils::tmp().join("miri_test_libc_sync_file_range.txt");
+    // Cleanup before test.
+    remove_file(&path).ok();
+
+    // Write to a file.
+    let mut file = File::create(&path).unwrap();
+    let bytes = b"Hello, World!\n";
+    file.write(bytes).unwrap();
+
+    // Test calling sync_file_range on the file.
+    let result_1 = unsafe {
+        libc::sync_file_range(
+            file.as_raw_fd(),
+            0,
+            0,
+            libc::SYNC_FILE_RANGE_WAIT_BEFORE
+                | libc::SYNC_FILE_RANGE_WRITE
+                | libc::SYNC_FILE_RANGE_WAIT_AFTER,
+        )
+    };
+    drop(file);
+
+    // Test calling sync_file_range on a file opened for reading.
+    let file = File::open(&path).unwrap();
+    let result_2 = unsafe {
+        libc::sync_file_range(
+            file.as_raw_fd(),
+            0,
+            0,
+            libc::SYNC_FILE_RANGE_WAIT_BEFORE
+                | libc::SYNC_FILE_RANGE_WRITE
+                | libc::SYNC_FILE_RANGE_WAIT_AFTER,
+        )
+    };
+    drop(file);
+
+    remove_file(&path).unwrap();
+    assert_eq!(result_1, 0);
+    assert_eq!(result_2, 0);
+}
+
+fn test_isatty() {
+    // Testing whether our isatty shim returns the right value would require controlling whether
+    // these streams are actually TTYs, which is hard.
+    // For now, we just check that these calls are supported at all.
+    unsafe {
+        libc::isatty(libc::STDIN_FILENO);
+        libc::isatty(libc::STDOUT_FILENO);
+        libc::isatty(libc::STDERR_FILENO);
+
+        // But when we open a file, it is definitely not a TTY.
+        let path = utils::tmp().join("notatty.txt");
+        // Cleanup before test.
+        remove_file(&path).ok();
+        let file = File::create(&path).unwrap();
+
+        assert_eq!(libc::isatty(file.as_raw_fd()), 0);
+        assert_eq!(std::io::Error::last_os_error().raw_os_error().unwrap(), libc::ENOTTY);
+
+        // Cleanup after test.
+        drop(file);
+        remove_file(&path).unwrap();
+    }
+}
diff --git a/src/tools/miri/tests/pass-dep/shims/libc-getentropy.rs b/src/tools/miri/tests/pass-dep/shims/libc-getentropy.rs
deleted file mode 100644
index 4b863f68516..00000000000
--- a/src/tools/miri/tests/pass-dep/shims/libc-getentropy.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-//@ignore-target-windows: no libc
-
-// on macOS this is not in the `libc` crate.
-#[cfg(target_os = "macos")]
-extern "C" {
-    fn getentropy(bytes: *mut libc::c_void, count: libc::size_t) -> libc::c_int;
-}
-
-#[cfg(not(target_os = "macos"))]
-use libc::getentropy;
-
-fn main() {
-    let mut buf1 = [0u8; 256];
-    let mut buf2 = [0u8; 257];
-    unsafe {
-        assert_eq!(getentropy(buf1.as_mut_ptr() as *mut libc::c_void, buf1.len()), 0);
-        assert_eq!(getentropy(buf2.as_mut_ptr() as *mut libc::c_void, buf2.len()), -1);
-        assert_eq!(std::io::Error::last_os_error().raw_os_error().unwrap(), libc::EIO);
-    }
-}
diff --git a/src/tools/miri/tests/pass-dep/shims/libc-getrandom-without-isolation.rs b/src/tools/miri/tests/pass-dep/shims/libc-getrandom-without-isolation.rs
deleted file mode 100644
index 349b447569a..00000000000
--- a/src/tools/miri/tests/pass-dep/shims/libc-getrandom-without-isolation.rs
+++ /dev/null
@@ -1,41 +0,0 @@
-//@only-target-linux
-//@compile-flags: -Zmiri-disable-isolation
-
-use std::ptr;
-
-fn main() {
-    let mut buf = [0u8; 5];
-    unsafe {
-        assert_eq!(
-            libc::syscall(
-                libc::SYS_getrandom,
-                ptr::null_mut::<libc::c_void>(),
-                0 as libc::size_t,
-                0 as libc::c_uint,
-            ),
-            0,
-        );
-        assert_eq!(
-            libc::syscall(
-                libc::SYS_getrandom,
-                buf.as_mut_ptr() as *mut libc::c_void,
-                5 as libc::size_t,
-                0 as libc::c_uint,
-            ),
-            5,
-        );
-
-        assert_eq!(
-            libc::getrandom(ptr::null_mut::<libc::c_void>(), 0 as libc::size_t, 0 as libc::c_uint),
-            0,
-        );
-        assert_eq!(
-            libc::getrandom(
-                buf.as_mut_ptr() as *mut libc::c_void,
-                5 as libc::size_t,
-                0 as libc::c_uint,
-            ),
-            5,
-        );
-    }
-}
diff --git a/src/tools/miri/tests/pass-dep/shims/libc-misc.rs b/src/tools/miri/tests/pass-dep/shims/libc-misc.rs
index f710daf5277..9644920c499 100644
--- a/src/tools/miri/tests/pass-dep/shims/libc-misc.rs
+++ b/src/tools/miri/tests/pass-dep/shims/libc-misc.rs
@@ -1,158 +1,16 @@
 //@ignore-target-windows: No libc on Windows
 //@compile-flags: -Zmiri-disable-isolation
 #![feature(io_error_more)]
+#![feature(pointer_is_aligned_to)]
+#![feature(strict_provenance)]
 
-use std::fs::{remove_file, File};
-use std::mem::transmute;
-use std::os::unix::io::AsRawFd;
-use std::path::PathBuf;
-
-#[path = "../../utils/mod.rs"]
-mod utils;
-
-/// Test allocating variant of `realpath`.
-fn test_posix_realpath_alloc() {
-    use std::ffi::OsString;
-    use std::ffi::{CStr, CString};
-    use std::os::unix::ffi::OsStrExt;
-    use std::os::unix::ffi::OsStringExt;
-
-    let buf;
-    let path = utils::tmp().join("miri_test_libc_posix_realpath_alloc");
-    let c_path = CString::new(path.as_os_str().as_bytes()).expect("CString::new failed");
-
-    // Cleanup before test.
-    remove_file(&path).ok();
-    // Create file.
-    drop(File::create(&path).unwrap());
-    unsafe {
-        let r = libc::realpath(c_path.as_ptr(), std::ptr::null_mut());
-        assert!(!r.is_null());
-        buf = CStr::from_ptr(r).to_bytes().to_vec();
-        libc::free(r as *mut _);
-    }
-    let canonical = PathBuf::from(OsString::from_vec(buf));
-    assert_eq!(path.file_name(), canonical.file_name());
-
-    // Cleanup after test.
-    remove_file(&path).unwrap();
-}
-
-/// Test non-allocating variant of `realpath`.
-fn test_posix_realpath_noalloc() {
-    use std::ffi::{CStr, CString};
-    use std::os::unix::ffi::OsStrExt;
-
-    let path = utils::tmp().join("miri_test_libc_posix_realpath_noalloc");
-    let c_path = CString::new(path.as_os_str().as_bytes()).expect("CString::new failed");
-
-    let mut v = vec![0; libc::PATH_MAX as usize];
-
-    // Cleanup before test.
-    remove_file(&path).ok();
-    // Create file.
-    drop(File::create(&path).unwrap());
-    unsafe {
-        let r = libc::realpath(c_path.as_ptr(), v.as_mut_ptr());
-        assert!(!r.is_null());
-    }
-    let c = unsafe { CStr::from_ptr(v.as_ptr()) };
-    let canonical = PathBuf::from(c.to_str().expect("CStr to str"));
-
-    assert_eq!(path.file_name(), canonical.file_name());
-
-    // Cleanup after test.
-    remove_file(&path).unwrap();
-}
-
-/// Test failure cases for `realpath`.
-fn test_posix_realpath_errors() {
-    use std::ffi::CString;
-    use std::io::ErrorKind;
-
-    // Test nonexistent path returns an error.
-    let c_path = CString::new("./nothing_to_see_here").expect("CString::new failed");
-    let r = unsafe { libc::realpath(c_path.as_ptr(), std::ptr::null_mut()) };
-    assert!(r.is_null());
-    let e = std::io::Error::last_os_error();
-    assert_eq!(e.raw_os_error(), Some(libc::ENOENT));
-    assert_eq!(e.kind(), ErrorKind::NotFound);
-}
-
-#[cfg(target_os = "linux")]
-fn test_posix_fadvise() {
-    use std::io::Write;
-
-    let path = utils::tmp().join("miri_test_libc_posix_fadvise.txt");
-    // Cleanup before test
-    remove_file(&path).ok();
-
-    // Set up an open file
-    let mut file = File::create(&path).unwrap();
-    let bytes = b"Hello, World!\n";
-    file.write(bytes).unwrap();
-
-    // Test calling posix_fadvise on a file.
-    let result = unsafe {
-        libc::posix_fadvise(
-            file.as_raw_fd(),
-            0,
-            bytes.len().try_into().unwrap(),
-            libc::POSIX_FADV_DONTNEED,
-        )
-    };
-    drop(file);
-    remove_file(&path).unwrap();
-    assert_eq!(result, 0);
-}
-
-#[cfg(target_os = "linux")]
-fn test_sync_file_range() {
-    use std::io::Write;
-
-    let path = utils::tmp().join("miri_test_libc_sync_file_range.txt");
-    // Cleanup before test.
-    remove_file(&path).ok();
-
-    // Write to a file.
-    let mut file = File::create(&path).unwrap();
-    let bytes = b"Hello, World!\n";
-    file.write(bytes).unwrap();
-
-    // Test calling sync_file_range on the file.
-    let result_1 = unsafe {
-        libc::sync_file_range(
-            file.as_raw_fd(),
-            0,
-            0,
-            libc::SYNC_FILE_RANGE_WAIT_BEFORE
-                | libc::SYNC_FILE_RANGE_WRITE
-                | libc::SYNC_FILE_RANGE_WAIT_AFTER,
-        )
-    };
-    drop(file);
-
-    // Test calling sync_file_range on a file opened for reading.
-    let file = File::open(&path).unwrap();
-    let result_2 = unsafe {
-        libc::sync_file_range(
-            file.as_raw_fd(),
-            0,
-            0,
-            libc::SYNC_FILE_RANGE_WAIT_BEFORE
-                | libc::SYNC_FILE_RANGE_WRITE
-                | libc::SYNC_FILE_RANGE_WAIT_AFTER,
-        )
-    };
-    drop(file);
-
-    remove_file(&path).unwrap();
-    assert_eq!(result_1, 0);
-    assert_eq!(result_2, 0);
-}
+use std::mem::{self, transmute};
+use std::ptr;
 
 /// Tests whether each thread has its own `__errno_location`.
 fn test_thread_local_errno() {
+    #[cfg(any(target_os = "illumos", target_os = "solaris"))]
+    use libc::___errno as __errno_location;
     #[cfg(target_os = "linux")]
     use libc::__errno_location;
     #[cfg(any(target_os = "macos", target_os = "freebsd"))]
@@ -171,116 +29,6 @@ fn test_thread_local_errno() {
     }
 }
 
-/// Tests whether clock support exists at all
-fn test_clocks() {
-    let mut tp = std::mem::MaybeUninit::<libc::timespec>::uninit();
-    let is_error = unsafe { libc::clock_gettime(libc::CLOCK_REALTIME, tp.as_mut_ptr()) };
-    assert_eq!(is_error, 0);
-    let is_error = unsafe { libc::clock_gettime(libc::CLOCK_MONOTONIC, tp.as_mut_ptr()) };
-    assert_eq!(is_error, 0);
-    #[cfg(any(target_os = "linux", target_os = "freebsd"))]
-    {
-        let is_error = unsafe { libc::clock_gettime(libc::CLOCK_REALTIME_COARSE, tp.as_mut_ptr()) };
-        assert_eq!(is_error, 0);
-        let is_error =
-            unsafe { libc::clock_gettime(libc::CLOCK_MONOTONIC_COARSE, tp.as_mut_ptr()) };
-        assert_eq!(is_error, 0);
-    }
-    #[cfg(target_os = "macos")]
-    {
-        let is_error = unsafe { libc::clock_gettime(libc::CLOCK_UPTIME_RAW, tp.as_mut_ptr()) };
-        assert_eq!(is_error, 0);
-    }
-}
-
-fn test_posix_gettimeofday() {
-    let mut tp = std::mem::MaybeUninit::<libc::timeval>::uninit();
-    let tz = std::ptr::null_mut::<libc::timezone>();
-    #[cfg(target_os = "macos")] // `tz` has a different type on macOS
-    let tz = tz as *mut libc::c_void;
-    let is_error = unsafe { libc::gettimeofday(tp.as_mut_ptr(), tz) };
-    assert_eq!(is_error, 0);
-    let tv = unsafe { tp.assume_init() };
-    assert!(tv.tv_sec > 0);
-    assert!(tv.tv_usec >= 0); // Theoretically this could be 0.
-
-    // Test that non-null tz returns an error.
-    let mut tz = std::mem::MaybeUninit::<libc::timezone>::uninit();
-    let tz_ptr = tz.as_mut_ptr();
-    #[cfg(target_os = "macos")] // `tz` has a different type on macOS
-    let tz_ptr = tz_ptr as *mut libc::c_void;
-    let is_error = unsafe { libc::gettimeofday(tp.as_mut_ptr(), tz_ptr) };
-    assert_eq!(is_error, -1);
-}
-
-fn test_localtime_r() {
-    use std::ffi::CStr;
-    use std::{env, ptr};
-
-    // Set timezone to GMT.
-    let key = "TZ";
-    env::set_var(key, "GMT");
-
-    const TIME_SINCE_EPOCH: libc::time_t = 1712475836;
-    let custom_time_ptr = &TIME_SINCE_EPOCH;
-    let mut tm = libc::tm {
-        tm_sec: 0,
-        tm_min: 0,
-        tm_hour: 0,
-        tm_mday: 0,
-        tm_mon: 0,
-        tm_year: 0,
-        tm_wday: 0,
-        tm_yday: 0,
-        tm_isdst: 0,
-        tm_gmtoff: 0,
-        tm_zone: std::ptr::null_mut::<libc::c_char>(),
-    };
-    let res = unsafe { libc::localtime_r(custom_time_ptr, &mut tm) };
-
-    assert_eq!(tm.tm_sec, 56);
-    assert_eq!(tm.tm_min, 43);
-    assert_eq!(tm.tm_hour, 7);
-    assert_eq!(tm.tm_mday, 7);
-    assert_eq!(tm.tm_mon, 3);
-    assert_eq!(tm.tm_year, 124);
-    assert_eq!(tm.tm_wday, 0);
-    assert_eq!(tm.tm_yday, 97);
-    assert_eq!(tm.tm_isdst, -1);
-    assert_eq!(tm.tm_gmtoff, 0);
-    unsafe { assert_eq!(CStr::from_ptr(tm.tm_zone).to_str().unwrap(), "+00") };
-
-    // The returned value is the pointer passed in.
-    assert!(ptr::eq(res, &mut tm));
-
-    //Remove timezone setting.
-    env::remove_var(key);
-}
-
-fn test_isatty() {
-    // Testing whether our isatty shim returns the right value would require controlling whether
-    // these streams are actually TTYs, which is hard.
-    // For now, we just check that these calls are supported at all.
-    unsafe {
-        libc::isatty(libc::STDIN_FILENO);
-        libc::isatty(libc::STDOUT_FILENO);
-        libc::isatty(libc::STDERR_FILENO);
-
-        // But when we open a file, it is definitely not a TTY.
-        let path = utils::tmp().join("notatty.txt");
-        // Cleanup before test.
-        remove_file(&path).ok();
-        let file = File::create(&path).unwrap();
-
-        assert_eq!(libc::isatty(file.as_raw_fd()), 0);
-        assert_eq!(std::io::Error::last_os_error().raw_os_error().unwrap(), libc::ENOTTY);
-
-        // Cleanup after test.
-        drop(file);
-        remove_file(&path).unwrap();
-    }
-}
-
 fn test_memcpy() {
     unsafe {
         let src = [1i8, 2, 3];
@@ -306,7 +54,7 @@ fn test_memcpy() {
         libc::memcpy(
             &mut dest as *mut i32 as *mut libc::c_void,
             &src as *const i32 as *const libc::c_void,
-            std::mem::size_of::<i32>(),
+            mem::size_of::<i32>(),
         );
         assert_eq!(dest, src);
     }
@@ -317,7 +65,7 @@ fn test_memcpy() {
         libc::memcpy(
             &mut dest as *mut Option<i32> as *mut libc::c_void,
             &src as *const Option<i32> as *const libc::c_void,
-            std::mem::size_of::<Option<i32>>(),
+            mem::size_of::<Option<i32>>(),
         );
         assert_eq!(dest, src);
     }
@@ -328,7 +76,7 @@ fn test_memcpy() {
         libc::memcpy(
             &mut dest as *mut &'static i32 as *mut libc::c_void,
             &src as *const &'static i32 as *const libc::c_void,
-            std::mem::size_of::<&'static i32>(),
+            mem::size_of::<&'static i32>(),
         );
         assert_eq!(*dest, 123);
     }
@@ -388,7 +136,7 @@ fn test_dlsym() {
     assert_eq!(errno, libc::EBADF);
 }
 
-#[cfg(not(target_os = "macos"))]
+#[cfg(not(any(target_os = "macos", target_os = "illumos")))]
 fn test_reallocarray() {
     unsafe {
         let mut p = libc::reallocarray(std::ptr::null_mut(), 4096, 2);
@@ -401,33 +149,94 @@ fn test_reallocarray() {
     }
 }
 
-fn main() {
-    test_posix_gettimeofday();
+fn test_memalign() {
+    // A normal allocation.
+    unsafe {
+        let mut ptr: *mut libc::c_void = ptr::null_mut();
+        let align = 8;
+        let size = 64;
+        assert_eq!(libc::posix_memalign(&mut ptr, align, size), 0);
+        assert!(!ptr.is_null());
+        assert!(ptr.is_aligned_to(align));
+        ptr.cast::<u8>().write_bytes(1, size);
+        libc::free(ptr);
+    }
 
-    test_posix_realpath_alloc();
-    test_posix_realpath_noalloc();
-    test_posix_realpath_errors();
+    // Align > size.
+    unsafe {
+        let mut ptr: *mut libc::c_void = ptr::null_mut();
+        let align = 64;
+        let size = 8;
+        assert_eq!(libc::posix_memalign(&mut ptr, align, size), 0);
+        assert!(!ptr.is_null());
+        assert!(ptr.is_aligned_to(align));
+        ptr.cast::<u8>().write_bytes(1, size);
+        libc::free(ptr);
+    }
 
-    test_thread_local_errno();
-    test_localtime_r();
+    // Size not multiple of align
+    unsafe {
+        let mut ptr: *mut libc::c_void = ptr::null_mut();
+        let align = 16;
+        let size = 31;
+        assert_eq!(libc::posix_memalign(&mut ptr, align, size), 0);
+        assert!(!ptr.is_null());
+        assert!(ptr.is_aligned_to(align));
+        ptr.cast::<u8>().write_bytes(1, size);
+        libc::free(ptr);
+    }
 
-    test_isatty();
+    // Size == 0
+    unsafe {
+        let mut ptr: *mut libc::c_void = ptr::null_mut();
+        let align = 64;
+        let size = 0;
+        assert_eq!(libc::posix_memalign(&mut ptr, align, size), 0);
+        // We are not required to return null if size == 0, but we currently do.
+        // It's fine to remove this assert if we start returning non-null pointers.
+        assert!(ptr.is_null());
+        assert!(ptr.is_aligned_to(align));
+        // Regardless of what we return, it must be `free`able.
+        libc::free(ptr);
+    }
 
-    test_clocks();
+    // Non-power of 2 align
+    unsafe {
+        let mut ptr: *mut libc::c_void = ptr::without_provenance_mut(0x1234567);
+        let align = 15;
+        let size = 8;
+        assert_eq!(libc::posix_memalign(&mut ptr, align, size), libc::EINVAL);
+        // The pointer is not modified on failure, posix_memalign(3) says:
+        // > On Linux (and other systems), posix_memalign() does  not  modify  memptr  on failure.
+        // > A requirement standardizing this behavior was added in POSIX.1-2008 TC2.
+        assert_eq!(ptr.addr(), 0x1234567);
+    }
+
+    // Too small align (smaller than ptr)
+    unsafe {
+        let mut ptr: *mut libc::c_void = ptr::without_provenance_mut(0x1234567);
+        let align = std::mem::size_of::<usize>() / 2;
+        let size = 8;
+        assert_eq!(libc::posix_memalign(&mut ptr, align, size), libc::EINVAL);
+        // The pointer is not modified on failure, posix_memalign(3) says:
+        // > On Linux (and other systems), posix_memalign() does  not  modify  memptr  on failure.
+        // > A requirement standardizing this behavior was added in POSIX.1-2008 TC2.
+        assert_eq!(ptr.addr(), 0x1234567);
+    }
+}
+
+fn main() {
+    test_thread_local_errno();
 
     test_dlsym();
 
     test_memcpy();
     test_strcpy();
 
-    #[cfg(not(target_os = "macos"))] // reallocarray does not exist on macOS
+    test_memalign();
+    #[cfg(not(any(target_os = "macos", target_os = "illumos")))]
     test_reallocarray();
 
-    // These are Linux-specific
     #[cfg(target_os = "linux")]
-    {
-        test_posix_fadvise();
-        test_sync_file_range();
-        test_sigrt();
-    }
+    test_sigrt();
 }
diff --git a/src/tools/miri/tests/pass-dep/shims/libc-getrandom.rs b/src/tools/miri/tests/pass-dep/shims/libc-random.rs
index 9c670cbd507..71e33522634 100644
--- a/src/tools/miri/tests/pass-dep/shims/libc-getrandom.rs
+++ b/src/tools/miri/tests/pass-dep/shims/libc-random.rs
@@ -1,9 +1,29 @@
 //@ignore-target-windows: no libc
-//@ignore-target-apple: no getrandom
-
-use std::ptr;
+//@revisions: isolation no_isolation
+//@[no_isolation]compile-flags: -Zmiri-disable-isolation
 
 fn main() {
+    test_getentropy();
+    #[cfg(not(target_os = "macos"))]
+    test_getrandom();
+}
+
+fn test_getentropy() {
+    use libc::getentropy;
+
+    let mut buf1 = [0u8; 256];
+    let mut buf2 = [0u8; 257];
+    unsafe {
+        assert_eq!(getentropy(buf1.as_mut_ptr() as *mut libc::c_void, buf1.len()), 0);
+        assert_eq!(getentropy(buf2.as_mut_ptr() as *mut libc::c_void, buf2.len()), -1);
+        assert_eq!(std::io::Error::last_os_error().raw_os_error().unwrap(), libc::EIO);
+    }
+}
+
+#[cfg(not(target_os = "macos"))]
+fn test_getrandom() {
+    use std::ptr;
+
     let mut buf = [0u8; 5];
     unsafe {
         #[cfg(target_os = "linux")]
diff --git a/src/tools/miri/tests/pass-dep/shims/libc-rsfs.stdout b/src/tools/miri/tests/pass-dep/shims/libc-rsfs.stdout
deleted file mode 100644
index b6fa69e3d5d..00000000000
--- a/src/tools/miri/tests/pass-dep/shims/libc-rsfs.stdout
+++ /dev/null
@@ -1 +0,0 @@
-hello dup fd
diff --git a/src/tools/miri/tests/pass-dep/shims/libc-time.rs b/src/tools/miri/tests/pass-dep/shims/libc-time.rs
new file mode 100644
index 00000000000..69c75bd8caf
--- /dev/null
+++ b/src/tools/miri/tests/pass-dep/shims/libc-time.rs
@@ -0,0 +1,93 @@
+//@ignore-target-windows: no libc on Windows
+//@compile-flags: -Zmiri-disable-isolation
+use std::ffi::CStr;
+use std::{env, mem, ptr};
+
+fn main() {
+    test_clocks();
+    test_posix_gettimeofday();
+    test_localtime_r();
+}
+
+/// Tests whether clock support exists at all
+fn test_clocks() {
+    let mut tp = mem::MaybeUninit::<libc::timespec>::uninit();
+    let is_error = unsafe { libc::clock_gettime(libc::CLOCK_REALTIME, tp.as_mut_ptr()) };
+    assert_eq!(is_error, 0);
+    let is_error = unsafe { libc::clock_gettime(libc::CLOCK_MONOTONIC, tp.as_mut_ptr()) };
+    assert_eq!(is_error, 0);
+    #[cfg(any(target_os = "linux", target_os = "freebsd"))]
+    {
+        let is_error = unsafe { libc::clock_gettime(libc::CLOCK_REALTIME_COARSE, tp.as_mut_ptr()) };
+        assert_eq!(is_error, 0);
+        let is_error =
+            unsafe { libc::clock_gettime(libc::CLOCK_MONOTONIC_COARSE, tp.as_mut_ptr()) };
+        assert_eq!(is_error, 0);
+    }
+    #[cfg(target_os = "macos")]
+    {
+        let is_error = unsafe { libc::clock_gettime(libc::CLOCK_UPTIME_RAW, tp.as_mut_ptr()) };
+        assert_eq!(is_error, 0);
+    }
+}
+
+fn test_posix_gettimeofday() {
+    let mut tp = mem::MaybeUninit::<libc::timeval>::uninit();
+    let tz = ptr::null_mut::<libc::timezone>();
+    let is_error = unsafe { libc::gettimeofday(tp.as_mut_ptr(), tz.cast()) };
+    assert_eq!(is_error, 0);
+    let tv = unsafe { tp.assume_init() };
+    assert!(tv.tv_sec > 0);
+    assert!(tv.tv_usec >= 0); // Theoretically this could be 0.
+
+    // Test that non-null tz returns an error.
+    let mut tz = mem::MaybeUninit::<libc::timezone>::uninit();
+    let tz_ptr = tz.as_mut_ptr();
+    let is_error = unsafe { libc::gettimeofday(tp.as_mut_ptr(), tz_ptr.cast()) };
+    assert_eq!(is_error, -1);
+}
+
+fn test_localtime_r() {
+    // Set timezone to GMT.
+    let key = "TZ";
+    env::set_var(key, "GMT");
+
+    const TIME_SINCE_EPOCH: libc::time_t = 1712475836;
+    let custom_time_ptr = &TIME_SINCE_EPOCH;
+    let mut tm = libc::tm {
+        tm_sec: 0,
+        tm_min: 0,
+        tm_hour: 0,
+        tm_mday: 0,
+        tm_mon: 0,
+        tm_year: 0,
+        tm_wday: 0,
+        tm_yday: 0,
+        tm_isdst: 0,
+        tm_gmtoff: 0,
+        tm_zone: std::ptr::null_mut::<libc::c_char>(),
+    };
+    let res = unsafe { libc::localtime_r(custom_time_ptr, &mut tm) };
+
+    assert_eq!(tm.tm_sec, 56);
+    assert_eq!(tm.tm_min, 43);
+    assert_eq!(tm.tm_hour, 7);
+    assert_eq!(tm.tm_mday, 7);
+    assert_eq!(tm.tm_mon, 3);
+    assert_eq!(tm.tm_year, 124);
+    assert_eq!(tm.tm_wday, 0);
+    assert_eq!(tm.tm_yday, 97);
+    assert_eq!(tm.tm_isdst, -1);
+    #[cfg(any(target_os = "linux", target_os = "macos", target_os = "freebsd"))]
+    assert_eq!(tm.tm_gmtoff, 0);
+    #[cfg(any(target_os = "linux", target_os = "macos", target_os = "freebsd"))]
+    unsafe {
+        assert_eq!(CStr::from_ptr(tm.tm_zone).to_str().unwrap(), "+00")
+    };
+
+    // The returned value is the pointer passed in.
+    assert!(ptr::eq(res, &mut tm));
+
+    // Remove timezone setting.
+    env::remove_var(key);
+}
diff --git a/src/tools/miri/tests/pass-dep/shims/posix_memalign.rs b/src/tools/miri/tests/pass-dep/shims/posix_memalign.rs
deleted file mode 100644
index db66b213416..00000000000
--- a/src/tools/miri/tests/pass-dep/shims/posix_memalign.rs
+++ /dev/null
@@ -1,82 +0,0 @@
-//@ignore-target-windows: No libc on Windows
-
-#![feature(pointer_is_aligned_to)]
-#![feature(strict_provenance)]
-
-use core::ptr;
-
-fn main() {
-    // A normal allocation.
-    unsafe {
-        let mut ptr: *mut libc::c_void = ptr::null_mut();
-        let align = 8;
-        let size = 64;
-        assert_eq!(libc::posix_memalign(&mut ptr, align, size), 0);
-        assert!(!ptr.is_null());
-        assert!(ptr.is_aligned_to(align));
-        ptr.cast::<u8>().write_bytes(1, size);
-        libc::free(ptr);
-    }
-
-    // Align > size.
-    unsafe {
-        let mut ptr: *mut libc::c_void = ptr::null_mut();
-        let align = 64;
-        let size = 8;
-        assert_eq!(libc::posix_memalign(&mut ptr, align, size), 0);
-        assert!(!ptr.is_null());
-        assert!(ptr.is_aligned_to(align));
-        ptr.cast::<u8>().write_bytes(1, size);
-        libc::free(ptr);
-    }
-
-    // Size not multiple of align
-    unsafe {
-        let mut ptr: *mut libc::c_void = ptr::null_mut();
-        let align = 16;
-        let size = 31;
-        assert_eq!(libc::posix_memalign(&mut ptr, align, size), 0);
-        assert!(!ptr.is_null());
-        assert!(ptr.is_aligned_to(align));
-        ptr.cast::<u8>().write_bytes(1, size);
-        libc::free(ptr);
-    }
-
-    // Size == 0
-    unsafe {
-        let mut ptr: *mut libc::c_void = ptr::null_mut();
-        let align = 64;
-        let size = 0;
-        assert_eq!(libc::posix_memalign(&mut ptr, align, size), 0);
-        // We are not required to return null if size == 0, but we currently do.
-        // It's fine to remove this assert if we start returning non-null pointers.
-        assert!(ptr.is_null());
-        assert!(ptr.is_aligned_to(align));
-        // Regardless of what we return, it must be `free`able.
-        libc::free(ptr);
-    }
-
-    // Non-power of 2 align
-    unsafe {
-        let mut ptr: *mut libc::c_void = ptr::without_provenance_mut(0x1234567);
-        let align = 15;
-        let size = 8;
-        assert_eq!(libc::posix_memalign(&mut ptr, align, size), libc::EINVAL);
-        // The pointer is not modified on failure, posix_memalign(3) says:
-        // > On Linux (and other systems), posix_memalign() does  not  modify  memptr  on failure.
-        // > A requirement standardizing this behavior was added in POSIX.1-2008 TC2.
-        assert_eq!(ptr.addr(), 0x1234567);
-    }
-
-    // Too small align (smaller than ptr)
-    unsafe {
-        let mut ptr: *mut libc::c_void = ptr::without_provenance_mut(0x1234567);
-        let align = std::mem::size_of::<usize>() / 2;
-        let size = 8;
-        assert_eq!(libc::posix_memalign(&mut ptr, align, size), libc::EINVAL);
-        // The pointer is not modified on failure, posix_memalign(3) says:
-        // > On Linux (and other systems), posix_memalign() does  not  modify  memptr  on failure.
-        // > A requirement standardizing this behavior was added in POSIX.1-2008 TC2.
-        assert_eq!(ptr.addr(), 0x1234567);
-    }
-}
diff --git a/src/tools/miri/tests/pass-dep/shims/pthread-sync.rs b/src/tools/miri/tests/pass-dep/shims/pthread-sync.rs
index c9d10cb83d4..12d3f2b6f14 100644
--- a/src/tools/miri/tests/pass-dep/shims/pthread-sync.rs
+++ b/src/tools/miri/tests/pass-dep/shims/pthread-sync.rs
@@ -19,6 +19,7 @@ fn main() {
     check_rwlock_write();
     check_rwlock_read_no_deadlock();
     check_cond();
+    check_condattr();
 }
 
 fn test_mutex_libc_init_recursive() {
@@ -261,6 +262,31 @@ fn check_cond() {
     }
 }
 
+fn check_condattr() {
+    unsafe {
+        // Just smoke-testing that these functions can be called.
+        let mut attr: MaybeUninit<libc::pthread_condattr_t> = MaybeUninit::uninit();
+        assert_eq!(libc::pthread_condattr_init(attr.as_mut_ptr()), 0);
+
+        #[cfg(not(target_os = "macos"))] // setclock-getclock do not exist on macOS
+        {
+            let clock_id = libc::CLOCK_MONOTONIC;
+            assert_eq!(libc::pthread_condattr_setclock(attr.as_mut_ptr(), clock_id), 0);
+            let mut check_clock_id = MaybeUninit::<libc::clockid_t>::uninit();
+            assert_eq!(
+                libc::pthread_condattr_getclock(attr.as_mut_ptr(), check_clock_id.as_mut_ptr()),
+                0
+            );
+            assert_eq!(check_clock_id.assume_init(), clock_id);
+        }
+
+        let mut cond: MaybeUninit<libc::pthread_cond_t> = MaybeUninit::uninit();
+        assert_eq!(libc::pthread_cond_init(cond.as_mut_ptr(), attr.as_ptr()), 0);
+        assert_eq!(libc::pthread_condattr_destroy(attr.as_mut_ptr()), 0);
+        assert_eq!(libc::pthread_cond_destroy(cond.as_mut_ptr()), 0);
+    }
+}
+
 // std::sync::RwLock does not even used pthread_rwlock any more.
 // Do some smoke testing of the API surface.
 fn test_rwlock_libc_static_initializer() {
diff --git a/src/tools/miri/tests/pass/align_offset_symbolic.rs b/src/tools/miri/tests/pass/align_offset_symbolic.rs
index c32fa2c8f9b..dec3d779a78 100644
--- a/src/tools/miri/tests/pass/align_offset_symbolic.rs
+++ b/src/tools/miri/tests/pass/align_offset_symbolic.rs
@@ -62,7 +62,10 @@ fn test_from_utf8() {
     const N: usize = 10;
     let vec = vec![0x4141414141414141u64; N];
     let content = unsafe { std::slice::from_raw_parts(vec.as_ptr() as *const u8, 8 * N) };
-    println!("{:?}", std::str::from_utf8(content).unwrap());
+    assert_eq!(
+        std::str::from_utf8(content).unwrap(),
+        "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
+    );
 }
 
 fn test_u64_array() {
diff --git a/src/tools/miri/tests/pass/align_offset_symbolic.stdout b/src/tools/miri/tests/pass/align_offset_symbolic.stdout
deleted file mode 100644
index 66d43994815..00000000000
--- a/src/tools/miri/tests/pass/align_offset_symbolic.stdout
+++ /dev/null
@@ -1 +0,0 @@
-"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
diff --git a/src/tools/miri/tests/pass/alloc-access-tracking.rs b/src/tools/miri/tests/pass/alloc-access-tracking.rs
index 29c1ee2f7b7..a226783155b 100644
--- a/src/tools/miri/tests/pass/alloc-access-tracking.rs
+++ b/src/tools/miri/tests/pass/alloc-access-tracking.rs
@@ -1,7 +1,8 @@
 #![feature(start)]
 #![no_std]
-//@compile-flags: -Zmiri-track-alloc-id=18 -Zmiri-track-alloc-accesses -Cpanic=abort
-//@only-target-linux: alloc IDs differ between OSes for some reason
+//@compile-flags: -Zmiri-track-alloc-id=20 -Zmiri-track-alloc-accesses -Cpanic=abort
+//@normalize-stderr-test: "id 20" -> "id $$ALLOC"
+//@only-target-linux: alloc IDs differ between OSes (due to extern static allocations)
 
 extern "Rust" {
     fn miri_alloc(size: usize, align: usize) -> *mut u8;
diff --git a/src/tools/miri/tests/pass/alloc-access-tracking.stderr b/src/tools/miri/tests/pass/alloc-access-tracking.stderr
index bef13701ea2..0af6cde833f 100644
--- a/src/tools/miri/tests/pass/alloc-access-tracking.stderr
+++ b/src/tools/miri/tests/pass/alloc-access-tracking.stderr
@@ -2,7 +2,7 @@ note: tracking was triggered
   --> $DIR/alloc-access-tracking.rs:LL:CC
    |
 LL |         let ptr = miri_alloc(123, 1);
-   |                   ^^^^^^^^^^^^^^^^^^ created Miri bare-metal heap allocation of 123 bytes (alignment ALIGN bytes) with id 18
+   |                   ^^^^^^^^^^^^^^^^^^ created Miri bare-metal heap allocation of 123 bytes (alignment ALIGN bytes) with id $ALLOC
    |
    = note: BACKTRACE:
    = note: inside `start` at $DIR/alloc-access-tracking.rs:LL:CC
@@ -11,7 +11,7 @@ note: tracking was triggered
   --> $DIR/alloc-access-tracking.rs:LL:CC
    |
 LL |         *ptr = 42; // Crucially, only a write is printed here, no read!
-   |         ^^^^^^^^^ write access to allocation with id 18
+   |         ^^^^^^^^^ write access to allocation with id $ALLOC
    |
    = note: BACKTRACE:
    = note: inside `start` at $DIR/alloc-access-tracking.rs:LL:CC
@@ -20,7 +20,7 @@ note: tracking was triggered
   --> $DIR/alloc-access-tracking.rs:LL:CC
    |
 LL |         assert_eq!(*ptr, 42);
-   |         ^^^^^^^^^^^^^^^^^^^^ read access to allocation with id 18
+   |         ^^^^^^^^^^^^^^^^^^^^ read access to allocation with id $ALLOC
    |
    = note: BACKTRACE:
    = note: inside `start` at RUSTLIB/core/src/macros/mod.rs:LL:CC
@@ -30,7 +30,7 @@ note: tracking was triggered
   --> $DIR/alloc-access-tracking.rs:LL:CC
    |
 LL |         miri_dealloc(ptr, 123, 1);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ freed allocation with id 18
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ freed allocation with id $ALLOC
    |
    = note: BACKTRACE:
    = note: inside `start` at $DIR/alloc-access-tracking.rs:LL:CC
diff --git a/src/tools/miri/tests/pass/concurrency/thread_name.rs b/src/tools/miri/tests/pass/concurrency/threadname.rs
index 6dd5f1f5c91..6dd5f1f5c91 100644
--- a/src/tools/miri/tests/pass/concurrency/thread_name.rs
+++ b/src/tools/miri/tests/pass/concurrency/threadname.rs
diff --git a/src/tools/miri/tests/pass/hello.rs b/src/tools/miri/tests/pass/hello.rs
index e7a11a969c0..2a02a7a9e20 100644
--- a/src/tools/miri/tests/pass/hello.rs
+++ b/src/tools/miri/tests/pass/hello.rs
@@ -1,3 +1,4 @@
 fn main() {
     println!("Hello, world!");
+    eprintln!("Hello, error!");
 }
diff --git a/src/tools/miri/tests/pass/hello.stderr b/src/tools/miri/tests/pass/hello.stderr
new file mode 100644
index 00000000000..445a1bc8fa4
--- /dev/null
+++ b/src/tools/miri/tests/pass/hello.stderr
@@ -0,0 +1 @@
+Hello, error!
diff --git a/src/tools/miri/tests/pass/ints.rs b/src/tools/miri/tests/pass/integers.rs
index c04c6921f3c..c04c6921f3c 100644
--- a/src/tools/miri/tests/pass/ints.rs
+++ b/src/tools/miri/tests/pass/integers.rs
diff --git a/src/tools/miri/tests/pass/intrinsics-integer.rs b/src/tools/miri/tests/pass/intrinsics/integer.rs
index 13e7bd8e1b9..13e7bd8e1b9 100644
--- a/src/tools/miri/tests/pass/intrinsics-integer.rs
+++ b/src/tools/miri/tests/pass/intrinsics/integer.rs
diff --git a/src/tools/miri/tests/pass/intrinsics.rs b/src/tools/miri/tests/pass/intrinsics/intrinsics.rs
index 0dda5aadce2..0dda5aadce2 100644
--- a/src/tools/miri/tests/pass/intrinsics.rs
+++ b/src/tools/miri/tests/pass/intrinsics/intrinsics.rs
diff --git a/src/tools/miri/tests/pass/portable-simd-ptrs.rs b/src/tools/miri/tests/pass/intrinsics/portable-simd-ptrs.rs
index 096ec78da1a..096ec78da1a 100644
--- a/src/tools/miri/tests/pass/portable-simd-ptrs.rs
+++ b/src/tools/miri/tests/pass/intrinsics/portable-simd-ptrs.rs
diff --git a/src/tools/miri/tests/pass/portable-simd.rs b/src/tools/miri/tests/pass/intrinsics/portable-simd.rs
index 1fc713d48dc..1fc713d48dc 100644
--- a/src/tools/miri/tests/pass/portable-simd.rs
+++ b/src/tools/miri/tests/pass/intrinsics/portable-simd.rs
diff --git a/src/tools/miri/tests/pass/volatile.rs b/src/tools/miri/tests/pass/intrinsics/volatile.rs
index c9799801455..c9799801455 100644
--- a/src/tools/miri/tests/pass/volatile.rs
+++ b/src/tools/miri/tests/pass/intrinsics/volatile.rs
diff --git a/src/tools/miri/tests/pass/available-parallelism-miri-num-cpus.rs b/src/tools/miri/tests/pass/shims/available-parallelism-miri-num-cpus.rs
index 137fa510249..137fa510249 100644
--- a/src/tools/miri/tests/pass/available-parallelism-miri-num-cpus.rs
+++ b/src/tools/miri/tests/pass/shims/available-parallelism-miri-num-cpus.rs
diff --git a/src/tools/miri/tests/pass/available-parallelism.rs b/src/tools/miri/tests/pass/shims/available-parallelism.rs
index 77fb78424ba..77fb78424ba 100644
--- a/src/tools/miri/tests/pass/available-parallelism.rs
+++ b/src/tools/miri/tests/pass/shims/available-parallelism.rs
diff --git a/src/tools/miri/tests/pass/intrinsics-x86-aes-vaes.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-aes-vaes.rs
index 7363c753617..7363c753617 100644
--- a/src/tools/miri/tests/pass/intrinsics-x86-aes-vaes.rs
+++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-aes-vaes.rs
diff --git a/src/tools/miri/tests/pass/intrinsics-x86-avx.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-avx.rs
index 7d43cc596ae..7d43cc596ae 100644
--- a/src/tools/miri/tests/pass/intrinsics-x86-avx.rs
+++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-avx.rs
diff --git a/src/tools/miri/tests/pass/intrinsics-x86-avx2.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-avx2.rs
index 80d125bb856..80d125bb856 100644
--- a/src/tools/miri/tests/pass/intrinsics-x86-avx2.rs
+++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-avx2.rs
diff --git a/src/tools/miri/tests/pass/intrinsics-x86-avx512.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-avx512.rs
index 66bfcb20f1c..66bfcb20f1c 100644
--- a/src/tools/miri/tests/pass/intrinsics-x86-avx512.rs
+++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-avx512.rs
diff --git a/src/tools/miri/tests/pass/intrinsics-x86-pause-without-sse2.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-pause-without-sse2.rs
index c8b92fd5458..c8b92fd5458 100644
--- a/src/tools/miri/tests/pass/intrinsics-x86-pause-without-sse2.rs
+++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-pause-without-sse2.rs
diff --git a/src/tools/miri/tests/pass/intrinsics-x86-sse.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse.rs
index a62a5ee3781..a62a5ee3781 100644
--- a/src/tools/miri/tests/pass/intrinsics-x86-sse.rs
+++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse.rs
diff --git a/src/tools/miri/tests/pass/intrinsics-x86-sse2.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse2.rs
index e0088b9eb24..e0088b9eb24 100644
--- a/src/tools/miri/tests/pass/intrinsics-x86-sse2.rs
+++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse2.rs
diff --git a/src/tools/miri/tests/pass/intrinsics-x86-sse3-ssse3.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse3-ssse3.rs
index 7566be4431b..7566be4431b 100644
--- a/src/tools/miri/tests/pass/intrinsics-x86-sse3-ssse3.rs
+++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse3-ssse3.rs
diff --git a/src/tools/miri/tests/pass/intrinsics-x86-sse41.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse41.rs
index 06607f3fd59..06607f3fd59 100644
--- a/src/tools/miri/tests/pass/intrinsics-x86-sse41.rs
+++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse41.rs
diff --git a/src/tools/miri/tests/pass/intrinsics-x86.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86.rs
index 90bcdba4353..90bcdba4353 100644
--- a/src/tools/miri/tests/pass/intrinsics-x86.rs
+++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86.rs
diff --git a/src/tools/miri/tests/pass/vecdeque.rs b/src/tools/miri/tests/pass/vecdeque.rs
index ccecf3d30a4..77c4ca5a04e 100644
--- a/src/tools/miri/tests/pass/vecdeque.rs
+++ b/src/tools/miri/tests/pass/vecdeque.rs
@@ -31,8 +31,8 @@ fn main() {
     }
 
     // Regression test for Debug impl's
-    println!("{:?} {:?}", dst, dst.iter());
-    println!("{:?}", VecDeque::<u32>::new().iter());
+    format!("{:?} {:?}", dst, dst.iter());
+    format!("{:?}", VecDeque::<u32>::new().iter());
 
     for a in dst {
         assert_eq!(*a, 2);
diff --git a/src/tools/miri/tests/pass/vecdeque.stack.stdout b/src/tools/miri/tests/pass/vecdeque.stack.stdout
deleted file mode 100644
index 63de960ee2b..00000000000
--- a/src/tools/miri/tests/pass/vecdeque.stack.stdout
+++ /dev/null
@@ -1,2 +0,0 @@
-[2, 2] Iter([2, 2], [])
-Iter([], [])
diff --git a/src/tools/miri/tests/pass/vecdeque.tree.stdout b/src/tools/miri/tests/pass/vecdeque.tree.stdout
deleted file mode 100644
index 63de960ee2b..00000000000
--- a/src/tools/miri/tests/pass/vecdeque.tree.stdout
+++ /dev/null
@@ -1,2 +0,0 @@
-[2, 2] Iter([2, 2], [])
-Iter([], [])
diff --git a/src/tools/miri/tests/pass/vecdeque.tree_uniq.stdout b/src/tools/miri/tests/pass/vecdeque.tree_uniq.stdout
deleted file mode 100644
index 63de960ee2b..00000000000
--- a/src/tools/miri/tests/pass/vecdeque.tree_uniq.stdout
+++ /dev/null
@@ -1,2 +0,0 @@
-[2, 2] Iter([2, 2], [])
-Iter([], [])
diff --git a/src/tools/miri/triagebot.toml b/src/tools/miri/triagebot.toml
index 3b767b3e62f..addb36418d4 100644
--- a/src/tools/miri/triagebot.toml
+++ b/src/tools/miri/triagebot.toml
@@ -10,5 +10,10 @@ allow-unauthenticated = [
 # Gives us the commands 'ready', 'author', 'blocked'
 [shortcut]
 
+# Enables assigning users to issues and PRs.
+[assign]
+warn_non_default_branch = true
+contributing_url = "https://github.com/rust-lang/miri/blob/master/CONTRIBUTING.md"
+
 [no-merges]
 exclude_titles = ["Rustup"]