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 
DeallocateContents(jvmtiLocalVariableEntry * vars,jint nvars)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 
Java_art_Locals_EnableLocalVariableAccess(JNIEnv * env,jclass)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 
Java_art_Locals_SetLocalVariableObject(JNIEnv * env,jclass,jthread t,jint depth,jint slot,jobject val)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 
Java_art_Locals_SetLocalVariableDouble(JNIEnv * env,jclass,jthread t,jint depth,jint slot,jdouble val)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 
Java_art_Locals_SetLocalVariableFloat(JNIEnv * env,jclass,jthread t,jint depth,jint slot,jfloat val)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 
Java_art_Locals_SetLocalVariableLong(JNIEnv * env,jclass,jthread t,jint depth,jint slot,jlong val)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 
Java_art_Locals_SetLocalVariableInt(JNIEnv * env,jclass,jthread t,jint depth,jint slot,jint val)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 
Java_art_Locals_GetLocalVariableDouble(JNIEnv * env,jclass,jthread t,jint depth,jint slot)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 
Java_art_Locals_GetLocalVariableFloat(JNIEnv * env,jclass,jthread t,jint depth,jint slot)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 
Java_art_Locals_GetLocalVariableLong(JNIEnv * env,jclass,jthread t,jint depth,jint slot)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 
Java_art_Locals_GetLocalVariableInt(JNIEnv * env,jclass,jthread t,jint depth,jint slot)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 
Java_art_Locals_GetLocalInstance(JNIEnv * env,jclass,jthread t,jint depth)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 
Java_art_Locals_GetLocalVariableObject(JNIEnv * env,jclass,jthread t,jint depth,jint slot)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 
Java_art_Locals_GetLocalVariableTable(JNIEnv * env,jclass,jobject m)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