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 "common_helper.h" 18 19 #include "jni.h" 20 #include "jvmti.h" 21 22 #include "jvmti_helper.h" 23 #include "scoped_local_ref.h" 24 #include "test_env.h" 25 26 namespace art { 27 namespace common_locals { 28 29 static void DeallocateContents(jvmtiLocalVariableEntry* vars, jint nvars) { 30 for (jint i = 0; i < nvars; i++) { 31 jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(vars[i].name)); 32 jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(vars[i].signature)); 33 jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(vars[i].generic_signature)); 34 } 35 } 36 37 extern "C" JNIEXPORT void Java_art_Locals_EnableLocalVariableAccess(JNIEnv* env, jclass) { 38 jvmtiCapabilities caps; 39 if (JvmtiErrorToException(env, jvmti_env, jvmti_env->GetCapabilities(&caps))) { 40 return; 41 } 42 caps.can_access_local_variables = 1; 43 JvmtiErrorToException(env, jvmti_env, jvmti_env->AddCapabilities(&caps)); 44 } 45 46 extern "C" JNIEXPORT void Java_art_Locals_SetLocalVariableObject(JNIEnv* env, 47 jclass, 48 jthread t, 49 jint depth, 50 jint slot, 51 jobject val) { 52 JvmtiErrorToException(env, jvmti_env, jvmti_env->SetLocalObject(t, depth, slot, val)); 53 } 54 55 extern "C" JNIEXPORT void Java_art_Locals_SetLocalVariableDouble(JNIEnv* env, 56 jclass, 57 jthread t, 58 jint depth, 59 jint slot, 60 jdouble val) { 61 JvmtiErrorToException(env, jvmti_env, jvmti_env->SetLocalDouble(t, depth, slot, val)); 62 } 63 64 extern "C" JNIEXPORT void Java_art_Locals_SetLocalVariableFloat(JNIEnv* env, 65 jclass, 66 jthread t, 67 jint depth, 68 jint slot, 69 jfloat val) { 70 JvmtiErrorToException(env, jvmti_env, jvmti_env->SetLocalFloat(t, depth, slot, val)); 71 } 72 73 extern "C" JNIEXPORT void Java_art_Locals_SetLocalVariableLong(JNIEnv* env, 74 jclass, 75 jthread t, 76 jint depth, 77 jint slot, 78 jlong val) { 79 JvmtiErrorToException(env, jvmti_env, jvmti_env->SetLocalLong(t, depth, slot, val)); 80 } 81 82 extern "C" JNIEXPORT void Java_art_Locals_SetLocalVariableInt(JNIEnv* env, 83 jclass, 84 jthread t, 85 jint depth, 86 jint slot, 87 jint val) { 88 JvmtiErrorToException(env, jvmti_env, jvmti_env->SetLocalInt(t, depth, slot, val)); 89 } 90 91 extern "C" JNIEXPORT jdouble Java_art_Locals_GetLocalVariableDouble(JNIEnv* env, 92 jclass, 93 jthread t, 94 jint depth, 95 jint slot) { 96 jdouble ret = 0; 97 JvmtiErrorToException(env, jvmti_env, jvmti_env->GetLocalDouble(t, depth, slot, &ret)); 98 return ret; 99 } 100 101 extern "C" JNIEXPORT jfloat Java_art_Locals_GetLocalVariableFloat(JNIEnv* env, 102 jclass, 103 jthread t, 104 jint depth, 105 jint slot) { 106 jfloat ret = 0; 107 JvmtiErrorToException(env, jvmti_env, jvmti_env->GetLocalFloat(t, depth, slot, &ret)); 108 return ret; 109 } 110 111 extern "C" JNIEXPORT jlong Java_art_Locals_GetLocalVariableLong(JNIEnv* env, 112 jclass, 113 jthread t, 114 jint depth, 115 jint slot) { 116 jlong ret = 0; 117 JvmtiErrorToException(env, jvmti_env, jvmti_env->GetLocalLong(t, depth, slot, &ret)); 118 return ret; 119 } 120 121 extern "C" JNIEXPORT jint Java_art_Locals_GetLocalVariableInt(JNIEnv* env, 122 jclass, 123 jthread t, 124 jint depth, 125 jint slot) { 126 jint ret = 0; 127 JvmtiErrorToException(env, jvmti_env, jvmti_env->GetLocalInt(t, depth, slot, &ret)); 128 return ret; 129 } 130 131 extern "C" JNIEXPORT jobject Java_art_Locals_GetLocalInstance(JNIEnv* env, 132 jclass, 133 jthread t, 134 jint depth) { 135 jobject ret = nullptr; 136 JvmtiErrorToException(env, jvmti_env, jvmti_env->GetLocalInstance(t, depth, &ret)); 137 return ret; 138 } 139 140 extern "C" JNIEXPORT jobject Java_art_Locals_GetLocalVariableObject(JNIEnv* env, 141 jclass, 142 jthread t, 143 jint depth, 144 jint slot) { 145 jobject ret = nullptr; 146 JvmtiErrorToException(env, jvmti_env, jvmti_env->GetLocalObject(t, depth, slot, &ret)); 147 return ret; 148 } 149 150 extern "C" JNIEXPORT jobjectArray Java_art_Locals_GetLocalVariableTable(JNIEnv* env, 151 jclass, 152 jobject m) { 153 jmethodID method = env->FromReflectedMethod(m); 154 if (env->ExceptionCheck()) { 155 return nullptr; 156 } 157 ScopedLocalRef<jclass> klass(env, env->FindClass("art/Locals$VariableDescription")); 158 if (env->ExceptionCheck()) { 159 return nullptr; 160 } 161 jint nvars; 162 jvmtiLocalVariableEntry* vars = nullptr; 163 if (JvmtiErrorToException(env, jvmti_env, 164 jvmti_env->GetLocalVariableTable(method, &nvars, &vars))) { 165 return nullptr; 166 } 167 jobjectArray vars_array = env->NewObjectArray(nvars, klass.get(), nullptr); 168 if (env->ExceptionCheck()) { 169 DeallocateContents(vars, nvars); 170 jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(vars)); 171 return nullptr; 172 } 173 174 jmethodID constructor = env->GetMethodID( 175 klass.get(), "<init>", "(JILjava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V"); 176 if (env->ExceptionCheck()) { 177 return nullptr; 178 } 179 for (jint i = 0; i < nvars; i++) { 180 ScopedLocalRef<jstring> name_string(env, env->NewStringUTF(vars[i].name)); 181 ScopedLocalRef<jstring> sig_string(env, env->NewStringUTF(vars[i].signature)); 182 ScopedLocalRef<jstring> generic_sig_string(env, env->NewStringUTF(vars[i].generic_signature)); 183 jobject var_obj = env->NewObject(klass.get(), 184 constructor, 185 vars[i].start_location, 186 vars[i].length, 187 name_string.get(), 188 sig_string.get(), 189 generic_sig_string.get(), 190 vars[i].slot); 191 if (env->ExceptionCheck()) { 192 DeallocateContents(vars, nvars); 193 jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(vars)); 194 return nullptr; 195 } 196 env->SetObjectArrayElement(vars_array, i, var_obj); 197 if (env->ExceptionCheck()) { 198 DeallocateContents(vars, nvars); 199 jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(vars)); 200 return nullptr; 201 } 202 } 203 204 DeallocateContents(vars, nvars); 205 jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(vars)); 206 return vars_array; 207 } 208 209 } // namespace common_locals 210 } // namespace art 211