Skip to content

Commit

Permalink
Panic if multiple distributed slices with same name
Browse files Browse the repository at this point in the history
  • Loading branch information
dtolnay committed Jul 12, 2022
1 parent 710773e commit 64e7c63
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 13 deletions.
54 changes: 53 additions & 1 deletion impl/src/declaration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ pub fn expand(input: TokenStream) -> TokenStream {
let vis = decl.vis;
let ident = decl.ident;
let ty = decl.ty;
let name = ident.to_string();

let linkme_path = match attr::linkme_path(&mut attrs) {
Ok(path) => path,
Expand All @@ -59,20 +60,37 @@ pub fn expand(input: TokenStream) -> TokenStream {
let linux_section = linker::linux::section(&ident);
let linux_section_start = linker::linux::section_start(&ident);
let linux_section_stop = linker::linux::section_stop(&ident);
let linux_dupcheck = linux_section.replacen("linkme", "linkm2", 1);
let linux_dupcheck_start = linux_section_start.replacen("linkme", "linkm2", 1);
let linux_dupcheck_stop = linux_section_stop.replacen("linkme", "linkm2", 1);

let macho_section = linker::macho::section(&ident);
let macho_section_start = linker::macho::section_start(&ident);
let macho_section_stop = linker::macho::section_stop(&ident);
let macho_dupcheck = macho_section.replacen("linkme", "linkm2", 1);
let macho_dupcheck_start = macho_section_start.replacen("linkme", "linkm2", 1);
let macho_dupcheck_stop = macho_section_stop.replacen("linkme", "linkm2", 1);

let windows_section = linker::windows::section(&ident);
let windows_section_start = linker::windows::section_start(&ident);
let windows_section_stop = linker::windows::section_stop(&ident);
let windows_dupcheck = windows_section.replacen("linkme", "linkm2", 1);
let windows_dupcheck_start = windows_section_start.replacen("linkme", "linkm2", 1);
let windows_dupcheck_stop = windows_section_stop.replacen("linkme", "linkm2", 1);

let illumos_section = linker::illumos::section(&ident);
let illumos_section_start = linker::illumos::section_start(&ident);
let illumos_section_stop = linker::illumos::section_stop(&ident);
let illumos_dupcheck = illumos_section.replacen("linkme", "linkm2", 1);
let illumos_dupcheck_start = illumos_section_start.replacen("linkme", "linkm2", 1);
let illumos_dupcheck_stop = illumos_section_stop.replacen("linkme", "linkm2", 1);

let freebsd_section = linker::freebsd::section(&ident);
let freebsd_section_start = linker::freebsd::section_start(&ident);
let freebsd_section_stop = linker::freebsd::section_stop(&ident);
let freebsd_dupcheck = freebsd_section.replacen("linkme", "linkm2", 1);
let freebsd_dupcheck_start = freebsd_section_start.replacen("linkme", "linkm2", 1);
let freebsd_dupcheck_stop = freebsd_section_stop.replacen("linkme", "linkm2", 1);

let call_site = Span::call_site();
let ident_str = ident.to_string();
Expand Down Expand Up @@ -105,6 +123,18 @@ pub fn expand(input: TokenStream) -> TokenStream {
#[cfg_attr(target_os = "illumos", link_name = #illumos_section_stop)]
#[cfg_attr(target_os = "freebsd", link_name = #freebsd_section_stop)]
static LINKME_STOP: <#ty as #linkme_path::private::Slice>::Element;

#[cfg_attr(any(target_os = "none", target_os = "linux"), link_name = #linux_dupcheck_start)]
#[cfg_attr(any(target_os = "macos", target_os = "ios", target_os = "tvos"), link_name = #macho_dupcheck_start)]
#[cfg_attr(target_os = "illumos", link_name = #illumos_dupcheck_start)]
#[cfg_attr(target_os = "freebsd", link_name = #freebsd_dupcheck_start)]
static DUPCHECK_START: #linkme_path::private::usize;

#[cfg_attr(any(target_os = "none", target_os = "linux"), link_name = #linux_dupcheck_stop)]
#[cfg_attr(any(target_os = "macos", target_os = "ios", target_os = "tvos"), link_name = #macho_dupcheck_stop)]
#[cfg_attr(target_os = "illumos", link_name = #illumos_dupcheck_stop)]
#[cfg_attr(target_os = "freebsd", link_name = #freebsd_dupcheck_stop)]
static DUPCHECK_STOP: #linkme_path::private::usize;
}

#[cfg(target_os = "windows")]
Expand All @@ -115,13 +145,29 @@ pub fn expand(input: TokenStream) -> TokenStream {
#[link_section = #windows_section_stop]
static LINKME_STOP: () = ();

#[cfg(target_os = "windows")]
#[link_section = #windows_dupcheck_start]
static DUPCHECK_START: () = ();

#[cfg(target_os = "windows")]
#[link_section = #windows_dupcheck_stop]
static DUPCHECK_STOP: () = ();

#[used]
#[cfg(any(target_os = "none", target_os = "linux", target_os = "illumos", target_os = "freebsd"))]
#[cfg_attr(any(target_os = "none", target_os = "linux"), link_section = #linux_section)]
#[cfg_attr(target_os = "illumos", link_section = #illumos_section)]
#[cfg_attr(target_os = "freebsd", link_section = #freebsd_section)]
static mut LINKME_PLEASE: [<#ty as #linkme_path::private::Slice>::Element; 0] = [];

#[used]
#[cfg_attr(any(target_os = "none", target_os = "linux"), link_section = #linux_dupcheck)]
#[cfg_attr(any(target_os = "macos", target_os = "ios", target_os = "tvos"), link_section = #macho_dupcheck)]
#[cfg_attr(target_os = "windows", link_section = #windows_dupcheck)]
#[cfg_attr(target_os = "illumos", link_section = #illumos_dupcheck)]
#[cfg_attr(target_os = "freebsd", link_section = #freebsd_dupcheck)]
static DUPCHECK: #linkme_path::private::usize = 1;

#[cfg(not(any(
target_os = "none",
target_os = "linux",
Expand All @@ -139,7 +185,13 @@ pub fn expand(input: TokenStream) -> TokenStream {
);

unsafe {
#linkme_path::DistributedSlice::private_new(&LINKME_START, &LINKME_STOP)
#linkme_path::DistributedSlice::private_new(
#name,
&LINKME_START,
&LINKME_STOP,
&DUPCHECK_START,
&DUPCHECK_STOP,
)
}
};

Expand Down
55 changes: 43 additions & 12 deletions src/distributed_slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,11 @@ use crate::private::Slice;
/// }
/// ```
pub struct DistributedSlice<T: ?Sized + Slice> {
start: StaticPtr<T::Element>,
stop: StaticPtr<T::Element>,
name: &'static str,
section_start: StaticPtr<T::Element>,
section_stop: StaticPtr<T::Element>,
dupcheck_start: StaticPtr<usize>,
dupcheck_stop: StaticPtr<usize>,
}

struct StaticPtr<T> {
Expand Down Expand Up @@ -155,22 +158,46 @@ impl<T> DistributedSlice<[T]> {
target_os = "illumos",
target_os = "freebsd"
))]
pub const unsafe fn private_new(start: *const T, stop: *const T) -> Self {
pub const unsafe fn private_new(
name: &'static str,
section_start: *const T,
section_stop: *const T,
dupcheck_start: *const usize,
dupcheck_stop: *const usize,
) -> Self {
DistributedSlice {
start: StaticPtr { ptr: start },
stop: StaticPtr { ptr: stop },
name,
section_start: StaticPtr { ptr: section_start },
section_stop: StaticPtr { ptr: section_stop },
dupcheck_start: StaticPtr {
ptr: dupcheck_start,
},
dupcheck_stop: StaticPtr { ptr: dupcheck_stop },
}
}

#[doc(hidden)]
#[cfg(target_os = "windows")]
pub const unsafe fn private_new(start: *const (), stop: *const ()) -> Self {
pub const unsafe fn private_new(
name: &'static str,
section_start: *const (),
section_stop: *const (),
dupcheck_start: *const (),
dupcheck_stop: *const (),
) -> Self {
DistributedSlice {
start: StaticPtr {
ptr: start as *const T,
name,
section_start: StaticPtr {
ptr: section_start as *const T,
},
section_stop: StaticPtr {
ptr: section_stop as *const T,
},
dupcheck_start: StaticPtr {
ptr: dupcheck_start as *const usize,
},
stop: StaticPtr {
ptr: stop as *const T,
dupcheck_stop: StaticPtr {
ptr: dupcheck_stop as *const usize,
},
}
}
Expand Down Expand Up @@ -217,9 +244,13 @@ impl<T> DistributedSlice<[T]> {
/// }
/// ```
pub fn static_slice(self) -> &'static [T] {
if self.dupcheck_start.ptr.wrapping_add(1) < self.dupcheck_stop.ptr {
panic!("duplicate #[distributed_slice] with name \"{}\"", self.name);
}

let stride = mem::size_of::<T>();
let start = self.start.ptr;
let stop = self.stop.ptr;
let start = self.section_start.ptr;
let stop = self.section_stop.ptr;
let byte_offset = stop as usize - start as usize;
let len = match byte_offset.checked_div(stride) {
Some(len) => len,
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@
clippy::doc_markdown,
clippy::empty_enum,
clippy::expl_impl_clone_on_copy,
clippy::manual_assert,
clippy::missing_panics_doc,
clippy::must_use_candidate,
clippy::unused_self
Expand Down
1 change: 1 addition & 0 deletions src/private.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pub use core::assert;
pub use core::mem;
pub use core::primitive::usize;

pub trait Slice {
type Element;
Expand Down

0 comments on commit 64e7c63

Please sign in to comment.