blob: f004ca45cdb3635d9a388f18b1d31e480f81a627 [file] [log] [blame]
James Dong8635b7b2011-03-14 17:01:38 -07001/*
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) {
Oscar Rydhé6d39eb92013-01-22 11:09:54 +010052 strncat(mPtr, s, MAX_SIZE - size() - 1);
James Dong8635b7b2011-03-14 17:01:38 -070053 }
54
55 const char *string() const {
56 return mPtr;
57 }
58
59 size_t size() const {
60 return strlen(mPtr);
61 }
62
Oscar Rydhé6d39eb92013-01-22 11:09:54 +010063 void clear() {
64 *mPtr = '\0';
65 }
66
James Dong8635b7b2011-03-14 17:01:38 -070067private:
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
Oscar Rydhé6d39eb92013-01-22 11:09:54 +0100146 write(fd, result.string(), result.size());
147 result.clear();
148
James Dong8635b7b2011-03-14 17:01:38 -0700149 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");
Oscar Rydhé6d39eb92013-01-22 11:09:54 +0100162
163 write(fd, result.string(), result.size());
164 result.clear();
James Dong8635b7b2011-03-14 17:01:38 -0700165 }
166
167 delete[] entries;
168 free_malloc_leak_info(info);
169 }
James Dong8635b7b2011-03-14 17:01:38 -0700170}
171
172#else
173// Does nothing
174void dumpMemoryAddresses(int fd) {}
175
176#endif
177} // namespace android