163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris/* 263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * Copyright (C) 2009 The Android Open Source Project 363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * All rights reserved. 463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * 563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * Redistribution and use in source and binary forms, with or without 663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * modification, are permitted provided that the following conditions 763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * are met: 863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * * Redistributions of source code must retain the above copyright 963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * notice, this list of conditions and the following disclaimer. 1063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * * Redistributions in binary form must reproduce the above copyright 1163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * notice, this list of conditions and the following disclaimer in 1263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * the documentation and/or other materials provided with the 1363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * distribution. 1463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * 1563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 1863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 1963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 2063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 2163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 2263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 2363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 2463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 2563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * SUCH DAMAGE. 2763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris */ 2863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 2963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// Contains a thin layer that calls whatever real native allocator 3063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// has been defined. For the libc shared library, this allows the 3163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// implementation of a debug malloc that can intercept all of the allocation 3263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// calls and add special debugging code to attempt to catch allocation 3363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// errors. All of the debugging code is implemented in a separate shared 3463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// library that is only loaded when the property "libc.debug.malloc.options" 3563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// is set to a non-zero value. There are two functions exported to 3663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// allow ddms, or other external users to get information from the debug 3763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// allocation. 3863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// get_malloc_leak_info: Returns information about all of the known native 3963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// allocations that are currently in use. 4063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// free_malloc_leak_info: Frees the data allocated by the call to 4163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// get_malloc_leak_info. 4263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 43869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross#include <pthread.h> 44869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross 4563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris#include <private/bionic_config.h> 4663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris#include <private/bionic_globals.h> 4763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris#include <private/bionic_malloc_dispatch.h> 4863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 4963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris#include "jemalloc.h" 5063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris#define Malloc(function) je_ ## function 5163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 5263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferrisstatic constexpr MallocDispatch __libc_malloc_default_dispatch 5363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris __attribute__((unused)) = { 5463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris Malloc(calloc), 5563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris Malloc(free), 5663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris Malloc(mallinfo), 5763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris Malloc(malloc), 5863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris Malloc(malloc_usable_size), 5963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris Malloc(memalign), 6063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris Malloc(posix_memalign), 6163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris#if defined(HAVE_DEPRECATED_MALLOC_FUNCS) 6263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris Malloc(pvalloc), 6363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris#endif 6463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris Malloc(realloc), 6563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris#if defined(HAVE_DEPRECATED_MALLOC_FUNCS) 6663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris Malloc(valloc), 6763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris#endif 68869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross Malloc(iterate), 69869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross Malloc(malloc_disable), 70869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross Malloc(malloc_enable), 71a1c0d2fd4ce96e123c4ae6506c9d637d747e1fe2Christopher Ferris Malloc(mallopt), 72d69ee59594088c0d92ba9273188ef53ea5e6cd6aChristopher Ferris Malloc(aligned_alloc), 7363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris }; 7463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 75d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris// Malloc hooks. 76d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferrisvoid* (*volatile __malloc_hook)(size_t, const void*); 77d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferrisvoid* (*volatile __realloc_hook)(void*, size_t, const void*); 78d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferrisvoid (*volatile __free_hook)(void*, const void*); 79d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferrisvoid* (*volatile __memalign_hook)(size_t, size_t, const void*); 80d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris 8163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// In a VM process, this is set to 1 after fork()ing out of zygote. 8263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferrisint gMallocLeakZygoteChild = 0; 8363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 8463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// ============================================================================= 8563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// Allocation functions 8663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// ============================================================================= 8763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferrisextern "C" void* calloc(size_t n_elements, size_t elem_size) { 8863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris auto _calloc = __libc_globals->malloc_dispatch.calloc; 8963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris if (__predict_false(_calloc != nullptr)) { 9063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris return _calloc(n_elements, elem_size); 9163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris } 9263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris return Malloc(calloc)(n_elements, elem_size); 9363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris} 9463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 9563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferrisextern "C" void free(void* mem) { 9663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris auto _free = __libc_globals->malloc_dispatch.free; 9763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris if (__predict_false(_free != nullptr)) { 9863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris _free(mem); 9963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris } else { 10063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris Malloc(free)(mem); 10163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris } 10263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris} 10363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 10463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferrisextern "C" struct mallinfo mallinfo() { 10563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris auto _mallinfo = __libc_globals->malloc_dispatch.mallinfo; 10663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris if (__predict_false(_mallinfo != nullptr)) { 10763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris return _mallinfo(); 10863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris } 10963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris return Malloc(mallinfo)(); 11063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris} 11163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 112a1c0d2fd4ce96e123c4ae6506c9d637d747e1fe2Christopher Ferrisextern "C" int mallopt(int param, int value) { 113a1c0d2fd4ce96e123c4ae6506c9d637d747e1fe2Christopher Ferris auto _mallopt = __libc_globals->malloc_dispatch.mallopt; 114a1c0d2fd4ce96e123c4ae6506c9d637d747e1fe2Christopher Ferris if (__predict_false(_mallopt != nullptr)) { 115a1c0d2fd4ce96e123c4ae6506c9d637d747e1fe2Christopher Ferris return _mallopt(param, value); 116a1c0d2fd4ce96e123c4ae6506c9d637d747e1fe2Christopher Ferris } 117a1c0d2fd4ce96e123c4ae6506c9d637d747e1fe2Christopher Ferris return Malloc(mallopt)(param, value); 118a1c0d2fd4ce96e123c4ae6506c9d637d747e1fe2Christopher Ferris} 119a1c0d2fd4ce96e123c4ae6506c9d637d747e1fe2Christopher Ferris 12063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferrisextern "C" void* malloc(size_t bytes) { 12163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris auto _malloc = __libc_globals->malloc_dispatch.malloc; 12263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris if (__predict_false(_malloc != nullptr)) { 12363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris return _malloc(bytes); 12463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris } 12563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris return Malloc(malloc)(bytes); 12663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris} 12763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 12863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferrisextern "C" size_t malloc_usable_size(const void* mem) { 12963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris auto _malloc_usable_size = __libc_globals->malloc_dispatch.malloc_usable_size; 13063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris if (__predict_false(_malloc_usable_size != nullptr)) { 13163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris return _malloc_usable_size(mem); 13263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris } 13363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris return Malloc(malloc_usable_size)(mem); 13463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris} 13563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 13663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferrisextern "C" void* memalign(size_t alignment, size_t bytes) { 13763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris auto _memalign = __libc_globals->malloc_dispatch.memalign; 13863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris if (__predict_false(_memalign != nullptr)) { 13963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris return _memalign(alignment, bytes); 14063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris } 14163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris return Malloc(memalign)(alignment, bytes); 14263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris} 14363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 14463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferrisextern "C" int posix_memalign(void** memptr, size_t alignment, size_t size) { 14563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris auto _posix_memalign = __libc_globals->malloc_dispatch.posix_memalign; 14663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris if (__predict_false(_posix_memalign != nullptr)) { 14763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris return _posix_memalign(memptr, alignment, size); 14863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris } 14963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris return Malloc(posix_memalign)(memptr, alignment, size); 15063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris} 15163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 152d69ee59594088c0d92ba9273188ef53ea5e6cd6aChristopher Ferrisextern "C" void* aligned_alloc(size_t alignment, size_t size) { 153d69ee59594088c0d92ba9273188ef53ea5e6cd6aChristopher Ferris auto _aligned_alloc = __libc_globals->malloc_dispatch.aligned_alloc; 154d69ee59594088c0d92ba9273188ef53ea5e6cd6aChristopher Ferris if (__predict_false(_aligned_alloc != nullptr)) { 155d69ee59594088c0d92ba9273188ef53ea5e6cd6aChristopher Ferris return _aligned_alloc(alignment, size); 156d69ee59594088c0d92ba9273188ef53ea5e6cd6aChristopher Ferris } 157d69ee59594088c0d92ba9273188ef53ea5e6cd6aChristopher Ferris return Malloc(aligned_alloc)(alignment, size); 158d69ee59594088c0d92ba9273188ef53ea5e6cd6aChristopher Ferris} 159d69ee59594088c0d92ba9273188ef53ea5e6cd6aChristopher Ferris 16063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferrisextern "C" void* realloc(void* old_mem, size_t bytes) { 16163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris auto _realloc = __libc_globals->malloc_dispatch.realloc; 16263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris if (__predict_false(_realloc != nullptr)) { 16363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris return _realloc(old_mem, bytes); 16463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris } 16563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris return Malloc(realloc)(old_mem, bytes); 16663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris} 16763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 16863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris#if defined(HAVE_DEPRECATED_MALLOC_FUNCS) 16963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferrisextern "C" void* pvalloc(size_t bytes) { 17063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris auto _pvalloc = __libc_globals->malloc_dispatch.pvalloc; 17163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris if (__predict_false(_pvalloc != nullptr)) { 17263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris return _pvalloc(bytes); 17363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris } 17463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris return Malloc(pvalloc)(bytes); 17563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris} 17663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 17763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferrisextern "C" void* valloc(size_t bytes) { 17863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris auto _valloc = __libc_globals->malloc_dispatch.valloc; 17963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris if (__predict_false(_valloc != nullptr)) { 18063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris return _valloc(bytes); 18163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris } 18263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris return Malloc(valloc)(bytes); 18363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris} 18463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris#endif 18563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 18663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// We implement malloc debugging only in libc.so, so the code below 18763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// must be excluded if we compile this file for static libc.a 18863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris#if !defined(LIBC_STATIC) 18963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 19063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris#include <dlfcn.h> 19163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris#include <stdio.h> 19263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris#include <stdlib.h> 19363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 1947a3681e5b6c39bc2b3b62031ca5941dbf7bc4e63Christopher Ferris#include <async_safe/log.h> 19563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris#include <sys/system_properties.h> 19663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 19763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferrisextern "C" int __cxa_atexit(void (*func)(void *), void *arg, void *dso); 19863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 199d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferrisstatic const char* HOOKS_SHARED_LIB = "libc_malloc_hooks.so"; 200d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferrisstatic const char* HOOKS_PROPERTY_ENABLE = "libc.debug.hooks.enable"; 201d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferrisstatic const char* HOOKS_ENV_ENABLE = "LIBC_HOOKS_ENABLE"; 20263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 203d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferrisstatic const char* DEBUG_SHARED_LIB = "libc_malloc_debug.so"; 204d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferrisstatic const char* DEBUG_PROPERTY_OPTIONS = "libc.debug.malloc.options"; 205d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferrisstatic const char* DEBUG_PROPERTY_PROGRAM = "libc.debug.malloc.program"; 206d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferrisstatic const char* DEBUG_ENV_OPTIONS = "LIBC_DEBUG_MALLOC_OPTIONS"; 207d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris 208d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferrisenum FunctionEnum : uint8_t { 209d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris FUNC_INITIALIZE, 210d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris FUNC_FINALIZE, 211d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris FUNC_GET_MALLOC_LEAK_INFO, 212d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris FUNC_FREE_MALLOC_LEAK_INFO, 213d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris FUNC_MALLOC_BACKTRACE, 214d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris FUNC_LAST, 215d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris}; 216d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferrisstatic void* g_functions[FUNC_LAST]; 217d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris 218d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferristypedef void (*finalize_func_t)(); 219d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferristypedef bool (*init_func_t)(const MallocDispatch*, int*, const char*); 220d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferristypedef void (*get_malloc_leak_info_func_t)(uint8_t**, size_t*, size_t*, size_t*, size_t*); 221d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferristypedef void (*free_malloc_leak_info_func_t)(uint8_t*); 222d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferristypedef ssize_t (*malloc_backtrace_func_t)(void*, uintptr_t*, size_t); 22363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 22463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// ============================================================================= 22563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// Log functions 22663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// ============================================================================= 22763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris#define error_log(format, ...) \ 2287a3681e5b6c39bc2b3b62031ca5941dbf7bc4e63Christopher Ferris async_safe_format_log(ANDROID_LOG_ERROR, "libc", (format), ##__VA_ARGS__ ) 22963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris#define info_log(format, ...) \ 2307a3681e5b6c39bc2b3b62031ca5941dbf7bc4e63Christopher Ferris async_safe_format_log(ANDROID_LOG_INFO, "libc", (format), ##__VA_ARGS__ ) 23163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// ============================================================================= 23263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 23363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// ============================================================================= 23463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// Exported for use by ddms. 23563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// ============================================================================= 23663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 23763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// Retrieve native heap information. 23863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// 23963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// "*info" is set to a buffer we allocate 24063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// "*overall_size" is set to the size of the "info" buffer 24163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// "*info_size" is set to the size of a single entry 24263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// "*total_memory" is set to the sum of all allocations we're tracking; does 24363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// not include heap overhead 24463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// "*backtrace_size" is set to the maximum number of entries in the back trace 24563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferrisextern "C" void get_malloc_leak_info(uint8_t** info, size_t* overall_size, 24663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris size_t* info_size, size_t* total_memory, size_t* backtrace_size) { 247d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris void* func = g_functions[FUNC_GET_MALLOC_LEAK_INFO]; 248d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris if (func == nullptr) { 24963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris return; 25063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris } 251d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris reinterpret_cast<get_malloc_leak_info_func_t>(func)(info, overall_size, info_size, total_memory, 252d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris backtrace_size); 25363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris} 25463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 25563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferrisextern "C" void free_malloc_leak_info(uint8_t* info) { 256d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris void* func = g_functions[FUNC_FREE_MALLOC_LEAK_INFO]; 257d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris if (func == nullptr) { 25863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris return; 25963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris } 260d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris reinterpret_cast<free_malloc_leak_info_func_t>(func)(info); 26163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris} 262869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross 26363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// ============================================================================= 26463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 26563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferristemplate<typename FunctionType> 26663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferrisstatic bool InitMallocFunction(void* malloc_impl_handler, FunctionType* func, const char* prefix, const char* suffix) { 26763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris char symbol[128]; 26863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris snprintf(symbol, sizeof(symbol), "%s_%s", prefix, suffix); 26963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris *func = reinterpret_cast<FunctionType>(dlsym(malloc_impl_handler, symbol)); 27063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris if (*func == nullptr) { 27163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris error_log("%s: dlsym(\"%s\") failed", getprogname(), symbol); 27263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris return false; 27363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris } 27463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris return true; 27563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris} 27663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 277d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferrisstatic bool InitMallocFunctions(void* impl_handler, MallocDispatch* table, const char* prefix) { 278d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris if (!InitMallocFunction<MallocCalloc>(impl_handler, &table->calloc, prefix, "calloc")) { 27963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris return false; 28063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris } 281d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris if (!InitMallocFunction<MallocFree>(impl_handler, &table->free, prefix, "free")) { 28263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris return false; 28363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris } 284d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris if (!InitMallocFunction<MallocMallinfo>(impl_handler, &table->mallinfo, prefix, "mallinfo")) { 28563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris return false; 28663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris } 287d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris if (!InitMallocFunction<MallocMallopt>(impl_handler, &table->mallopt, prefix, "mallopt")) { 288a1c0d2fd4ce96e123c4ae6506c9d637d747e1fe2Christopher Ferris return false; 289a1c0d2fd4ce96e123c4ae6506c9d637d747e1fe2Christopher Ferris } 290d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris if (!InitMallocFunction<MallocMalloc>(impl_handler, &table->malloc, prefix, "malloc")) { 29163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris return false; 29263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris } 293d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris if (!InitMallocFunction<MallocMallocUsableSize>(impl_handler, &table->malloc_usable_size, prefix, 294d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris "malloc_usable_size")) { 29563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris return false; 29663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris } 297d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris if (!InitMallocFunction<MallocMemalign>(impl_handler, &table->memalign, prefix, "memalign")) { 29863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris return false; 29963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris } 300d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris if (!InitMallocFunction<MallocPosixMemalign>(impl_handler, &table->posix_memalign, prefix, 301d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris "posix_memalign")) { 30263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris return false; 30363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris } 304d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris if (!InitMallocFunction<MallocAlignedAlloc>(impl_handler, &table->aligned_alloc, 305d69ee59594088c0d92ba9273188ef53ea5e6cd6aChristopher Ferris prefix, "aligned_alloc")) { 306d69ee59594088c0d92ba9273188ef53ea5e6cd6aChristopher Ferris return false; 307d69ee59594088c0d92ba9273188ef53ea5e6cd6aChristopher Ferris } 308d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris if (!InitMallocFunction<MallocRealloc>(impl_handler, &table->realloc, prefix, "realloc")) { 30963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris return false; 31063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris } 311d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris if (!InitMallocFunction<MallocIterate>(impl_handler, &table->iterate, prefix, "iterate")) { 312869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross return false; 313869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross } 314d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris if (!InitMallocFunction<MallocMallocDisable>(impl_handler, &table->malloc_disable, prefix, 315d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris "malloc_disable")) { 316869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross return false; 317869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross } 318d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris if (!InitMallocFunction<MallocMallocEnable>(impl_handler, &table->malloc_enable, prefix, 319d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris "malloc_enable")) { 320869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross return false; 321869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross } 32263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris#if defined(HAVE_DEPRECATED_MALLOC_FUNCS) 323d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris if (!InitMallocFunction<MallocPvalloc>(impl_handler, &table->pvalloc, prefix, "pvalloc")) { 32463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris return false; 32563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris } 326d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris if (!InitMallocFunction<MallocValloc>(impl_handler, &table->valloc, prefix, "valloc")) { 32763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris return false; 32863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris } 32963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris#endif 33063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 33163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris return true; 33263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris} 33363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 33463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferrisstatic void malloc_fini_impl(void*) { 33563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris // Our BSD stdio implementation doesn't close the standard streams, 33663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris // it only flushes them. Other unclosed FILE*s will show up as 33763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris // malloc leaks, but to avoid the standard streams showing up in 33863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris // leak reports, close them here. 33963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris fclose(stdin); 34063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris fclose(stdout); 34163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris fclose(stderr); 34263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 343d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris reinterpret_cast<finalize_func_t>(g_functions[FUNC_FINALIZE])(); 34463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris} 34563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 346d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferrisstatic bool CheckLoadMallocHooks(char** options) { 347d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris char* env = getenv(HOOKS_ENV_ENABLE); 348d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris if ((env == nullptr || env[0] == '\0' || env[0] == '0') && 349d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris (__system_property_get(HOOKS_PROPERTY_ENABLE, *options) == 0 || *options[0] == '\0' || *options[0] == '0')) { 350d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris return false; 351d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris } 352d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris *options = nullptr; 353d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris return true; 354d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris} 35563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 356d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferrisstatic bool CheckLoadMallocDebug(char** options) { 357ac81fe8657119c265edcc2f05b3e5b7c5b17ae9fTamas Berghammer // If DEBUG_MALLOC_ENV_OPTIONS is set then it overrides the system properties. 358d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris char* env = getenv(DEBUG_ENV_OPTIONS); 359d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris if (env == nullptr || env[0] == '\0') { 360d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris if (__system_property_get(DEBUG_PROPERTY_OPTIONS, *options) == 0 || *options[0] == '\0') { 361d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris return false; 362ac81fe8657119c265edcc2f05b3e5b7c5b17ae9fTamas Berghammer } 36363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 364ac81fe8657119c265edcc2f05b3e5b7c5b17ae9fTamas Berghammer // Check to see if only a specific program should have debug malloc enabled. 365ac81fe8657119c265edcc2f05b3e5b7c5b17ae9fTamas Berghammer char program[PROP_VALUE_MAX]; 366d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris if (__system_property_get(DEBUG_PROPERTY_PROGRAM, program) != 0 && 367ac81fe8657119c265edcc2f05b3e5b7c5b17ae9fTamas Berghammer strstr(getprogname(), program) == nullptr) { 368d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris return false; 369ac81fe8657119c265edcc2f05b3e5b7c5b17ae9fTamas Berghammer } 370d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris } else { 371d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris *options = env; 37263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris } 373d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris return true; 374d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris} 37563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 376d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferrisstatic void ClearGlobalFunctions() { 377d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris for (size_t i = 0; i < FUNC_LAST; i++) { 378d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris g_functions[i] = nullptr; 37963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris } 380d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris} 38163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 382d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferrisstatic void* LoadSharedLibrary(const char* shared_lib, const char* prefix, MallocDispatch* dispatch_table) { 383d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris void* impl_handle = dlopen(shared_lib, RTLD_NOW | RTLD_LOCAL); 384d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris if (impl_handle == nullptr) { 385d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris error_log("%s: Unable to open shared library %s: %s", getprogname(), shared_lib, dlerror()); 386d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris return nullptr; 38763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris } 38863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 389d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris static constexpr const char* names[] = { 390d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris "initialize", 391d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris "finalize", 392d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris "get_malloc_leak_info", 393d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris "free_malloc_leak_info", 394d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris "malloc_backtrace", 395d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris }; 396d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris for (size_t i = 0; i < FUNC_LAST; i++) { 397d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris char symbol[128]; 398d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris snprintf(symbol, sizeof(symbol), "%s_%s", prefix, names[i]); 399d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris g_functions[i] = dlsym(impl_handle, symbol); 400d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris if (g_functions[i] == nullptr) { 401d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris error_log("%s: %s routine not found in %s", getprogname(), symbol, shared_lib); 402d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris dlclose(impl_handle); 403d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris ClearGlobalFunctions(); 404d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris return nullptr; 405d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris } 40663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris } 40763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 408d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris if (!InitMallocFunctions(impl_handle, dispatch_table, prefix)) { 409d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris dlclose(impl_handle); 410d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris ClearGlobalFunctions(); 411d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris return nullptr; 41263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris } 41363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 414d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris return impl_handle; 415d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris} 41663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 417d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris// Initializes memory allocation framework once per process. 418d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferrisstatic void malloc_init_impl(libc_globals* globals) { 419d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris const char* prefix; 420d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris const char* shared_lib; 421d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris char prop[PROP_VALUE_MAX]; 422d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris char* options = prop; 423d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris // Prefer malloc debug since it existed first and is a more complete 424d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris // malloc interceptor than the hooks. 425d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris if (CheckLoadMallocDebug(&options)) { 426d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris prefix = "debug"; 427d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris shared_lib = DEBUG_SHARED_LIB; 428d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris } else if (CheckLoadMallocHooks(&options)) { 429d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris prefix = "hooks"; 430d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris shared_lib = HOOKS_SHARED_LIB; 431d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris } else { 4322d4721c0c57fe2f7c1e1b40df4763a561b3cf856Colin Cross return; 4332d4721c0c57fe2f7c1e1b40df4763a561b3cf856Colin Cross } 4342d4721c0c57fe2f7c1e1b40df4763a561b3cf856Colin Cross 435d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris MallocDispatch dispatch_table; 436d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris void* impl_handle = LoadSharedLibrary(shared_lib, prefix, &dispatch_table); 437d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris if (impl_handle == nullptr) { 43863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris return; 43963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris } 44063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 441d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris init_func_t init_func = reinterpret_cast<init_func_t>(g_functions[FUNC_INITIALIZE]); 442d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris if (!init_func(&__libc_malloc_default_dispatch, &gMallocLeakZygoteChild, options)) { 443d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris dlclose(impl_handle); 444d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris ClearGlobalFunctions(); 44563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris return; 44663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris } 44763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 448d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris globals->malloc_dispatch = dispatch_table; 44963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 450d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris info_log("%s: malloc %s enabled", getprogname(), prefix); 45163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 45263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris // Use atexit to trigger the cleanup function. This avoids a problem 45363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris // where another atexit function is used to cleanup allocated memory, 45463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris // but the finalize function was already called. This particular error 45563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris // seems to be triggered by a zygote spawned process calling exit. 45663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris int ret_value = __cxa_atexit(malloc_fini_impl, nullptr, nullptr); 45763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris if (ret_value != 0) { 45863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris error_log("failed to set atexit cleanup function: %d", ret_value); 45963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris } 46063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris} 46163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris 46263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// Initializes memory allocation framework. 46363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// This routine is called from __libc_init routines in libc_init_dynamic.cpp. 46463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris__LIBC_HIDDEN__ void __libc_init_malloc(libc_globals* globals) { 46563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris malloc_init_impl(globals); 46663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris} 46763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris#endif // !LIBC_STATIC 468869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross 469869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross// ============================================================================= 470869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross// Exported for use by libmemunreachable. 471869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross// ============================================================================= 472869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross 473869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross// Calls callback for every allocation in the anonymous heap mapping 474869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross// [base, base+size). Must be called between malloc_disable and malloc_enable. 475869691c6f7691dd5bf343617aa185c32e0d3d160Colin Crossextern "C" int malloc_iterate(uintptr_t base, size_t size, 476869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross void (*callback)(uintptr_t base, size_t size, void* arg), void* arg) { 477869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross auto _iterate = __libc_globals->malloc_dispatch.iterate; 478869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross if (__predict_false(_iterate != nullptr)) { 479869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross return _iterate(base, size, callback, arg); 480869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross } 481869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross return Malloc(iterate)(base, size, callback, arg); 482869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross} 483869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross 484869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross// Disable calls to malloc so malloc_iterate gets a consistent view of 485869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross// allocated memory. 486869691c6f7691dd5bf343617aa185c32e0d3d160Colin Crossextern "C" void malloc_disable() { 487869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross auto _malloc_disable = __libc_globals->malloc_dispatch.malloc_disable; 488869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross if (__predict_false(_malloc_disable != nullptr)) { 489869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross return _malloc_disable(); 490869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross } 491869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross return Malloc(malloc_disable)(); 492869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross} 493869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross 494869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross// Re-enable calls to malloc after a previous call to malloc_disable. 495869691c6f7691dd5bf343617aa185c32e0d3d160Colin Crossextern "C" void malloc_enable() { 496869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross auto _malloc_enable = __libc_globals->malloc_dispatch.malloc_enable; 497869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross if (__predict_false(_malloc_enable != nullptr)) { 498869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross return _malloc_enable(); 499869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross } 500869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross return Malloc(malloc_enable)(); 501869691c6f7691dd5bf343617aa185c32e0d3d160Colin Cross} 5022d4721c0c57fe2f7c1e1b40df4763a561b3cf856Colin Cross 5032d4721c0c57fe2f7c1e1b40df4763a561b3cf856Colin Cross#ifndef LIBC_STATIC 5042d4721c0c57fe2f7c1e1b40df4763a561b3cf856Colin Crossextern "C" ssize_t malloc_backtrace(void* pointer, uintptr_t* frames, size_t frame_count) { 505d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris void* func = g_functions[FUNC_MALLOC_BACKTRACE]; 506d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris if (func == nullptr) { 5072d4721c0c57fe2f7c1e1b40df4763a561b3cf856Colin Cross return 0; 5082d4721c0c57fe2f7c1e1b40df4763a561b3cf856Colin Cross } 509d6a1dc23796696f73f483943534d4c5c4b312d39Christopher Ferris return reinterpret_cast<malloc_backtrace_func_t>(func)(pointer, frames, frame_count); 5102d4721c0c57fe2f7c1e1b40df4763a561b3cf856Colin Cross} 5112d4721c0c57fe2f7c1e1b40df4763a561b3cf856Colin Cross#else 5122d4721c0c57fe2f7c1e1b40df4763a561b3cf856Colin Crossextern "C" ssize_t malloc_backtrace(void*, uintptr_t*, size_t) { 5132d4721c0c57fe2f7c1e1b40df4763a561b3cf856Colin Cross return 0; 5142d4721c0c57fe2f7c1e1b40df4763a561b3cf856Colin Cross} 5152d4721c0c57fe2f7c1e1b40df4763a561b3cf856Colin Cross#endif 516