Skip to main content

link_section/
lib.rs

1#![doc = include_str!("../docs/BUILD.md")]
2//! # link-section
3#![doc = include_str!("../docs/PREAMBLE.md")]
4#![allow(unsafe_code)]
5#![cfg_attr(linktime_used_linker, doc(test(attr(feature(used_with_arg)))))]
6
7#[doc = include_str!("../docs/LIFE_BEFORE_MAIN.md")]
8pub mod life_before_main {}
9
10#[cfg(target_family = "wasm")]
11extern crate alloc;
12
13/// Declarative forms of the `#[section]` and `#[in_section(...)]` macros.
14///
15/// The declarative forms wrap and parse a proc_macro-like syntax like so, and
16/// are identical in expansion to the undecorated procedural macros. The
17/// declarative forms support the same attribute parameters as the procedural
18/// macros.
19pub mod declarative {
20    pub use crate::__in_section_parse as in_section;
21    pub use crate::__section_parse as section;
22}
23
24#[doc(hidden)]
25pub mod __support {
26    pub use crate::__add_section_link_attribute as add_section_link_attribute;
27    pub use crate::__def_section_name as def_section_name;
28    pub use crate::__get_section as get_section;
29    pub use crate::__in_section_crate as in_section_crate;
30    pub use crate::__in_section_parse as in_section_parse;
31    pub use crate::__section_parse as section_parse;
32
33    #[cfg(feature = "proc_macro")]
34    pub use linktime_proc_macro::hash;
35    #[cfg(feature = "proc_macro")]
36    pub use linktime_proc_macro::ident_concat;
37
38    #[cfg(target_family = "wasm")]
39    extern "C" {
40        /// Read custom section with name/name_length as a UTF8 string
41        pub(crate) fn read_custom_section(
42            name: *const u8,
43            name_length: usize,
44            target_address: *mut u8,
45            target_address_length: usize,
46        ) -> usize;
47    }
48
49    /// Declares the section_name macro.
50    #[macro_export]
51    #[doc(hidden)]
52    macro_rules! __def_section_name {
53        (
54            {$(
55                $__section:ident $__type:ident => $__prefix:tt __ $__suffix:tt;
56            )*}
57            AUXILIARY = $__aux_sep:literal;
58            MAX_LENGTH = $__max_length:literal;
59            HASH_LENGTH = $__hash_length:literal;
60            VALID_SECTION_CHARS = $__valid_section_chars:literal;
61        ) => {
62            /// Internal macro for generating a section name.
63            #[macro_export]
64            #[doc(hidden)]
65            macro_rules! __section_name {
66                $(
67                    (raw $__section $__type $name:ident) => {
68                        concat!(concat! $__prefix, stringify!($name), concat! $__suffix);
69                    };
70                    (raw $__section $__type $name:ident $aux:ident) => {
71                        concat!(concat! $__prefix, stringify!($name), $__aux_sep, stringify!($aux), concat! $__suffix);
72                    };
73                    ($pattern:tt $__section $__type $name:ident) => {
74                        $crate::__support::hash!($pattern ($__prefix) $name ($__suffix) $__hash_length $__max_length $__valid_section_chars);
75                    };
76                    ($pattern:tt $__section $__type $name:ident $aux:ident) => {
77                        $crate::__support::hash!($pattern ($__prefix) ($name $__aux_sep $aux) ($__suffix) $__hash_length $__max_length $__valid_section_chars);
78                    };
79                )*
80                ($pattern:tt $unknown_section:ident $unknown_type:ident $name:ident) => {
81                    const _: () = {
82                        compile_error!("Unknown section type: `{}`/`{}`", stringify!($unknown_section), stringify!($unknown_type));
83                    };
84                };
85            }
86        };
87    }
88
89    #[cfg(not(linktime_used_linker))]
90    #[doc(hidden)]
91    #[macro_export]
92    macro_rules! __add_used {
93        (
94            $section:ident $type:ident $name:ident $($aux:ident)? #[$attr:ident = __]
95            $(#[$meta:meta])*
96            $vis:vis static $($static:tt)*
97        ) => {
98            $crate::__add_section_link_attribute_impl!(
99                $section $type $name $($aux)? #[$attr = __]
100                $(#[$meta])*
101                #[used]
102                $vis static $($static)*
103            );
104        };
105    }
106
107    #[cfg(linktime_used_linker)]
108    #[doc(hidden)]
109    #[macro_export]
110    macro_rules! __add_used {
111        (
112            $section:ident $type:ident $name:ident $($aux:ident)? #[$attr:ident = __]
113            $(#[$meta:meta])*
114            $vis:vis static $($static:tt)*
115        ) => {
116            $crate::__add_section_link_attribute_impl!(
117                $section $type $name $($aux)? #[$attr = __]
118                $(#[$meta])*
119                #[used(linker)]
120                $vis static $($static)*
121            );
122        };
123    }
124
125    #[doc(hidden)]
126    #[macro_export]
127    macro_rules! __add_section_link_attribute(
128        ($section:ident $type:ident $name:ident $($aux:ident)? #[$attr:ident = __]
129            $(#[$meta:meta])*
130            $vis:vis static $($static:tt)*
131        ) => {
132            $crate::__add_used!(
133                $section $type $name $($aux)? #[$attr = __]
134                $(#[$meta])*
135                $vis static $($static)*
136            );
137        };
138        ($section:ident $type:ident $name:ident $($aux:ident)? #[$attr:ident = __]
139            extern "C" {
140                $(#[$meta:meta])*
141                $vis:vis static $($static:tt)*
142            }
143        ) => {
144            extern "C" {
145                $crate::__add_section_link_attribute_impl!(
146                    $section $type $name $($aux)? #[$attr = __]
147                    $(#[$meta])*
148                    #[allow(unsafe_code)]
149                    $vis static $($static)*
150                );
151            }
152        };
153        ($section:ident $type:ident $name:ident $($aux:ident)? #[$attr:ident = __]
154            $(#[$meta:meta])* $($item:tt)*) => {
155            $crate::__add_section_link_attribute_impl!(
156                $section $type $name $($aux)? #[$attr = __]
157                $(#[$meta])*
158                #[allow(unsafe_code)]
159                $($item)*
160            );
161        };
162    );
163
164    #[cfg(feature = "proc_macro")]
165    #[doc(hidden)]
166    #[macro_export]
167    macro_rules! __add_section_link_attribute_impl(
168        ($section:ident $type:ident $name:ident $($aux:ident)? #[$attr:ident = __] $($item:tt)*) => {
169            $crate::__section_name!(
170                (#[$attr = __] #[allow(unsafe_code)] $($item)*)
171                $section $type $name $($aux)?
172            );
173        }
174    );
175
176    #[cfg(not(feature = "proc_macro"))]
177    #[doc(hidden)]
178    #[macro_export]
179    macro_rules! __add_section_link_attribute_impl(
180        ($section:ident $type:ident $name:ident #[$attr:ident = __] $($item:tt)*) => {
181            #[$attr = $crate::__section_name!(
182                raw $section $type $name
183            )] $($item)*
184        }
185    );
186
187    // \x01: "do not mangle" (ref https://github.com/rust-lang/rust-bindgen/issues/2935)
188    #[cfg(target_vendor = "apple")]
189    def_section_name! {
190        {
191            data bare =>    ("__DATA,") __ ();
192            code bare =>    ("__TEXT,") __ ();
193            data section => ("__DATA,") __ (",regular,no_dead_strip");
194            code section => ("__TEXT,") __ (",regular,pure_instructions");
195            data start =>   ("\x01section$start$__DATA$") __ ();
196            data end =>     ("\x01section$end$__DATA$") __ ();
197        }
198        AUXILIARY = "_";
199        MAX_LENGTH = 16;
200        HASH_LENGTH = 6;
201        VALID_SECTION_CHARS = "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
202    }
203
204    #[cfg(target_family = "wasm")]
205    def_section_name! {
206        {
207            data bare =>    (".data", ".link_section.") __ ();
208            data section => (".data", ".link_section.") __ ();
209            code bare =>    (".text", ".link_section.") __ ();
210            code section => (".text", ".link_section.") __ ();
211        }
212        AUXILIARY = ".";
213        MAX_LENGTH = 16;
214        HASH_LENGTH = 6;
215        VALID_SECTION_CHARS = "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
216    }
217
218    #[cfg(all(
219        not(target_vendor = "apple"),
220        not(target_vendor = "pc"),
221        not(target_family = "wasm")
222    ))]
223    def_section_name! {
224        {
225            data bare =>    ("_data", "_link_section_") __ ();
226            data section => ("_data", "_link_section_") __ ();
227            data start =>   ("__start_", "_data", "_link_section_") __ ();
228            data end =>     ("__stop_", "_data", "_link_section_") __ ();
229            code bare =>    ("_text", "_link_section_") __ ();
230            code section => ("_text", "_link_section_") __ ();
231            code start =>   ("__start_", "_text", "_link_section_") __ ();
232            code end =>     ("__stop_", "_text", "_link_section_") __ ();
233        }
234        AUXILIARY = "_";
235        MAX_LENGTH = 64;
236        HASH_LENGTH = 10;
237        VALID_SECTION_CHARS = "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
238    }
239
240    #[cfg(target_vendor = "pc")]
241    def_section_name! {
242        {
243            data bare =>    (".data", "$") __ ();
244            data section => (".data", "$") __ ("$b");
245            data start =>   (".data", "$") __ ("$a");
246            data end =>     (".data", "$") __ ("$c");
247            code bare =>    (".text", "$") __ ();
248            code section => (".text", "$") __ ("$b");
249            code start =>   (".text", "$") __ ("$a");
250            code end =>     (".text", "$") __ ("$c");
251        }
252        AUXILIARY = "$d$";
253        MAX_LENGTH = 64;
254        HASH_LENGTH = 10;
255        VALID_SECTION_CHARS = "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
256    }
257
258    #[cfg(not(feature = "proc_macro"))]
259    #[doc(hidden)]
260    #[macro_export]
261    macro_rules! __declare_macro {
262        ($vis:vis $ident:ident $generic_macro:ident $args:tt) => {
263            /// Internal macro for parsing the section. This is exported with
264            /// the same name as the type below.
265            #[doc(hidden)]
266            $vis use $crate::$generic_macro as $ident;
267        };
268    }
269
270    #[cfg(feature = "proc_macro")]
271    #[doc(hidden)]
272    #[macro_export]
273    macro_rules! __declare_macro {
274        ($vis:vis $ident:ident $generic_macro:ident $args:tt) => {
275            $crate::__support::ident_concat!(
276                (#[macro_export]
277                #[doc(hidden)]
278                macro_rules!)  (__ $ident __link_section_private_macro__) ({
279                    ($passthru:tt) => {
280                        $crate::$generic_macro!($passthru $args);
281                    };
282                })
283            );
284
285            $crate::__support::ident_concat!(
286                (#[doc(hidden)] pub use) (__ $ident __link_section_private_macro__) (as $ident;)
287            );
288        }
289    }
290
291    /// Define a link section.
292    #[macro_export]
293    #[doc(hidden)]
294    macro_rules! __section_parse {
295        // Has a generic (note that $generic eats the trailing semicolon)
296        (#[section $($args:tt)*] $(#[$meta:meta])* $vis:vis static $ident:ident : $(:: $path_prefix:ident ::)? $($path:ident)::* < $($generic:tt)*) => {
297            $crate::__section_parse!(@parsed #[section $($args)*] $(#[$meta])* $vis static $ident: ( $(:: $path_prefix ::)? $($path)::* < $($generic)*) ( $($generic)* ) __in_section_helper_macro_generic);
298        };
299        // No generic
300        (#[section $($args:tt)*] $(#[$meta:meta])* $vis:vis static $ident:ident : $(:: $path_prefix:ident ::)? $($path:ident)::* ;) => {
301            $crate::__section_parse!(@parsed #[section $($args)*] $(#[$meta])* $vis static $ident: ( $(:: $path_prefix ::)? $($path)::* ;) ( () > ; ) __in_section_helper_macro_no_generic);
302        };
303        // Both end up here...
304        (@parsed #[section(aux = $name:ident, no_macro)] $(#[$meta:meta])* $vis:vis static $ident:ident : ($ty:ty ;) ( $generic_ty:ty > ; ) $generic_macro:ident) => {
305            $crate::__section_parse!(@generate #[section(aux = $name)] $(#[$meta])* $vis static $ident: $ty, $generic_ty, $generic_macro);
306        };
307        (@parsed #[section(no_macro)] $(#[$meta:meta])* $vis:vis static $ident:ident : ($ty:ty ;) ( $generic_ty:ty > ; ) $generic_macro:ident) => {
308            $crate::__section_parse!(@generate #[section] $(#[$meta])* $vis static $ident: $ty, $generic_ty, $generic_macro);
309        };
310        (@parsed #[section $($args:tt)*] $(#[$meta:meta])* $vis:vis static $ident:ident : ($ty:ty ;) ( $generic_ty:ty > ; ) $generic_macro:ident) => {
311            $crate::__declare_macro!($vis $ident $generic_macro ($($args)*));
312            $crate::__section_parse!(@generate #[section $($args)*] $(#[$meta])* $vis static $ident: $ty, $generic_ty, $generic_macro);
313        };
314        (@generate #[section $($args:tt)*] $(#[$meta:meta])* $vis:vis static $ident:ident : $ty:ty, $generic_ty:ty, __in_section_helper_macro_generic) => {
315            $crate::__section_parse!(@generate #[section $($args)*] $(#[$meta])* $vis static $ident: $ty, $generic_ty, __base_case__);
316
317            impl ::core::iter::IntoIterator for $ident {
318                type Item = &'static $generic_ty;
319                type IntoIter = ::core::slice::Iter<'static, $generic_ty>;
320                fn into_iter(self) -> Self::IntoIter {
321                    $ident.as_slice().iter()
322                }
323            }
324        };
325        (@generate #[section $($args:tt)*] $(#[$meta:meta])* $vis:vis static $ident:ident : $ty:ty, $generic_ty:ty, $generic_macro:ident) => {
326            $(#[$meta])*
327            #[allow(non_camel_case_types)]
328            $vis struct $ident;
329
330            impl $crate::__support::SectionItemType for $ident {
331                type Item = $generic_ty;
332            }
333
334            impl ::core::fmt::Debug for $ident {
335                fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
336                    ::core::ops::Deref::deref(self).fmt(f)
337                }
338            }
339
340            impl ::core::ops::Deref for $ident {
341                type Target = $ty;
342                fn deref(&self) -> &Self::Target {
343                    self.const_deref()
344                }
345            }
346
347            $crate::__section_parse!(@deref #[section $($args)*] $(#[$meta])* $vis static $ident: $ty, $generic_ty, __base_case__);
348        };
349        (@deref #[section] $(#[$meta:meta])* $vis:vis static $ident:ident : $ty:ty, $generic_ty:ty, __base_case__) => {
350            impl $ident {
351                /// Get a `const` reference to the underlying section. In
352                /// non-const contexts, `deref` is sufficient.
353                pub const fn const_deref(&self) -> &$ty {
354                    static SECTION: $ty = {
355                        let section = $crate::__support::get_section!(name=$ident, type=$generic_ty, aux=);
356                        let name = $crate::__section_name!(
357                            raw data bare $ident
358                        );
359                        unsafe { <$ty>::new(name, section.0, section.1) }
360                    };
361                    &SECTION
362                }
363            }
364        };
365        (@deref #[section(aux=$aux:ident)] $(#[$meta:meta])* $vis:vis static $ident:ident : $ty:ty, $generic_ty:ty, __base_case__) => {
366            impl $ident {
367                /// Get a `const` reference to the underlying section. In
368                /// non-const contexts, `deref` is sufficient.
369                pub const fn const_deref(&self) -> &$ty {
370                    static SECTION: $ty = {
371                        let section = $crate::__support::get_section!(name=$ident, type=$generic_ty, aux=$aux);
372                        let name = $crate::__section_name!(
373                            raw data bare $aux $ident // swap
374                        );
375                        unsafe { <$ty>::new(name, section.0, section.1) }
376                    };
377                    &SECTION
378                }
379            }
380        };
381    }
382
383    #[cfg(miri)]
384    mod section {
385        #[doc(hidden)]
386        #[macro_export]
387        macro_rules! __get_section {
388            (name=$ident:ident, type=$generic_ty:ty, aux=$($aux:ident)?) => {{
389                (std::ptr::null_mut(), std::ptr::null_mut())
390            }};
391        }
392
393        /// On Apple platforms, the linker provides a pointer to the start and end
394        /// of the section regardless of the section's name.
395        pub type SectionPtr<T> = *const ::core::marker::PhantomData<T>;
396    }
397
398    #[cfg(all(not(miri), target_family = "wasm"))]
399    mod section {
400        #[doc(hidden)]
401        #[macro_export]
402        macro_rules! __get_section {
403            (name=$ident:ident, type=$generic_ty:ty, aux=$($aux:ident)?) => {
404                {
405                    static __START: ::core::sync::atomic::AtomicPtr::<::core::marker::PhantomData<$generic_ty>> = unsafe {
406                        ::core::sync::atomic::AtomicPtr::<::core::marker::PhantomData<$generic_ty>>::new(::core::ptr::null_mut())
407                    };
408                    static __END: ::core::sync::atomic::AtomicPtr::<::core::marker::PhantomData<$generic_ty>> = unsafe {
409                        ::core::sync::atomic::AtomicPtr::<::core::marker::PhantomData<$generic_ty>>::new(::core::ptr::null_mut())
410                    };
411
412                    (&__START, &__END)
413                }
414            }
415        }
416
417        /// On WASM, we use an atomic pointer to the start and end of the
418        /// section. The host environment is responsible for registering the
419        /// section with the runtime.
420        pub type SectionPtr<T> =
421            &'static ::core::sync::atomic::AtomicPtr<::core::marker::PhantomData<T>>;
422    }
423
424    #[cfg(all(not(miri), target_vendor = "pc"))]
425    mod section {
426        #[doc(hidden)]
427        #[macro_export]
428        macro_rules! __get_section {
429            (name=$ident:ident, type=$generic_ty:ty, aux=$($aux:ident)?) => {
430                {
431                    $crate::__support::add_section_link_attribute!(
432                        data start $ident $($aux)?
433                        #[link_section = __]
434                        static __START: [$generic_ty; 0] = [];
435                    );
436                    $crate::__support::add_section_link_attribute!(
437                        data end $ident $($aux)?
438                        #[link_section = __]
439                        static __END: [$generic_ty; 0] = [];
440                    );
441
442                    (
443                        unsafe { &raw const __START as $crate::__support::SectionPtr<$generic_ty> },
444                        unsafe { &raw const __END as $crate::__support::SectionPtr<$generic_ty> },
445                    )
446                }
447            }
448        }
449
450        /// On Windows platforms we don't have start/end symbols, but we do have
451        /// section sorting so we drop a [T; 0] at the start and end of the
452        /// section.
453        pub type SectionPtr<T> = *const [T; 0];
454    }
455
456    #[cfg(all(not(miri), not(target_family = "wasm"), not(target_vendor = "pc")))]
457    mod section {
458        #[doc(hidden)]
459        #[macro_export]
460        macro_rules! __get_section {
461            (name=$ident:ident, type=$generic_ty:ty, aux=$($aux:ident)?) => {
462                {
463                    $crate::__support::add_section_link_attribute!(
464                        data start $ident $($aux)?
465                        #[link_name = __]
466                        extern "C" {
467                            static __START: $crate::__support::SectionPtr<$generic_ty>;
468                        }
469                    );
470                    $crate::__support::add_section_link_attribute!(
471                        data end $ident $($aux)?
472                        #[link_name = __]
473                        extern "C" {
474                            static __END: $crate::__support::SectionPtr<$generic_ty>;
475                        }
476                    );
477
478                    (
479                        unsafe { &raw const __START as $crate::__support::SectionPtr<$generic_ty> },
480                        unsafe { &raw const __END as $crate::__support::SectionPtr<$generic_ty> },
481                    )
482                }
483            }
484        }
485
486        /// On LLVM/GCC platforms we can use orphan sections with _start and
487        /// _end symbols.
488        pub type SectionPtr<T> = *const ::core::marker::PhantomData<T>;
489    }
490
491    /// Export a symbol into a link section.
492    #[macro_export]
493    #[doc(hidden)]
494    macro_rules! __in_section_parse {
495        // Needs to handle:
496        //  <name>
497        //  :: <name>
498        //  <path> :: <name>
499        //  :: <path> :: <name>
500        //  etc...
501        (#[in_section(unsafe, type = $stored_ty:ty, name = $ident:ident $( , aux = $aux:ident)?)] $($item:tt)*) => {
502            $crate::__support::in_section_crate!((type = $stored_ty), $ident, $($aux)?, $ident, ($($item)*));
503        };
504        (#[in_section(unsafe, name = $ident:ident $( , aux = $aux:ident)?)] $($item:tt)*) => {
505            $crate::__support::in_section_crate!(data, $ident, $($aux)?, $ident, ($($item)*));
506        };
507        (#[in_section( $($path:tt)* )] $($item:tt)*) => {
508            $crate::__support::in_section_parse!(path=[$($path)*] #[in_section($($path)*)] $($item)*);
509        };
510        (path=[$orig_path:path] #[in_section($name:ident)] $($item:tt)*) => {
511            $orig_path ! (
512                (v=0 (name=$name (path=[$orig_path] (item=($($item)*) ()))))
513            );
514        };
515        (path=[$orig_path:path] #[in_section(:: $($path:ident)::*)] $($item:tt)*) => {
516            $crate::__support::in_section_parse!(path=[$orig_path] #[in_section($($path)::*)] $($item)*);
517        };
518        (path=[$orig_path:path] #[in_section($prefix:ident :: $($path:ident)::*)] $($item:tt)*) => {
519            $crate::__support::in_section_parse!(path=[$orig_path] #[in_section($($path)::*)] $($item)*);
520        };
521    }
522
523    #[macro_export]
524    #[doc(hidden)]
525    macro_rules! __in_section_helper_macro_generic {
526        ((v=0 (name=$ident:ident (path=[$path:path] (item=$item:tt $rest:tt))))) => {
527            $crate::__support::in_section_crate!(section, $ident,, $path, $item);
528        };
529        ((v=0 (name=$ident:ident (path=[$path:path] (item=$item:tt $rest:tt)))) ((aux=$aux:ident)) )=> {
530            $crate::__support::in_section_crate!(section, $ident, $aux, $path, $item);
531        };
532        ((v=0 (name=$ident:ident (path=[$path:path] (item=$item:tt $rest:tt)))) () )=> {
533            $crate::__support::in_section_crate!(section, $ident,, $path, $item);
534        };
535        (v=$v:literal $rest:tt) => {
536            const _: () = {
537                compile_error!(concat!(
538                    "link-section: Unsupported version: `",
539                    stringify!($v),
540                    "`: ",
541                    stringify!($rest)
542                ));
543            };
544        };
545    }
546
547    #[macro_export]
548    #[doc(hidden)]
549    macro_rules! __in_section_helper_macro_no_generic {
550        ((v=0 (name=$ident:ident (path=[$path:path] (item=$item:tt $rest:tt))))) => {
551            $crate::__support::in_section_crate!(data, $ident,, $path, $item);
552        };
553        ((v=0 (name=$ident:ident (path=[$path:path] (item=$item:tt $rest:tt)))) ((aux=$aux:ident)) )=> {
554            $crate::__support::in_section_crate!(data, $ident, $aux, $path, $item);
555        };
556        ((v=0 (name=$ident:ident (path=[$path:path] (item=$item:tt $rest:tt)))) () )=> {
557            $crate::__support::in_section_crate!(data, $ident,, $path, $item);
558        };
559        (v=$v:literal $rest:tt) => {
560            const _: () = {
561                compile_error!(concat!(
562                    "link-section: Unsupported version: `",
563                    stringify!($v),
564                    "`: ",
565                    stringify!($rest)
566                ));
567            };
568        };
569    }
570
571    #[macro_export]
572    #[doc(hidden)]
573    #[allow(unknown_lints, edition_2024_expr_fragment_specifier)]
574    macro_rules! __in_section_crate {
575        (@type_select section $path:path, $item_ty:ty) => {
576            <$path as $crate::__support::SectionItemType>::Item
577        };
578        (@type_select data $path:path, $item_ty:ty) => {
579            $item_ty
580        };
581        (@type_select (type = $stored_ty:ty) $path:path, $item_ty:ty) => {
582            $stored_ty
583        };
584        ($type_source:tt, $ident:ident, $($aux:ident)?, $path:path, ($(#[$meta:meta])* $vis:vis fn $ident_fn:ident($($args:tt)*) $(-> $ret:ty)? $body:block)) => {
585            const _: () = {
586                type __InSecStoredTy = $crate::__in_section_crate!(@type_select $type_source $path, fn($($args)*) $(-> $ret)?);
587                $crate::__add_section_link_attribute!(
588                    data section $ident $($aux)?
589                    #[link_section = __]
590                    $(#[$meta])*
591                    #[allow(non_upper_case_globals)]
592                    $vis static __LINK_SECTION_FN_ITEM: __InSecStoredTy = $ident_fn;
593                );
594            };
595
596            $crate::__add_section_link_attribute!(
597                code section $ident $($aux)?
598                #[link_section = __]
599                fn $ident_fn($($args)*) $(-> $ret)? $body
600            );
601        };
602        ($type_source:tt, $ident:ident, $($aux:ident)?, $path:path, ($(#[$meta:meta])* $vis:vis static _ : $ty:ty = $value:expr;)) => {
603            const _: () = {
604                type __InSecStoredTy = $crate::__in_section_crate!(@type_select $type_source $path, $ty);
605                $crate::__add_section_link_attribute!(
606                    data section $ident $($aux)?
607                    #[link_section = __]
608                    $(#[$meta])* $vis static ANONYMOUS: __InSecStoredTy = $value;
609                );
610            };
611        };
612        ($type_source:tt, $ident:ident, $($aux:ident)?, $path:path, ($(#[$meta:meta])* $vis:vis static $ident_static:ident : $ty:ty = $value:expr;)) => {
613            $crate::__add_section_link_attribute!(
614                data section $ident $($aux)?
615                #[link_section = __]
616                $(#[$meta])* $vis static $ident_static: $crate::__in_section_crate!(@type_select $type_source $path, $ty) = $value;
617            );
618        };
619        (data, $ident:ident, $($aux:ident)?, $path:path, ($(#[$meta:meta])* $item:item)) => {
620            $crate::__add_section_link_attribute!(
621                data section $ident $($aux)?
622                #[link_section = __]
623                $(#[$meta])* $item
624            );
625        };
626    }
627
628    pub trait SectionItemType {
629        type Item;
630    }
631
632    impl<T> SectionItemType for super::TypedSection<T> {
633        type Item = T;
634    }
635
636    pub use section::SectionPtr;
637}
638
639/// Define a link section.
640///
641/// The definition site generates two items: a static section struct that is
642/// used to access the section, and a macro that is used to place items into the
643/// section. The macro is used by the [`in_section`] procedural macro.
644///
645/// # Attributes
646///
647/// - `no_macro`: Does not generate the submission macro at the definition site.
648///   This will require any associated [`in_section`] invocations to use the raw
649///   name of the section.
650/// - `aux = <name>`: Specifies that this section is an auxiliary section, and
651///   that the section is named `<name>+<aux>`.
652///
653/// # Example
654/// ```rust
655/// use link_section::{in_section, section};
656///
657/// #[section]
658/// pub static DATA_SECTION: link_section::Section;
659///
660/// #[in_section(DATA_SECTION)]
661/// pub fn data_function() {
662///     println!("data_function");
663/// }
664/// ```
665#[cfg(feature = "proc_macro")]
666pub use ::linktime_proc_macro::section;
667
668/// Place an item into a link section.
669///
670/// # Functions and typed sections
671///
672/// As a special case, since function declarations by themselves are not sized,
673/// functions in typed sections are split and stored as function pointers.
674#[cfg(feature = "proc_macro")]
675pub use ::linktime_proc_macro::in_section;
676
677/// An untyped link section that can be used to store any type. The underlying
678/// data is not enumerable.
679#[repr(C)]
680pub struct Section {
681    name: &'static str,
682    start: __support::SectionPtr<()>,
683    end: __support::SectionPtr<()>,
684}
685
686impl Section {
687    #[doc(hidden)]
688    pub const unsafe fn new(
689        name: &'static str,
690        start: __support::SectionPtr<()>,
691        end: __support::SectionPtr<()>,
692    ) -> Self {
693        Self { name, start, end }
694    }
695
696    /// The byte length of the section.
697    pub fn byte_len(&self) -> usize {
698        unsafe { (self.end_ptr() as *const u8).offset_from(self.start_ptr() as *const u8) as usize }
699    }
700}
701
702#[cfg(target_family = "wasm")]
703impl Section {
704    /// The start address of the section.
705    pub fn start_ptr(&self) -> *const () {
706        let ptr = self.start.load(::core::sync::atomic::Ordering::Relaxed) as *const ();
707        if ptr.is_null() {
708            unsafe {
709                let required = crate::__support::read_custom_section(
710                    self.name.as_ptr(),
711                    self.name.len(),
712                    ::core::ptr::null_mut(),
713                    0,
714                );
715                let ptr = ::alloc::alloc::alloc(
716                    ::core::alloc::Layout::from_size_align(required, 1).unwrap(),
717                );
718                self.start
719                    .store(ptr as _, ::core::sync::atomic::Ordering::Relaxed);
720                self.end.store(
721                    ptr.add(required) as _,
722                    ::core::sync::atomic::Ordering::Relaxed,
723                );
724                crate::__support::read_custom_section(
725                    self.name.as_ptr(),
726                    self.name.len(),
727                    ptr as *mut u8,
728                    required,
729                );
730            }
731        }
732        ptr
733    }
734    /// The end address of the section.
735    pub fn end_ptr(&self) -> *const () {
736        let ptr = self.end.load(::core::sync::atomic::Ordering::Relaxed) as *const ();
737        if ptr.is_null() {
738            unsafe {
739                let required = crate::__support::read_custom_section(
740                    self.name.as_ptr(),
741                    self.name.len(),
742                    ::core::ptr::null_mut(),
743                    0,
744                );
745                let ptr = ::alloc::alloc::alloc(
746                    ::core::alloc::Layout::from_size_align(required, 1).unwrap(),
747                );
748                self.start
749                    .store(ptr as _, ::core::sync::atomic::Ordering::Relaxed);
750                self.end.store(
751                    ptr.add(required) as _,
752                    ::core::sync::atomic::Ordering::Relaxed,
753                );
754                crate::__support::read_custom_section(
755                    self.name.as_ptr(),
756                    self.name.len(),
757                    ptr as *mut u8,
758                    required,
759                );
760            }
761        }
762        ptr
763    }
764}
765
766#[cfg(not(target_family = "wasm"))]
767impl Section {
768    /// The start address of the section.
769    pub fn start_ptr(&self) -> *const () {
770        self.start as *const ()
771    }
772    /// The end address of the section.
773    pub fn end_ptr(&self) -> *const () {
774        self.end as *const ()
775    }
776}
777
778impl ::core::fmt::Debug for Section {
779    fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
780        f.debug_struct("Section")
781            .field("name", &self.name)
782            .field("start", &self.start_ptr())
783            .field("end", &self.end_ptr())
784            .field("byte_len", &self.byte_len())
785            .finish()
786    }
787}
788
789unsafe impl Sync for Section {}
790unsafe impl Send for Section {}
791
792/// A typed link section that can be used to store any sized type. The
793/// underlying data is enumerable.
794#[repr(C)]
795pub struct TypedSection<T: 'static> {
796    name: &'static str,
797    start: __support::SectionPtr<T>,
798    end: __support::SectionPtr<T>,
799    _phantom: ::core::marker::PhantomData<T>,
800}
801
802#[cfg(target_family = "wasm")]
803impl<T: 'static> TypedSection<T> {
804    /// The start address of the section.
805    pub fn start_ptr(&self) -> *const T {
806        let ptr = self.start.load(::core::sync::atomic::Ordering::Relaxed) as *const T;
807        if ptr.is_null() {
808            unsafe {
809                let required = crate::__support::read_custom_section(
810                    self.name.as_ptr(),
811                    self.name.len(),
812                    ::core::ptr::null_mut(),
813                    0,
814                );
815                let ptr = ::alloc::alloc::alloc(
816                    ::core::alloc::Layout::from_size_align(required, ::core::mem::align_of::<T>())
817                        .unwrap(),
818                );
819                self.start
820                    .store(ptr as _, ::core::sync::atomic::Ordering::Relaxed);
821                self.end.store(
822                    ptr.add(required) as _,
823                    ::core::sync::atomic::Ordering::Relaxed,
824                );
825                crate::__support::read_custom_section(
826                    self.name.as_ptr(),
827                    self.name.len(),
828                    ptr as *mut u8,
829                    required,
830                );
831            }
832        }
833        ptr
834    }
835
836    /// The end address of the section.
837    pub fn end_ptr(&self) -> *const T {
838        let ptr = self.end.load(::core::sync::atomic::Ordering::Relaxed) as *const T;
839        if ptr.is_null() {
840            unsafe {
841                let required = crate::__support::read_custom_section(
842                    self.name.as_ptr(),
843                    self.name.len(),
844                    ::core::ptr::null_mut(),
845                    0,
846                );
847                let ptr = ::alloc::alloc::alloc(
848                    ::core::alloc::Layout::from_size_align(required, ::core::mem::align_of::<T>())
849                        .unwrap(),
850                );
851                self.start
852                    .store(ptr as _, ::core::sync::atomic::Ordering::Relaxed);
853                self.end.store(
854                    ptr.add(required) as _,
855                    ::core::sync::atomic::Ordering::Relaxed,
856                );
857                crate::__support::read_custom_section(
858                    self.name.as_ptr(),
859                    self.name.len(),
860                    ptr as *mut u8,
861                    required,
862                );
863            }
864        }
865        ptr
866    }
867}
868
869#[cfg(not(target_family = "wasm"))]
870impl<T: 'static> TypedSection<T> {
871    /// The start address of the section.
872    #[inline(always)]
873    pub fn start_ptr(&self) -> *const T {
874        self.start as usize as *const T
875    }
876
877    /// The end address of the section.
878    #[inline(always)]
879    pub fn end_ptr(&self) -> *const T {
880        self.end as *const T
881    }
882}
883
884// Non-const, shared functions (or functions that don't depend on the pointers)
885impl<T: 'static> TypedSection<T> {
886    #[doc(hidden)]
887    pub const unsafe fn new(
888        name: &'static str,
889        start: __support::SectionPtr<T>,
890        end: __support::SectionPtr<T>,
891    ) -> Self {
892        Self {
893            name,
894            start,
895            end,
896            _phantom: ::core::marker::PhantomData,
897        }
898    }
899
900    /// The stride of the typed section.
901    pub const fn stride(&self) -> usize {
902        assert!(
903            ::core::mem::size_of::<T>() > 0
904                && ::core::mem::size_of::<T>() * 2 == ::core::mem::size_of::<[T; 2]>()
905        );
906        ::core::mem::size_of::<T>()
907    }
908
909    /// The byte length of the section.
910    pub fn byte_len(&self) -> usize {
911        unsafe { (self.end_ptr() as *const u8).offset_from(self.start_ptr() as *const u8) as usize }
912    }
913
914    /// The number of elements in the section.
915    pub fn len(&self) -> usize {
916        self.byte_len() / self.stride()
917    }
918
919    /// True if the section is empty.
920    pub fn is_empty(&self) -> bool {
921        self.len() == 0
922    }
923
924    /// The section as a slice.
925    pub fn as_slice(&self) -> &[T] {
926        if self.is_empty() {
927            &[]
928        } else {
929            unsafe { ::core::slice::from_raw_parts(self.start_ptr(), self.len()) }
930        }
931    }
932
933    /// The offset of the item in the section, if it is in the section.
934    pub fn offset_of(&self, item: &T) -> Option<usize> {
935        let ptr = item as *const T;
936        if ptr < self.start_ptr() || ptr >= self.end_ptr() {
937            None
938        } else {
939            Some(unsafe { ptr.offset_from(self.start_ptr()) as usize })
940        }
941    }
942
943    /// The section as a mutable slice.
944    ///
945    /// # Safety
946    ///
947    /// This cannot be safely used and is _absolutely unsound_ if any other
948    /// slices are live.
949    #[allow(clippy::mut_from_ref)]
950    pub unsafe fn as_mut_slice(&self) -> &mut [T] {
951        if self.is_empty() {
952            &mut []
953        } else {
954            unsafe { ::core::slice::from_raw_parts_mut(self.start_ptr() as *mut T, self.len()) }
955        }
956    }
957
958    /// The start address of the section.
959    #[inline(always)]
960    pub fn start_ptr_mut(&self) -> *mut T {
961        self.start_ptr() as *mut T
962    }
963
964    /// The start address of the section.
965    #[inline(always)]
966    pub fn end_ptr_mut(&self) -> *mut T {
967        self.end_ptr() as *mut T
968    }
969}
970
971impl<'a, T> ::core::iter::IntoIterator for &'a TypedSection<T> {
972    type Item = &'a T;
973    type IntoIter = ::core::slice::Iter<'a, T>;
974    fn into_iter(self) -> Self::IntoIter {
975        self.as_slice().iter()
976    }
977}
978
979impl<T> ::core::ops::Deref for TypedSection<T> {
980    type Target = [T];
981    fn deref(&self) -> &Self::Target {
982        self.as_slice()
983    }
984}
985
986impl<T> ::core::fmt::Debug for TypedSection<T> {
987    fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
988        f.debug_struct("TypedSection")
989            .field("name", &self.name)
990            .field("start", &self.start_ptr())
991            .field("end", &self.end_ptr())
992            .field("len", &self.len())
993            .field("stride", &self.stride())
994            .finish()
995    }
996}
997
998unsafe impl<T> Sync for TypedSection<T> where T: Sync {}
999unsafe impl<T> Send for TypedSection<T> where T: Send {}