/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "common_helper.h" #include "jni.h" #include "jvmti.h" #include "jvmti_helper.h" #include "scoped_local_ref.h" #include "test_env.h" namespace art { namespace common_locals { static void DeallocateContents(jvmtiLocalVariableEntry* vars, jint nvars) { for (jint i = 0; i < nvars; i++) { jvmti_env->Deallocate(reinterpret_cast(vars[i].name)); jvmti_env->Deallocate(reinterpret_cast(vars[i].signature)); jvmti_env->Deallocate(reinterpret_cast(vars[i].generic_signature)); } } extern "C" JNIEXPORT void Java_art_Locals_EnableLocalVariableAccess(JNIEnv* env, jclass) { jvmtiCapabilities caps; if (JvmtiErrorToException(env, jvmti_env, jvmti_env->GetCapabilities(&caps))) { return; } caps.can_access_local_variables = 1; JvmtiErrorToException(env, jvmti_env, jvmti_env->AddCapabilities(&caps)); } extern "C" JNIEXPORT void Java_art_Locals_SetLocalVariableObject(JNIEnv* env, jclass, jthread t, jint depth, jint slot, jobject val) { JvmtiErrorToException(env, jvmti_env, jvmti_env->SetLocalObject(t, depth, slot, val)); } extern "C" JNIEXPORT void Java_art_Locals_SetLocalVariableDouble(JNIEnv* env, jclass, jthread t, jint depth, jint slot, jdouble val) { JvmtiErrorToException(env, jvmti_env, jvmti_env->SetLocalDouble(t, depth, slot, val)); } extern "C" JNIEXPORT void Java_art_Locals_SetLocalVariableFloat(JNIEnv* env, jclass, jthread t, jint depth, jint slot, jfloat val) { JvmtiErrorToException(env, jvmti_env, jvmti_env->SetLocalFloat(t, depth, slot, val)); } extern "C" JNIEXPORT void Java_art_Locals_SetLocalVariableLong(JNIEnv* env, jclass, jthread t, jint depth, jint slot, jlong val) { JvmtiErrorToException(env, jvmti_env, jvmti_env->SetLocalLong(t, depth, slot, val)); } extern "C" JNIEXPORT void Java_art_Locals_SetLocalVariableInt(JNIEnv* env, jclass, jthread t, jint depth, jint slot, jint val) { JvmtiErrorToException(env, jvmti_env, jvmti_env->SetLocalInt(t, depth, slot, val)); } extern "C" JNIEXPORT jdouble Java_art_Locals_GetLocalVariableDouble(JNIEnv* env, jclass, jthread t, jint depth, jint slot) { jdouble ret = 0; JvmtiErrorToException(env, jvmti_env, jvmti_env->GetLocalDouble(t, depth, slot, &ret)); return ret; } extern "C" JNIEXPORT jfloat Java_art_Locals_GetLocalVariableFloat(JNIEnv* env, jclass, jthread t, jint depth, jint slot) { jfloat ret = 0; JvmtiErrorToException(env, jvmti_env, jvmti_env->GetLocalFloat(t, depth, slot, &ret)); return ret; } extern "C" JNIEXPORT jlong Java_art_Locals_GetLocalVariableLong(JNIEnv* env, jclass, jthread t, jint depth, jint slot) { jlong ret = 0; JvmtiErrorToException(env, jvmti_env, jvmti_env->GetLocalLong(t, depth, slot, &ret)); return ret; } extern "C" JNIEXPORT jint Java_art_Locals_GetLocalVariableInt(JNIEnv* env, jclass, jthread t, jint depth, jint slot) { jint ret = 0; JvmtiErrorToException(env, jvmti_env, jvmti_env->GetLocalInt(t, depth, slot, &ret)); return ret; } extern "C" JNIEXPORT jobject Java_art_Locals_GetLocalInstance(JNIEnv* env, jclass, jthread t, jint depth) { jobject ret = nullptr; JvmtiErrorToException(env, jvmti_env, jvmti_env->GetLocalInstance(t, depth, &ret)); return ret; } extern "C" JNIEXPORT jobject Java_art_Locals_GetLocalVariableObject(JNIEnv* env, jclass, jthread t, jint depth, jint slot) { jobject ret = nullptr; JvmtiErrorToException(env, jvmti_env, jvmti_env->GetLocalObject(t, depth, slot, &ret)); return ret; } extern "C" JNIEXPORT jobjectArray Java_art_Locals_GetLocalVariableTable(JNIEnv* env, jclass, jobject m) { jmethodID method = env->FromReflectedMethod(m); if (env->ExceptionCheck()) { return nullptr; } ScopedLocalRef klass(env, env->FindClass("art/Locals$VariableDescription")); if (env->ExceptionCheck()) { return nullptr; } jint nvars; jvmtiLocalVariableEntry* vars = nullptr; if (JvmtiErrorToException(env, jvmti_env, jvmti_env->GetLocalVariableTable(method, &nvars, &vars))) { return nullptr; } jobjectArray vars_array = env->NewObjectArray(nvars, klass.get(), nullptr); if (env->ExceptionCheck()) { DeallocateContents(vars, nvars); jvmti_env->Deallocate(reinterpret_cast(vars)); return nullptr; } jmethodID constructor = env->GetMethodID( klass.get(), "", "(JILjava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V"); if (env->ExceptionCheck()) { return nullptr; } for (jint i = 0; i < nvars; i++) { ScopedLocalRef name_string(env, env->NewStringUTF(vars[i].name)); ScopedLocalRef sig_string(env, env->NewStringUTF(vars[i].signature)); ScopedLocalRef generic_sig_string(env, env->NewStringUTF(vars[i].generic_signature)); jobject var_obj = env->NewObject(klass.get(), constructor, vars[i].start_location, vars[i].length, name_string.get(), sig_string.get(), generic_sig_string.get(), vars[i].slot); if (env->ExceptionCheck()) { DeallocateContents(vars, nvars); jvmti_env->Deallocate(reinterpret_cast(vars)); return nullptr; } env->SetObjectArrayElement(vars_array, i, var_obj); if (env->ExceptionCheck()) { DeallocateContents(vars, nvars); jvmti_env->Deallocate(reinterpret_cast(vars)); return nullptr; } } DeallocateContents(vars, nvars); jvmti_env->Deallocate(reinterpret_cast(vars)); return vars_array; } } // namespace common_locals } // namespace art