MemoryLeakTrackUtil.cpp revision 80a5d305a8408651fbc9b11e9d21125887da8c40
18635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong/* 28635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong * Copyright 2011, The Android Open Source Project 38635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong * 48635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong * Licensed under the Apache License, Version 2.0 (the "License"); 58635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong * you may not use this file except in compliance with the License. 68635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong * You may obtain a copy of the License at 78635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong * 88635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong * http://www.apache.org/licenses/LICENSE-2.0 98635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong * 108635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong * Unless required by applicable law or agreed to in writing, software 118635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong * distributed under the License is distributed on an "AS IS" BASIS, 128635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong * See the License for the specific language governing permissions and 148635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong * limitations under the License. 158635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong */ 168635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 178635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong#include <media/MemoryLeakTrackUtil.h> 188635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 198635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong#include <stdio.h> 2080a5d305a8408651fbc9b11e9d21125887da8c40Igor Chernyshev#include <stdlib.h> 218635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong#include <sys/types.h> 228635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong#include <unistd.h> 238635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 248635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong/* 258635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong * The code here originally resided in MediaPlayerService.cpp and was 268635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong * shamelessly copied over to support memory leak tracking from 278635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong * multiple places. 288635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong */ 298635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dongnamespace android { 308635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 318635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong#if defined(__arm__) 328635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 338635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dongextern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize, 348635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong size_t* infoSize, size_t* totalMemory, size_t* backtraceSize); 358635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 368635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dongextern "C" void free_malloc_leak_info(uint8_t* info); 378635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 388635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong// Use the String-class below instead of String8 to allocate all memory 398635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong// beforehand and not reenter the heap while we are examining it... 408635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dongstruct MyString8 { 418635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong static const size_t MAX_SIZE = 256 * 1024; 428635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 438635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong MyString8() 448635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong : mPtr((char *)malloc(MAX_SIZE)) { 458635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong *mPtr = '\0'; 468635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong } 478635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 488635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong ~MyString8() { 498635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong free(mPtr); 508635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong } 518635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 528635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong void append(const char *s) { 536d39eb9d7da2ca8eb733f2d2eba686c56b24885bOscar Rydhé strncat(mPtr, s, MAX_SIZE - size() - 1); 548635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong } 558635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 568635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong const char *string() const { 578635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong return mPtr; 588635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong } 598635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 608635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong size_t size() const { 618635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong return strlen(mPtr); 628635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong } 638635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 646d39eb9d7da2ca8eb733f2d2eba686c56b24885bOscar Rydhé void clear() { 656d39eb9d7da2ca8eb733f2d2eba686c56b24885bOscar Rydhé *mPtr = '\0'; 666d39eb9d7da2ca8eb733f2d2eba686c56b24885bOscar Rydhé } 676d39eb9d7da2ca8eb733f2d2eba686c56b24885bOscar Rydhé 688635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dongprivate: 698635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong char *mPtr; 708635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 718635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong MyString8(const MyString8 &); 728635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong MyString8 &operator=(const MyString8 &); 738635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong}; 748635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 758635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dongvoid dumpMemoryAddresses(int fd) 768635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong{ 778635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong const size_t SIZE = 256; 788635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong char buffer[SIZE]; 798635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong MyString8 result; 808635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 818635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong typedef struct { 828635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong size_t size; 838635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong size_t dups; 848635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong intptr_t * backtrace; 858635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong } AllocEntry; 868635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 878635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong uint8_t *info = NULL; 888635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong size_t overallSize = 0; 898635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong size_t infoSize = 0; 908635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong size_t totalMemory = 0; 918635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong size_t backtraceSize = 0; 928635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 938635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong get_malloc_leak_info(&info, &overallSize, &infoSize, &totalMemory, &backtraceSize); 948635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong if (info) { 958635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong uint8_t *ptr = info; 968635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong size_t count = overallSize / infoSize; 978635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 988635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong snprintf(buffer, SIZE, " Allocation count %i\n", count); 998635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong result.append(buffer); 1008635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong snprintf(buffer, SIZE, " Total memory %i\n", totalMemory); 1018635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong result.append(buffer); 1028635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 1038635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong AllocEntry * entries = new AllocEntry[count]; 1048635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 1058635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong for (size_t i = 0; i < count; i++) { 1068635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong // Each entry should be size_t, size_t, intptr_t[backtraceSize] 1078635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong AllocEntry *e = &entries[i]; 1088635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 1098635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong e->size = *reinterpret_cast<size_t *>(ptr); 1108635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong ptr += sizeof(size_t); 1118635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 1128635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong e->dups = *reinterpret_cast<size_t *>(ptr); 1138635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong ptr += sizeof(size_t); 1148635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 1158635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong e->backtrace = reinterpret_cast<intptr_t *>(ptr); 1168635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong ptr += sizeof(intptr_t) * backtraceSize; 1178635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong } 1188635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 1198635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong // Now we need to sort the entries. They come sorted by size but 1208635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong // not by stack trace which causes problems using diff. 1218635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong bool moved; 1228635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong do { 1238635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong moved = false; 1248635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong for (size_t i = 0; i < (count - 1); i++) { 1258635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong AllocEntry *e1 = &entries[i]; 1268635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong AllocEntry *e2 = &entries[i+1]; 1278635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 1288635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong bool swap = e1->size < e2->size; 1298635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong if (e1->size == e2->size) { 1308635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong for(size_t j = 0; j < backtraceSize; j++) { 1318635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong if (e1->backtrace[j] == e2->backtrace[j]) { 1328635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong continue; 1338635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong } 1348635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong swap = e1->backtrace[j] < e2->backtrace[j]; 1358635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong break; 1368635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong } 1378635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong } 1388635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong if (swap) { 1398635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong AllocEntry t = entries[i]; 1408635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong entries[i] = entries[i+1]; 1418635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong entries[i+1] = t; 1428635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong moved = true; 1438635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong } 1448635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong } 1458635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong } while (moved); 1468635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 1476d39eb9d7da2ca8eb733f2d2eba686c56b24885bOscar Rydhé write(fd, result.string(), result.size()); 1486d39eb9d7da2ca8eb733f2d2eba686c56b24885bOscar Rydhé result.clear(); 1496d39eb9d7da2ca8eb733f2d2eba686c56b24885bOscar Rydhé 1508635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong for (size_t i = 0; i < count; i++) { 1518635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong AllocEntry *e = &entries[i]; 1528635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 1538635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong snprintf(buffer, SIZE, "size %8i, dup %4i, ", e->size, e->dups); 1548635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong result.append(buffer); 1558635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong for (size_t ct = 0; (ct < backtraceSize) && e->backtrace[ct]; ct++) { 1568635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong if (ct) { 1578635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong result.append(", "); 1588635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong } 1598635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong snprintf(buffer, SIZE, "0x%08x", e->backtrace[ct]); 1608635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong result.append(buffer); 1618635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong } 1628635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong result.append("\n"); 1636d39eb9d7da2ca8eb733f2d2eba686c56b24885bOscar Rydhé 1646d39eb9d7da2ca8eb733f2d2eba686c56b24885bOscar Rydhé write(fd, result.string(), result.size()); 1656d39eb9d7da2ca8eb733f2d2eba686c56b24885bOscar Rydhé result.clear(); 1668635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong } 1678635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 1688635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong delete[] entries; 1698635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong free_malloc_leak_info(info); 1708635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong } 1718635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong} 1728635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 1738635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong#else 1748635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong// Does nothing 1758635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dongvoid dumpMemoryAddresses(int fd) {} 1768635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 1778635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong#endif 1788635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong} // namespace android 179