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(NSK_CPP_STUB3(Allocate, 69 jvmti_env, class_data_len, &klass_bytes))) 70 nsk_jvmti_setFailStatus(); 71 else { 72 memcpy(klass_bytes, class_data, class_data_len); 73 klass_byte_count = class_data_len; 74 for (i = 0; i < klass_byte_count - 3; i++) { 75 if (((jint)klass_bytes[i+3] | 76 ((jint)klass_bytes[i+2] << 8) | 77 ((jint)klass_bytes[i+1] << 16) | 78 ((jint)klass_bytes[i] << 24)) == magicNumber) { 79 magicIndex = i; 80 break; 81 } 82 } 83 if (klass_byte_count == 0) { 84 NSK_COMPLAIN0("Cannot find magic number\n"); 85 nsk_jvmti_setFailStatus(); 86 } 87 } 88 } 89 } 90 } 91 92 /* ========================================================================== */ 93 94 static int prepare(jvmtiEnv* jvmti, JNIEnv* jni) { 95 96 NSK_DISPLAY1("Find class: %s\n", CLASS_NAME); 97 if (!NSK_JNI_VERIFY(jni, (testedClass = 98 NSK_CPP_STUB2(FindClass, jni, CLASS_NAME)) != NULL)) 99 return NSK_FALSE; 100 101 if (!NSK_JNI_VERIFY(jni, (testedClass = (jclass) 102 NSK_CPP_STUB2(NewGlobalRef, jni, testedClass)) != NULL)) 103 return NSK_FALSE; 104 105 return NSK_TRUE; 106 } 107 108 /* ========================================================================== */ 109 110 static int redefine(jvmtiEnv* jvmti, jint value) { 111 jvmtiClassDefinition class_def; 112 113 if (!NSK_VERIFY(klass_byte_count != 0 && klass_bytes != NULL)) 114 return NSK_FALSE; 115 116 if (!NSK_VERIFY(magicIndex != 0)) 117 return NSK_FALSE; 118 119 NSK_DISPLAY1("Redefining with %d\n", value); 120 121 klass_bytes[magicIndex] = 0; 122 klass_bytes[magicIndex+1] = 0; 123 klass_bytes[magicIndex+2] = 0; 124 klass_bytes[magicIndex+3] = (jbyte)value; 125 126 class_def.klass = testedClass; 127 class_def.class_byte_count = klass_byte_count; 128 class_def.class_bytes = klass_bytes; 129 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(RedefineClasses, jvmti, 1, &class_def))) 130 return NSK_FALSE; 131 132 return NSK_TRUE; 133 } 134 135 /* ========================================================================== */ 136 137 /** Agent algorithm. */ 138 static void JNICALL 139 agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) { 140 141 if (!nsk_jvmti_waitForSync(timeout)) 142 return; 143 144 if (!NSK_VERIFY(ClassFileLoadHookEventFlag)) { 145 NSK_COMPLAIN0("Missing initial ClassFileLoadHook event\n"); 146 nsk_jvmti_setFailStatus(); 147 return; 148 } 149 150 ClassFileLoadHookEventFlag = NSK_FALSE; 151 152 if (!prepare(jvmti, jni)) { 153 nsk_jvmti_setFailStatus(); 154 return; 155 } 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 (!redefine(jvmti, 2)) 177 nsk_jvmti_setFailStatus(); 178 179 if (!NSK_VERIFY(ClassFileLoadHookEventFlag)) { 180 NSK_COMPLAIN0("Missing ClassFileLoadHook event #3\n"); 181 nsk_jvmti_setFailStatus(); 182 } 183 184 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode, 185 jvmti, JVMTI_DISABLE, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, NULL))) 186 nsk_jvmti_setFailStatus(); 187 188 NSK_TRACE(NSK_CPP_STUB2(DeleteGlobalRef, jni, testedClass)); 189 190 if (!nsk_jvmti_resumeSync()) 191 return; 192 } 193 194 /* ========================================================================== */ 195 196 /** Agent library initialization. */ 197 #ifdef STATIC_BUILD 198 JNIEXPORT jint JNICALL Agent_OnLoad_ma06t001a(JavaVM *jvm, char *options, void *reserved) { 199 return Agent_Initialize(jvm, options, reserved); 200 } 201 JNIEXPORT jint JNICALL Agent_OnAttach_ma06t001a(JavaVM *jvm, char *options, void *reserved) { 202 return Agent_Initialize(jvm, options, reserved); 203 } 204 JNIEXPORT jint JNI_OnLoad_ma06t001a(JavaVM *jvm, char *options, void *reserved) { 205 return JNI_VERSION_1_8; 206 } 207 #endif 208 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 209 jvmtiEnv* jvmti = NULL; 210 jvmtiEventCallbacks callbacks; 211 jvmtiCapabilities caps; 212 213 NSK_DISPLAY0("Agent_OnLoad\n"); 214 215 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) 216 return JNI_ERR; 217 218 timeout = nsk_jvmti_getWaitTime() * 60 * 1000; 219 220 if (!NSK_VERIFY((jvmti = 221 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) 222 return JNI_ERR; 223 224 memset(&caps, 0, sizeof(caps)); 225 caps.can_redefine_classes = 1; 226 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(AddCapabilities, jvmti, &caps))) 227 return JNI_ERR; 228 229 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) 230 return JNI_ERR; 231 232 memset(&callbacks, 0, sizeof(callbacks)); 233 callbacks.ClassFileLoadHook = &ClassFileLoadHook; 234 if (!NSK_VERIFY(nsk_jvmti_init_MA(&callbacks))) 235 return JNI_ERR; 236 237 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode, 238 jvmti, JVMTI_ENABLE, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, NULL))) 239 return JNI_ERR; 240 241 return JNI_OK; 242 } 243 244 /* ========================================================================== */ 245 246 }