blob: 3e2b16802bb16317e0fb644af0c30a3e00fc37c9 [file] [log] [blame]
Alex Light1e07ca62016-12-02 11:40:56 -08001/*
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 "ti-agent/common_helper.h"
18
19#include <stdio.h>
20
21#include "jni.h"
22#include "openjdkjvmti/jvmti.h"
Alex Light1e07ca62016-12-02 11:40:56 -080023#include "ti-agent/common_load.h"
24#include "utils.h"
25
26namespace art {
27bool RuntimeIsJVM;
28
29bool IsJVM() {
30 return RuntimeIsJVM;
31}
32
33void SetAllCapabilities(jvmtiEnv* env) {
34 jvmtiCapabilities caps;
35 env->GetPotentialCapabilities(&caps);
36 env->AddCapabilities(&caps);
37}
38
39namespace common_redefine {
40
41using RedefineDirectFunction = jvmtiError (*)(jvmtiEnv*, jclass, jint, const unsigned char*);
42static void DoClassTransformation(jvmtiEnv* jvmti_env, JNIEnv* env,
43 jclass target,
44 jbyteArray class_file_bytes,
45 jbyteArray dex_file_bytes) {
46 jbyteArray desired_array = IsJVM() ? class_file_bytes : dex_file_bytes;
47 jint len = static_cast<jint>(env->GetArrayLength(desired_array));
48 const unsigned char* redef_bytes = reinterpret_cast<const unsigned char*>(
49 env->GetByteArrayElements(desired_array, nullptr));
50 jvmtiError res;
51 if (IsJVM()) {
52 jvmtiClassDefinition def;
53 def.klass = target;
54 def.class_byte_count = static_cast<jint>(len);
55 def.class_bytes = redef_bytes;
56 res = jvmti_env->RedefineClasses(1, &def);
57 } else {
58 RedefineDirectFunction f =
59 reinterpret_cast<RedefineDirectFunction>(jvmti_env->functions->reserved3);
60 res = f(jvmti_env, target, len, redef_bytes);
61 }
62 if (res != JVMTI_ERROR_NONE) {
63 printf("Redefinition failed!");
64 }
65}
66
67// Magic JNI export that classes can use for redefining classes.
68// To use classes should declare this as a native function with signature (Ljava/lang/Class;[B[B)V
69extern "C" JNIEXPORT void JNICALL Java_Main_doCommonClassRedefinition(JNIEnv* env,
70 jclass,
71 jclass target,
72 jbyteArray class_file_bytes,
73 jbyteArray dex_file_bytes) {
74 DoClassTransformation(jvmti_env, env, target, class_file_bytes, dex_file_bytes);
75}
76
77// Don't do anything
78jint OnLoad(JavaVM* vm,
79 char* options ATTRIBUTE_UNUSED,
80 void* reserved ATTRIBUTE_UNUSED) {
81 if (vm->GetEnv(reinterpret_cast<void**>(&jvmti_env), JVMTI_VERSION_1_0)) {
82 printf("Unable to get jvmti env!\n");
83 return 1;
84 }
85 SetAllCapabilities(jvmti_env);
86 return 0;
87}
88
89} // namespace common_redefine
90
91} // namespace art