@@ -67,6 +67,47 @@ extern "C" {
67
67
pub fn mi_free ( p : * mut c_void ) ;
68
68
}
69
69
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
+
70
111
#[ cfg( test) ]
71
112
mod tests {
72
113
use super :: * ;
0 commit comments