11dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 31dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * All rights reserved. 41dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Redistribution and use in source and binary forms, with or without 61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * modification, are permitted provided that the following conditions 71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * are met: 81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * * Redistributions of source code must retain the above copyright 91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notice, this list of conditions and the following disclaimer. 101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * * Redistributions in binary form must reproduce the above copyright 111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notice, this list of conditions and the following disclaimer in 121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * the documentation and/or other materials provided with the 131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * distribution. 141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * SUCH DAMAGE. 271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 287f5aa4f35e23fd37425b3a5041737cdf58f87385Xi Wang 297f5aa4f35e23fd37425b3a5041737cdf58f87385Xi Wang#include <dlfcn.h> 301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <errno.h> 317f5aa4f35e23fd37425b3a5041737cdf58f87385Xi Wang#include <fcntl.h> 321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <pthread.h> 337f5aa4f35e23fd37425b3a5041737cdf58f87385Xi Wang#include <stdarg.h> 347f5aa4f35e23fd37425b3a5041737cdf58f87385Xi Wang#include <stddef.h> 357f5aa4f35e23fd37425b3a5041737cdf58f87385Xi Wang#include <stdint.h> 361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdio.h> 371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdlib.h> 381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <string.h> 391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <unistd.h> 401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <unwind.h> 411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 427f5aa4f35e23fd37425b3a5041737cdf58f87385Xi Wang#include <arpa/inet.h> 431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/select.h> 447f5aa4f35e23fd37425b3a5041737cdf58f87385Xi Wang#include <sys/socket.h> 451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/system_properties.h> 467f5aa4f35e23fd37425b3a5041737cdf58f87385Xi Wang#include <sys/types.h> 477f5aa4f35e23fd37425b3a5041737cdf58f87385Xi Wang#include <sys/un.h> 481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "dlmalloc.h" 501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "logd.h" 51b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine#include "malloc_debug_common.h" 521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 53b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine// This file should be included into the build only when 54b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine// MALLOC_LEAK_CHECK, or MALLOC_QEMU_INSTRUMENT, or both 55b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine// macros are defined. 56b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine#ifndef MALLOC_LEAK_CHECK 57b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine#error MALLOC_LEAK_CHECK is not defined. 58b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine#endif // !MALLOC_LEAK_CHECK 591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 60b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine// Global variables defined in malloc_debug_common.c 61b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkineextern int gMallocLeakZygoteChild; 62b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkineextern pthread_mutex_t gAllocationsMutex; 63b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkineextern HashTable gHashTable; 641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project// ============================================================================= 66e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev// stack trace functions 6739f3745cf30efe38482ffead1c32f4e62f6fe32eAndy McFadden// ============================================================================= 6839f3745cf30efe38482ffead1c32f4e62f6fe32eAndy McFadden 699862f5e08bcbf51c80542fb148fc505df140cb95Jin Wei#ifndef MALLOC_ALIGNMENT 709862f5e08bcbf51c80542fb148fc505df140cb95Jin Wei#define MALLOC_ALIGNMENT ((size_t)8U) 719862f5e08bcbf51c80542fb148fc505df140cb95Jin Wei#endif 721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define GUARD 0x48151642 731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define DEBUG 0 741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project// ============================================================================= 761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project// Structures 771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project// ============================================================================= 78c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes 791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstruct AllocationEntry { 801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project HashEntry* entry; 811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project uint32_t guard; 821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}; 831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 84c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesstatic AllocationEntry* to_header(void* mem) { 85c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes return reinterpret_cast<AllocationEntry*>(mem) - 1; 86c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes} 871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project// ============================================================================= 891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project// Hash Table functions 901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project// ============================================================================= 91c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes 92c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesstatic uint32_t get_hash(intptr_t* backtrace, size_t numEntries) { 931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (backtrace == NULL) return 0; 941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int hash = 0; 961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project size_t i; 971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (i = 0 ; i < numEntries ; i++) { 981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project hash = (hash * 33) + (backtrace[i] >> 2); 991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return hash; 1021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 1031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic HashEntry* find_entry(HashTable* table, int slot, 105c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes intptr_t* backtrace, size_t numEntries, size_t size) { 1061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project HashEntry* entry = table->slots[slot]; 1071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while (entry != NULL) { 1081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project //debug_log("backtrace: %p, entry: %p entry->backtrace: %p\n", 1091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project // backtrace, entry, (entry != NULL) ? entry->backtrace : NULL); 1101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 1111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * See if the entry matches exactly. We compare the "size" field, 1121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * including the flag bits. 1131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 1141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (entry->size == size && entry->numEntries == numEntries && 1151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project !memcmp(backtrace, entry->backtrace, numEntries * sizeof(intptr_t))) { 1161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return entry; 1171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project entry = entry->next; 1201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NULL; 1231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 1241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 125c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesstatic HashEntry* record_backtrace(intptr_t* backtrace, size_t numEntries, size_t size) { 1261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project size_t hash = get_hash(backtrace, numEntries); 1271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project size_t slot = hash % HASHTABLE_SIZE; 1281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (size & SIZE_FLAG_MASK) { 1301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project debug_log("malloc_debug: allocation %zx exceeds bit width\n", size); 1311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project abort(); 1321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 134c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes if (gMallocLeakZygoteChild) { 1351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project size |= SIZE_FLAG_ZYGOTE_CHILD; 136c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes } 1371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project HashEntry* entry = find_entry(&gHashTable, slot, backtrace, numEntries, size); 1391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (entry != NULL) { 1411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project entry->allocations++; 1421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else { 1431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project // create a new entry 144c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes entry = static_cast<HashEntry*>(dlmalloc(sizeof(HashEntry) + numEntries*sizeof(intptr_t))); 145c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes if (!entry) { 1465751c54bf1c84ad9b1e23a6909c59431c973deaeAndré Goddard Rosa return NULL; 147c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes } 1481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project entry->allocations = 1; 1491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project entry->slot = slot; 1501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project entry->prev = NULL; 1511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project entry->next = gHashTable.slots[slot]; 1521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project entry->numEntries = numEntries; 1531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project entry->size = size; 1541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memcpy(entry->backtrace, backtrace, numEntries * sizeof(intptr_t)); 1561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project gHashTable.slots[slot] = entry; 1581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (entry->next != NULL) { 1601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project entry->next->prev = entry; 1611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project // we just added an entry, increase the size of the hashtable 1641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project gHashTable.count++; 1651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return entry; 1681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 1691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 170c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesstatic int is_valid_entry(HashEntry* entry) { 1711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (entry != NULL) { 1721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int i; 1731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (i = 0 ; i < HASHTABLE_SIZE ; i++) { 1741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project HashEntry* e1 = gHashTable.slots[i]; 1751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while (e1 != NULL) { 1771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (e1 == entry) { 1781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 1; 1791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project e1 = e1->next; 1821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 1871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 1881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 189c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesstatic void remove_entry(HashEntry* entry) { 1901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project HashEntry* prev = entry->prev; 1911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project HashEntry* next = entry->next; 1921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (prev != NULL) entry->prev->next = next; 1941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (next != NULL) entry->next->prev = prev; 1951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (prev == NULL) { 1971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project // we are the head of the list. set the head to be next 1981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project gHashTable.slots[entry->slot] = entry->next; 1991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project // we just removed and entry, decrease the size of the hashtable 2021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project gHashTable.count--; 2031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 2041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project// ============================================================================= 206e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev// malloc fill functions 2071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project// ============================================================================= 2081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define CHK_FILL_FREE 0xef 210c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes#define CHK_SENTINEL_VALUE 0xeb 211c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes 212c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesextern "C" void* fill_calloc(size_t n_elements, size_t elem_size) { 213c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes return dlcalloc(n_elements, elem_size); 214c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes} 2151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 216c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesextern "C" void* fill_malloc(size_t bytes) { 2171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project void* buffer = dlmalloc(bytes); 2181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (buffer) { 2191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memset(buffer, CHK_SENTINEL_VALUE, bytes); 2201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return buffer; 2221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 2231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 224c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesextern "C" void fill_free(void* mem) { 2251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project size_t bytes = dlmalloc_usable_size(mem); 2261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memset(mem, CHK_FILL_FREE, bytes); 2271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dlfree(mem); 2281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 2291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 230c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesextern "C" void* fill_realloc(void* mem, size_t bytes) { 2311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project void* buffer = fill_malloc(bytes); 2321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (mem == NULL) { 2331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return buffer; 2341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (buffer) { 2361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project size_t old_size = dlmalloc_usable_size(mem); 2371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project size_t size = (bytes < old_size)?(bytes):(old_size); 2381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memcpy(buffer, mem, size); 2391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project fill_free(mem); 2401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return buffer; 2421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 2431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 244c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesextern "C" void* fill_memalign(size_t alignment, size_t bytes) { 2451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project void* buffer = dlmemalign(alignment, bytes); 2461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (buffer) { 2471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memset(buffer, CHK_SENTINEL_VALUE, bytes); 2481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return buffer; 2501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 2511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project// ============================================================================= 2531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project// malloc leak functions 2541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project// ============================================================================= 2551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 256c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesstatic void* MEMALIGN_GUARD = reinterpret_cast<void*>(0xA1A41520); 2571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 258c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesextern __LIBC_HIDDEN__ int get_backtrace(intptr_t* addrs, size_t max_entries); 259e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev 260c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesextern "C" void* leak_malloc(size_t bytes) { 2611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project // allocate enough space infront of the allocation to store the pointer for 2621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project // the alloc structure. This will making free'ing the structer really fast! 2631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project // 1. allocate enough memory and include our header 2651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project // 2. set the base pointer to be right after our header 2661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2677f5aa4f35e23fd37425b3a5041737cdf58f87385Xi Wang size_t size = bytes + sizeof(AllocationEntry); 2687f5aa4f35e23fd37425b3a5041737cdf58f87385Xi Wang if (size < bytes) { // Overflow. 2697f5aa4f35e23fd37425b3a5041737cdf58f87385Xi Wang return NULL; 2707f5aa4f35e23fd37425b3a5041737cdf58f87385Xi Wang } 2717f5aa4f35e23fd37425b3a5041737cdf58f87385Xi Wang 2727f5aa4f35e23fd37425b3a5041737cdf58f87385Xi Wang void* base = dlmalloc(size); 2731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (base != NULL) { 274c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes ScopedPthreadMutexLocker locker(&gAllocationsMutex); 2751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 276c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes intptr_t backtrace[BACKTRACE_SIZE]; 277c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes size_t numEntries = get_backtrace(backtrace, BACKTRACE_SIZE); 278b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine 279c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes AllocationEntry* header = reinterpret_cast<AllocationEntry*>(base); 280c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes header->entry = record_backtrace(backtrace, numEntries, bytes); 281c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes header->guard = GUARD; 282b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine 283c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes // now increment base to point to after our header. 284c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes // this should just work since our header is 8 bytes. 285c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes base = reinterpret_cast<AllocationEntry*>(base) + 1; 2861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return base; 2891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 2901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 291c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesextern "C" void leak_free(void* mem) { 2921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (mem != NULL) { 293c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes ScopedPthreadMutexLocker locker(&gAllocationsMutex); 2941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project // check the guard to make sure it is valid 296c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes AllocationEntry* header = to_header(mem); 297b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine 2981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (header->guard != GUARD) { 2991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project // could be a memaligned block 300c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes if (reinterpret_cast<void**>(mem)[-1] == MEMALIGN_GUARD) { 301c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes mem = reinterpret_cast<void**>(mem)[-2]; 302c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes header = to_header(mem); 3031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 305b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine 3061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (header->guard == GUARD || is_valid_entry(header->entry)) { 3071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project // decrement the allocations 3081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project HashEntry* entry = header->entry; 3091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project entry->allocations--; 3101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (entry->allocations <= 0) { 3111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project remove_entry(entry); 3121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dlfree(entry); 3131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project // now free the memory! 3161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dlfree(header); 3171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else { 3181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project debug_log("WARNING bad header guard: '0x%x'! and invalid entry: %p\n", 3191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project header->guard, header->entry); 3201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 3231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 324c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesextern "C" void* leak_calloc(size_t n_elements, size_t elem_size) { 3251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Fail on overflow - just to be safe even though this code runs only 3261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * within the debugging C library, not the production one */ 3271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (n_elements && MAX_SIZE_T / n_elements < elem_size) { 3281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NULL; 3291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 330c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes size_t size = n_elements * elem_size; 331c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes void* ptr = leak_malloc(size); 3321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ptr != NULL) { 3331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memset(ptr, 0, size); 3341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return ptr; 3361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 3371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 338c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesextern "C" void* leak_realloc(void* oldMem, size_t bytes) { 3391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (oldMem == NULL) { 3401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return leak_malloc(bytes); 3411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project void* newMem = NULL; 343c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes AllocationEntry* header = to_header(oldMem); 3441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (header && header->guard == GUARD) { 3451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project size_t oldSize = header->entry->size & ~SIZE_FLAG_MASK; 3461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project newMem = leak_malloc(bytes); 3471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (newMem != NULL) { 3481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project size_t copySize = (oldSize <= bytes) ? oldSize : bytes; 3491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memcpy(newMem, oldMem, copySize); 3501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project leak_free(oldMem); 3511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else { 3531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project newMem = dlrealloc(oldMem, bytes); 3541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return newMem; 3561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 3571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 358c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesextern "C" void* leak_memalign(size_t alignment, size_t bytes) { 3591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project // we can just use malloc 360c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes if (alignment <= MALLOC_ALIGNMENT) { 3611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return leak_malloc(bytes); 362c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes } 3631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project // need to make sure it's a power of two 365c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes if (alignment & (alignment-1)) { 3661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project alignment = 1L << (31 - __builtin_clz(alignment)); 367c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes } 368b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine 3691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project // here, aligment is at least MALLOC_ALIGNMENT<<1 bytes 3701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project // we will align by at least MALLOC_ALIGNMENT bytes 3711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project // and at most alignment-MALLOC_ALIGNMENT bytes 3721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project size_t size = (alignment-MALLOC_ALIGNMENT) + bytes; 3737f5aa4f35e23fd37425b3a5041737cdf58f87385Xi Wang if (size < bytes) { // Overflow. 3747f5aa4f35e23fd37425b3a5041737cdf58f87385Xi Wang return NULL; 3757f5aa4f35e23fd37425b3a5041737cdf58f87385Xi Wang } 3767f5aa4f35e23fd37425b3a5041737cdf58f87385Xi Wang 3771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project void* base = leak_malloc(size); 3781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (base != NULL) { 379c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes intptr_t ptr = reinterpret_cast<intptr_t>(base); 380c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes if ((ptr % alignment) == 0) { 3811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return base; 382c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes } 3831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project // align the pointer 3851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ptr += ((-ptr) % alignment); 386b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine 3871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project // there is always enough space for the base pointer and the guard 388c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes reinterpret_cast<void**>(ptr)[-1] = MEMALIGN_GUARD; 389c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes reinterpret_cast<void**>(ptr)[-2] = base; 3901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 391c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes return reinterpret_cast<void*>(ptr); 3921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return base; 3941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 395