19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* //device/libs/android_runtime/android_ddm_DdmHandleNativeHeap.cpp 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Copyright 2006, The Android Open Source Project 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License"); 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** you may not use this file except in compliance with the License. 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** You may obtain a copy of the License at 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** http://www.apache.org/licenses/LICENSE-2.0 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Unless required by applicable law or agreed to in writing, software 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS, 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** See the License for the specific language governing permissions and 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** limitations under the License. 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project*/ 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#undef LOG_TAG 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LOG_TAG "DdmHandleNativeHeap" 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <JNIHelp.h> 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <jni.h> 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <android_runtime/AndroidRuntime.h> 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Log.h> 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <fcntl.h> 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <errno.h> 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/types.h> 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/stat.h> 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if defined(__arm__) 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectextern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize, 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t* infoSize, size_t* totalMemory, size_t* backtraceSize); 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectextern "C" void free_malloc_leak_info(uint8_t* info); 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define MAPS_FILE_SIZE 65 * 1024 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstruct Header { 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t mapSize; 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t allocSize; 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t allocInfoSize; 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t totalMemory; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t backtraceSize; 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android { 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Retrieve the native heap information and the info from /proc/<self>/maps, 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * copy them into a byte[] with a "struct Header" that holds data offsets, 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and return the array. 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jbyteArray getLeakInfo(JNIEnv *env, jobject clazz) 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if defined(__arm__) 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // get the info in /proc/[pid]/map 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Header header; 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memset(&header, 0, sizeof(header)); 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pid_t pid = getpid(); 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char path[FILENAME_MAX]; 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sprintf(path, "/proc/%d/maps", pid); 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct stat sb; 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ret = stat(path, &sb); 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint8_t* mapsFile = NULL; 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ret == 0) { 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mapsFile = (uint8_t*)malloc(MAPS_FILE_SIZE); 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fd = open(path, O_RDONLY); 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mapsFile != NULL && fd != -1) { 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int amount = 0; 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project do { 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint8_t* ptr = mapsFile + header.mapSize; 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project amount = read(fd, ptr, MAPS_FILE_SIZE); 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (amount <= 0) { 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (errno != EINTR) 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project header.mapSize += amount; 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } while (header.mapSize < MAPS_FILE_SIZE); 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGD("**** read %d bytes from '%s'", (int) header.mapSize, path); 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint8_t* allocBytes; 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project get_malloc_leak_info(&allocBytes, &header.allocSize, &header.allocInfoSize, 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project &header.totalMemory, &header.backtraceSize); 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jbyte* bytes = NULL; 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jbyte* ptr = NULL; 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jbyteArray array = env->NewByteArray(sizeof(Header) + header.mapSize + header.allocSize); 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (array == NULL) { 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto done; 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bytes = env->GetByteArrayElements(array, NULL); 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ptr = bytes; 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// LOGD("*** mapSize: %d allocSize: %d allocInfoSize: %d totalMemory: %d", 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// header.mapSize, header.allocSize, header.allocInfoSize, header.totalMemory); 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memcpy(ptr, &header, sizeof(header)); 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ptr += sizeof(header); 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (header.mapSize > 0 && mapsFile != NULL) { 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memcpy(ptr, mapsFile, header.mapSize); 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ptr += header.mapSize; 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memcpy(ptr, allocBytes, header.allocSize); 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ReleaseByteArrayElements(array, bytes, 0); 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectdone: 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mapsFile != NULL) { 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project free(mapsFile); 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // free the info up! 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project free_malloc_leak_info(allocBytes); 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return array; 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod method_table[] = { 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { "getLeakInfo", "()[B", (void*)getLeakInfo }, 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_ddm_DdmHandleNativeHeap(JNIEnv *env) 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return AndroidRuntime::registerNativeMethods(env, "android/ddm/DdmHandleNativeHeap", method_table, NELEM(method_table)); 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 145