android_ddm_DdmHandleNativeHeap.cpp revision ed6b9dff563c5e22f040ff37e12c0d771e0478ae
173b526fb4af0f60634f0078583d92b931d5c0eebnethercote/* //device/libs/android_runtime/android_ddm_DdmHandleNativeHeap.cpp 273b526fb4af0f60634f0078583d92b931d5c0eebnethercote** 34de47b1c9bfe84ddd76a9e71e486c5085c51e3a8njn** Copyright 2006, The Android Open Source Project 473b526fb4af0f60634f0078583d92b931d5c0eebnethercote** 573b526fb4af0f60634f0078583d92b931d5c0eebnethercote** Licensed under the Apache License, Version 2.0 (the "License"); 673b526fb4af0f60634f0078583d92b931d5c0eebnethercote** you may not use this file except in compliance with the License. 7b9c427c63a278cc612ae0ec573be7bb1abaa447fnjn** You may obtain a copy of the License at 8b9c427c63a278cc612ae0ec573be7bb1abaa447fnjn** 973b526fb4af0f60634f0078583d92b931d5c0eebnethercote** http://www.apache.org/licenses/LICENSE-2.0 10ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes** 1173b526fb4af0f60634f0078583d92b931d5c0eebnethercote** Unless required by applicable law or agreed to in writing, software 1273b526fb4af0f60634f0078583d92b931d5c0eebnethercote** distributed under the License is distributed on an "AS IS" BASIS, 1373b526fb4af0f60634f0078583d92b931d5c0eebnethercote** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1473b526fb4af0f60634f0078583d92b931d5c0eebnethercote** See the License for the specific language governing permissions and 1573b526fb4af0f60634f0078583d92b931d5c0eebnethercote** limitations under the License. 1673b526fb4af0f60634f0078583d92b931d5c0eebnethercote*/ 1773b526fb4af0f60634f0078583d92b931d5c0eebnethercote 1873b526fb4af0f60634f0078583d92b931d5c0eebnethercote#undef LOG_TAG 1973b526fb4af0f60634f0078583d92b931d5c0eebnethercote#define LOG_TAG "DdmHandleNativeHeap" 2073b526fb4af0f60634f0078583d92b931d5c0eebnethercote 2173b526fb4af0f60634f0078583d92b931d5c0eebnethercote#include <JNIHelp.h> 2273b526fb4af0f60634f0078583d92b931d5c0eebnethercote#include <jni.h> 2373b526fb4af0f60634f0078583d92b931d5c0eebnethercote#include "core_jni_helpers.h" 2473b526fb4af0f60634f0078583d92b931d5c0eebnethercote 2573b526fb4af0f60634f0078583d92b931d5c0eebnethercote#include <utils/Log.h> 2673b526fb4af0f60634f0078583d92b931d5c0eebnethercote#include <utils/String8.h> 2773b526fb4af0f60634f0078583d92b931d5c0eebnethercote 2873b526fb4af0f60634f0078583d92b931d5c0eebnethercote#include <fcntl.h> 2973b526fb4af0f60634f0078583d92b931d5c0eebnethercote#include <errno.h> 3073b526fb4af0f60634f0078583d92b931d5c0eebnethercote#include <sys/types.h> 3173b526fb4af0f60634f0078583d92b931d5c0eebnethercote#include <sys/stat.h> 3273b526fb4af0f60634f0078583d92b931d5c0eebnethercote 3373b526fb4af0f60634f0078583d92b931d5c0eebnethercoteextern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize, 3473b526fb4af0f60634f0078583d92b931d5c0eebnethercote size_t* infoSize, size_t* totalMemory, size_t* backtraceSize); 3573b526fb4af0f60634f0078583d92b931d5c0eebnethercote 3673b526fb4af0f60634f0078583d92b931d5c0eebnethercoteextern "C" void free_malloc_leak_info(uint8_t* info); 3773b526fb4af0f60634f0078583d92b931d5c0eebnethercote 3873b526fb4af0f60634f0078583d92b931d5c0eebnethercote#define DDMS_HEADER_SIGNATURE 0x812345dd 3973b526fb4af0f60634f0078583d92b931d5c0eebnethercote#define DDMS_VERSION 2 4073b526fb4af0f60634f0078583d92b931d5c0eebnethercote 4173b526fb4af0f60634f0078583d92b931d5c0eebnethercotestruct Header { 4273b526fb4af0f60634f0078583d92b931d5c0eebnethercote#if defined(__LP64__) 4373b526fb4af0f60634f0078583d92b931d5c0eebnethercote uint32_t signature; 4473b526fb4af0f60634f0078583d92b931d5c0eebnethercote uint16_t version; 4573b526fb4af0f60634f0078583d92b931d5c0eebnethercote uint16_t pointerSize; 4673b526fb4af0f60634f0078583d92b931d5c0eebnethercote#endif 47ac7924c7eedce947578c571ae419c4c84eaa5aefnjn size_t mapSize; 48edef146c47eda894495d2b3b71b32b10349f8d91sewardj size_t allocSize; 494de47b1c9bfe84ddd76a9e71e486c5085c51e3a8njn size_t allocInfoSize; 504de47b1c9bfe84ddd76a9e71e486c5085c51e3a8njn size_t totalMemory; 51ac7924c7eedce947578c571ae419c4c84eaa5aefnjn size_t backtraceSize; 52ac7924c7eedce947578c571ae419c4c84eaa5aefnjn}; 53ac7924c7eedce947578c571ae419c4c84eaa5aefnjn 54ac7924c7eedce947578c571ae419c4c84eaa5aefnjnnamespace android { 55ac7924c7eedce947578c571ae419c4c84eaa5aefnjn 5673b526fb4af0f60634f0078583d92b931d5c0eebnethercotestatic void ReadFile(const char* path, String8& s) { 5773b526fb4af0f60634f0078583d92b931d5c0eebnethercote int fd = open(path, O_RDONLY); 5873b526fb4af0f60634f0078583d92b931d5c0eebnethercote if (fd != -1) { 5973b526fb4af0f60634f0078583d92b931d5c0eebnethercote char bytes[1024]; 604cfea4f9480393ed6799db463b2e0fb8865a1a2fsewardj ssize_t byteCount; 614cfea4f9480393ed6799db463b2e0fb8865a1a2fsewardj while ((byteCount = TEMP_FAILURE_RETRY(read(fd, bytes, sizeof(bytes)))) > 0) { 624cfea4f9480393ed6799db463b2e0fb8865a1a2fsewardj s.append(bytes, byteCount); 634cfea4f9480393ed6799db463b2e0fb8865a1a2fsewardj } 644cfea4f9480393ed6799db463b2e0fb8865a1a2fsewardj close(fd); 654cfea4f9480393ed6799db463b2e0fb8865a1a2fsewardj } 664cfea4f9480393ed6799db463b2e0fb8865a1a2fsewardj} 674cfea4f9480393ed6799db463b2e0fb8865a1a2fsewardj 684cfea4f9480393ed6799db463b2e0fb8865a1a2fsewardj/* 694cfea4f9480393ed6799db463b2e0fb8865a1a2fsewardj * Retrieve the native heap information and the info from /proc/self/maps, 704cfea4f9480393ed6799db463b2e0fb8865a1a2fsewardj * copy them into a byte[] with a "struct Header" that holds data offsets, 714cfea4f9480393ed6799db463b2e0fb8865a1a2fsewardj * and return the array. 724cfea4f9480393ed6799db463b2e0fb8865a1a2fsewardj */ 734cfea4f9480393ed6799db463b2e0fb8865a1a2fsewardjstatic jbyteArray DdmHandleNativeHeap_getLeakInfo(JNIEnv* env, jobject) { 744cfea4f9480393ed6799db463b2e0fb8865a1a2fsewardj Header header; 754de47b1c9bfe84ddd76a9e71e486c5085c51e3a8njn memset(&header, 0, sizeof(header)); 764de47b1c9bfe84ddd76a9e71e486c5085c51e3a8njn 7773b526fb4af0f60634f0078583d92b931d5c0eebnethercote String8 maps; 7873b526fb4af0f60634f0078583d92b931d5c0eebnethercote ReadFile("/proc/self/maps", maps); 7973b526fb4af0f60634f0078583d92b931d5c0eebnethercote header.mapSize = maps.size(); 8073b526fb4af0f60634f0078583d92b931d5c0eebnethercote 8173b526fb4af0f60634f0078583d92b931d5c0eebnethercote uint8_t* allocBytes; 824de47b1c9bfe84ddd76a9e71e486c5085c51e3a8njn get_malloc_leak_info(&allocBytes, &header.allocSize, &header.allocInfoSize, 834cfea4f9480393ed6799db463b2e0fb8865a1a2fsewardj &header.totalMemory, &header.backtraceSize); 844de47b1c9bfe84ddd76a9e71e486c5085c51e3a8njn 854cfea4f9480393ed6799db463b2e0fb8865a1a2fsewardj ALOGD("*** mapSize: %zu allocSize: %zu allocInfoSize: %zu totalMemory: %zu", 8685665ca6fa29dd64754dabe50eb98f25896e752acerion header.mapSize, header.allocSize, header.allocInfoSize, header.totalMemory); 874cfea4f9480393ed6799db463b2e0fb8865a1a2fsewardj 88cae0cc22b83ffb260ee8379e92099c5a701944cbcarll#if defined(__LP64__) 894cfea4f9480393ed6799db463b2e0fb8865a1a2fsewardj header.signature = DDMS_HEADER_SIGNATURE; 9059570ffbe31930ab4d678754daaeec0715117a3dsewardj header.version = DDMS_VERSION; 9159570ffbe31930ab4d678754daaeec0715117a3dsewardj header.pointerSize = sizeof(void*); 92f0c1250e324f6684757c6a15545366447ef1d64fsewardj#endif 93f0c1250e324f6684757c6a15545366447ef1d64fsewardj 94b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj jbyteArray array = env->NewByteArray(sizeof(Header) + header.mapSize + header.allocSize); 95b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj if (array != NULL) { 965db15403e889d4db339b342bc2a824ef0bfaa654sewardj env->SetByteArrayRegion(array, 0, 975db15403e889d4db339b342bc2a824ef0bfaa654sewardj sizeof(header), reinterpret_cast<jbyte*>(&header)); 984df0bfc0614379192c780c944415dc420d9cfe8epetarj env->SetByteArrayRegion(array, sizeof(header), 994df0bfc0614379192c780c944415dc420d9cfe8epetarj maps.size(), reinterpret_cast<const jbyte*>(maps.string())); 1004de47b1c9bfe84ddd76a9e71e486c5085c51e3a8njn env->SetByteArrayRegion(array, sizeof(header) + maps.size(), 1014de47b1c9bfe84ddd76a9e71e486c5085c51e3a8njn header.allocSize, reinterpret_cast<jbyte*>(allocBytes)); 1024de47b1c9bfe84ddd76a9e71e486c5085c51e3a8njn } 10373b526fb4af0f60634f0078583d92b931d5c0eebnethercote 10473b526fb4af0f60634f0078583d92b931d5c0eebnethercote free_malloc_leak_info(allocBytes); 10507b168da387c8cf6e250fa042fc93dcc80e32752bart return array; 10607b168da387c8cf6e250fa042fc93dcc80e32752bart} 10707b168da387c8cf6e250fa042fc93dcc80e32752bart 10807b168da387c8cf6e250fa042fc93dcc80e32752bartstatic JNINativeMethod method_table[] = { 10907b168da387c8cf6e250fa042fc93dcc80e32752bart { "getLeakInfo", "()[B", (void*) DdmHandleNativeHeap_getLeakInfo }, 11007b168da387c8cf6e250fa042fc93dcc80e32752bart}; 11107b168da387c8cf6e250fa042fc93dcc80e32752bart 11207b168da387c8cf6e250fa042fc93dcc80e32752bartint register_android_ddm_DdmHandleNativeHeap(JNIEnv* env) { 11307b168da387c8cf6e250fa042fc93dcc80e32752bart return RegisterMethodsOrDie(env, "android/ddm/DdmHandleNativeHeap", method_table, 11407b168da387c8cf6e250fa042fc93dcc80e32752bart NELEM(method_table)); 11507b168da387c8cf6e250fa042fc93dcc80e32752bart} 11607b168da387c8cf6e250fa042fc93dcc80e32752bart 11707b168da387c8cf6e250fa042fc93dcc80e32752bart}; 11807b168da387c8cf6e250fa042fc93dcc80e32752bart