10b57cec5SDimitry Andric//===-- sanitizer_malloc_mac.inc --------------------------------*- C++ -*-===// 20b57cec5SDimitry Andric// 30b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric// 70b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric// 90b57cec5SDimitry Andric// This file contains Mac-specific malloc interceptors and a custom zone 100b57cec5SDimitry Andric// implementation, which together replace the system allocator. 110b57cec5SDimitry Andric// 120b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric#include "sanitizer_common/sanitizer_platform.h" 1581ad6265SDimitry Andric#if !SANITIZER_APPLE 160b57cec5SDimitry Andric#error "This file should only be compiled on Darwin." 170b57cec5SDimitry Andric#endif 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric#include <AvailabilityMacros.h> 200b57cec5SDimitry Andric#include <CoreFoundation/CFBase.h> 210b57cec5SDimitry Andric#include <dlfcn.h> 220b57cec5SDimitry Andric#include <malloc/malloc.h> 230b57cec5SDimitry Andric#include <sys/mman.h> 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric#include "interception/interception.h" 26349cc55cSDimitry Andric#include "sanitizer_common/sanitizer_allocator_dlsym.h" 270b57cec5SDimitry Andric#include "sanitizer_common/sanitizer_mac.h" 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric// Similar code is used in Google Perftools, 300b57cec5SDimitry Andric// https://github.com/gperftools/gperftools. 310b57cec5SDimitry Andric 320b57cec5SDimitry Andricnamespace __sanitizer { 330b57cec5SDimitry Andric 340b57cec5SDimitry Andricextern malloc_zone_t sanitizer_zone; 350b57cec5SDimitry Andric 360b57cec5SDimitry Andricstruct sanitizer_malloc_introspection_t : public malloc_introspection_t { 370b57cec5SDimitry Andric // IMPORTANT: Do not change the order, alignment, or types of these fields to 380b57cec5SDimitry Andric // maintain binary compatibility. You should only add fields to this struct. 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric // Used to track changes to the allocator that will affect 410b57cec5SDimitry Andric // zone enumeration. 420b57cec5SDimitry Andric u64 allocator_enumeration_version; 430b57cec5SDimitry Andric uptr allocator_ptr; 440b57cec5SDimitry Andric uptr allocator_size; 450b57cec5SDimitry Andric}; 460b57cec5SDimitry Andric 470b57cec5SDimitry Andricu64 GetMallocZoneAllocatorEnumerationVersion() { 480b57cec5SDimitry Andric // This represents the current allocator ABI version. 490b57cec5SDimitry Andric // This field should be incremented every time the Allocator 500b57cec5SDimitry Andric // ABI changes in a way that breaks allocator enumeration. 510b57cec5SDimitry Andric return 0; 520b57cec5SDimitry Andric} 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric} // namespace __sanitizer 550b57cec5SDimitry Andric 560b57cec5SDimitry AndricINTERCEPTOR(malloc_zone_t *, malloc_create_zone, 570b57cec5SDimitry Andric vm_size_t start_size, unsigned zone_flags) { 580b57cec5SDimitry Andric COMMON_MALLOC_ENTER(); 590b57cec5SDimitry Andric uptr page_size = GetPageSizeCached(); 600b57cec5SDimitry Andric uptr allocated_size = RoundUpTo(sizeof(sanitizer_zone), page_size); 610b57cec5SDimitry Andric COMMON_MALLOC_MEMALIGN(page_size, allocated_size); 620b57cec5SDimitry Andric malloc_zone_t *new_zone = (malloc_zone_t *)p; 630b57cec5SDimitry Andric internal_memcpy(new_zone, &sanitizer_zone, sizeof(sanitizer_zone)); 640b57cec5SDimitry Andric new_zone->zone_name = NULL; // The name will be changed anyway. 650b57cec5SDimitry Andric // Prevent the client app from overwriting the zone contents. 660b57cec5SDimitry Andric // Library functions that need to modify the zone will set PROT_WRITE on it. 670b57cec5SDimitry Andric // This matches the behavior of malloc_create_zone() on OSX 10.7 and higher. 680b57cec5SDimitry Andric mprotect(new_zone, allocated_size, PROT_READ); 690b57cec5SDimitry Andric // We're explicitly *NOT* registering the zone. 700b57cec5SDimitry Andric return new_zone; 710b57cec5SDimitry Andric} 720b57cec5SDimitry Andric 730b57cec5SDimitry AndricINTERCEPTOR(void, malloc_destroy_zone, malloc_zone_t *zone) { 740b57cec5SDimitry Andric COMMON_MALLOC_ENTER(); 750b57cec5SDimitry Andric // We don't need to do anything here. We're not registering new zones, so we 760b57cec5SDimitry Andric // don't to unregister. Just un-mprotect and free() the zone. 770b57cec5SDimitry Andric uptr page_size = GetPageSizeCached(); 780b57cec5SDimitry Andric uptr allocated_size = RoundUpTo(sizeof(sanitizer_zone), page_size); 790b57cec5SDimitry Andric mprotect(zone, allocated_size, PROT_READ | PROT_WRITE); 800b57cec5SDimitry Andric if (zone->zone_name) { 810b57cec5SDimitry Andric COMMON_MALLOC_FREE((void *)zone->zone_name); 820b57cec5SDimitry Andric } 830b57cec5SDimitry Andric COMMON_MALLOC_FREE(zone); 840b57cec5SDimitry Andric} 850b57cec5SDimitry Andric 860b57cec5SDimitry AndricINTERCEPTOR(malloc_zone_t *, malloc_default_zone, void) { 870b57cec5SDimitry Andric COMMON_MALLOC_ENTER(); 880b57cec5SDimitry Andric return &sanitizer_zone; 890b57cec5SDimitry Andric} 900b57cec5SDimitry Andric 9168d75effSDimitry AndricINTERCEPTOR(malloc_zone_t *, malloc_zone_from_ptr, const void *ptr) { 9268d75effSDimitry Andric COMMON_MALLOC_ENTER(); 9368d75effSDimitry Andric size_t size = sanitizer_zone.size(&sanitizer_zone, ptr); 9468d75effSDimitry Andric if (size) { // Claimed by sanitizer zone? 9568d75effSDimitry Andric return &sanitizer_zone; 9668d75effSDimitry Andric } 9768d75effSDimitry Andric return REAL(malloc_zone_from_ptr)(ptr); 9868d75effSDimitry Andric} 9968d75effSDimitry Andric 1000b57cec5SDimitry AndricINTERCEPTOR(malloc_zone_t *, malloc_default_purgeable_zone, void) { 1010b57cec5SDimitry Andric // FIXME: ASan should support purgeable allocations. 1020b57cec5SDimitry Andric // https://github.com/google/sanitizers/issues/139 1030b57cec5SDimitry Andric COMMON_MALLOC_ENTER(); 1040b57cec5SDimitry Andric return &sanitizer_zone; 1050b57cec5SDimitry Andric} 1060b57cec5SDimitry Andric 1070b57cec5SDimitry AndricINTERCEPTOR(void, malloc_make_purgeable, void *ptr) { 1080b57cec5SDimitry Andric // FIXME: ASan should support purgeable allocations. Ignoring them is fine 1090b57cec5SDimitry Andric // for now. 1100b57cec5SDimitry Andric COMMON_MALLOC_ENTER(); 1110b57cec5SDimitry Andric} 1120b57cec5SDimitry Andric 1130b57cec5SDimitry AndricINTERCEPTOR(int, malloc_make_nonpurgeable, void *ptr) { 1140b57cec5SDimitry Andric // FIXME: ASan should support purgeable allocations. Ignoring them is fine 1150b57cec5SDimitry Andric // for now. 1160b57cec5SDimitry Andric COMMON_MALLOC_ENTER(); 1170b57cec5SDimitry Andric // Must return 0 if the contents were not purged since the last call to 1180b57cec5SDimitry Andric // malloc_make_purgeable(). 1190b57cec5SDimitry Andric return 0; 1200b57cec5SDimitry Andric} 1210b57cec5SDimitry Andric 1220b57cec5SDimitry AndricINTERCEPTOR(void, malloc_set_zone_name, malloc_zone_t *zone, const char *name) { 1230b57cec5SDimitry Andric COMMON_MALLOC_ENTER(); 124fe6060f1SDimitry Andric InternalScopedString new_name; 1250b57cec5SDimitry Andric if (name && zone->introspect == sanitizer_zone.introspect) { 1265f757f3fSDimitry Andric new_name.AppendF(COMMON_MALLOC_ZONE_NAME "-%s", name); 1270b57cec5SDimitry Andric name = new_name.data(); 1280b57cec5SDimitry Andric } 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric // Call the system malloc's implementation for both external and our zones, 1310b57cec5SDimitry Andric // since that appropriately changes VM region protections on the zone. 1320b57cec5SDimitry Andric REAL(malloc_set_zone_name)(zone, name); 1330b57cec5SDimitry Andric} 1340b57cec5SDimitry Andric 1350b57cec5SDimitry AndricINTERCEPTOR(void *, malloc, size_t size) { 1360b57cec5SDimitry Andric COMMON_MALLOC_ENTER(); 1370b57cec5SDimitry Andric COMMON_MALLOC_MALLOC(size); 1380b57cec5SDimitry Andric return p; 1390b57cec5SDimitry Andric} 1400b57cec5SDimitry Andric 1410b57cec5SDimitry AndricINTERCEPTOR(void, free, void *ptr) { 1420b57cec5SDimitry Andric COMMON_MALLOC_ENTER(); 1430b57cec5SDimitry Andric if (!ptr) return; 1440b57cec5SDimitry Andric COMMON_MALLOC_FREE(ptr); 1450b57cec5SDimitry Andric} 1460b57cec5SDimitry Andric 1470b57cec5SDimitry AndricINTERCEPTOR(void *, realloc, void *ptr, size_t size) { 1480b57cec5SDimitry Andric COMMON_MALLOC_ENTER(); 1490b57cec5SDimitry Andric COMMON_MALLOC_REALLOC(ptr, size); 1500b57cec5SDimitry Andric return p; 1510b57cec5SDimitry Andric} 1520b57cec5SDimitry Andric 1530b57cec5SDimitry AndricINTERCEPTOR(void *, calloc, size_t nmemb, size_t size) { 1540b57cec5SDimitry Andric COMMON_MALLOC_ENTER(); 1550b57cec5SDimitry Andric COMMON_MALLOC_CALLOC(nmemb, size); 1560b57cec5SDimitry Andric return p; 1570b57cec5SDimitry Andric} 1580b57cec5SDimitry Andric 1590b57cec5SDimitry AndricINTERCEPTOR(void *, valloc, size_t size) { 1600b57cec5SDimitry Andric COMMON_MALLOC_ENTER(); 1610b57cec5SDimitry Andric COMMON_MALLOC_VALLOC(size); 1620b57cec5SDimitry Andric return p; 1630b57cec5SDimitry Andric} 1640b57cec5SDimitry Andric 1650b57cec5SDimitry AndricINTERCEPTOR(size_t, malloc_good_size, size_t size) { 1660b57cec5SDimitry Andric COMMON_MALLOC_ENTER(); 1670b57cec5SDimitry Andric return sanitizer_zone.introspect->good_size(&sanitizer_zone, size); 1680b57cec5SDimitry Andric} 1690b57cec5SDimitry Andric 1700b57cec5SDimitry AndricINTERCEPTOR(int, posix_memalign, void **memptr, size_t alignment, size_t size) { 1710b57cec5SDimitry Andric COMMON_MALLOC_ENTER(); 1720b57cec5SDimitry Andric CHECK(memptr); 1730b57cec5SDimitry Andric COMMON_MALLOC_POSIX_MEMALIGN(memptr, alignment, size); 1740b57cec5SDimitry Andric return res; 1750b57cec5SDimitry Andric} 1760b57cec5SDimitry Andric 1770b57cec5SDimitry Andricnamespace { 1780b57cec5SDimitry Andric 1790b57cec5SDimitry Andric// TODO(glider): the __sanitizer_mz_* functions should be united with the Linux 1800b57cec5SDimitry Andric// wrappers, as they are basically copied from there. 1810b57cec5SDimitry Andricextern "C" 1820b57cec5SDimitry AndricSANITIZER_INTERFACE_ATTRIBUTE 1830b57cec5SDimitry Andricsize_t __sanitizer_mz_size(malloc_zone_t* zone, const void* ptr) { 1840b57cec5SDimitry Andric COMMON_MALLOC_SIZE(ptr); 1850b57cec5SDimitry Andric return size; 1860b57cec5SDimitry Andric} 1870b57cec5SDimitry Andric 1880b57cec5SDimitry Andricextern "C" 1890b57cec5SDimitry AndricSANITIZER_INTERFACE_ATTRIBUTE 1900b57cec5SDimitry Andricvoid *__sanitizer_mz_malloc(malloc_zone_t *zone, uptr size) { 1910b57cec5SDimitry Andric COMMON_MALLOC_ENTER(); 1920b57cec5SDimitry Andric COMMON_MALLOC_MALLOC(size); 1930b57cec5SDimitry Andric return p; 1940b57cec5SDimitry Andric} 1950b57cec5SDimitry Andric 196349cc55cSDimitry Andricstruct DlsymAlloc : public DlSymAllocator<DlsymAlloc> { 197349cc55cSDimitry Andric static bool UseImpl() { return !COMMON_MALLOC_SANITIZER_INITIALIZED; } 198349cc55cSDimitry Andric}; 199349cc55cSDimitry Andric 2000b57cec5SDimitry Andricextern "C" 2010b57cec5SDimitry AndricSANITIZER_INTERFACE_ATTRIBUTE 2020b57cec5SDimitry Andricvoid *__sanitizer_mz_calloc(malloc_zone_t *zone, size_t nmemb, size_t size) { 203349cc55cSDimitry Andric if (DlsymAlloc::Use()) 204349cc55cSDimitry Andric return DlsymAlloc::Callocate(nmemb, size); 2050b57cec5SDimitry Andric COMMON_MALLOC_CALLOC(nmemb, size); 2060b57cec5SDimitry Andric return p; 2070b57cec5SDimitry Andric} 2080b57cec5SDimitry Andric 2090b57cec5SDimitry Andricextern "C" 2100b57cec5SDimitry AndricSANITIZER_INTERFACE_ATTRIBUTE 2110b57cec5SDimitry Andricvoid *__sanitizer_mz_valloc(malloc_zone_t *zone, size_t size) { 2120b57cec5SDimitry Andric COMMON_MALLOC_ENTER(); 2130b57cec5SDimitry Andric COMMON_MALLOC_VALLOC(size); 2140b57cec5SDimitry Andric return p; 2150b57cec5SDimitry Andric} 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric// TODO(glider): the allocation callbacks need to be refactored. 2180b57cec5SDimitry Andricextern "C" 2190b57cec5SDimitry AndricSANITIZER_INTERFACE_ATTRIBUTE 2200b57cec5SDimitry Andricvoid __sanitizer_mz_free(malloc_zone_t *zone, void *ptr) { 2210b57cec5SDimitry Andric if (!ptr) return; 222349cc55cSDimitry Andric if (DlsymAlloc::PointerIsMine(ptr)) 223349cc55cSDimitry Andric return DlsymAlloc::Free(ptr); 2240b57cec5SDimitry Andric COMMON_MALLOC_FREE(ptr); 2250b57cec5SDimitry Andric} 2260b57cec5SDimitry Andric 2270b57cec5SDimitry Andric#define GET_ZONE_FOR_PTR(ptr) \ 22868d75effSDimitry Andric malloc_zone_t *zone_ptr = WRAP(malloc_zone_from_ptr)(ptr); \ 2290b57cec5SDimitry Andric const char *zone_name = (zone_ptr == 0) ? 0 : zone_ptr->zone_name 2300b57cec5SDimitry Andric 2310b57cec5SDimitry Andricextern "C" 2320b57cec5SDimitry AndricSANITIZER_INTERFACE_ATTRIBUTE 2330b57cec5SDimitry Andricvoid *__sanitizer_mz_realloc(malloc_zone_t *zone, void *ptr, size_t new_size) { 2340b57cec5SDimitry Andric if (!ptr) { 2350b57cec5SDimitry Andric COMMON_MALLOC_MALLOC(new_size); 2360b57cec5SDimitry Andric return p; 2370b57cec5SDimitry Andric } else { 2380b57cec5SDimitry Andric COMMON_MALLOC_SIZE(ptr); 2390b57cec5SDimitry Andric if (size) { 2400b57cec5SDimitry Andric COMMON_MALLOC_REALLOC(ptr, new_size); 2410b57cec5SDimitry Andric return p; 2420b57cec5SDimitry Andric } else { 2430b57cec5SDimitry Andric // We can't recover from reallocating an unknown address, because 2440b57cec5SDimitry Andric // this would require reading at most |new_size| bytes from 2450b57cec5SDimitry Andric // potentially unaccessible memory. 2460b57cec5SDimitry Andric GET_ZONE_FOR_PTR(ptr); 2470b57cec5SDimitry Andric COMMON_MALLOC_REPORT_UNKNOWN_REALLOC(ptr, zone_ptr, zone_name); 2480b57cec5SDimitry Andric return nullptr; 2490b57cec5SDimitry Andric } 2500b57cec5SDimitry Andric } 2510b57cec5SDimitry Andric} 2520b57cec5SDimitry Andric 2530b57cec5SDimitry Andricextern "C" 2540b57cec5SDimitry AndricSANITIZER_INTERFACE_ATTRIBUTE 2550b57cec5SDimitry Andricvoid __sanitizer_mz_destroy(malloc_zone_t* zone) { 2560b57cec5SDimitry Andric // A no-op -- we will not be destroyed! 2570b57cec5SDimitry Andric Report("__sanitizer_mz_destroy() called -- ignoring\n"); 2580b57cec5SDimitry Andric} 2590b57cec5SDimitry Andric 2600b57cec5SDimitry Andricextern "C" 2610b57cec5SDimitry AndricSANITIZER_INTERFACE_ATTRIBUTE 2620b57cec5SDimitry Andricvoid *__sanitizer_mz_memalign(malloc_zone_t *zone, size_t align, size_t size) { 2630b57cec5SDimitry Andric COMMON_MALLOC_ENTER(); 2640b57cec5SDimitry Andric COMMON_MALLOC_MEMALIGN(align, size); 2650b57cec5SDimitry Andric return p; 2660b57cec5SDimitry Andric} 2670b57cec5SDimitry Andric 2680b57cec5SDimitry Andric// This public API exists purely for testing purposes. 2690b57cec5SDimitry Andricextern "C" 2700b57cec5SDimitry AndricSANITIZER_INTERFACE_ATTRIBUTE 2710b57cec5SDimitry Andricmalloc_zone_t* __sanitizer_mz_default_zone() { 2720b57cec5SDimitry Andric return &sanitizer_zone; 2730b57cec5SDimitry Andric} 2740b57cec5SDimitry Andric 2750b57cec5SDimitry Andric// This function is currently unused, and we build with -Werror. 2760b57cec5SDimitry Andric#if 0 2770b57cec5SDimitry Andricvoid __sanitizer_mz_free_definite_size( 2780b57cec5SDimitry Andric malloc_zone_t* zone, void *ptr, size_t size) { 2790b57cec5SDimitry Andric // TODO(glider): check that |size| is valid. 2800b57cec5SDimitry Andric UNIMPLEMENTED(); 2810b57cec5SDimitry Andric} 2820b57cec5SDimitry Andric#endif 2830b57cec5SDimitry Andric 2840b57cec5SDimitry Andric#ifndef COMMON_MALLOC_HAS_ZONE_ENUMERATOR 2850b57cec5SDimitry Andric#error "COMMON_MALLOC_HAS_ZONE_ENUMERATOR must be defined" 2860b57cec5SDimitry Andric#endif 2870b57cec5SDimitry Andricstatic_assert((COMMON_MALLOC_HAS_ZONE_ENUMERATOR) == 0 || 2880b57cec5SDimitry Andric (COMMON_MALLOC_HAS_ZONE_ENUMERATOR) == 1, 2890b57cec5SDimitry Andric "COMMON_MALLOC_HAS_ZONE_ENUMERATOR must be 0 or 1"); 2900b57cec5SDimitry Andric 2910b57cec5SDimitry Andric#if COMMON_MALLOC_HAS_ZONE_ENUMERATOR 2920b57cec5SDimitry Andric// Forward declare and expect the implementation to provided by 2930b57cec5SDimitry Andric// includer. 2940b57cec5SDimitry Andrickern_return_t mi_enumerator(task_t task, void *, unsigned type_mask, 2950b57cec5SDimitry Andric vm_address_t zone_address, memory_reader_t reader, 2960b57cec5SDimitry Andric vm_range_recorder_t recorder); 2970b57cec5SDimitry Andric#else 2980b57cec5SDimitry Andric// Provide stub implementation that fails. 2990b57cec5SDimitry Andrickern_return_t mi_enumerator(task_t task, void *, unsigned type_mask, 3000b57cec5SDimitry Andric vm_address_t zone_address, memory_reader_t reader, 3010b57cec5SDimitry Andric vm_range_recorder_t recorder) { 3020b57cec5SDimitry Andric // Not supported. 3030b57cec5SDimitry Andric return KERN_FAILURE; 3040b57cec5SDimitry Andric} 3050b57cec5SDimitry Andric#endif 3060b57cec5SDimitry Andric 3070b57cec5SDimitry Andric#ifndef COMMON_MALLOC_HAS_EXTRA_INTROSPECTION_INIT 3080b57cec5SDimitry Andric#error "COMMON_MALLOC_HAS_EXTRA_INTROSPECTION_INIT must be defined" 3090b57cec5SDimitry Andric#endif 3100b57cec5SDimitry Andricstatic_assert((COMMON_MALLOC_HAS_EXTRA_INTROSPECTION_INIT) == 0 || 3110b57cec5SDimitry Andric (COMMON_MALLOC_HAS_EXTRA_INTROSPECTION_INIT) == 1, 3120b57cec5SDimitry Andric "COMMON_MALLOC_HAS_EXTRA_INTROSPECTION_INIT must be 0 or 1"); 3130b57cec5SDimitry Andric#if COMMON_MALLOC_HAS_EXTRA_INTROSPECTION_INIT 3140b57cec5SDimitry Andric// Forward declare and expect the implementation to provided by 3150b57cec5SDimitry Andric// includer. 3160b57cec5SDimitry Andricvoid mi_extra_init( 3170b57cec5SDimitry Andric sanitizer_malloc_introspection_t *mi); 3180b57cec5SDimitry Andric#else 3190b57cec5SDimitry Andricvoid mi_extra_init( 3200b57cec5SDimitry Andric sanitizer_malloc_introspection_t *mi) { 3210b57cec5SDimitry Andric // Just zero initialize the fields. 3220b57cec5SDimitry Andric mi->allocator_ptr = 0; 3230b57cec5SDimitry Andric mi->allocator_size = 0; 3240b57cec5SDimitry Andric} 3250b57cec5SDimitry Andric#endif 3260b57cec5SDimitry Andric 3270b57cec5SDimitry Andricsize_t mi_good_size(malloc_zone_t *zone, size_t size) { 3280b57cec5SDimitry Andric // I think it's always safe to return size, but we maybe could do better. 3290b57cec5SDimitry Andric return size; 3300b57cec5SDimitry Andric} 3310b57cec5SDimitry Andric 3320b57cec5SDimitry Andricboolean_t mi_check(malloc_zone_t *zone) { 3330b57cec5SDimitry Andric UNIMPLEMENTED(); 3340b57cec5SDimitry Andric} 3350b57cec5SDimitry Andric 3360b57cec5SDimitry Andricvoid mi_print(malloc_zone_t *zone, boolean_t verbose) { 3370b57cec5SDimitry Andric UNIMPLEMENTED(); 3380b57cec5SDimitry Andric} 3390b57cec5SDimitry Andric 3400b57cec5SDimitry Andricvoid mi_log(malloc_zone_t *zone, void *address) { 3410b57cec5SDimitry Andric // I don't think we support anything like this 3420b57cec5SDimitry Andric} 3430b57cec5SDimitry Andric 3440b57cec5SDimitry Andricvoid mi_force_lock(malloc_zone_t *zone) { 3450b57cec5SDimitry Andric COMMON_MALLOC_FORCE_LOCK(); 3460b57cec5SDimitry Andric} 3470b57cec5SDimitry Andric 3480b57cec5SDimitry Andricvoid mi_force_unlock(malloc_zone_t *zone) { 3490b57cec5SDimitry Andric COMMON_MALLOC_FORCE_UNLOCK(); 3500b57cec5SDimitry Andric} 3510b57cec5SDimitry Andric 3520b57cec5SDimitry Andricvoid mi_statistics(malloc_zone_t *zone, malloc_statistics_t *stats) { 3530b57cec5SDimitry Andric COMMON_MALLOC_FILL_STATS(zone, stats); 3540b57cec5SDimitry Andric} 3550b57cec5SDimitry Andric 3560b57cec5SDimitry Andricboolean_t mi_zone_locked(malloc_zone_t *zone) { 3570b57cec5SDimitry Andric // UNIMPLEMENTED(); 3580b57cec5SDimitry Andric return false; 3590b57cec5SDimitry Andric} 3600b57cec5SDimitry Andric 3610b57cec5SDimitry Andric} // unnamed namespace 3620b57cec5SDimitry Andric 3630b57cec5SDimitry Andricnamespace COMMON_MALLOC_NAMESPACE { 3640b57cec5SDimitry Andric 3650b57cec5SDimitry Andricvoid InitMallocZoneFields() { 3660b57cec5SDimitry Andric static sanitizer_malloc_introspection_t sanitizer_zone_introspection; 3670b57cec5SDimitry Andric // Ok to use internal_memset, these places are not performance-critical. 3680b57cec5SDimitry Andric internal_memset(&sanitizer_zone_introspection, 0, 3690b57cec5SDimitry Andric sizeof(sanitizer_zone_introspection)); 3700b57cec5SDimitry Andric 3710b57cec5SDimitry Andric sanitizer_zone_introspection.enumerator = &mi_enumerator; 3720b57cec5SDimitry Andric sanitizer_zone_introspection.good_size = &mi_good_size; 3730b57cec5SDimitry Andric sanitizer_zone_introspection.check = &mi_check; 3740b57cec5SDimitry Andric sanitizer_zone_introspection.print = &mi_print; 3750b57cec5SDimitry Andric sanitizer_zone_introspection.log = &mi_log; 3760b57cec5SDimitry Andric sanitizer_zone_introspection.force_lock = &mi_force_lock; 3770b57cec5SDimitry Andric sanitizer_zone_introspection.force_unlock = &mi_force_unlock; 3780b57cec5SDimitry Andric sanitizer_zone_introspection.statistics = &mi_statistics; 3790b57cec5SDimitry Andric sanitizer_zone_introspection.zone_locked = &mi_zone_locked; 3800b57cec5SDimitry Andric 3810b57cec5SDimitry Andric // Set current allocator enumeration version. 3820b57cec5SDimitry Andric sanitizer_zone_introspection.allocator_enumeration_version = 3830b57cec5SDimitry Andric GetMallocZoneAllocatorEnumerationVersion(); 3840b57cec5SDimitry Andric 3850b57cec5SDimitry Andric // Perform any sanitizer specific initialization. 3860b57cec5SDimitry Andric mi_extra_init(&sanitizer_zone_introspection); 3870b57cec5SDimitry Andric 3880b57cec5SDimitry Andric internal_memset(&sanitizer_zone, 0, sizeof(malloc_zone_t)); 3890b57cec5SDimitry Andric 3900b57cec5SDimitry Andric // Use version 6 for OSX >= 10.6. 3910b57cec5SDimitry Andric sanitizer_zone.version = 6; 3920b57cec5SDimitry Andric sanitizer_zone.zone_name = COMMON_MALLOC_ZONE_NAME; 3930b57cec5SDimitry Andric sanitizer_zone.size = &__sanitizer_mz_size; 3940b57cec5SDimitry Andric sanitizer_zone.malloc = &__sanitizer_mz_malloc; 3950b57cec5SDimitry Andric sanitizer_zone.calloc = &__sanitizer_mz_calloc; 3960b57cec5SDimitry Andric sanitizer_zone.valloc = &__sanitizer_mz_valloc; 3970b57cec5SDimitry Andric sanitizer_zone.free = &__sanitizer_mz_free; 3980b57cec5SDimitry Andric sanitizer_zone.realloc = &__sanitizer_mz_realloc; 3990b57cec5SDimitry Andric sanitizer_zone.destroy = &__sanitizer_mz_destroy; 4000b57cec5SDimitry Andric sanitizer_zone.batch_malloc = 0; 4010b57cec5SDimitry Andric sanitizer_zone.batch_free = 0; 4020b57cec5SDimitry Andric sanitizer_zone.free_definite_size = 0; 4030b57cec5SDimitry Andric sanitizer_zone.memalign = &__sanitizer_mz_memalign; 4040b57cec5SDimitry Andric sanitizer_zone.introspect = &sanitizer_zone_introspection; 4050b57cec5SDimitry Andric} 4060b57cec5SDimitry Andric 4070b57cec5SDimitry Andricvoid ReplaceSystemMalloc() { 4080b57cec5SDimitry Andric InitMallocZoneFields(); 4090b57cec5SDimitry Andric 4100b57cec5SDimitry Andric // Register the zone. 4110b57cec5SDimitry Andric malloc_zone_register(&sanitizer_zone); 4120b57cec5SDimitry Andric} 4130b57cec5SDimitry Andric 4140b57cec5SDimitry Andric} // namespace COMMON_MALLOC_NAMESPACE 415