blob: d31f7210448068f703c11ecdae9f663c0939759e [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>
Igor Chernyshev80a5d302014-04-02 14:51:40 -070020#include <stdlib.h>
Elliott Hughes9d014d02015-01-28 17:27:45 -080021#include <string.h>
James Dong8635b7b2011-03-14 17:01:38 -070022#include <sys/types.h>
23#include <unistd.h>
24
25/*
26 * The code here originally resided in MediaPlayerService.cpp and was
27 * shamelessly copied over to support memory leak tracking from
28 * multiple places.
29 */
30namespace android {
31
32#if defined(__arm__)
33
34extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize,
35 size_t* infoSize, size_t* totalMemory, size_t* backtraceSize);
36
37extern "C" void free_malloc_leak_info(uint8_t* info);
38
39// Use the String-class below instead of String8 to allocate all memory
40// beforehand and not reenter the heap while we are examining it...
41struct MyString8 {
42 static const size_t MAX_SIZE = 256 * 1024;
43
44 MyString8()
45 : mPtr((char *)malloc(MAX_SIZE)) {
46 *mPtr = '\0';
47 }
48
49 ~MyString8() {
50 free(mPtr);
51 }
52
53 void append(const char *s) {
Oscar Rydhé6d39eb92013-01-22 11:09:54 +010054 strncat(mPtr, s, MAX_SIZE - size() - 1);
James Dong8635b7b2011-03-14 17:01:38 -070055 }
56
57 const char *string() const {
58 return mPtr;
59 }
60
61 size_t size() const {
62 return strlen(mPtr);
63 }
64
Oscar Rydhé6d39eb92013-01-22 11:09:54 +010065 void clear() {
66 *mPtr = '\0';
67 }
68
James Dong8635b7b2011-03-14 17:01:38 -070069private:
70 char *mPtr;
71
72 MyString8(const MyString8 &);
73 MyString8 &operator=(const MyString8 &);
74};
75
76void dumpMemoryAddresses(int fd)
77{
78 const size_t SIZE = 256;
79 char buffer[SIZE];
80 MyString8 result;
81
82 typedef struct {
83 size_t size;
84 size_t dups;
85 intptr_t * backtrace;
86 } AllocEntry;
87
88 uint8_t *info = NULL;
89 size_t overallSize = 0;
90 size_t infoSize = 0;
91 size_t totalMemory = 0;
92 size_t backtraceSize = 0;
93
94 get_malloc_leak_info(&info, &overallSize, &infoSize, &totalMemory, &backtraceSize);
95 if (info) {
96 uint8_t *ptr = info;
97 size_t count = overallSize / infoSize;
98
99 snprintf(buffer, SIZE, " Allocation count %i\n", count);
100 result.append(buffer);
101 snprintf(buffer, SIZE, " Total memory %i\n", totalMemory);
102 result.append(buffer);
103
104 AllocEntry * entries = new AllocEntry[count];
105
106 for (size_t i = 0; i < count; i++) {
107 // Each entry should be size_t, size_t, intptr_t[backtraceSize]
108 AllocEntry *e = &entries[i];
109
110 e->size = *reinterpret_cast<size_t *>(ptr);
111 ptr += sizeof(size_t);
112
113 e->dups = *reinterpret_cast<size_t *>(ptr);
114 ptr += sizeof(size_t);
115
116 e->backtrace = reinterpret_cast<intptr_t *>(ptr);
117 ptr += sizeof(intptr_t) * backtraceSize;
118 }
119
120 // Now we need to sort the entries. They come sorted by size but
121 // not by stack trace which causes problems using diff.
122 bool moved;
123 do {
124 moved = false;
125 for (size_t i = 0; i < (count - 1); i++) {
126 AllocEntry *e1 = &entries[i];
127 AllocEntry *e2 = &entries[i+1];
128
129 bool swap = e1->size < e2->size;
130 if (e1->size == e2->size) {
131 for(size_t j = 0; j < backtraceSize; j++) {
132 if (e1->backtrace[j] == e2->backtrace[j]) {
133 continue;
134 }
135 swap = e1->backtrace[j] < e2->backtrace[j];
136 break;
137 }
138 }
139 if (swap) {
140 AllocEntry t = entries[i];
141 entries[i] = entries[i+1];
142 entries[i+1] = t;
143 moved = true;
144 }
145 }
146 } while (moved);
147
Oscar Rydhé6d39eb92013-01-22 11:09:54 +0100148 write(fd, result.string(), result.size());
149 result.clear();
150
James Dong8635b7b2011-03-14 17:01:38 -0700151 for (size_t i = 0; i < count; i++) {
152 AllocEntry *e = &entries[i];
153
154 snprintf(buffer, SIZE, "size %8i, dup %4i, ", e->size, e->dups);
155 result.append(buffer);
156 for (size_t ct = 0; (ct < backtraceSize) && e->backtrace[ct]; ct++) {
157 if (ct) {
158 result.append(", ");
159 }
160 snprintf(buffer, SIZE, "0x%08x", e->backtrace[ct]);
161 result.append(buffer);
162 }
163 result.append("\n");
Oscar Rydhé6d39eb92013-01-22 11:09:54 +0100164
165 write(fd, result.string(), result.size());
166 result.clear();
James Dong8635b7b2011-03-14 17:01:38 -0700167 }
168
169 delete[] entries;
170 free_malloc_leak_info(info);
171 }
James Dong8635b7b2011-03-14 17:01:38 -0700172}
173
174#else
175// Does nothing
176void dumpMemoryAddresses(int fd) {}
177
178#endif
179} // namespace android