Skip to main content

ctor/
lib.rs

1#![recursion_limit = "256"]
2#![no_std]
3#![doc = include_str!("../docs/BUILD.md")]
4//! # ctor
5#![doc = include_str!("../docs/PREAMBLE.md")]
6#![doc = include_str!("../docs/GENERATED.md")]
7// Used as part of ctor collection
8#![cfg_attr(
9    all(target_vendor = "apple", linktime_used_linker),
10    feature(used_with_arg)
11)]
12#![cfg_attr(linktime_used_linker, doc(test(attr(feature(used_with_arg)))))]
13
14#[cfg(feature = "std")]
15extern crate std;
16
17mod macros;
18mod parse;
19mod priority;
20#[cfg(target_os = "aix")]
21mod priority_aix;
22
23pub mod statics;
24
25#[doc = include_str!("../docs/LIFE_BEFORE_MAIN.md")]
26pub mod life_before_main {}
27
28#[doc(hidden)]
29#[allow(unused)]
30pub mod __support {
31    // Required for proc_macro.
32    pub use crate::__ctor_parse as ctor_parse;
33
34    // Re-export link_section::TypedSection and declarative::{section, in_section}
35    #[cfg(all(feature = "priority", target_vendor = "apple"))]
36    pub use link_section::declarative::in_section;
37}
38
39#[cfg(all(feature = "priority", target_vendor = "apple"))]
40crate::__ctor_parse_internal!(
41    __ctor_features,
42    /// Define a link section when using the priority parameter on Apple
43    /// targets. This is awkwardly placed in the root module because it needs to
44    /// use a generated macro and we cannot use an absolute path to it. (see
45    /// <https://github.com/rust-lang/rust/issues/52234>)
46    #[ctor(unsafe, naked)]
47    #[allow(unsafe_code)]
48    fn priority_ctor() {
49        unsafe {
50            crate::collect::run_constructors();
51        }
52    }
53);
54
55/// Collected constructors for platforms requiring manual invocation.
56#[cfg(all(feature = "priority", target_vendor = "apple"))]
57#[doc(hidden)]
58pub mod collect {
59    use core::sync::atomic::{AtomicU8, Ordering};
60
61    #[doc(hidden)]
62    pub const PROCESSED: isize = isize::MIN;
63    #[doc(hidden)]
64    pub const LATE: isize = isize::MAX;
65
66    const GUARD_NOT_RUN: u8 = 0;
67    const GUARD_RUNNING: u8 = 1;
68    const GUARD_FINISHED: u8 = 2;
69
70    /// A constructor record.
71    #[derive(Copy, Clone)]
72    #[repr(C)]
73    pub struct Constructor {
74        pub priority: isize,
75        pub ctor: unsafe extern "C" fn(),
76    }
77
78    /// Run all constructors in the CTOR section. It is assumed that there is
79    /// only ever one of these calls active at any time, regardless of how many
80    /// versions of the ctor crate are in use.
81    ///
82    /// # Safety
83    ///
84    /// We use a guard section to ensure that only one version of the ctor crate
85    /// is running constructors at any time.
86    ///
87    /// If another copy of this function is running, we will return early, but
88    /// the constructors will not have been guaranteed to have run.
89    #[allow(unsafe_code)]
90    pub(crate) unsafe fn run_constructors() {
91        // Multiple ctor crates may contribute multiple guards, but there will
92        // only ever be one "first" guard.
93        let Some(guard) = _CTR0GR_ISIZE_FN.first() else {
94            return;
95        };
96
97        // In the unlikely case we are racing multiple threads, one will win.
98        loop {
99            match guard.compare_exchange_weak(
100                GUARD_NOT_RUN,
101                GUARD_RUNNING,
102                Ordering::AcqRel,
103                Ordering::Acquire,
104            ) {
105                Ok(_) => break,
106                Err(GUARD_NOT_RUN) => {
107                    // Spurious failure, try again
108                    continue;
109                }
110                Err(_) => return,
111            }
112        }
113
114        // SAFETY: Limit the scope of the mutable slice. This slice is only ever
115        // accessed under the guard.
116        unsafe {
117            let slice = _CTOR0_ISIZE_FN.as_mut_slice();
118            slice.sort_unstable_by_key(|constructor| constructor.priority);
119        }
120
121        unsafe {
122            let start = _CTOR0_ISIZE_FN.start_ptr_mut();
123            let end = _CTOR0_ISIZE_FN.end_ptr_mut();
124            let mut ptr = start;
125            while ptr < end {
126                let mut constructor = ptr.read();
127                if constructor.priority != crate::collect::PROCESSED {
128                    constructor.priority = crate::collect::PROCESSED;
129                    ptr.write(constructor);
130                    (constructor.ctor)();
131                }
132                ptr = ptr.add(1);
133            }
134        }
135
136        guard.store(GUARD_FINISHED, Ordering::Release);
137    }
138
139    // Note: The section names must be <= 16 characters long to fit in the mach-o limits.
140    // These sections are shared between multiple versions of the ctor crate.
141
142    #[doc(hidden)]
143    link_section::declarative::section!(
144        #[section(no_macro)]
145        pub static _CTOR0_ISIZE_FN: link_section::TypedSection<Constructor>;
146    );
147
148    #[macro_export]
149    #[doc(hidden)]
150    macro_rules! __register_ctor {
151        (priority = (), fn = $fn:ident) => {
152            $crate::__register_ctor!(priority = ($crate::collect::EARLY), fn = $fn);
153        };
154        (priority = early, fn = $fn:ident) => {
155            $crate::__register_ctor!(priority = ($crate::collect::EARLY), fn = $fn);
156        };
157        (priority = late, fn = $fn:ident) => {
158            $crate::__register_ctor!(priority = ($crate::collect::LATE), fn = $fn);
159        };
160        (priority = $priority:tt, fn = $fn:ident) => {
161            $crate::__support::in_section!(
162                #[in_section(unsafe, type = $crate::collect::Constructor, name = _CTOR0_ISIZE_FN)]
163                pub const _: $crate::collect::Constructor = $crate::collect::Constructor {
164                    priority: $priority,
165                    ctor: $fn,
166                };
167            );
168        };
169        (priority = $priority:tt, fn = (array $array:ident)) => {
170            $crate::__support::in_section!(
171                #[in_section(unsafe, type = [$crate::collect::Constructor; if $array.len() == 0 { 1 } else { $array.len() }], name = _CTOR0_ISIZE_FN)]
172                pub const _: [$crate::collect::Constructor; if $array.len() == 0 { 1 } else { $array.len() }] = {
173                    use core::mem::MaybeUninit;
174
175                    // If length zero, register a stub that doesn't get executed
176                    if $array.len() == 0 {
177                        unsafe extern "C" fn empty_ctor() {}
178                        [$crate::collect::Constructor {
179                            priority: $crate::collect::PROCESSED,
180                            ctor: empty_ctor,
181                        }; if $array.len() == 0 { 1 } else { $array.len() }]
182                    } else {
183                        let mut array: MaybeUninit<[$crate::collect::Constructor; if $array.len() == 0 { 1 } else { $array.len() }]> = MaybeUninit::uninit();
184                        let mut array_ptr: *mut $crate::collect::Constructor = array.as_mut_ptr() as _;
185                        const fn ctor_fn(i: usize) -> $crate::collect::Constructor {
186                            $crate::collect::Constructor {
187                                priority: $priority,
188                                ctor: $array[i],
189                            }
190                        }
191
192                        let mut i = 0;
193                        while i < $array.len() {
194                            unsafe { array_ptr.add(i).write(ctor_fn(i)) };
195                            i += 1;
196                        }
197
198                        unsafe { array.assume_init() }
199                    }
200                };
201            );
202        };
203    }
204
205    #[doc(hidden)]
206    link_section::declarative::section!(
207        #[section(no_macro)]
208        pub static _CTR0GR_ISIZE_FN: link_section::TypedSection<AtomicU8>;
209    );
210
211    link_section::declarative::in_section!(
212        #[in_section(unsafe, type = AtomicU8, name = _CTR0GR_ISIZE_FN)]
213        pub static GUARD_ATOMIC: AtomicU8 = AtomicU8::new(GUARD_NOT_RUN);
214    );
215}
216
217/// Declarative form of the `#[ctor]` macro.
218pub mod declarative {
219    /// Declarative form of the [`#[ctor]`](crate::ctor) macro.
220    ///
221    /// The declarative forms wrap and parse a proc_macro-like syntax like so, and
222    /// are identical in expansion to the undecorated procedural macros. The
223    /// declarative forms support the same attribute parameters as the procedural
224    /// macros.
225    ///
226    /// ```rust
227    /// # #[cfg(not(miri))] mod test { use ctor::*; use libc_print::*;
228    /// ctor::declarative::ctor! {
229    ///   #[ctor(unsafe)]
230    ///   fn foo() {
231    ///     libc_println!("Hello, world!");
232    ///   }
233    /// }
234    /// # }
235    ///
236    /// // ... the above is identical to:
237    ///
238    /// # #[cfg(not(miri))] mod test_2 { use ctor::*; use libc_print::*;
239    /// #[ctor(unsafe)]
240    /// fn foo() {
241    ///   libc_println!("Hello, world!");
242    /// }
243    /// # }
244    /// ```
245    #[doc(inline)]
246    pub use crate::__support::ctor_parse as ctor;
247}
248
249/// Marks a function or static variable as a library/executable constructor.
250/// This uses OS-specific linker sections to call a specific function at load
251/// time.
252///
253/// # Important notes
254///
255/// Rust does not make any guarantees about stdlib support for life-before or
256/// life-after main. This means that the `ctor` crate may not work as expected
257/// in some cases, such as when used in an `async` runtime or making use of
258/// stdlib services.
259///
260/// Multiple startup functions/statics are supported, but the invocation order
261/// is not guaranteed.
262///
263/// The `ctor` crate assumes it is available as a direct dependency, If you
264/// re-export `ctor` items as part of your crate, you can use the `crate_path`
265/// parameter to redirect the macro's output to the correct crate, or use the
266/// [`declarative::ctor`] form.
267///
268/// # Examples
269///
270/// Print a startup message (using `libc_print` for safety):
271///
272/// ```rust
273/// # #[cfg(not(miri))] mod test {
274/// # use ctor::ctor;
275/// use libc_print::std_name::println;
276///
277/// #[ctor(unsafe)]
278/// fn foo() {
279///   // Using libc_print which is safe in `#[ctor]`
280///   println!("Hello, world!");
281/// }
282///
283/// # fn main() {
284/// println!("main()");
285/// # }}
286/// ```
287///
288/// Make changes to `static` variables:
289///
290/// ```rust
291/// # mod test {
292/// use ctor::*;
293/// use std::sync::atomic::{AtomicBool, Ordering};
294/// static INITED: AtomicBool = AtomicBool::new(false);
295///
296/// #[ctor(unsafe)]
297/// fn set_inited() {
298///   INITED.store(true, Ordering::SeqCst);
299/// }
300/// # }
301/// ```
302///
303/// Initialize a `HashMap` at startup time:
304///
305/// ```rust
306/// # mod test {
307/// # use std::collections::HashMap;
308/// # use ctor::*;
309/// #[ctor(unsafe)]
310/// pub static STATIC_CTOR: HashMap<u32, String> = {
311///   let mut m = HashMap::new();
312///   for i in 0..100 {
313///     m.insert(i, format!("x*100={}", i*100));
314///   }
315///   m
316/// };
317/// # }
318/// # pub fn main() {
319/// #   assert_eq!(test::STATIC_CTOR.len(), 100);
320/// #   assert_eq!(test::STATIC_CTOR[&20], "x*100=2000");
321/// # }
322/// ```
323///
324/// # Details
325///
326/// The `#[ctor]` macro makes use of linker sections to ensure that a function
327/// is run at startup time.
328///
329/// ```rust
330/// # mod test {
331/// # use ctor::*;
332/// #[ctor(unsafe)]
333/// fn my_init_fn() {
334///   /* ... */
335/// }
336/// # }
337/// ```
338///
339/// The above example translates into the following Rust code (approximately):
340///
341/// ```rust
342/// # fn my_init_fn() {}
343/// #[used]
344/// #[cfg_attr(target_os = "linux", link_section = ".init_array")]
345/// #[cfg_attr(target_vendor = "apple", link_section = "__DATA,__mod_init_func,mod_init_funcs")]
346/// #[cfg_attr(target_os = "windows", link_section = ".CRT$XCU")]
347/// /* ... other platforms elided ... */
348/// static INIT_FN: extern fn() = {
349///     extern fn init_fn() { my_init_fn(); };
350///     init_fn
351/// };
352/// ```
353///
354/// For `static` items, the macro generates a `std::sync::OnceLock` that is
355/// initialized at startup time. `#[ctor]` on `static` items requires the
356/// default `std` feature.
357///
358/// ```rust
359/// # mod test {
360/// # use ctor::*;
361/// # use std::collections::HashMap;
362/// #[ctor]
363/// static FOO: HashMap<u32, String> = unsafe {
364///   let mut m = HashMap::new();
365///   for i in 0..100 {
366///     m.insert(i, format!("x*100={}", i*100));
367///   }
368///   m
369/// };
370/// # }
371/// ```
372///
373/// The above example translates into the following Rust code (approximately),
374/// which eagerly initializes the `HashMap` inside a `OnceLock` at startup time:
375///
376/// ```rust
377/// # mod test {
378/// # use ctor::ctor;
379/// # use std::collections::HashMap;
380/// static FOO: FooStatic = FooStatic { value: ::std::sync::OnceLock::new() };
381/// struct FooStatic {
382///   value: ::std::sync::OnceLock<HashMap<u32, String>>,
383/// }
384///
385/// impl ::core::ops::Deref for FooStatic {
386///   type Target = HashMap<u32, String>;
387///   fn deref(&self) -> &Self::Target {
388///     self.value.get_or_init(|| unsafe {
389///       let mut m = HashMap::new();
390///       for i in 0..100 {
391///         m.insert(i, format!("x*100={}", i*100));
392///       }
393///       m
394///     })
395///   }
396/// }
397///
398/// #[ctor]
399/// unsafe fn init_foo_ctor() {
400///   _ = &*FOO;
401/// }
402/// # }
403/// ```
404#[doc(inline)]
405#[cfg(feature = "proc_macro")]
406pub use ::linktime_proc_macro::ctor;
407
408__declare_features!(
409    ctor: __ctor_features;
410
411    /// Do not give the constructor a name in the generated code (allows for
412    /// multiple constructors with the same name). Equivalent to wrapping the
413    /// constructor in an anonymous const (i.e.: `const _ = { ... };`).
414    anonymous {
415        attr: [(anonymous) => (anonymous)];
416    };
417    /// Place the constructor body in a custom link section. By default, this
418    /// uses the appropriate platform-specific link section.
419    ///
420    /// Co-locating startup functions may improve performance by allowing the binary
421    /// to page them in and out of memory together.
422    body_link_section {
423        attr: [(body(link_section = $body_section:literal)) => ($body_section)];
424        example: "body(link_section = \".text.startup\")";
425        default {
426            (target_os = "linux") => ".text.startup",
427            (target_os = "android") => ".text.startup",
428            (target_os = "freebsd") => ".text.startup",
429            // Windows MSVC: sort startup functions near the start of the binary
430            (all(target_vendor = "pc", any(target_env = "gnu", target_env = "msvc"))) => ".text$A",
431            // Windows non-MSVC: .text.startup
432            (all(target_vendor = "pc", not(any(target_env = "gnu", target_env = "msvc")))) => ".text.startup",
433            (target_vendor = "apple") => "__TEXT,__text_startup,regular,pure_instructions",
434            _ => ()
435        }
436    };
437    /// The path to the `ctor` crate containing the support macros. If you
438    /// re-export `ctor` items as part of your crate, you can use this to
439    /// redirect the macro’s output to the correct crate.
440    ///
441    /// Using the declarative [`ctor!`][c] form is
442    /// preferred over this parameter.
443    ///
444    /// [c]: crate::declarative::ctor!
445    crate_path {
446        attr: [(crate_path = $path:pat) => (($path))];
447        example: "crate_path = ::path::to::ctor::crate";
448    };
449    /// Specify a custom export name prefix for the constructor function.
450    ///
451    /// If specified, an export with the given prefix will be generated in the form:
452    ///
453    /// `<prefix><priority>_<unique_id>`
454    export_name_prefix {
455        attr: [(export_name_prefix = $export_name_prefix_str:literal) => ($export_name_prefix_str)];
456        example: "export_name_prefix = \"ctor_\"";
457        default {
458            (target_os = "aix") => "__sinit",
459            _ => (),
460        }
461    };
462    /// Place the constructor function pointer in a custom link section. By
463    /// default, this uses the appropriate platform-specific link section.
464    // NOTE: Keep in sync w/dtor::ctor_link_section!
465    link_section {
466        attr: [(link_section = $section:literal) => ($section)];
467        example: "link_section = \".ctors\"";
468        default {
469            (target_vendor = "apple") => "__DATA,__mod_init_func,mod_init_funcs",
470            // Most LLVM/GCC targets can use .init_array
471            (any(
472                target_os = "linux",
473                target_os = "android",
474                target_os = "freebsd",
475                target_os = "netbsd",
476                target_os = "openbsd",
477                target_os = "dragonfly",
478                target_os = "illumos",
479                target_os = "haiku",
480                target_os = "vxworks",
481                target_os = "nto",
482                target_family = "wasm"
483            )) => ".init_array",
484            // No OS
485            (target_os = "none") => ".init_array",
486            // xtensa targets: .ctors
487            (target_arch = "xtensa") => ".ctors",
488            // Windows targets: .CRT$XCU
489            (all(target_vendor = "pc", any(target_env = "gnu", target_env = "msvc"))) => ".CRT$XCU",
490            // ... except GNU
491            (all(target_vendor = "pc", not(any(target_env = "gnu", target_env = "msvc")))) => ".ctors",
492            (all(target_os = "aix")) => (), // AIX uses export_name_prefix
493            _ => (compile_error!("Unsupported target for #[ctor]"))
494        }
495    };
496    /// Use the least-possibly mangled version of the linker invocation for this
497    /// constructor. This is not recommended for general use as it may prevent
498    /// authors of binary crates from having low-level control over the order of
499    /// initialization.
500    ///
501    /// There are no guarantees about the order of execution of constructors
502    /// with this attribute, just that it will be called at some point before
503    /// `main`.
504    ///
505    /// `naked` constructors are always executed directly by the underlying C
506    /// library and/or dynamic loader.
507    ///
508    /// `naked` cannot be used with the `priority` attribute.
509    naked {
510        attr: [(naked) => (naked)];
511    };
512    /// The priority of the constructor. Higher-`N`-priority constructors are
513    /// run last. `N` must be between 0 and 999 inclusive for ordering
514    /// guarantees (`N` >= 1000 ordering is platform-defined).
515    ///
516    /// Priority is specified as numeric value, string literal, or the
517    /// identifiers `early`, `default`, or `late`. The integer value will be
518    /// clamped to a platform-defined range (typically 0-65535), while string
519    /// priorities are passed through unprocessed.
520    ///
521    /// Most platforms reserve the numeric values range of 0..100 for their own
522    /// internal use and it may not be safe to access platform services (`libc`
523    /// or other) in constructors with those priorities.
524    ///
525    /// Priority is applied as follows:
526    ///
527    ///  - `N` is run in increasing order, from `0 <= N <= 999`.
528    ///  - `early` is run at a priority level where it is safe to access the C
529    ///    runtime. This is equivalent to a priority of 101 on most platforms.
530    ///  - `default` is the default, and is run after `early`. This is
531    ///    equivalent to a priority of 500.
532    ///  - `late` is run last, and will be positioned to run after most
533    ///    constructors, even outside the range `0 <= N <= 999`. The equivalent
534    ///    priority is platform-defined.
535    ///  - `main` is run, for binary targets.
536    ///
537    /// Ordering with explicit priority values outside of `0 <= N <= 999` is
538    /// platform-defined with respect to the list above, however platforms will
539    /// order constructors within a given priority range in ascending order
540    /// (i.e.: 10000 will run before 20000).
541    priority {
542        attr: [(priority = $priority_value:tt) => ($priority_value)];
543        example: "priority = N | early | late";
544        validate: [($priority:literal), (early), (late), (default)];
545        default {
546            (feature = "priority") => default,
547            _ => ()
548        }
549    };
550    /// Enable support for the priority parameter.
551    priority_enabled {
552        feature: "priority";
553    };
554    /// Enable support for the proc-macro `#[ctor]` attribute. The declarative
555    /// form (`ctor!(...)`) is always available. It is recommended that crates
556    /// re-exporting the `ctor` macro disable this feature and only use the
557    /// declarative form.
558    proc_macro {
559        feature: "proc_macro";
560    };
561    /// Enable support for the standard library.
562    std {
563        feature: "std";
564    };
565    r#unsafe {
566        /// attr
567        ///
568        /// Marks a ctor as unsafe. Required.
569        ///
570        /// The `ctor` crate rejects `#[ctor]` without marking the item unsafe;
571        /// that error can be suppressed by passing
572        /// `RUSTFLAGS="--cfg linktime_no_fail_on_missing_unsafe"` to Cargo.
573        attr: [(unsafe) => (no_fail_on_missing_unsafe)];
574        default {
575            (linktime_no_fail_on_missing_unsafe) => (no_fail_on_missing_unsafe),
576            _ => (),
577        }
578    };
579    used_linker {
580        /// attr
581        ///
582        /// Mark generated function pointers `used(linker)`. Requires nightly
583        /// for the nightly-only feature `feature(used_with_arg)` (see
584        /// <https://github.com/rust-lang/rust/issues/93798>).
585        ///
586        /// This can be made the default by using the `cfg` flag
587        /// `linktime_used_linker` (`RUSTFLAGS="--cfg linktime_used_linker"`).
588        ///
589        /// For a crate using this macro to function correctly with and without
590        /// this flag, it is recommended to add the following line to the top of
591        /// lib.rs in the crate root:
592        ///
593        /// `#![cfg_attr(linktime_used_linker, feature(used_with_arg))]`
594        attr: [(used(linker)) => (used_linker)];
595        default {
596            (linktime_used_linker) => used_linker,
597            _ => (),
598        }
599    };
600);
601
602#[cfg(doc)]
603__generate_docs!(__ctor_features);