Skip to main content

link_section/
lib.rs

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