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 "common_helper.h"
18 
19 #include <sstream>
20 #include <string>
21 
22 #include "android-base/stringprintf.h"
23 #include "jni.h"
24 #include "jvmti.h"
25 
26 #include "jvmti_helper.h"
27 
28 namespace art {
29 
GetJavaField(jvmtiEnv * jvmti,JNIEnv * env,jclass field_klass,jfieldID f)30 jobject GetJavaField(jvmtiEnv* jvmti, JNIEnv* env, jclass field_klass, jfieldID f) {
31   jint mods = 0;
32   if (JvmtiErrorToException(env, jvmti, jvmti->GetFieldModifiers(field_klass, f, &mods))) {
33     return nullptr;
34   }
35 
36   bool is_static = (mods & kAccStatic) != 0;
37   return env->ToReflectedField(field_klass, f, is_static);
38 }
39 
GetJavaMethod(jvmtiEnv * jvmti,JNIEnv * env,jmethodID m)40 jobject GetJavaMethod(jvmtiEnv* jvmti, JNIEnv* env, jmethodID m) {
41   jint mods = 0;
42   if (JvmtiErrorToException(env, jvmti, jvmti->GetMethodModifiers(m, &mods))) {
43     return nullptr;
44   }
45 
46   bool is_static = (mods & kAccStatic) != 0;
47   jclass method_klass = nullptr;
48   if (JvmtiErrorToException(env, jvmti, jvmti->GetMethodDeclaringClass(m, &method_klass))) {
49     return nullptr;
50   }
51   jobject res = env->ToReflectedMethod(method_klass, m, is_static);
52   env->DeleteLocalRef(method_klass);
53   return res;
54 }
55 
GetJavaValueByType(JNIEnv * env,char type,jvalue value)56 jobject GetJavaValueByType(JNIEnv* env, char type, jvalue value) {
57   std::string name;
58   switch (type) {
59     case 'V':
60       return nullptr;
61     case '[':
62     case 'L':
63       return value.l;
64     case 'Z':
65       name = "java/lang/Boolean";
66       break;
67     case 'B':
68       name = "java/lang/Byte";
69       break;
70     case 'C':
71       name = "java/lang/Character";
72       break;
73     case 'S':
74       name = "java/lang/Short";
75       break;
76     case 'I':
77       name = "java/lang/Integer";
78       break;
79     case 'J':
80       name = "java/lang/Long";
81       break;
82     case 'F':
83       name = "java/lang/Float";
84       break;
85     case 'D':
86       name = "java/lang/Double";
87       break;
88     default:
89       LOG(FATAL) << "Unable to figure out type!";
90       return nullptr;
91   }
92   std::ostringstream oss;
93   oss << "(" << type << ")L" << name << ";";
94   std::string args = oss.str();
95   jclass target = env->FindClass(name.c_str());
96   jmethodID valueOfMethod = env->GetStaticMethodID(target, "valueOf", args.c_str());
97 
98   CHECK(valueOfMethod != nullptr) << args;
99   jobject res = env->CallStaticObjectMethodA(target, valueOfMethod, &value);
100   env->DeleteLocalRef(target);
101   return res;
102 }
103 
GetJavaValue(jvmtiEnv * jvmtienv,JNIEnv * env,jmethodID m,jvalue value)104 jobject GetJavaValue(jvmtiEnv* jvmtienv, JNIEnv* env, jmethodID m, jvalue value) {
105   char *fname, *fsig, *fgen;
106   if (JvmtiErrorToException(env, jvmtienv, jvmtienv->GetMethodName(m, &fname, &fsig, &fgen))) {
107     return nullptr;
108   }
109   std::string type(fsig);
110   type = type.substr(type.find(')') + 1);
111   jvmtienv->Deallocate(reinterpret_cast<unsigned char*>(fsig));
112   jvmtienv->Deallocate(reinterpret_cast<unsigned char*>(fname));
113   jvmtienv->Deallocate(reinterpret_cast<unsigned char*>(fgen));
114   return GetJavaValueByType(env, type[0], value);
115 }
116 
117 }  // namespace art
118