about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/tools/miri/src/helpers.rs17
-rw-r--r--src/tools/miri/tests/pass/shims/ctor.rs15
2 files changed, 22 insertions, 10 deletions
diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs
index 0c96ddf00db..ab7e35710d3 100644
--- a/src/tools/miri/src/helpers.rs
+++ b/src/tools/miri/src/helpers.rs
@@ -1087,8 +1087,21 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                         "failed to evaluate static in required link_section: {def_id:?}\n{err:?}"
                     )
                 });
-                let val = this.read_immediate(&const_val)?;
-                array.push(val);
+                match const_val.layout.ty.kind() {
+                    ty::FnPtr(..) => {
+                        array.push(this.read_immediate(&const_val)?);
+                    }
+                    ty::Array(elem_ty, _) if matches!(elem_ty.kind(), ty::FnPtr(..)) => {
+                        let mut elems = this.project_array_fields(&const_val)?;
+                        while let Some((_idx, elem)) = elems.next(this)? {
+                            array.push(this.read_immediate(&elem)?);
+                        }
+                    }
+                    _ =>
+                        throw_unsup_format!(
+                            "only function pointers and arrays of function pointers are supported in well-known linker sections"
+                        ),
+                }
             }
             interp_ok(())
         })?;
diff --git a/src/tools/miri/tests/pass/shims/ctor.rs b/src/tools/miri/tests/pass/shims/ctor.rs
index b997d2386b8..a0fcdb1081e 100644
--- a/src/tools/miri/tests/pass/shims/ctor.rs
+++ b/src/tools/miri/tests/pass/shims/ctor.rs
@@ -2,13 +2,13 @@ use std::sync::atomic::{AtomicUsize, Ordering};
 
 static COUNT: AtomicUsize = AtomicUsize::new(0);
 
-unsafe extern "C" fn ctor() {
-    COUNT.fetch_add(1, Ordering::Relaxed);
+unsafe extern "C" fn ctor<const N: usize>() {
+    COUNT.fetch_add(N, Ordering::Relaxed);
 }
 
 #[rustfmt::skip]
 macro_rules! ctor {
-    ($ident:ident = $ctor:ident) => {
+    ($ident:ident: $ty:ty = $ctor:expr) => {
         #[cfg_attr(
             all(any(
                 target_os = "linux",
@@ -33,14 +33,13 @@ macro_rules! ctor {
             link_section = "__DATA,__mod_init_func"
         )]
         #[used]
-        static $ident: unsafe extern "C" fn() = $ctor;
+        static $ident: $ty = $ctor;
     };
 }
 
-ctor! { CTOR1 = ctor }
-ctor! { CTOR2 = ctor }
-ctor! { CTOR3 = ctor }
+ctor! { CTOR1: unsafe extern "C" fn() = ctor::<1> }
+ctor! { CTOR2: [unsafe extern "C" fn(); 2] = [ctor::<2>, ctor::<3>] }
 
 fn main() {
-    assert_eq!(COUNT.load(Ordering::Relaxed), 3, "ctors did not run");
+    assert_eq!(COUNT.load(Ordering::Relaxed), 6, "ctors did not run");
 }