211 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			211 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			C++
		
	
	
	
| /*
 | |
|  * 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<unsigned char*>(vars[i].name));
 | |
|     jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(vars[i].signature));
 | |
|     jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(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<jclass> 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<unsigned char*>(vars));
 | |
|     return nullptr;
 | |
|   }
 | |
| 
 | |
|   jmethodID constructor = env->GetMethodID(
 | |
|       klass.get(), "<init>", "(JILjava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V");
 | |
|   if (env->ExceptionCheck()) {
 | |
|     return nullptr;
 | |
|   }
 | |
|   for (jint i = 0; i < nvars; i++) {
 | |
|     ScopedLocalRef<jstring> name_string(env, env->NewStringUTF(vars[i].name));
 | |
|     ScopedLocalRef<jstring> sig_string(env, env->NewStringUTF(vars[i].signature));
 | |
|     ScopedLocalRef<jstring> 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<unsigned char*>(vars));
 | |
|       return nullptr;
 | |
|     }
 | |
|     env->SetObjectArrayElement(vars_array, i, var_obj);
 | |
|     if (env->ExceptionCheck()) {
 | |
|       DeallocateContents(vars, nvars);
 | |
|       jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(vars));
 | |
|       return nullptr;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   DeallocateContents(vars, nvars);
 | |
|   jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(vars));
 | |
|   return vars_array;
 | |
| }
 | |
| 
 | |
| }  // namespace common_locals
 | |
| }  // namespace art
 |