ed73246b32
bug - 4099038 Change-Id: I6c048eaf3d7f34bc144b8daaa5fdef1ed474af66
170 lines
4.7 KiB
C++
170 lines
4.7 KiB
C++
/*
|
|
* Copyright 2011, The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include <media/MemoryLeakTrackUtil.h>
|
|
|
|
#include <stdio.h>
|
|
#include <sys/types.h>
|
|
#include <unistd.h>
|
|
|
|
/*
|
|
* The code here originally resided in MediaPlayerService.cpp and was
|
|
* shamelessly copied over to support memory leak tracking from
|
|
* multiple places.
|
|
*/
|
|
namespace android {
|
|
|
|
#if defined(__arm__)
|
|
|
|
extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize,
|
|
size_t* infoSize, size_t* totalMemory, size_t* backtraceSize);
|
|
|
|
extern "C" void free_malloc_leak_info(uint8_t* info);
|
|
|
|
// Use the String-class below instead of String8 to allocate all memory
|
|
// beforehand and not reenter the heap while we are examining it...
|
|
struct MyString8 {
|
|
static const size_t MAX_SIZE = 256 * 1024;
|
|
|
|
MyString8()
|
|
: mPtr((char *)malloc(MAX_SIZE)) {
|
|
*mPtr = '\0';
|
|
}
|
|
|
|
~MyString8() {
|
|
free(mPtr);
|
|
}
|
|
|
|
void append(const char *s) {
|
|
strcat(mPtr, s);
|
|
}
|
|
|
|
const char *string() const {
|
|
return mPtr;
|
|
}
|
|
|
|
size_t size() const {
|
|
return strlen(mPtr);
|
|
}
|
|
|
|
private:
|
|
char *mPtr;
|
|
|
|
MyString8(const MyString8 &);
|
|
MyString8 &operator=(const MyString8 &);
|
|
};
|
|
|
|
void dumpMemoryAddresses(int fd)
|
|
{
|
|
const size_t SIZE = 256;
|
|
char buffer[SIZE];
|
|
MyString8 result;
|
|
|
|
typedef struct {
|
|
size_t size;
|
|
size_t dups;
|
|
intptr_t * backtrace;
|
|
} AllocEntry;
|
|
|
|
uint8_t *info = NULL;
|
|
size_t overallSize = 0;
|
|
size_t infoSize = 0;
|
|
size_t totalMemory = 0;
|
|
size_t backtraceSize = 0;
|
|
|
|
get_malloc_leak_info(&info, &overallSize, &infoSize, &totalMemory, &backtraceSize);
|
|
if (info) {
|
|
uint8_t *ptr = info;
|
|
size_t count = overallSize / infoSize;
|
|
|
|
snprintf(buffer, SIZE, " Allocation count %i\n", count);
|
|
result.append(buffer);
|
|
snprintf(buffer, SIZE, " Total memory %i\n", totalMemory);
|
|
result.append(buffer);
|
|
|
|
AllocEntry * entries = new AllocEntry[count];
|
|
|
|
for (size_t i = 0; i < count; i++) {
|
|
// Each entry should be size_t, size_t, intptr_t[backtraceSize]
|
|
AllocEntry *e = &entries[i];
|
|
|
|
e->size = *reinterpret_cast<size_t *>(ptr);
|
|
ptr += sizeof(size_t);
|
|
|
|
e->dups = *reinterpret_cast<size_t *>(ptr);
|
|
ptr += sizeof(size_t);
|
|
|
|
e->backtrace = reinterpret_cast<intptr_t *>(ptr);
|
|
ptr += sizeof(intptr_t) * backtraceSize;
|
|
}
|
|
|
|
// Now we need to sort the entries. They come sorted by size but
|
|
// not by stack trace which causes problems using diff.
|
|
bool moved;
|
|
do {
|
|
moved = false;
|
|
for (size_t i = 0; i < (count - 1); i++) {
|
|
AllocEntry *e1 = &entries[i];
|
|
AllocEntry *e2 = &entries[i+1];
|
|
|
|
bool swap = e1->size < e2->size;
|
|
if (e1->size == e2->size) {
|
|
for(size_t j = 0; j < backtraceSize; j++) {
|
|
if (e1->backtrace[j] == e2->backtrace[j]) {
|
|
continue;
|
|
}
|
|
swap = e1->backtrace[j] < e2->backtrace[j];
|
|
break;
|
|
}
|
|
}
|
|
if (swap) {
|
|
AllocEntry t = entries[i];
|
|
entries[i] = entries[i+1];
|
|
entries[i+1] = t;
|
|
moved = true;
|
|
}
|
|
}
|
|
} while (moved);
|
|
|
|
for (size_t i = 0; i < count; i++) {
|
|
AllocEntry *e = &entries[i];
|
|
|
|
snprintf(buffer, SIZE, "size %8i, dup %4i, ", e->size, e->dups);
|
|
result.append(buffer);
|
|
for (size_t ct = 0; (ct < backtraceSize) && e->backtrace[ct]; ct++) {
|
|
if (ct) {
|
|
result.append(", ");
|
|
}
|
|
snprintf(buffer, SIZE, "0x%08x", e->backtrace[ct]);
|
|
result.append(buffer);
|
|
}
|
|
result.append("\n");
|
|
}
|
|
|
|
delete[] entries;
|
|
free_malloc_leak_info(info);
|
|
}
|
|
|
|
write(fd, result.string(), result.size());
|
|
}
|
|
|
|
#else
|
|
// Does nothing
|
|
void dumpMemoryAddresses(int fd) {}
|
|
|
|
#endif
|
|
} // namespace android
|