• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* //device/libs/android_runtime/android_ddm_DdmHandleNativeHeap.cpp
2 **
3 ** Copyright 2006, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 **     http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17 
18 #undef LOG_TAG
19 #define LOG_TAG "DdmHandleNativeHeap"
20 
21 #include <JNIHelp.h>
22 #include <jni.h>
23 #include <android_runtime/AndroidRuntime.h>
24 
25 #include <utils/Log.h>
26 
27 #include <fcntl.h>
28 #include <errno.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 
32 #if defined(__arm__)
33 extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize,
34         size_t* infoSize, size_t* totalMemory, size_t* backtraceSize);
35 
36 extern "C" void free_malloc_leak_info(uint8_t* info);
37 #endif
38 
39 #define MAPS_FILE_SIZE 65 * 1024
40 
41 struct Header {
42     size_t mapSize;
43     size_t allocSize;
44     size_t allocInfoSize;
45     size_t totalMemory;
46     size_t backtraceSize;
47 };
48 
49 namespace android {
50 
51 /*
52  * Retrieve the native heap information and the info from /proc/<self>/maps,
53  * copy them into a byte[] with a "struct Header" that holds data offsets,
54  * and return the array.
55  */
getLeakInfo(JNIEnv * env,jobject clazz)56 static jbyteArray getLeakInfo(JNIEnv *env, jobject clazz)
57 {
58 #if defined(__arm__)
59     // get the info in /proc/[pid]/map
60     Header header;
61     memset(&header, 0, sizeof(header));
62 
63     pid_t pid = getpid();
64 
65     char path[FILENAME_MAX];
66     sprintf(path, "/proc/%d/maps", pid);
67 
68     struct stat sb;
69     int ret = stat(path, &sb);
70 
71     uint8_t* mapsFile = NULL;
72     if (ret == 0) {
73         mapsFile = (uint8_t*)malloc(MAPS_FILE_SIZE);
74         int fd = open(path, O_RDONLY);
75 
76         if (mapsFile != NULL && fd != -1) {
77             int amount = 0;
78             do {
79                 uint8_t* ptr = mapsFile + header.mapSize;
80                 amount = read(fd, ptr, MAPS_FILE_SIZE);
81                 if (amount <= 0) {
82                     if (errno != EINTR)
83                         break;
84                     else
85                         continue;
86                 }
87                 header.mapSize += amount;
88             } while (header.mapSize < MAPS_FILE_SIZE);
89 
90             LOGD("**** read %d bytes from '%s'", (int) header.mapSize, path);
91         }
92     }
93 
94     uint8_t* allocBytes;
95     get_malloc_leak_info(&allocBytes, &header.allocSize, &header.allocInfoSize,
96             &header.totalMemory, &header.backtraceSize);
97 
98     jbyte* bytes = NULL;
99     jbyte* ptr = NULL;
100     jbyteArray array = env->NewByteArray(sizeof(Header) + header.mapSize + header.allocSize);
101     if (array == NULL) {
102         goto done;
103     }
104 
105     bytes = env->GetByteArrayElements(array, NULL);
106     ptr = bytes;
107 
108 //    LOGD("*** mapSize: %d allocSize: %d allocInfoSize: %d totalMemory: %d",
109 //            header.mapSize, header.allocSize, header.allocInfoSize, header.totalMemory);
110 
111     memcpy(ptr, &header, sizeof(header));
112     ptr += sizeof(header);
113 
114     if (header.mapSize > 0 && mapsFile != NULL) {
115         memcpy(ptr, mapsFile, header.mapSize);
116         ptr += header.mapSize;
117     }
118 
119     memcpy(ptr, allocBytes, header.allocSize);
120     env->ReleaseByteArrayElements(array, bytes, 0);
121 
122 done:
123     if (mapsFile != NULL) {
124         free(mapsFile);
125     }
126     // free the info up!
127     free_malloc_leak_info(allocBytes);
128 
129     return array;
130 #else
131     return NULL;
132 #endif
133 }
134 
135 static JNINativeMethod method_table[] = {
136     { "getLeakInfo", "()[B", (void*)getLeakInfo },
137 };
138 
register_android_ddm_DdmHandleNativeHeap(JNIEnv * env)139 int register_android_ddm_DdmHandleNativeHeap(JNIEnv *env)
140 {
141     return AndroidRuntime::registerNativeMethods(env, "android/ddm/DdmHandleNativeHeap", method_table, NELEM(method_table));
142 }
143 
144 };
145