1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <jni.h> 18 #include <jvmti.h> 19 20 #include <algorithm> 21 #include <mutex> 22 #include <vector> 23 24 #include "android-base/logging.h" 25 #include "jvmti_helper.h" 26 #include "scoped_utf_chars.h" 27 #include "test_env.h" 28 29 namespace art { 30 31 static std::mutex gVectorMutex; 32 static std::vector<std::string> gLoadedDescriptors; 33 34 static std::string GetClassName(jvmtiEnv* jenv, JNIEnv* jni_env, jclass klass) { 35 char* name; 36 jvmtiError result = jenv->GetClassSignature(klass, &name, nullptr); 37 if (result != JVMTI_ERROR_NONE) { 38 if (jni_env != nullptr) { 39 JvmtiErrorToException(jni_env, jenv, result); 40 } else { 41 printf("Failed to get class signature.\n"); 42 } 43 return ""; 44 } 45 46 std::string tmp(name); 47 jenv->Deallocate(reinterpret_cast<unsigned char*>(name)); 48 49 return tmp; 50 } 51 52 static void EnableEvents(JNIEnv* env, 53 jboolean enable, 54 decltype(jvmtiEventCallbacks().ClassLoad) class_load, 55 decltype(jvmtiEventCallbacks().ClassPrepare) class_prepare) { 56 if (enable == JNI_FALSE) { 57 jvmtiError ret = jvmti_env->SetEventNotificationMode(JVMTI_DISABLE, 58 JVMTI_EVENT_CLASS_LOAD, 59 nullptr); 60 if (JvmtiErrorToException(env, jvmti_env, ret)) { 61 return; 62 } 63 ret = jvmti_env->SetEventNotificationMode(JVMTI_DISABLE, 64 JVMTI_EVENT_CLASS_PREPARE, 65 nullptr); 66 JvmtiErrorToException(env, jvmti_env, ret); 67 return; 68 } 69 70 jvmtiEventCallbacks callbacks; 71 memset(&callbacks, 0, sizeof(jvmtiEventCallbacks)); 72 callbacks.ClassLoad = class_load; 73 callbacks.ClassPrepare = class_prepare; 74 jvmtiError ret = jvmti_env->SetEventCallbacks(&callbacks, sizeof(callbacks)); 75 if (JvmtiErrorToException(env, jvmti_env, ret)) { 76 return; 77 } 78 79 ret = jvmti_env->SetEventNotificationMode(JVMTI_ENABLE, 80 JVMTI_EVENT_CLASS_LOAD, 81 nullptr); 82 if (JvmtiErrorToException(env, jvmti_env, ret)) { 83 return; 84 } 85 ret = jvmti_env->SetEventNotificationMode(JVMTI_ENABLE, 86 JVMTI_EVENT_CLASS_PREPARE, 87 nullptr); 88 JvmtiErrorToException(env, jvmti_env, ret); 89 } 90 91 static void JNICALL ClassPrepareCallback(jvmtiEnv* jenv, 92 JNIEnv* jni_env, 93 jthread thread ATTRIBUTE_UNUSED, 94 jclass klass) { 95 std::string name = GetClassName(jenv, jni_env, klass); 96 if (name == "") { 97 return; 98 } 99 std::lock_guard<std::mutex> guard(gVectorMutex); 100 gLoadedDescriptors.push_back(name); 101 } 102 103 extern "C" JNIEXPORT jboolean JNICALL Java_android_jvmti_JvmtiActivity_didSeeLoadOf( 104 JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED, jstring descriptor) { 105 std::lock_guard<std::mutex> guard(gVectorMutex); 106 ScopedUtfChars str(env, descriptor); 107 std::string tmp = str.c_str(); 108 bool found = std::find(gLoadedDescriptors.begin(), gLoadedDescriptors.end(), tmp) != 109 gLoadedDescriptors.end(); 110 return found ? JNI_TRUE : JNI_FALSE; 111 } 112 113 extern "C" JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM* vm, 114 char* options ATTRIBUTE_UNUSED, 115 void* reserved ATTRIBUTE_UNUSED) { 116 if (vm->GetEnv(reinterpret_cast<void**>(&jvmti_env), JVMTI_VERSION_1_0) != 0) { 117 LOG(FATAL) << "Could not get shared jvmtiEnv"; 118 } 119 120 SetAllCapabilities(jvmti_env); 121 return 0; 122 } 123 124 extern "C" JNIEXPORT jint JNICALL Agent_OnAttach(JavaVM* vm, 125 char* options ATTRIBUTE_UNUSED, 126 void* reserved ATTRIBUTE_UNUSED) { 127 JNIEnv* env; 128 CHECK_EQ(0, vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6)) 129 << "Could not get JNIEnv"; 130 131 if (vm->GetEnv(reinterpret_cast<void**>(&jvmti_env), JVMTI_VERSION_1_0) != 0) { 132 LOG(FATAL) << "Could not get shared jvmtiEnv"; 133 } 134 135 SetAllCapabilities(jvmti_env); 136 137 EnableEvents(env, JNI_TRUE, nullptr, ClassPrepareCallback); 138 139 return 0; 140 } 141 142 } // namespace art 143