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