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