Skip to content

Commit 9650cee

Browse files
committed
Add #[used] to always override
At least when the final linker invocation is driven by `rustc`.
1 parent 2586fdc commit 9650cee

File tree

1 file changed

+41
-0
lines changed

1 file changed

+41
-0
lines changed

libmimalloc-sys/src/lib.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,47 @@ extern "C" {
6767
pub fn mi_free(p: *mut c_void);
6868
}
6969

70+
/// When using the `"override"` feature flag, the user wants us to globally
71+
/// override the system allocator.
72+
///
73+
/// However, since we build and link `mimalloc` as a static library/archive,
74+
/// the linker may decide to not care about our overrides if it can't directly
75+
/// see references to the symbols, see the following link for details:
76+
/// <https://maskray.me/blog/2021-06-20-symbol-processing#archive-processing>
77+
///
78+
/// This is problematic if `mimalloc` is used from a library that by itself
79+
/// doesn't allocate, yet invokes other shared libraries that do, since then
80+
/// the linker wouldn't see any references to `malloc`/`free`, and the symbols
81+
/// would not be overridden.
82+
///
83+
/// To avoid this problem, we make sure that the allocator functions are
84+
/// visible to the linker.
85+
///
86+
/// To avoid this problem, we reference `mi_malloc` in a `#[used]` static.
87+
/// This makes it known to `rustc`, which will create a reference to it in a
88+
/// `symbols.o` stub file that is later passed directly to the linker (instead
89+
/// of being in an archive). See the following link for details on how this
90+
/// works: <https://github.com/rust-lang/rust/pull/95604>
91+
///
92+
/// NOTE: This works because `mimalloc` is compiled into a single object file
93+
/// in `static.c`. If it was split across multiple files, we'd need to
94+
/// reference each symbol. See also the comment at the top of `static.c`.
95+
///
96+
/// NOTE: On macOS, mimalloc doesn't just override malloc/free, but also
97+
/// registers itself with the allocator's zone APIs in a ctor
98+
/// (`_mi_macos_override_malloc`, marked with `__attribute__((constructor))`).
99+
/// Similarly to above, for the Mach-O linker to actually consider ctors as
100+
/// "used" when defined in an archive member in a static library, so we need
101+
/// to explicitly reference something in the object file. The constructor
102+
/// symbol itself is static, so we can't get a reference to that, so instead
103+
/// we reference `mi_malloc` here too).
104+
#[cfg(feature = "override")]
105+
mod set_up_statics {
106+
use super::*;
107+
#[used] // Could be `#[used(linker)]` once stable
108+
static USED: unsafe extern "C" fn(usize) -> *mut c_void = mi_malloc;
109+
}
110+
70111
#[cfg(test)]
71112
mod tests {
72113
use super::*;

0 commit comments

Comments
 (0)