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