blob: 42d408d23ce6d4aeef9f89bdb66ce749eef9175a [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/* //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__)
33extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize,
34 size_t* infoSize, size_t* totalMemory, size_t* backtraceSize);
35
36extern "C" void free_malloc_leak_info(uint8_t* info);
37#endif
38
39#define MAPS_FILE_SIZE 65 * 1024
40
41struct Header {
42 size_t mapSize;
43 size_t allocSize;
44 size_t allocInfoSize;
45 size_t totalMemory;
46 size_t backtraceSize;
47};
48
49namespace 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 */
56static 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
Steve Block5baa3a62011-12-20 16:23:08 +000090 ALOGD("**** read %d bytes from '%s'", (int) header.mapSize, path);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080091 }
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
Steve Block5baa3a62011-12-20 16:23:08 +0000108// ALOGD("*** mapSize: %d allocSize: %d allocInfoSize: %d totalMemory: %d",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109// 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
122done:
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
135static JNINativeMethod method_table[] = {
136 { "getLeakInfo", "()[B", (void*)getLeakInfo },
137};
138
139int register_android_ddm_DdmHandleNativeHeap(JNIEnv *env)
140{
141 return AndroidRuntime::registerNativeMethods(env, "android/ddm/DdmHandleNativeHeap", method_table, NELEM(method_table));
142}
143
144};