1 /* 2 * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 #include <stdlib.h> 25 #include <string.h> 26 #include "jni_tools.h" 27 #include "agent_common.h" 28 #include "jvmti_tools.h" 29 30 #define PASSED 0 31 #define STATUS_FAILED 2 32 33 extern "C" { 34 35 /* ========================================================================== */ 36 37 /* scaffold objects */ 38 static jlong timeout = 0; 39 40 /* test objects */ 41 static jclass testedClass = NULL; 42 static jint klass_byte_count = 0; 43 static unsigned char *klass_bytes = NULL; 44 static int magicIndex = 0; 45 static int ClassFileLoadHookEventFlag = NSK_FALSE; 46 47 const char* CLASS_NAME = "nsk/jvmti/scenarios/multienv/MA06/ma06t001a"; 48 static const jint magicNumber = 0x12345678; 49 50 /* ========================================================================== */ 51 52 /** callback functions **/ 53 54 static void JNICALL 55 ClassFileLoadHook(jvmtiEnv *jvmti_env, JNIEnv *jni_env, 56 jclass class_being_redefined, jobject loader, 57 const char* name, jobject protection_domain, 58 jint class_data_len, const unsigned char* class_data, 59 jint *new_class_data_len, unsigned char** new_class_data) { 60 jint i; 61 62 if (name != NULL && (strcmp(name, CLASS_NAME) == 0)) { 63 ClassFileLoadHookEventFlag = NSK_TRUE; 64 NSK_DISPLAY0("ClassFileLoadHook event\n"); 65 66 if (class_being_redefined == NULL) { 67 /* sent by class load */ 68 if (!NSK_JVMTI_VERIFY(jvmti_env->Allocate(class_data_len, &klass_bytes))) 69 nsk_jvmti_setFailStatus(); 70 else { 71 memcpy(klass_bytes, class_data, class_data_len); 72 klass_byte_count = class_data_len; 73 for (i = 0; i < klass_byte_count - 3; i++) { 74 if (((jint)klass_bytes[i+3] | 75 ((jint)klass_bytes[i+2] << 8) | 76 ((jint)klass_bytes[i+1] << 16) | 77 ((jint)klass_bytes[i] << 24)) == magicNumber) { 78 magicIndex = i; 79 break; 80 } 81 } 82 if (klass_byte_count == 0) { 83 NSK_COMPLAIN0("Cannot find magic number\n"); 84 nsk_jvmti_setFailStatus(); 85 } 86 } 87 } 88 } 89 } 90 91 /* ========================================================================== */ 92 93 static int prepare(jvmtiEnv* jvmti, JNIEnv* jni) { 94 95 NSK_DISPLAY1("Find class: %s\n", CLASS_NAME); 96 if (!NSK_JNI_VERIFY(jni, (testedClass = jni->FindClass(CLASS_NAME)) != NULL)) 97 return NSK_FALSE; 98 99 if (!NSK_JNI_VERIFY(jni, (testedClass = (jclass) jni->NewGlobalRef(testedClass)) != NULL)) 100 return NSK_FALSE; 101 102 return NSK_TRUE; 103 } 104 105 /* ========================================================================== */ 106 107 static int redefine(jvmtiEnv* jvmti, jint value) { 108 jvmtiClassDefinition class_def; 109 110 if (!NSK_VERIFY(klass_byte_count != 0 && klass_bytes != NULL)) 111 return NSK_FALSE; 112 113 if (!NSK_VERIFY(magicIndex != 0)) 114 return NSK_FALSE; 115 116 NSK_DISPLAY1("Redefining with %d\n", value); 117 118 klass_bytes[magicIndex] = 0; 119 klass_bytes[magicIndex+1] = 0; 120 klass_bytes[magicIndex+2] = 0; 121 klass_bytes[magicIndex+3] = (jbyte)value; 122 123 class_def.klass = testedClass; 124 class_def.class_byte_count = klass_byte_count; 125 class_def.class_bytes = klass_bytes; 126 if (!NSK_JVMTI_VERIFY(jvmti->RedefineClasses(1, &class_def))) 127 return NSK_FALSE; 128 129 return NSK_TRUE; 130 } 131 132 /* ========================================================================== */ 133 134 /** Agent algorithm. */ 135 static void JNICALL 136 agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) { 137 138 if (!nsk_jvmti_waitForSync(timeout)) 139 return; 140 141 if (!NSK_VERIFY(ClassFileLoadHookEventFlag)) { 142 NSK_COMPLAIN0("Missing initial ClassFileLoadHook event\n"); 143 nsk_jvmti_setFailStatus(); 144 return; 145 } 146 147 ClassFileLoadHookEventFlag = NSK_FALSE; 148 149 if (!prepare(jvmti, jni)) { 150 nsk_jvmti_setFailStatus(); 151 return; 152 } 153 154 if (!redefine(jvmti, 1)) 155 nsk_jvmti_setFailStatus(); 156 157 /* resume debugee and wait for sync */ 158 if (!nsk_jvmti_resumeSync()) 159 return; 160 if (!nsk_jvmti_waitForSync(timeout)) 161 return; 162 163 if (!NSK_VERIFY(ClassFileLoadHookEventFlag)) { 164 NSK_COMPLAIN0("Missing ClassFileLoadHook event #1\n"); 165 nsk_jvmti_setFailStatus(); 166 } 167 168 ClassFileLoadHookEventFlag = NSK_FALSE; 169 170 /* resume debugee and wait for sync */ 171 if (!nsk_jvmti_resumeSync()) 172 return; 173 if (!nsk_jvmti_waitForSync(timeout)) 174 return; 175 176 if (!NSK_VERIFY(ClassFileLoadHookEventFlag)) { 177 NSK_COMPLAIN0("Missing ClassFileLoadHook event #3\n"); 178 nsk_jvmti_setFailStatus(); 179 } 180 181 if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(JVMTI_DISABLE, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, NULL))) 182 nsk_jvmti_setFailStatus(); 183 184 NSK_TRACE(jni->DeleteGlobalRef(testedClass)); 185 186 if (!nsk_jvmti_resumeSync()) 187 return; 188 } 189 190 /* ========================================================================== */ 191 192 /** Agent library initialization. */ 193 #ifdef STATIC_BUILD 194 JNIEXPORT jint JNICALL Agent_OnLoad_ma06t001(JavaVM *jvm, char *options, void *reserved) { 195 return Agent_Initialize(jvm, options, reserved); 196 } 197 JNIEXPORT jint JNICALL Agent_OnAttach_ma06t001(JavaVM *jvm, char *options, void *reserved) { 198 return Agent_Initialize(jvm, options, reserved); 199 } 200 JNIEXPORT jint JNI_OnLoad_ma06t001(JavaVM *jvm, char *options, void *reserved) { 201 return JNI_VERSION_1_8; 202 } 203 #endif 204 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 205 jvmtiEnv* jvmti = NULL; 206 jvmtiEventCallbacks callbacks; 207 jvmtiCapabilities caps; 208 209 NSK_DISPLAY0("Agent_OnLoad\n"); 210 211 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) 212 return JNI_ERR; 213 214 timeout = nsk_jvmti_getWaitTime() * 60 * 1000; 215 216 if (!NSK_VERIFY((jvmti = 217 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) 218 return JNI_ERR; 219 220 memset(&caps, 0, sizeof(caps)); 221 caps.can_redefine_classes = 1; 222 if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps))) 223 return JNI_ERR; 224 225 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) 226 return JNI_ERR; 227 228 memset(&callbacks, 0, sizeof(callbacks)); 229 callbacks.ClassFileLoadHook = &ClassFileLoadHook; 230 if (!NSK_VERIFY(nsk_jvmti_init_MA(&callbacks))) 231 return JNI_ERR; 232 233 if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, NULL))) 234 return JNI_ERR; 235 236 return JNI_OK; 237 } 238 239 /* ========================================================================== */ 240 241 }