MemoryLeakTrackUtil.cpp revision 6d39eb9d7da2ca8eb733f2d2eba686c56b24885b
1/* 2 * Copyright 2011, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <media/MemoryLeakTrackUtil.h> 18 19#include <stdio.h> 20#include <sys/types.h> 21#include <unistd.h> 22 23/* 24 * The code here originally resided in MediaPlayerService.cpp and was 25 * shamelessly copied over to support memory leak tracking from 26 * multiple places. 27 */ 28namespace android { 29 30#if defined(__arm__) 31 32extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize, 33 size_t* infoSize, size_t* totalMemory, size_t* backtraceSize); 34 35extern "C" void free_malloc_leak_info(uint8_t* info); 36 37// Use the String-class below instead of String8 to allocate all memory 38// beforehand and not reenter the heap while we are examining it... 39struct MyString8 { 40 static const size_t MAX_SIZE = 256 * 1024; 41 42 MyString8() 43 : mPtr((char *)malloc(MAX_SIZE)) { 44 *mPtr = '\0'; 45 } 46 47 ~MyString8() { 48 free(mPtr); 49 } 50 51 void append(const char *s) { 52 strncat(mPtr, s, MAX_SIZE - size() - 1); 53 } 54 55 const char *string() const { 56 return mPtr; 57 } 58 59 size_t size() const { 60 return strlen(mPtr); 61 } 62 63 void clear() { 64 *mPtr = '\0'; 65 } 66 67private: 68 char *mPtr; 69 70 MyString8(const MyString8 &); 71 MyString8 &operator=(const MyString8 &); 72}; 73 74void dumpMemoryAddresses(int fd) 75{ 76 const size_t SIZE = 256; 77 char buffer[SIZE]; 78 MyString8 result; 79 80 typedef struct { 81 size_t size; 82 size_t dups; 83 intptr_t * backtrace; 84 } AllocEntry; 85 86 uint8_t *info = NULL; 87 size_t overallSize = 0; 88 size_t infoSize = 0; 89 size_t totalMemory = 0; 90 size_t backtraceSize = 0; 91 92 get_malloc_leak_info(&info, &overallSize, &infoSize, &totalMemory, &backtraceSize); 93 if (info) { 94 uint8_t *ptr = info; 95 size_t count = overallSize / infoSize; 96 97 snprintf(buffer, SIZE, " Allocation count %i\n", count); 98 result.append(buffer); 99 snprintf(buffer, SIZE, " Total memory %i\n", totalMemory); 100 result.append(buffer); 101 102 AllocEntry * entries = new AllocEntry[count]; 103 104 for (size_t i = 0; i < count; i++) { 105 // Each entry should be size_t, size_t, intptr_t[backtraceSize] 106 AllocEntry *e = &entries[i]; 107 108 e->size = *reinterpret_cast<size_t *>(ptr); 109 ptr += sizeof(size_t); 110 111 e->dups = *reinterpret_cast<size_t *>(ptr); 112 ptr += sizeof(size_t); 113 114 e->backtrace = reinterpret_cast<intptr_t *>(ptr); 115 ptr += sizeof(intptr_t) * backtraceSize; 116 } 117 118 // Now we need to sort the entries. They come sorted by size but 119 // not by stack trace which causes problems using diff. 120 bool moved; 121 do { 122 moved = false; 123 for (size_t i = 0; i < (count - 1); i++) { 124 AllocEntry *e1 = &entries[i]; 125 AllocEntry *e2 = &entries[i+1]; 126 127 bool swap = e1->size < e2->size; 128 if (e1->size == e2->size) { 129 for(size_t j = 0; j < backtraceSize; j++) { 130 if (e1->backtrace[j] == e2->backtrace[j]) { 131 continue; 132 } 133 swap = e1->backtrace[j] < e2->backtrace[j]; 134 break; 135 } 136 } 137 if (swap) { 138 AllocEntry t = entries[i]; 139 entries[i] = entries[i+1]; 140 entries[i+1] = t; 141 moved = true; 142 } 143 } 144 } while (moved); 145 146 write(fd, result.string(), result.size()); 147 result.clear(); 148 149 for (size_t i = 0; i < count; i++) { 150 AllocEntry *e = &entries[i]; 151 152 snprintf(buffer, SIZE, "size %8i, dup %4i, ", e->size, e->dups); 153 result.append(buffer); 154 for (size_t ct = 0; (ct < backtraceSize) && e->backtrace[ct]; ct++) { 155 if (ct) { 156 result.append(", "); 157 } 158 snprintf(buffer, SIZE, "0x%08x", e->backtrace[ct]); 159 result.append(buffer); 160 } 161 result.append("\n"); 162 163 write(fd, result.string(), result.size()); 164 result.clear(); 165 } 166 167 delete[] entries; 168 free_malloc_leak_info(info); 169 } 170} 171 172#else 173// Does nothing 174void dumpMemoryAddresses(int fd) {} 175 176#endif 177} // namespace android 178