|
| 1 | +//! Test that when overriding, that the `malloc` and `free` symbols are |
| 2 | +//! interoperable, even across a dylib boundary. |
| 3 | +use core::ffi::{c_char, c_void, CStr}; |
| 4 | + |
| 5 | +// Make sure that `rustc` links this. |
| 6 | +use libmimalloc_sys as _; |
| 7 | + |
| 8 | +extern "C-unwind" { |
| 9 | + fn dep_lookup_malloc_address() -> *const c_char; |
| 10 | + fn dep_malloc(size: libc::size_t) -> *mut c_void; |
| 11 | + fn dep_free(ptr: *mut c_void); |
| 12 | +} |
| 13 | + |
| 14 | +fn lookup_malloc_address() -> *const c_char { |
| 15 | + unsafe { |
| 16 | + let mut info: libc::Dl_info = core::mem::zeroed(); |
| 17 | + let fnptr: unsafe extern "C" fn(libc::size_t) -> *mut c_void = libc::malloc; |
| 18 | + let fnptr = fnptr as *const c_void; |
| 19 | + if libc::dladdr(fnptr, &mut info) == 0 { |
| 20 | + libc::printf(b"failed finding `malloc`\n\0".as_ptr().cast()); |
| 21 | + libc::abort(); |
| 22 | + } |
| 23 | + info.dli_fname |
| 24 | + } |
| 25 | +} |
| 26 | + |
| 27 | +fn main() { |
| 28 | + // Check that pointers created with `malloc` in a dylib dependency can be |
| 29 | + // free'd with `free` here. |
| 30 | + let ptr = unsafe { libc::malloc(10) }; |
| 31 | + unsafe { dep_free(ptr) }; |
| 32 | + let ptr = unsafe { dep_malloc(10) }; |
| 33 | + unsafe { libc::free(ptr) }; |
| 34 | + |
| 35 | + // If overidden, test that the same is true for `mi_malloc` being |
| 36 | + // interoperable with `free`. |
| 37 | + if cfg!(feature = "override") { |
| 38 | + let ptr = unsafe { libmimalloc_sys::mi_malloc(10) }; |
| 39 | + unsafe { dep_free(ptr) }; |
| 40 | + let ptr = unsafe { libmimalloc_sys::mi_malloc(10) }; |
| 41 | + unsafe { libc::free(ptr) }; |
| 42 | + |
| 43 | + let ptr = unsafe { libc::malloc(10) }; |
| 44 | + unsafe { libmimalloc_sys::mi_free(ptr) }; |
| 45 | + let ptr = unsafe { dep_malloc(10) }; |
| 46 | + unsafe { libmimalloc_sys::mi_free(ptr) }; |
| 47 | + } |
| 48 | + |
| 49 | + // Extra check that the symbol was actually from the same place. |
| 50 | + let dep = unsafe { CStr::from_ptr(dep_lookup_malloc_address()) }; |
| 51 | + let here = unsafe { CStr::from_ptr(lookup_malloc_address()) }; |
| 52 | + |
| 53 | + if cfg!(target_vendor = "apple") { |
| 54 | + // macOS / Mach-O symbols are not overriden in dependencies, they are |
| 55 | + // hooked into with `zone_register`. |
| 56 | + assert_eq!( |
| 57 | + dep.to_str().unwrap(), |
| 58 | + "/usr/lib/system/libsystem_malloc.dylib" |
| 59 | + ); |
| 60 | + } else { |
| 61 | + assert_eq!(dep, here); |
| 62 | + } |
| 63 | +} |
0 commit comments