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