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