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