1 /* 2 * Copyright (C) 2016 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 "901-hello-ti-agent/basics.h" 18 19 #include <thread> 20 21 #include <jni.h> 22 #include <stdio.h> 23 #include <string.h> 24 #include "android-base/macros.h" 25 #include "jvmti.h" 26 27 // Test infrastructure 28 #include "jvmti_helper.h" 29 #include "test_env.h" 30 31 namespace art { 32 namespace Test901HelloTi { 33 34 static void EnableEvent(jvmtiEnv* env, jvmtiEvent evt) { 35 jvmtiError error = env->SetEventNotificationMode(JVMTI_ENABLE, evt, nullptr); 36 if (error != JVMTI_ERROR_NONE) { 37 printf("Failed to enable event"); 38 } 39 } 40 41 static void JNICALL VMStartCallback(jvmtiEnv *jenv ATTRIBUTE_UNUSED, 42 JNIEnv* jni_env ATTRIBUTE_UNUSED) { 43 printf("VMStart\n"); 44 } 45 46 static void JNICALL VMInitCallback(jvmtiEnv *jvmti_env ATTRIBUTE_UNUSED, 47 JNIEnv* jni_env ATTRIBUTE_UNUSED, 48 jthread thread ATTRIBUTE_UNUSED) { 49 printf("VMInit\n"); 50 } 51 52 static void JNICALL VMDeatchCallback(jvmtiEnv *jenv ATTRIBUTE_UNUSED, 53 JNIEnv* jni_env ATTRIBUTE_UNUSED) { 54 printf("VMDeath\n"); 55 } 56 57 58 static void InstallVMEvents(jvmtiEnv* env) { 59 jvmtiEventCallbacks callbacks; 60 memset(&callbacks, 0, sizeof(jvmtiEventCallbacks)); 61 callbacks.VMStart = VMStartCallback; 62 callbacks.VMInit = VMInitCallback; 63 callbacks.VMDeath = VMDeatchCallback; 64 jvmtiError ret = env->SetEventCallbacks(&callbacks, sizeof(callbacks)); 65 if (ret != JVMTI_ERROR_NONE) { 66 printf("Failed to install callbacks"); 67 } 68 69 EnableEvent(env, JVMTI_EVENT_VM_START); 70 EnableEvent(env, JVMTI_EVENT_VM_INIT); 71 EnableEvent(env, JVMTI_EVENT_VM_DEATH); 72 } 73 74 jint OnLoad(JavaVM* vm, 75 char* options ATTRIBUTE_UNUSED, 76 void* reserved ATTRIBUTE_UNUSED) { 77 printf("Loaded Agent for test 901-hello-ti-agent\n"); 78 fsync(1); 79 jvmtiEnv* env = nullptr; 80 jvmtiEnv* env2 = nullptr; 81 82 #define CHECK_CALL_SUCCESS(c) \ 83 do { \ 84 if ((c) != JNI_OK) { \ 85 printf("call " #c " did not succeed\n"); \ 86 return -1; \ 87 } \ 88 } while (false) 89 90 CHECK_CALL_SUCCESS(vm->GetEnv(reinterpret_cast<void**>(&env), JVMTI_VERSION_1_0)); 91 CHECK_CALL_SUCCESS(vm->GetEnv(reinterpret_cast<void**>(&env2), JVMTI_VERSION_1_0)); 92 if (env == env2) { 93 printf("GetEnv returned same environment twice!\n"); 94 return -1; 95 } 96 unsigned char* local_data = nullptr; 97 CHECK_CALL_SUCCESS(env->Allocate(8, &local_data)); 98 strcpy(reinterpret_cast<char*>(local_data), "hello!!"); 99 CHECK_CALL_SUCCESS(env->SetEnvironmentLocalStorage(local_data)); 100 unsigned char* get_data = nullptr; 101 CHECK_CALL_SUCCESS(env->GetEnvironmentLocalStorage(reinterpret_cast<void**>(&get_data))); 102 if (get_data != local_data) { 103 printf("Got different data from local storage then what was set!\n"); 104 return -1; 105 } 106 CHECK_CALL_SUCCESS(env2->GetEnvironmentLocalStorage(reinterpret_cast<void**>(&get_data))); 107 if (get_data != nullptr) { 108 printf("env2 did not have nullptr local storage.\n"); 109 return -1; 110 } 111 CHECK_CALL_SUCCESS(env->Deallocate(local_data)); 112 jint version = 0; 113 CHECK_CALL_SUCCESS(env->GetVersionNumber(&version)); 114 if ((version & JVMTI_VERSION_1) != JVMTI_VERSION_1) { 115 printf("Unexpected version number!\n"); 116 return -1; 117 } 118 119 InstallVMEvents(env); 120 InstallVMEvents(env2); 121 122 CHECK_CALL_SUCCESS(env->DisposeEnvironment()); 123 CHECK_CALL_SUCCESS(env2->DisposeEnvironment()); 124 #undef CHECK_CALL_SUCCESS 125 126 if (vm->GetEnv(reinterpret_cast<void**>(&jvmti_env), JVMTI_VERSION_1_0)) { 127 printf("Unable to get jvmti env!\n"); 128 return 1; 129 } 130 SetAllCapabilities(jvmti_env); 131 132 jvmtiPhase current_phase; 133 jvmtiError phase_result = jvmti_env->GetPhase(¤t_phase); 134 if (phase_result != JVMTI_ERROR_NONE) { 135 printf("Could not get phase"); 136 return 1; 137 } 138 if (current_phase != JVMTI_PHASE_ONLOAD) { 139 printf("Wrong phase"); 140 return 1; 141 } 142 143 InstallVMEvents(jvmti_env); 144 145 return JNI_OK; 146 } 147 148 extern "C" JNIEXPORT void JNICALL Java_art_Test901_setVerboseFlag( 149 JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED, jint iflag, jboolean val) { 150 jvmtiVerboseFlag flag = static_cast<jvmtiVerboseFlag>(iflag); 151 jvmtiError result = jvmti_env->SetVerboseFlag(flag, val); 152 JvmtiErrorToException(env, jvmti_env, result); 153 } 154 155 extern "C" JNIEXPORT jboolean JNICALL Java_art_Test901_checkLivePhase( 156 JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED) { 157 jvmtiPhase current_phase; 158 jvmtiError phase_result = jvmti_env->GetPhase(¤t_phase); 159 if (JvmtiErrorToException(env, jvmti_env, phase_result)) { 160 return JNI_FALSE; 161 } 162 return (current_phase == JVMTI_PHASE_LIVE) ? JNI_TRUE : JNI_FALSE; 163 } 164 165 static void CallJvmtiFunction(jvmtiEnv* env, jclass klass, jvmtiError* err) { 166 jint n; 167 jmethodID* methods = nullptr; 168 *err = env->GetClassMethods(klass, &n, &methods); 169 } 170 171 extern "C" JNIEXPORT jboolean JNICALL Java_art_Test901_checkUnattached( 172 JNIEnv* env ATTRIBUTE_UNUSED, jclass Main_klass) { 173 jvmtiError res = JVMTI_ERROR_NONE; 174 std::thread t1(CallJvmtiFunction, jvmti_env, Main_klass, &res); 175 t1.join(); 176 return res == JVMTI_ERROR_UNATTACHED_THREAD; 177 } 178 179 extern "C" JNIEXPORT jstring JNICALL Java_art_Test901_getErrorName( 180 JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED, jint error) { 181 char* name; 182 jvmtiError res = jvmti_env->GetErrorName(static_cast<jvmtiError>(error), &name); 183 if (JvmtiErrorToException(env, jvmti_env, res)) { 184 return nullptr; 185 } 186 187 jstring ret_string = env->NewStringUTF(name); 188 jvmtiError dealloc = jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(name)); 189 if (JvmtiErrorToException(env, jvmti_env, dealloc)) { 190 return nullptr; 191 } 192 193 return ret_string; 194 } 195 196 } // namespace Test901HelloTi 197 } // namespace art 198