• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
MyString8android::MyString842     MyString8()
43         : mPtr((char *)malloc(MAX_SIZE)) {
44         *mPtr = '\0';
45     }
46 
~MyString8android::MyString847     ~MyString8() {
48         free(mPtr);
49     }
50 
appendandroid::MyString851     void append(const char *s) {
52         strcat(mPtr, s);
53     }
54 
stringandroid::MyString855     const char *string() const {
56         return mPtr;
57     }
58 
sizeandroid::MyString859     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 
dumpMemoryAddresses(int fd)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