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 */ 28 namespace android { 29 30 #if defined(__arm__) 31 32 extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize, 33 size_t* infoSize, size_t* totalMemory, size_t* backtraceSize); 34 35 extern "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... 39 struct 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 strcat(mPtr, s); 53 } 54 55 const char *string() const { 56 return mPtr; 57 } 58 59 size_t size() const { 60 return strlen(mPtr); 61 } 62 63 private: 64 char *mPtr; 65 66 MyString8(const MyString8 &); 67 MyString8 &operator=(const MyString8 &); 68 }; 69 70 void dumpMemoryAddresses(int fd) 71 { 72 const size_t SIZE = 256; 73 char buffer[SIZE]; 74 MyString8 result; 75 76 typedef struct { 77 size_t size; 78 size_t dups; 79 intptr_t * backtrace; 80 } AllocEntry; 81 82 uint8_t *info = NULL; 83 size_t overallSize = 0; 84 size_t infoSize = 0; 85 size_t totalMemory = 0; 86 size_t backtraceSize = 0; 87 88 get_malloc_leak_info(&info, &overallSize, &infoSize, &totalMemory, &backtraceSize); 89 if (info) { 90 uint8_t *ptr = info; 91 size_t count = overallSize / infoSize; 92 93 snprintf(buffer, SIZE, " Allocation count %i\n", count); 94 result.append(buffer); 95 snprintf(buffer, SIZE, " Total memory %i\n", totalMemory); 96 result.append(buffer); 97 98 AllocEntry * entries = new AllocEntry[count]; 99 100 for (size_t i = 0; i < count; i++) { 101 // Each entry should be size_t, size_t, intptr_t[backtraceSize] 102 AllocEntry *e = &entries[i]; 103 104 e->size = *reinterpret_cast<size_t *>(ptr); 105 ptr += sizeof(size_t); 106 107 e->dups = *reinterpret_cast<size_t *>(ptr); 108 ptr += sizeof(size_t); 109 110 e->backtrace = reinterpret_cast<intptr_t *>(ptr); 111 ptr += sizeof(intptr_t) * backtraceSize; 112 } 113 114 // Now we need to sort the entries. They come sorted by size but 115 // not by stack trace which causes problems using diff. 116 bool moved; 117 do { 118 moved = false; 119 for (size_t i = 0; i < (count - 1); i++) { 120 AllocEntry *e1 = &entries[i]; 121 AllocEntry *e2 = &entries[i+1]; 122 123 bool swap = e1->size < e2->size; 124 if (e1->size == e2->size) { 125 for(size_t j = 0; j < backtraceSize; j++) { 126 if (e1->backtrace[j] == e2->backtrace[j]) { 127 continue; 128 } 129 swap = e1->backtrace[j] < e2->backtrace[j]; 130 break; 131 } 132 } 133 if (swap) { 134 AllocEntry t = entries[i]; 135 entries[i] = entries[i+1]; 136 entries[i+1] = t; 137 moved = true; 138 } 139 } 140 } while (moved); 141 142 for (size_t i = 0; i < count; i++) { 143 AllocEntry *e = &entries[i]; 144 145 snprintf(buffer, SIZE, "size %8i, dup %4i, ", e->size, e->dups); 146 result.append(buffer); 147 for (size_t ct = 0; (ct < backtraceSize) && e->backtrace[ct]; ct++) { 148 if (ct) { 149 result.append(", "); 150 } 151 snprintf(buffer, SIZE, "0x%08x", e->backtrace[ct]); 152 result.append(buffer); 153 } 154 result.append("\n"); 155 } 156 157 delete[] entries; 158 free_malloc_leak_info(info); 159 } 160 161 write(fd, result.string(), result.size()); 162 } 163 164 #else 165 // Does nothing 166 void dumpMemoryAddresses(int fd) {} 167 168 #endif 169 } // namespace android 170