1b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine/*
2b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * Copyright (C) 2009 The Android Open Source Project
3b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * All rights reserved.
4b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine *
5b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * Redistribution and use in source and binary forms, with or without
6b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * modification, are permitted provided that the following conditions
7b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * are met:
8b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine *  * Redistributions of source code must retain the above copyright
9b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine *    notice, this list of conditions and the following disclaimer.
10b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine *  * Redistributions in binary form must reproduce the above copyright
11b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine *    notice, this list of conditions and the following disclaimer in
12b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine *    the documentation and/or other materials provided with the
13b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine *    distribution.
14b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine *
15b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * SUCH DAMAGE.
27b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine */
28b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
29b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine/*
3075fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine * Contains definition of structures, global variables, and implementation of
3175fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine * routines that are used by malloc leak detection code and other components in
32b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * the system. The trick is that some components expect these data and
33b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * routines to be defined / implemented in libc.so library, regardless
34b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * whether or not MALLOC_LEAK_CHECK macro is defined. To make things even
35b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * more tricky, malloc leak detection code, implemented in
36b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * libc_malloc_debug.so also requires access to these variables and routines
37b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * (to fill allocation entry hash table, for example). So, all relevant
38b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * variables and routines are defined / implemented here and exported
39b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * to all, leak detection code and other components via dynamic (libc.so),
40b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * or static (libc.a) linking.
41b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine */
42b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
43b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine#include <stdlib.h>
44b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine#include <pthread.h>
45b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine#include <unistd.h>
46b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine#include "dlmalloc.h"
47b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine#include "malloc_debug_common.h"
48b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
49b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine/*
50b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * In a VM process, this is set to 1 after fork()ing out of zygote.
51b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine */
52b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkineint gMallocLeakZygoteChild = 0;
53b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
54b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkinepthread_mutex_t gAllocationsMutex = PTHREAD_MUTEX_INITIALIZER;
55b74ceb25aae555570df64fa4d4076272733a9a20Vladimir ChtchetkineHashTable gHashTable;
56b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
57b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine// =============================================================================
58b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine// output functions
59b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine// =============================================================================
60b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
61c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesstatic int hash_entry_compare(const void* arg1, const void* arg2) {
6252e7d3d91ab6a5bab77c5dfb1ed47381fd52f9baChristopher Tate    int result;
6352e7d3d91ab6a5bab77c5dfb1ed47381fd52f9baChristopher Tate
64c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes    const HashEntry* e1 = *static_cast<HashEntry* const*>(arg1);
65c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes    const HashEntry* e2 = *static_cast<HashEntry* const*>(arg2);
66b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
6752e7d3d91ab6a5bab77c5dfb1ed47381fd52f9baChristopher Tate    // if one or both arg pointers are null, deal gracefully
6852e7d3d91ab6a5bab77c5dfb1ed47381fd52f9baChristopher Tate    if (e1 == NULL) {
6952e7d3d91ab6a5bab77c5dfb1ed47381fd52f9baChristopher Tate        result = (e2 == NULL) ? 0 : 1;
7052e7d3d91ab6a5bab77c5dfb1ed47381fd52f9baChristopher Tate    } else if (e2 == NULL) {
71b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        result = -1;
72b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    } else {
7352e7d3d91ab6a5bab77c5dfb1ed47381fd52f9baChristopher Tate        size_t nbAlloc1 = e1->allocations;
7452e7d3d91ab6a5bab77c5dfb1ed47381fd52f9baChristopher Tate        size_t nbAlloc2 = e2->allocations;
7552e7d3d91ab6a5bab77c5dfb1ed47381fd52f9baChristopher Tate        size_t size1 = e1->size & ~SIZE_FLAG_MASK;
7652e7d3d91ab6a5bab77c5dfb1ed47381fd52f9baChristopher Tate        size_t size2 = e2->size & ~SIZE_FLAG_MASK;
7752e7d3d91ab6a5bab77c5dfb1ed47381fd52f9baChristopher Tate        size_t alloc1 = nbAlloc1 * size1;
7852e7d3d91ab6a5bab77c5dfb1ed47381fd52f9baChristopher Tate        size_t alloc2 = nbAlloc2 * size2;
7952e7d3d91ab6a5bab77c5dfb1ed47381fd52f9baChristopher Tate
8052e7d3d91ab6a5bab77c5dfb1ed47381fd52f9baChristopher Tate        // sort in descending order by:
8152e7d3d91ab6a5bab77c5dfb1ed47381fd52f9baChristopher Tate        // 1) total size
8252e7d3d91ab6a5bab77c5dfb1ed47381fd52f9baChristopher Tate        // 2) number of allocations
8352e7d3d91ab6a5bab77c5dfb1ed47381fd52f9baChristopher Tate        //
8452e7d3d91ab6a5bab77c5dfb1ed47381fd52f9baChristopher Tate        // This is used for sorting, not determination of equality, so we don't
8552e7d3d91ab6a5bab77c5dfb1ed47381fd52f9baChristopher Tate        // need to compare the bit flags.
8652e7d3d91ab6a5bab77c5dfb1ed47381fd52f9baChristopher Tate        if (alloc1 > alloc2) {
87b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine            result = -1;
8852e7d3d91ab6a5bab77c5dfb1ed47381fd52f9baChristopher Tate        } else if (alloc1 < alloc2) {
89b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine            result = 1;
90b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        } else {
9152e7d3d91ab6a5bab77c5dfb1ed47381fd52f9baChristopher Tate            if (nbAlloc1 > nbAlloc2) {
9252e7d3d91ab6a5bab77c5dfb1ed47381fd52f9baChristopher Tate                result = -1;
9352e7d3d91ab6a5bab77c5dfb1ed47381fd52f9baChristopher Tate            } else if (nbAlloc1 < nbAlloc2) {
9452e7d3d91ab6a5bab77c5dfb1ed47381fd52f9baChristopher Tate                result = 1;
9552e7d3d91ab6a5bab77c5dfb1ed47381fd52f9baChristopher Tate            } else {
9652e7d3d91ab6a5bab77c5dfb1ed47381fd52f9baChristopher Tate                result = 0;
9752e7d3d91ab6a5bab77c5dfb1ed47381fd52f9baChristopher Tate            }
98b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        }
99b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    }
100b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    return result;
101b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine}
102b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
103b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine/*
104b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * Retrieve native heap information.
105b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine *
106b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * "*info" is set to a buffer we allocate
107b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * "*overallSize" is set to the size of the "info" buffer
108b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * "*infoSize" is set to the size of a single entry
109b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * "*totalMemory" is set to the sum of all allocations we're tracking; does
110b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine *   not include heap overhead
111b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * "*backtraceSize" is set to the maximum number of entries in the back trace
112b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine */
113c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesextern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize,
114c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes        size_t* infoSize, size_t* totalMemory, size_t* backtraceSize) {
115b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    // don't do anything if we have invalid arguments
116b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    if (info == NULL || overallSize == NULL || infoSize == NULL ||
117b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine            totalMemory == NULL || backtraceSize == NULL) {
118b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        return;
119b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    }
1209d8be5485c366b4f579bef0b88a4c99b899f21e1tedbo    *totalMemory = 0;
121b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
122c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes    ScopedPthreadMutexLocker locker(&gAllocationsMutex);
123b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
124b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    if (gHashTable.count == 0) {
125b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        *info = NULL;
126b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        *overallSize = 0;
127b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        *infoSize = 0;
128b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        *backtraceSize = 0;
129c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes        return;
130b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    }
131b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
132c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes    HashEntry** list = static_cast<HashEntry**>(dlmalloc(sizeof(void*) * gHashTable.count));
133b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
134b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    // get the entries into an array to be sorted
135b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    int index = 0;
136c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes    for (size_t i = 0 ; i < HASHTABLE_SIZE ; ++i) {
137b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        HashEntry* entry = gHashTable.slots[i];
138b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        while (entry != NULL) {
139b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine            list[index] = entry;
140b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine            *totalMemory = *totalMemory +
141b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine                ((entry->size & ~SIZE_FLAG_MASK) * entry->allocations);
142b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine            index++;
143b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine            entry = entry->next;
144b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        }
145b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    }
146b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
147b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    // XXX: the protocol doesn't allow variable size for the stack trace (yet)
148b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    *infoSize = (sizeof(size_t) * 2) + (sizeof(intptr_t) * BACKTRACE_SIZE);
149b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    *overallSize = *infoSize * gHashTable.count;
150b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    *backtraceSize = BACKTRACE_SIZE;
151b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
152c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes    // now get a byte array big enough for this
153c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes    *info = static_cast<uint8_t*>(dlmalloc(*overallSize));
154b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
155b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    if (*info == NULL) {
156b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        *overallSize = 0;
157c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes        dlfree(list);
158c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes        return;
159b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    }
160b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
161c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes    qsort(list, gHashTable.count, sizeof(void*), hash_entry_compare);
162b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
163b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    uint8_t* head = *info;
164b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    const int count = gHashTable.count;
165c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes    for (int i = 0 ; i < count ; ++i) {
166b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        HashEntry* entry = list[i];
167b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        size_t entrySize = (sizeof(size_t) * 2) + (sizeof(intptr_t) * entry->numEntries);
168b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        if (entrySize < *infoSize) {
169b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine            /* we're writing less than a full entry, clear out the rest */
17095faecefdea0f55edafdba09052a904df7cd2405The Android Open Source Project            memset(head + entrySize, 0, *infoSize - entrySize);
171b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        } else {
172b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine            /* make sure the amount we're copying doesn't exceed the limit */
173b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine            entrySize = *infoSize;
174b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        }
175b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        memcpy(head, &(entry->size), entrySize);
176b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        head += *infoSize;
177b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    }
178b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
179b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    dlfree(list);
180b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine}
181b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
182c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesextern "C" void free_malloc_leak_info(uint8_t* info) {
183b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    dlfree(info);
184b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine}
185b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
186c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesextern "C" struct mallinfo mallinfo() {
187b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    return dlmallinfo();
188b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine}
189b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
190c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesextern "C" size_t malloc_usable_size(void* mem) {
191999089181ef60bb67e1a49f2cf6f4ec608a7caf8Ian Rogers    return dlmalloc_usable_size(mem);
192999089181ef60bb67e1a49f2cf6f4ec608a7caf8Ian Rogers}
193999089181ef60bb67e1a49f2cf6f4ec608a7caf8Ian Rogers
194c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesextern "C" void* valloc(size_t bytes) {
195999089181ef60bb67e1a49f2cf6f4ec608a7caf8Ian Rogers    return dlvalloc(bytes);
196999089181ef60bb67e1a49f2cf6f4ec608a7caf8Ian Rogers}
197999089181ef60bb67e1a49f2cf6f4ec608a7caf8Ian Rogers
198c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesextern "C" void* pvalloc(size_t bytes) {
199999089181ef60bb67e1a49f2cf6f4ec608a7caf8Ian Rogers    return dlpvalloc(bytes);
200b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine}
201b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
202c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesextern "C" int posix_memalign(void** memptr, size_t alignment, size_t size) {
203bfc1d97531fa611ad2705c7179134b60e652ead4Brian Carlstrom    return dlposix_memalign(memptr, alignment, size);
204bfc1d97531fa611ad2705c7179134b60e652ead4Brian Carlstrom}
205bfc1d97531fa611ad2705c7179134b60e652ead4Brian Carlstrom
206b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine/* Support for malloc debugging.
207b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * Note that if USE_DL_PREFIX is not defined, it's assumed that memory
208b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * allocation routines are implemented somewhere else, so all our custom
209b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * malloc routines should not be compiled at all.
210b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine */
211b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine#ifdef USE_DL_PREFIX
212b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
213b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine/* Table for dispatching malloc calls, initialized with default dispatchers. */
214c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesextern const MallocDebug __libc_malloc_default_dispatch;
215c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesconst MallocDebug __libc_malloc_default_dispatch __attribute__((aligned(32))) = {
216b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    dlmalloc, dlfree, dlcalloc, dlrealloc, dlmemalign
217b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine};
218b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
219b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine/* Selector of dispatch table to use for dispatching malloc calls. */
220b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkineconst MallocDebug* __libc_malloc_dispatch = &__libc_malloc_default_dispatch;
221b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
222c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesextern "C" void* malloc(size_t bytes) {
223b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    return __libc_malloc_dispatch->malloc(bytes);
224b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine}
225c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes
226c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesextern "C" void free(void* mem) {
227b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    __libc_malloc_dispatch->free(mem);
228b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine}
229c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes
230c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesextern "C" void* calloc(size_t n_elements, size_t elem_size) {
231b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    return __libc_malloc_dispatch->calloc(n_elements, elem_size);
232b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine}
233c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes
234c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesextern "C" void* realloc(void* oldMem, size_t bytes) {
235b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    return __libc_malloc_dispatch->realloc(oldMem, bytes);
236b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine}
237c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes
238c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesextern "C" void* memalign(size_t alignment, size_t bytes) {
239b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    return __libc_malloc_dispatch->memalign(alignment, bytes);
240b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine}
241b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
242b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine/* We implement malloc debugging only in libc.so, so code bellow
243b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * must be excluded if we compile this file for static libc.a
244b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine */
245b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine#ifndef LIBC_STATIC
246b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine#include <sys/system_properties.h>
247b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine#include <dlfcn.h>
248c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes#include <stdio.h>
249b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine#include "logd.h"
250b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
251b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine/* Table for dispatching malloc calls, depending on environment. */
252b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkinestatic MallocDebug gMallocUse __attribute__((aligned(32))) = {
253b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    dlmalloc, dlfree, dlcalloc, dlrealloc, dlmemalign
254b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine};
255b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
256c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesextern char* __progname;
257b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
258b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine/* Handle to shared library where actual memory allocation is implemented.
259b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * This library is loaded and memory allocation calls are redirected there
260b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * when libc.debug.malloc environment variable contains value other than
261b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * zero:
262b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * 1  - For memory leak detections.
263b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * 5  - For filling allocated / freed memory with patterns defined by
264b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine *      CHK_SENTINEL_VALUE, and CHK_FILL_FREE macros.
265b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * 10 - For adding pre-, and post- allocation stubs in order to detect
266b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine *      buffer overruns.
26775fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine * Note that emulator's memory allocation instrumentation is not controlled by
26875fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine * libc.debug.malloc value, but rather by emulator, started with -memcheck
26975fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine * option. Note also, that if emulator has started with -memcheck option,
27075fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine * emulator's instrumented memory allocation will take over value saved in
27175fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine * libc.debug.malloc. In other words, if emulator has started with -memcheck
27275fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine * option, libc.debug.malloc value is ignored.
273b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * Actual functionality for debug levels 1-10 is implemented in
27475fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine * libc_malloc_debug_leak.so, while functionality for emultor's instrumented
27575fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine * allocations is implemented in libc_malloc_debug_qemu.so and can be run inside
27675fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine  * the emulator only.
277b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine */
278b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkinestatic void* libc_malloc_impl_handle = NULL;
279b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
28075fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine/* Make sure we have MALLOC_ALIGNMENT that matches the one that is
28175fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine * used in dlmalloc. Emulator's memchecker needs this value to properly
28275fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine * align its guarding zones.
28375fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine */
28475fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine#ifndef MALLOC_ALIGNMENT
28575fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine#define MALLOC_ALIGNMENT ((size_t)8U)
28675fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine#endif  /* MALLOC_ALIGNMENT */
28775fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine
288e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev/* This variable is set to the value of property libc.debug.malloc.backlog,
289e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev * when the value of libc.debug.malloc = 10.  It determines the size of the
290e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev * backlog we use to detect multiple frees.  If the property is not set, the
291e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev * backlog length defaults to an internal constant defined in
292c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes * malloc_debug_check.cpp.
293e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev */
294e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchevunsigned int malloc_double_free_backlog;
295e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev
296c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesstatic void InitMalloc(MallocDebug* table, int debug_level, const char* prefix) {
297c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes  __libc_android_log_print(ANDROID_LOG_INFO, "libc", "%s: using libc.debug.malloc %d (%s)\n",
298c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes                           __progname, debug_level, prefix);
299c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes
300c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes  char symbol[128];
301c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes
302c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes  snprintf(symbol, sizeof(symbol), "%s_malloc", prefix);
303c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes  table->malloc = reinterpret_cast<MallocDebugMalloc>(dlsym(libc_malloc_impl_handle, symbol));
304c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes  if (table->malloc == NULL) {
305c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes      error_log("%s: dlsym(\"%s\") failed", __progname, symbol);
306c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes  }
307c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes
308c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes  snprintf(symbol, sizeof(symbol), "%s_free", prefix);
309c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes  table->free = reinterpret_cast<MallocDebugFree>(dlsym(libc_malloc_impl_handle, symbol));
310c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes  if (table->free == NULL) {
311c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes      error_log("%s: dlsym(\"%s\") failed", __progname, symbol);
312c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes  }
313c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes
314c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes  snprintf(symbol, sizeof(symbol), "%s_calloc", prefix);
315c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes  table->calloc = reinterpret_cast<MallocDebugCalloc>(dlsym(libc_malloc_impl_handle, symbol));
316c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes  if (table->calloc == NULL) {
317c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes      error_log("%s: dlsym(\"%s\") failed", __progname, symbol);
318c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes  }
319c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes
320c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes  snprintf(symbol, sizeof(symbol), "%s_realloc", prefix);
321c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes  table->realloc = reinterpret_cast<MallocDebugRealloc>(dlsym(libc_malloc_impl_handle, symbol));
322c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes  if (table->realloc == NULL) {
323c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes      error_log("%s: dlsym(\"%s\") failed", __progname, symbol);
324c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes  }
325c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes
326c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes  snprintf(symbol, sizeof(symbol), "%s_memalign", prefix);
327c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes  table->memalign = reinterpret_cast<MallocDebugMemalign>(dlsym(libc_malloc_impl_handle, symbol));
328c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes  if (table->memalign == NULL) {
329c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes      error_log("%s: dlsym(\"%s\") failed", __progname, symbol);
330c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes  }
331c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes}
332c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes
333b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine/* Initializes memory allocation framework once per process. */
334c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesstatic void malloc_init_impl() {
335b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    const char* so_name = NULL;
33675fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine    MallocDebugInit malloc_debug_initialize = NULL;
337b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    unsigned int qemu_running = 0;
33875fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine    unsigned int debug_level = 0;
33975fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine    unsigned int memcheck_enabled = 0;
340b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    char env[PROP_VALUE_MAX];
34175fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine    char memcheck_tracing[PROP_VALUE_MAX];
3427d2e24eb167b6257f7935c7bd2023a708704ca1aIliyan Malchev    char debug_program[PROP_VALUE_MAX];
34375fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine
34475fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine    /* Get custom malloc debug level. Note that emulator started with
34575fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine     * memory checking option will have priority over debug level set in
34675fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine     * libc.debug.malloc system property. */
34775fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine    if (__system_property_get("ro.kernel.qemu", env) && atoi(env)) {
34875fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine        qemu_running = 1;
34975fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine        if (__system_property_get("ro.kernel.memcheck", memcheck_tracing)) {
35075fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine            if (memcheck_tracing[0] != '0') {
35175fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine                // Emulator has started with memory tracing enabled. Enforce it.
35275fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine                debug_level = 20;
35375fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine                memcheck_enabled = 1;
35475fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine            }
35575fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine        }
35675fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine    }
357b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
35875fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine    /* If debug level has not been set by memcheck option in the emulator,
35975fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine     * lets grab it from libc.debug.malloc system property. */
360c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes    if (debug_level == 0 && __system_property_get("libc.debug.malloc", env)) {
361b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        debug_level = atoi(env);
362b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    }
363b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
364b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    /* Debug level 0 means that we should use dlxxx allocation
36575fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine     * routines (default). */
366c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes    if (debug_level == 0) {
367b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        return;
368b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    }
369b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
3707d2e24eb167b6257f7935c7bd2023a708704ca1aIliyan Malchev    /* If libc.debug.malloc.program is set and is not a substring of progname,
3717d2e24eb167b6257f7935c7bd2023a708704ca1aIliyan Malchev     * then exit.
3727d2e24eb167b6257f7935c7bd2023a708704ca1aIliyan Malchev     */
3737d2e24eb167b6257f7935c7bd2023a708704ca1aIliyan Malchev    if (__system_property_get("libc.debug.malloc.program", debug_program)) {
3747d2e24eb167b6257f7935c7bd2023a708704ca1aIliyan Malchev        if (!strstr(__progname, debug_program)) {
3757d2e24eb167b6257f7935c7bd2023a708704ca1aIliyan Malchev            return;
3767d2e24eb167b6257f7935c7bd2023a708704ca1aIliyan Malchev        }
3777d2e24eb167b6257f7935c7bd2023a708704ca1aIliyan Malchev    }
3787d2e24eb167b6257f7935c7bd2023a708704ca1aIliyan Malchev
379b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    // Lets see which .so must be loaded for the requested debug level
380b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    switch (debug_level) {
381b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        case 1:
382b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        case 5:
383e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev        case 10: {
384e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev            char debug_backlog[PROP_VALUE_MAX];
385e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev            if (__system_property_get("libc.debug.malloc.backlog", debug_backlog)) {
386e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev                malloc_double_free_backlog = atoi(debug_backlog);
387e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev                info_log("%s: setting backlog length to %d\n",
388e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev                         __progname, malloc_double_free_backlog);
389e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev            }
390e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev
391b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine            so_name = "/system/lib/libc_malloc_debug_leak.so";
392b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine            break;
393e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev        }
394b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        case 20:
39575fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine            // Quick check: debug level 20 can only be handled in emulator.
396b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine            if (!qemu_running) {
39775fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine                error_log("%s: Debug level %d can only be set in emulator\n",
39875fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine                          __progname, debug_level);
39975fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine                return;
40075fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine            }
40175fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine            // Make sure that memory checking has been enabled in emulator.
40275fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine            if (!memcheck_enabled) {
40375fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine                error_log("%s: Memory checking is not enabled in the emulator\n",
40475fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine                          __progname);
405b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine                return;
406b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine            }
407b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine            so_name = "/system/lib/libc_malloc_debug_qemu.so";
408b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine            break;
409b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        default:
41075fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine            error_log("%s: Debug level %d is unknown\n",
41175fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine                      __progname, debug_level);
412b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine            return;
413b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    }
414b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
415b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    // Load .so that implements the required malloc debugging functionality.
416b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    libc_malloc_impl_handle = dlopen(so_name, RTLD_LAZY);
417b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    if (libc_malloc_impl_handle == NULL) {
418c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes        error_log("%s: Missing module %s required for malloc debug level %d: %s",
419c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes                  __progname, so_name, debug_level, dlerror());
420b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        return;
421b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    }
422b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
42375fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine    // Initialize malloc debugging in the loaded module.
424c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes    malloc_debug_initialize = reinterpret_cast<MallocDebugInit>(dlsym(libc_malloc_impl_handle,
425c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes                                                                      "malloc_debug_initialize"));
42675fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine    if (malloc_debug_initialize == NULL) {
42775fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine        error_log("%s: Initialization routine is not found in %s\n",
42875fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine                  __progname, so_name);
42975fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine        dlclose(libc_malloc_impl_handle);
43075fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine        return;
43175fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine    }
43275fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine    if (malloc_debug_initialize()) {
43375fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine        dlclose(libc_malloc_impl_handle);
43475fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine        return;
43575fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine    }
43675fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine
43775fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine    if (debug_level == 20) {
43875fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine        // For memory checker we need to do extra initialization.
439c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes        typedef int (*MemCheckInit)(int, const char*);
440c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes        MemCheckInit memcheck_initialize =
441c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes            reinterpret_cast<MemCheckInit>(dlsym(libc_malloc_impl_handle,
442c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes                                                 "memcheck_initialize"));
44375fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine        if (memcheck_initialize == NULL) {
44475fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine            error_log("%s: memcheck_initialize routine is not found in %s\n",
44575fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine                      __progname, so_name);
44675fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine            dlclose(libc_malloc_impl_handle);
44775fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine            return;
44875fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine        }
44975fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine        if (memcheck_initialize(MALLOC_ALIGNMENT, memcheck_tracing)) {
45075fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine            dlclose(libc_malloc_impl_handle);
45175fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine            return;
45275fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine        }
45375fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine    }
45475fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine
455b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    // Initialize malloc dispatch table with appropriate routines.
456b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    switch (debug_level) {
457b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        case 1:
458c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes            InitMalloc(&gMallocUse, debug_level, "leak");
459b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine            break;
460b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        case 5:
461c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes            InitMalloc(&gMallocUse, debug_level, "fill");
462b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine            break;
463b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        case 10:
464c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes            InitMalloc(&gMallocUse, debug_level, "chk");
465b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine            break;
466b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        case 20:
467c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes            InitMalloc(&gMallocUse, debug_level, "qemu_instrumented");
468b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine            break;
469b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        default:
470b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine            break;
471b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    }
472b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
473b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    // Make sure dispatch table is initialized
474b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    if ((gMallocUse.malloc == NULL) ||
475b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        (gMallocUse.free == NULL) ||
476b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        (gMallocUse.calloc == NULL) ||
477b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        (gMallocUse.realloc == NULL) ||
478b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        (gMallocUse.memalign == NULL)) {
479c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes        error_log("%s: some symbols for libc.debug.malloc level %d were not found (see above)",
480c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes                  __progname, debug_level);
481b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        dlclose(libc_malloc_impl_handle);
482b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        libc_malloc_impl_handle = NULL;
483b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    } else {
484b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        __libc_malloc_dispatch = &gMallocUse;
485b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    }
486b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine}
487b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
488c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesstatic void malloc_fini_impl() {
489e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev    if (libc_malloc_impl_handle) {
490c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes        MallocDebugFini malloc_debug_finalize =
491c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes            reinterpret_cast<MallocDebugFini>(dlsym(libc_malloc_impl_handle,
492c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes                                                    "malloc_debug_finalize"));
493c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes        if (malloc_debug_finalize) {
494e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev            malloc_debug_finalize();
495c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes        }
496e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev    }
497e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev}
498e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev
499b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkinestatic pthread_once_t  malloc_init_once_ctl = PTHREAD_ONCE_INIT;
500e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchevstatic pthread_once_t  malloc_fini_once_ctl = PTHREAD_ONCE_INIT;
501b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
502b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine#endif  // !LIBC_STATIC
503b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine#endif  // USE_DL_PREFIX
504b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine
505b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine/* Initializes memory allocation framework.
506b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * This routine is called from __libc_init routines implemented
507b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * in libc_init_static.c and libc_init_dynamic.c files.
508b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine */
509c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesextern "C" void malloc_debug_init() {
51075fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine    /* We need to initialize malloc iff we implement here custom
51175fba6888a1e5738f8255f3511c4ad40cbcc0edaVladimir Chtchetkine     * malloc routines (i.e. USE_DL_PREFIX is defined) for libc.so */
512b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine#if defined(USE_DL_PREFIX) && !defined(LIBC_STATIC)
513c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes  if (pthread_once(&malloc_init_once_ctl, malloc_init_impl)) {
514b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine        error_log("Unable to initialize malloc_debug component.");
515b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine    }
516b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine#endif  // USE_DL_PREFIX && !LIBC_STATIC
517b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine}
518e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev
519c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesextern "C" void malloc_debug_fini() {
520c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes  /* We need to finalize malloc iff we implement here custom
521e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev     * malloc routines (i.e. USE_DL_PREFIX is defined) for libc.so */
522e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev#if defined(USE_DL_PREFIX) && !defined(LIBC_STATIC)
523c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes  if (pthread_once(&malloc_fini_once_ctl, malloc_fini_impl)) {
524e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev        error_log("Unable to finalize malloc_debug component.");
525e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev    }
526e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev#endif  // USE_DL_PREFIX && !LIBC_STATIC
527e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev}
528