@@ -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) ]
71112mod tests {
72113 use super :: * ;
0 commit comments