Skip to main content

miri/shims/
extern_static.rs

1//! Provides the `extern static` that this platform expects.
2
3use rustc_target::spec::Os;
4
5use crate::*;
6
7impl<'tcx> MiriMachine<'tcx> {
8    fn alloc_extern_static(
9        ecx: &mut MiriInterpCx<'tcx>,
10        name: &str,
11        val: ImmTy<'tcx>,
12    ) -> InterpResult<'tcx> {
13        let place = ecx.allocate(val.layout, MiriMemoryKind::ExternStatic.into())?;
14        ecx.write_immediate(*val, &place)?;
15        Self::add_extern_static(ecx, name, place.ptr());
16        interp_ok(())
17    }
18
19    /// Extern statics that are initialized with function pointers to the symbols of the same name.
20    fn weak_symbol_extern_statics(
21        ecx: &mut MiriInterpCx<'tcx>,
22        names: &[&str],
23    ) -> InterpResult<'tcx> {
24        for name in names {
25            assert!(ecx.is_dyn_sym(name), "{name} is not a dynamic symbol");
26            let layout = ecx.machine.layouts.const_raw_ptr;
27            let ptr = ecx.fn_ptr(FnVal::Other(DynSym::from_str(name)));
28            let val = ImmTy::from_scalar(Scalar::from_pointer(ptr, ecx), layout);
29            Self::alloc_extern_static(ecx, name, val)?;
30        }
31        interp_ok(())
32    }
33
34    /// Sets up the "extern statics" for this machine.
35    pub fn init_extern_statics(ecx: &mut MiriInterpCx<'tcx>) -> InterpResult<'tcx> {
36        if ecx.target_os_is_unix() {
37            // "environ" is mandated by POSIX.
38            let environ = ecx.machine.env_vars.unix().environ();
39            Self::add_extern_static(ecx, "environ", environ);
40        }
41
42        match &ecx.tcx.sess.target.os {
43            Os::Linux => {
44                Self::weak_symbol_extern_statics(ecx, &["getrandom", "gettid", "statx", "strlen"])?;
45            }
46            Os::Android => {
47                Self::weak_symbol_extern_statics(ecx, &["signal", "getrandom", "gettid"])?;
48            }
49            Os::Windows => {
50                // "_tls_used"
51                // This is some obscure hack that is part of the Windows TLS story. It's a `u8`.
52                let val = ImmTy::from_int(0, ecx.machine.layouts.u8);
53                Self::alloc_extern_static(ecx, "_tls_used", val)?;
54            }
55            Os::Illumos | Os::Solaris => {
56                Self::weak_symbol_extern_statics(ecx, &["pthread_setname_np"])?;
57            }
58            _ => {} // No "extern statics" supported on this target.
59        }
60
61        // Also initialize `missing_weak_symbol`.
62        let place = ecx.allocate(ecx.machine.layouts.usize, MiriMemoryKind::ExternStatic.into())?;
63        ecx.write_null(&place)?;
64        ecx.machine.missing_weak_symbol = Some(place.ptr().into_pointer_or_addr().unwrap());
65
66        interp_ok(())
67    }
68}