MemoryLeakTrackUtil.cpp revision 8635b7b095fbf7ffc63d3ce791891a9116ace1f6
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> 208635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong#include <sys/types.h> 218635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong#include <unistd.h> 228635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 238635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong/* 248635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong * The code here originally resided in MediaPlayerService.cpp and was 258635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong * shamelessly copied over to support memory leak tracking from 268635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong * multiple places. 278635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong */ 288635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dongnamespace android { 298635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 308635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong#if defined(__arm__) 318635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 328635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dongextern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize, 338635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong size_t* infoSize, size_t* totalMemory, size_t* backtraceSize); 348635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 358635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dongextern "C" void free_malloc_leak_info(uint8_t* info); 368635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 378635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong// Use the String-class below instead of String8 to allocate all memory 388635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong// beforehand and not reenter the heap while we are examining it... 398635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dongstruct MyString8 { 408635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong static const size_t MAX_SIZE = 256 * 1024; 418635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 428635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong MyString8() 438635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong : mPtr((char *)malloc(MAX_SIZE)) { 448635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong *mPtr = '\0'; 458635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong } 468635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 478635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong ~MyString8() { 488635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong free(mPtr); 498635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong } 508635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 518635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong void append(const char *s) { 528635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong strcat(mPtr, s); 538635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong } 548635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 558635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong const char *string() const { 568635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong return mPtr; 578635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong } 588635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 598635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong size_t size() const { 608635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong return strlen(mPtr); 618635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong } 628635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 638635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dongprivate: 648635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong char *mPtr; 658635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 668635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong MyString8(const MyString8 &); 678635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong MyString8 &operator=(const MyString8 &); 688635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong}; 698635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 708635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dongvoid dumpMemoryAddresses(int fd) 718635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong{ 728635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong const size_t SIZE = 256; 738635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong char buffer[SIZE]; 748635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong MyString8 result; 758635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 768635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong typedef struct { 778635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong size_t size; 788635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong size_t dups; 798635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong intptr_t * backtrace; 808635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong } AllocEntry; 818635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 828635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong uint8_t *info = NULL; 838635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong size_t overallSize = 0; 848635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong size_t infoSize = 0; 858635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong size_t totalMemory = 0; 868635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong size_t backtraceSize = 0; 878635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 888635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong get_malloc_leak_info(&info, &overallSize, &infoSize, &totalMemory, &backtraceSize); 898635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong if (info) { 908635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong uint8_t *ptr = info; 918635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong size_t count = overallSize / infoSize; 928635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 938635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong snprintf(buffer, SIZE, " Allocation count %i\n", count); 948635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong result.append(buffer); 958635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong snprintf(buffer, SIZE, " Total memory %i\n", totalMemory); 968635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong result.append(buffer); 978635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 988635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong AllocEntry * entries = new AllocEntry[count]; 998635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 1008635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong for (size_t i = 0; i < count; i++) { 1018635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong // Each entry should be size_t, size_t, intptr_t[backtraceSize] 1028635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong AllocEntry *e = &entries[i]; 1038635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 1048635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong e->size = *reinterpret_cast<size_t *>(ptr); 1058635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong ptr += sizeof(size_t); 1068635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 1078635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong e->dups = *reinterpret_cast<size_t *>(ptr); 1088635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong ptr += sizeof(size_t); 1098635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 1108635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong e->backtrace = reinterpret_cast<intptr_t *>(ptr); 1118635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong ptr += sizeof(intptr_t) * backtraceSize; 1128635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong } 1138635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 1148635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong // Now we need to sort the entries. They come sorted by size but 1158635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong // not by stack trace which causes problems using diff. 1168635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong bool moved; 1178635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong do { 1188635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong moved = false; 1198635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong for (size_t i = 0; i < (count - 1); i++) { 1208635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong AllocEntry *e1 = &entries[i]; 1218635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong AllocEntry *e2 = &entries[i+1]; 1228635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 1238635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong bool swap = e1->size < e2->size; 1248635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong if (e1->size == e2->size) { 1258635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong for(size_t j = 0; j < backtraceSize; j++) { 1268635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong if (e1->backtrace[j] == e2->backtrace[j]) { 1278635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong continue; 1288635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong } 1298635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong swap = e1->backtrace[j] < e2->backtrace[j]; 1308635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong break; 1318635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong } 1328635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong } 1338635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong if (swap) { 1348635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong AllocEntry t = entries[i]; 1358635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong entries[i] = entries[i+1]; 1368635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong entries[i+1] = t; 1378635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong moved = true; 1388635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong } 1398635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong } 1408635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong } while (moved); 1418635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 1428635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong for (size_t i = 0; i < count; i++) { 1438635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong AllocEntry *e = &entries[i]; 1448635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 1458635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong snprintf(buffer, SIZE, "size %8i, dup %4i, ", e->size, e->dups); 1468635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong result.append(buffer); 1478635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong for (size_t ct = 0; (ct < backtraceSize) && e->backtrace[ct]; ct++) { 1488635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong if (ct) { 1498635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong result.append(", "); 1508635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong } 1518635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong snprintf(buffer, SIZE, "0x%08x", e->backtrace[ct]); 1528635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong result.append(buffer); 1538635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong } 1548635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong result.append("\n"); 1558635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong } 1568635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 1578635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong delete[] entries; 1588635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong free_malloc_leak_info(info); 1598635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong } 1608635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 1618635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong write(fd, result.string(), result.size()); 1628635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong} 1638635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 1648635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong#else 1658635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong// Does nothing 1668635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dongvoid dumpMemoryAddresses(int fd) {} 1678635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong 1688635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong#endif 1698635b7b095fbf7ffc63d3ce791891a9116ace1f6James Dong} // namespace android 170