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