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