1#![doc = include_str!("../README.md")]
2#![allow(unsafe_code)]
3
4#[doc(hidden)]
5pub mod __support {
6 pub use crate::__in_section_crate as in_section_crate;
7 pub use crate::__in_section_parse as in_section_parse;
8 pub use crate::__section_name as section_name;
9 pub use crate::__section_parse as section_parse;
10
11 pub use link_section_proc_macro::hash;
12
13 #[cfg(target_vendor = "apple")]
14 #[macro_export]
15 #[doc(hidden)]
16 macro_rules! __section_name {
17 ($pattern:tt data $($rest:tt)*) => {
18 $crate::__support::section_name!(__ $pattern symbol "__DATA" $($rest)*);
19 };
20 ($pattern:tt code $($rest:tt)*) => {
21 $crate::__support::section_name!(__ $pattern symbol "__TEXT" $($rest)*);
22 };
23 ($pattern:tt $unknown_section:ident $($rest:tt)*) => {
24 const _: () = {
25 compile_error!("Unknown section type: `{}`", stringify!($unknown_section));
26 };
27 };
28
29 (__ $pattern:tt symbol $section_prefix:literal bare $name:ident) => {
30 $crate::__support::section_name!(__ $pattern hash ($section_prefix ",") () $name);
31 };
32 (__ $pattern:tt symbol $section_prefix:literal section $name:ident) => {
33 $crate::__support::section_name!(__ $pattern hash ($section_prefix ",") (",regular,no_dead_strip") $name);
34 };
35 (__ $pattern:tt symbol $section_prefix:literal start $name:ident) => {
36 $crate::__support::section_name!(__ $pattern hash ("\x01section$start$" $section_prefix "$") () $name);
38 };
39 (__ $pattern:tt symbol $section_prefix:literal end $name:ident) => {
40 $crate::__support::section_name!(__ $pattern hash ("\x01section$end$" $section_prefix "$") ()$name);
41 };
42
43 (__ $pattern:tt hash $prefix:tt $suffix:tt $name:ident) => {
44 $crate::__support::hash!($pattern $name $prefix $suffix 6 16 "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
45 };
46 }
47
48 #[cfg(all(not(target_vendor = "apple"), not(target_vendor = "pc")))]
49 #[macro_export]
50 #[doc(hidden)]
51 macro_rules! __section_name {
52 ($pattern:tt data $($rest:tt)*) => {
53 $crate::__support::section_name!(__ $pattern symbol "_data" $($rest)*);
54 };
55 ($pattern:tt code $($rest:tt)*) => {
56 $crate::__support::section_name!(__ $pattern symbol "_text" $($rest)*);
57 };
58 ($pattern:tt $unknown_section:ident $($rest:tt)*) => {
59 const _: () = {
60 compile_error!("Unknown section type: `{}`", stringify!($unknown_section));
61 };
62 };
63
64 (__ $pattern:tt symbol $section_prefix:literal bare $name:ident) => {
67 $crate::__support::section_name!(__ $pattern hash ($section_prefix "_link_section_") () $name);
68 };
69 (__ $pattern:tt symbol $section_prefix:literal section $name:ident) => {
70 $crate::__support::section_name!(__ $pattern hash ($section_prefix "_link_section_") () $name);
71 };
72 (__ $pattern:tt symbol $section_prefix:literal start $name:ident) => {
73 $crate::__support::section_name!(__ $pattern hash ("__start_" $section_prefix "_link_section_") () $name);
74 };
75 (__ $pattern:tt symbol $section_prefix:literal end $name:ident) => {
76 $crate::__support::section_name!(__ $pattern hash ("__stop_" $section_prefix "_link_section_") () $name);
77 };
78
79 (__ $pattern:tt hash $prefix:tt $suffix:tt $name:ident) => {
80 $crate::__support::hash!($pattern $name $prefix $suffix 10 64 "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
81 };
82 }
83
84 #[cfg(target_vendor = "pc")]
85 #[macro_export]
86 #[doc(hidden)]
87 macro_rules! __section_name {
88 ($pattern:tt data $($rest:tt)*) => {
89 $crate::__support::section_name!(__ $pattern symbol ".data" $($rest)*);
90 };
91 ($pattern:tt code $($rest:tt)*) => {
92 $crate::__support::section_name!(__ $pattern symbol ".text" $($rest)*);
93 };
94 ($pattern:tt $unknown_section:ident $($rest:tt)*) => {
95 const _: () = {
96 compile_error!("Unknown section type: `{}`", stringify!($unknown_section));
97 };
98 };
99
100 (__ $pattern:tt symbol $section_prefix:literal bare $name:ident) => {
101 $crate::__support::section_name!(__ $pattern hash ($section_prefix "$") () $name);
102 };
103 (__ $pattern:tt symbol $section_prefix:literal section $name:ident) => {
104 $crate::__support::section_name!(__ $pattern hash ($section_prefix "$") ("$b") $name);
105 };
106 (__ $pattern:tt symbol $section_prefix:literal start $name:ident) => {
107 $crate::__support::section_name!(__ $pattern hash ($section_prefix "$") ("$a") $name);
108 };
109 (__ $pattern:tt symbol $section_prefix:literal end $name:ident) => {
110 $crate::__support::section_name!(__ $pattern hash ($section_prefix "$") ("$c") $name);
111 };
112
113 (__ $pattern:tt hash $prefix:tt $suffix:tt $name:ident) => {
114 $crate::__support::hash!($pattern $name $prefix $suffix 10 64 "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
115 };
116 }
117
118 #[macro_export]
120 #[doc(hidden)]
121 macro_rules! __section_parse {
122 (#[section] $(#[$meta:meta])* $vis:vis static $ident:ident : $(:: $path_prefix:ident ::)? $($path:ident)::* < $($generic:tt)*) => {
124 $crate::__section_parse!(#[section] $(#[$meta])* $vis static $ident: ( $(:: $path_prefix ::)? $($path)::* < $($generic)*) ( $($generic)* ) generic);
125 };
126 (#[section] $(#[$meta:meta])* $vis:vis static $ident:ident : $(:: $path_prefix:ident ::)? $($path:ident)::* ;) => {
128 $crate::__section_parse!(#[section] $(#[$meta])* $vis static $ident: ( $(:: $path_prefix ::)? $($path)::* ;) ( () > ; ) no_generic);
129 };
130 (#[section] $(#[$meta:meta])* $vis:vis static $ident:ident : ($ty:ty ;) ( $generic_ty:ty > ; ) $generic:ident) => {
132 macro_rules! $ident {
134 (v=0 (item=$item:tt $rest:tt)) => {
135 $crate::__support::in_section_crate!($ident $generic $ty, $item);
136 };
137 (v=$v:literal $rest:tt) => {
138 const _: () = { compile_error!(concat!("link-section: Unsupported version: `", stringify!($v), "`")); };
139 };
140 }
141
142 $(#[$meta])*
143 #[used]
144 $vis static $ident: $crate::__support::Section< $ty, $generic_ty > = $crate::__support::Section::new(
145 {
146 $crate::__support::section_name!(
147 (const fn section_name() -> &'static str { __ })
148 data bare $ident
149 );
150
151 section_name()
152 },
153 {
154 #[cfg(not(target_vendor = "pc"))]
155 $crate::__support::section_name!(
156 (
157 extern "C" {
158 #[link_name = __] static __START: $crate::__support::SectionPtr<$generic_ty>;
159 }
160 )
161 data start $ident
162 );
163
164 #[cfg(target_vendor = "pc")]
166 $crate::__support::section_name!(
167 (
168 #[link_section = __]
169 #[used]
170 static __START: [$generic_ty; 0] = [];
171 )
172 data start $ident
173 );
174
175 unsafe { &raw const __START as $crate::__support::SectionPtr<$generic_ty> }
176 },
177 {
178 #[cfg(not(target_vendor = "pc"))]
179 $crate::__support::section_name!(
180 (
181 extern "C" {
182 #[link_name = __] static __END: $crate::__support::SectionPtr<$generic_ty>;
183 }
184 )
185 data end $ident
186 );
187
188 #[cfg(target_vendor = "pc")]
189 $crate::__support::section_name!(
190 (
191 #[link_section = __]
192 #[used]
193 static __END: [$generic_ty; 0] = [];
194 )
195 data end $ident
196 );
197
198 unsafe { &raw const __END as $crate::__support::SectionPtr<$generic_ty> }
199 },
200 );
201 };
202 }
203
204 #[macro_export]
206 #[doc(hidden)]
207 macro_rules! __in_section_parse {
208 (#[in_section($name:path)] $($item:tt)*) => {
209 $name ! (
210 v=0 (item=($($item)*) ())
211 );
212 };
213 }
214
215 #[macro_export]
216 #[doc(hidden)]
217 #[allow(unknown_lints, edition_2024_expr_fragment_specifier)]
218 macro_rules! __in_section_crate {
219 ($ident:ident generic $section_ty:ty, ($(#[$meta:meta])* $vis:vis fn $ident_fn:ident($($args:tt)*) $(-> $ret:ty)? $body:block)) => {
220 $crate::__support::section_name!(
221 (
222 $(#[$meta])*
224 #[used]
225 #[link_section = __]
226 #[allow(non_upper_case_globals)]
227 $vis static $ident_fn: <$section_ty as $crate::__support::SectionItemType>::Item =
228 {
229 fn $ident_fn($($args)*) $(-> $ret)? $body
230 $ident_fn as <$section_ty as $crate::__support::SectionItemType>::Item
231 };
232 )
233 data section $ident
234 );
235 };
236 ($ident:ident generic $section_ty:ty, ($(#[$meta:meta])* $vis:vis static $ident_static:ident : $ty:ty = $value:expr;)) => {
237 $crate::__support::section_name!(
238 ($(#[$meta])* #[link_section = __] #[used] $vis static $ident_static: <$section_ty as $crate::__support::SectionItemType>::Item = $value;)
239 data section $ident
240 );
241 };
242 ($ident:ident no_generic $section_ty:ty, ($(#[$meta:meta])* $vis:vis fn $ident_fn:ident($($args:tt)*) $(-> $ret:ty)? $body:block)) => {
243 $crate::__support::section_name!(
244 (
245 $(#[$meta])*
246 #[link_section = __]
247 #[used]
248 #[allow(non_upper_case_globals)]
249 $vis static $ident_fn: fn($($args)*) $(-> $ret)? =
250 {
251 $crate::__support::section_name!(
252 (#[link_section = __] fn $ident_fn($($args)*) $(-> $ret)? $body)
253 code section $ident
254 );
255 $ident_fn
256 };
257 )
258 data section $ident
259 );
260 };
261 ($ident:ident no_generic $section_ty:ty, ($(#[$meta:meta])* $item:item)) => {
262 $crate::__support::section_name!(
263 ($(#[$meta])* #[link_section = __] #[used] $item)
264 data section $ident
265 );
266 };
267 }
268
269 pub trait SectionItemType {
270 type Item;
271 }
272
273 #[repr(C)]
274 pub struct Section<T: sealed::FromRawSection, S> {
275 name: &'static str,
276 start: SectionPtr<S>,
277 end: SectionPtr<S>,
278 _t: ::core::marker::PhantomData<T>,
279 }
280
281 impl<T> SectionItemType for super::TypedSection<T> {
282 type Item = T;
283 }
284
285 impl<T: sealed::FromRawSection, S> Section<T, S> {
286 pub const fn new(name: &'static str, start: SectionPtr<S>, end: SectionPtr<S>) -> Self {
287 Self {
288 name,
289 start,
290 end,
291 _t: ::core::marker::PhantomData,
292 }
293 }
294 }
295
296 impl<'a, T: sealed::FromRawSection, S> ::core::iter::IntoIterator for &'a Section<T, S>
297 where
298 for<'b> &'b T: ::core::iter::IntoIterator,
299 {
300 type Item = <&'a T as ::core::iter::IntoIterator>::Item;
301 type IntoIter = <&'a T as ::core::iter::IntoIterator>::IntoIter;
302 fn into_iter(self) -> Self::IntoIter {
303 ::core::ops::Deref::deref(self).into_iter()
304 }
305 }
306
307 impl<T: sealed::FromRawSection, S> ::core::ops::Deref for Section<T, S> {
308 type Target = T;
309 fn deref(&self) -> &Self::Target {
310 unsafe { ::core::mem::transmute(self) }
312 }
313 }
314
315 impl<T: sealed::FromRawSection + ::core::fmt::Debug, S> ::core::fmt::Debug for Section<T, S> {
316 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
317 ::core::fmt::Debug::fmt(::core::ops::Deref::deref(self), f)
318 }
319 }
320
321 unsafe impl<T: sealed::FromRawSection, S> Sync for Section<T, S> {}
322 unsafe impl<T: sealed::FromRawSection, S> Send for Section<T, S> {}
323
324 #[cfg(not(target_vendor = "pc"))]
327 pub type SectionPtr<T> = *const ::core::marker::PhantomData<T>;
328 #[cfg(target_vendor = "pc")]
332 pub type SectionPtr<T> = *const [T; 0];
333
334 mod sealed {
335 pub trait FromRawSection {}
336
337 impl FromRawSection for crate::Section {}
338
339 impl<T> FromRawSection for crate::TypedSection<T> {}
340 }
341}
342
343pub use ::link_section_proc_macro::section;
358
359pub use ::link_section_proc_macro::in_section;
366
367#[repr(C)]
370pub struct Section {
371 name: &'static str,
372 start: __support::SectionPtr<()>,
373 end: __support::SectionPtr<()>,
374}
375
376impl Section {
377 pub const fn start_ptr(&self) -> *const () {
379 self.start as *const ()
380 }
381 pub const fn end_ptr(&self) -> *const () {
383 self.end as *const ()
384 }
385 pub const fn byte_len(&self) -> usize {
387 unsafe { (self.end as *const u8).offset_from(self.start as *const u8) as usize }
388 }
389}
390
391impl ::core::fmt::Debug for Section {
392 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
393 f.debug_struct("Section")
394 .field("name", &self.name)
395 .field("start", &self.start_ptr())
396 .field("end", &self.end_ptr())
397 .field("byte_len", &self.byte_len())
398 .finish()
399 }
400}
401
402unsafe impl Sync for Section {}
403unsafe impl Send for Section {}
404
405#[repr(C)]
408pub struct TypedSection<T> {
409 name: &'static str,
410 start: __support::SectionPtr<T>,
411 end: __support::SectionPtr<T>,
412 _phantom: ::core::marker::PhantomData<T>,
413}
414
415impl<T> TypedSection<T> {
416 pub const fn stride(&self) -> usize {
418 #[repr(C)]
421 struct Sizer<T> {
422 t1: T,
423 t2: T,
424 t3: T,
425 }
426
427 let sizer = ::core::mem::MaybeUninit::<Sizer<T>>::uninit();
428 let ptr: *const Sizer<T> = sizer.as_ptr();
429 let start = ptr as *const u8;
430 let end = unsafe { ::core::ptr::addr_of!((*ptr).t3) } as *const u8;
431 unsafe { end.offset_from(start) as usize / 2 }
432 }
433
434 pub const fn start_ptr(&self) -> *const T {
436 self.start as *const T
437 }
438
439 pub const fn end_ptr(&self) -> *const T {
441 self.end as *const T
442 }
443
444 pub const fn byte_len(&self) -> usize {
446 unsafe { (self.end as *const u8).offset_from(self.start as *const u8) as usize }
447 }
448
449 pub const fn len(&self) -> usize {
451 self.byte_len() / self.stride()
452 }
453
454 pub const fn is_empty(&self) -> bool {
456 self.len() == 0
457 }
458
459 pub const fn as_slice(&self) -> &[T] {
461 if self.is_empty() {
462 &[]
463 } else {
464 unsafe { ::core::slice::from_raw_parts(self.start_ptr(), self.len()) }
465 }
466 }
467}
468
469impl<'a, T> ::core::iter::IntoIterator for &'a TypedSection<T> {
470 type Item = &'a T;
471 type IntoIter = ::core::slice::Iter<'a, T>;
472 fn into_iter(self) -> Self::IntoIter {
473 self.as_slice().iter()
474 }
475}
476
477impl<T> ::core::ops::Deref for TypedSection<T> {
478 type Target = [T];
479 fn deref(&self) -> &Self::Target {
480 self.as_slice()
481 }
482}
483
484impl<T> ::core::fmt::Debug for TypedSection<T> {
485 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
486 f.debug_struct("TypedSection")
487 .field("name", &self.name)
488 .field("start", &self.start_ptr())
489 .field("end", &self.end_ptr())
490 .field("len", &self.len())
491 .field("stride", &self.stride())
492 .finish()
493 }
494}
495
496unsafe impl<T> Sync for TypedSection<T> where T: Sync {}
497unsafe impl<T> Send for TypedSection<T> where T: Send {}