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
EnableEvent(jvmtiEnv * env,jvmtiEvent evt)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
VMStartCallback(jvmtiEnv * jenv ATTRIBUTE_UNUSED,JNIEnv * jni_env ATTRIBUTE_UNUSED)41 static void JNICALL VMStartCallback(jvmtiEnv *jenv ATTRIBUTE_UNUSED,
42 JNIEnv* jni_env ATTRIBUTE_UNUSED) {
43 printf("VMStart\n");
44 }
45
VMInitCallback(jvmtiEnv * jvmti_env ATTRIBUTE_UNUSED,JNIEnv * jni_env ATTRIBUTE_UNUSED,jthread thread ATTRIBUTE_UNUSED)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
VMDeatchCallback(jvmtiEnv * jenv ATTRIBUTE_UNUSED,JNIEnv * jni_env ATTRIBUTE_UNUSED)52 static void JNICALL VMDeatchCallback(jvmtiEnv *jenv ATTRIBUTE_UNUSED,
53 JNIEnv* jni_env ATTRIBUTE_UNUSED) {
54 printf("VMDeath\n");
55 }
56
57
InstallVMEvents(jvmtiEnv * env)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
OnLoad(JavaVM * vm,char * options ATTRIBUTE_UNUSED,void * reserved ATTRIBUTE_UNUSED)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
Java_art_Test901_setVerboseFlag(JNIEnv * env,jclass Main_klass ATTRIBUTE_UNUSED,jint iflag,jboolean val)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
Java_art_Test901_checkLivePhase(JNIEnv * env,jclass Main_klass ATTRIBUTE_UNUSED)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
CallJvmtiFunction(jvmtiEnv * env,jclass klass,jvmtiError * err)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
Java_art_Test901_checkUnattached(JNIEnv * env ATTRIBUTE_UNUSED,jclass Main_klass)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
Java_art_Test901_getErrorName(JNIEnv * env,jclass Main_klass ATTRIBUTE_UNUSED,jint error)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