|
| 1 | +#![crate_type = "rlib"] |
| 2 | + |
| 3 | +// This file contains a very minimalistic reproduction of what the |
| 4 | +// linkme (https://github.com/dtolnay/linkme) crate does. |
| 5 | +// This linker behavior fails with LLD without -znostart-stop-gc. |
| 6 | + |
| 7 | +type Item = fn(u32); |
| 8 | + |
| 9 | +pub struct DistributedSlice { |
| 10 | + section_start: *const Item, |
| 11 | + section_stop: *const Item, |
| 12 | +} |
| 13 | + |
| 14 | +unsafe impl Sync for DistributedSlice {} |
| 15 | + |
| 16 | +impl DistributedSlice { |
| 17 | + pub fn get_slice(&self) -> &'static [Item] { |
| 18 | + let stride = std::mem::size_of::<Item>(); |
| 19 | + let start = self.section_start; |
| 20 | + let stop = self.section_stop; |
| 21 | + let byte_offset = stop as usize - start as usize; |
| 22 | + let len = byte_offset / stride; |
| 23 | + unsafe { std::slice::from_raw_parts(start, len) } |
| 24 | + } |
| 25 | +} |
| 26 | + |
| 27 | +pub static EXTERN_FNS: DistributedSlice = { |
| 28 | + unsafe extern "Rust" { |
| 29 | + // The __start_ and __stop_ section names are magical for the linker, |
| 30 | + // It will put link sections named EXTERNFNS in-between them. |
| 31 | + #[link_name = "__start_EXTERNFNS"] |
| 32 | + static SECTION_START: Item; |
| 33 | + #[link_name = "__stop_EXTERNFNS"] |
| 34 | + static SECTION_STOP: Item; |
| 35 | + } |
| 36 | + DistributedSlice { |
| 37 | + section_start: &raw const SECTION_START, |
| 38 | + section_stop: &raw const SECTION_STOP, |
| 39 | + } |
| 40 | +}; |
0 commit comments