1 /* 2 * Copyright (c) 2003, 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 <string.h> 25 #include "jvmti.h" 26 #include "agent_common.h" 27 #include "jni_tools.h" 28 #include "jvmti_tools.h" 29 30 extern "C" { 31 32 /* ============================================================================= */ 33 34 /* scaffold objects */ 35 static jlong timeout = 0; 36 37 /* constant names */ 38 #define DEBUGEE_CLASS_NAME "nsk/jvmti/ClassFileLoadHook/classfloadhk004" 39 #define TESTED_CLASS_NAME "nsk/jvmti/ClassFileLoadHook/classfloadhk004r" 40 #define TESTED_CLASS_SIG "L" TESTED_CLASS_NAME ";" 41 42 #define BYTECODE_FIELD_SIG "[B" 43 #define NEW_BYTECODE_FIELD_NAME "newClassBytes" 44 45 static jint newClassSize = 0; 46 static unsigned char* newClassBytes = NULL; 47 48 static volatile int eventsCount = 0; 49 50 /* ============================================================================= */ 51 52 /** Get classfile bytecode from a static field of given class. */ 53 static int getBytecode(jvmtiEnv* jvmti, JNIEnv* jni, jclass cls, 54 const char fieldName[], const char fieldSig[], 55 jint* size, unsigned char* *bytes) { 56 57 jfieldID fieldID = NULL; 58 jbyteArray array = NULL; 59 jbyte* elements; 60 int i; 61 62 NSK_DISPLAY1("Find static field: %s\n", fieldName); 63 if (!NSK_JNI_VERIFY(jni, (fieldID = 64 NSK_CPP_STUB4(GetStaticFieldID, jni, cls, fieldName, fieldSig)) != NULL)) { 65 nsk_jvmti_setFailStatus(); 66 return NSK_FALSE; 67 } 68 NSK_DISPLAY1(" ... got fieldID: 0x%p\n", (void*)fieldID); 69 70 NSK_DISPLAY1("Get classfile bytes array from static field: %s\n", fieldName); 71 if (!NSK_JNI_VERIFY(jni, (array = (jbyteArray) 72 NSK_CPP_STUB3(GetStaticObjectField, jni, cls, fieldID)) != NULL)) { 73 nsk_jvmti_setFailStatus(); 74 return NSK_FALSE; 75 } 76 NSK_DISPLAY1(" ... got array object: 0x%p\n", (void*)array); 77 78 if (!NSK_JNI_VERIFY(jni, (*size = 79 NSK_CPP_STUB2(GetArrayLength, jni, array)) > 0)) { 80 nsk_jvmti_setFailStatus(); 81 return NSK_FALSE; 82 } 83 NSK_DISPLAY1(" ... got array size: %d bytes\n", (int)*size); 84 85 { 86 jboolean isCopy; 87 if (!NSK_JNI_VERIFY(jni, (elements = 88 NSK_CPP_STUB3(GetByteArrayElements, jni, array, 89 &isCopy)) != NULL)) { 90 nsk_jvmti_setFailStatus(); 91 return NSK_FALSE; 92 } 93 } 94 NSK_DISPLAY1(" ... got elements list: 0x%p\n", (void*)elements); 95 96 if (!NSK_JVMTI_VERIFY( 97 NSK_CPP_STUB3(Allocate, jvmti, *size, bytes))) { 98 nsk_jvmti_setFailStatus(); 99 return NSK_FALSE; 100 } 101 NSK_DISPLAY1(" ... created bytes array: 0x%p\n", (void*)*bytes); 102 103 for (i = 0; i < *size; i++) { 104 (*bytes)[i] = (unsigned char)elements[i]; 105 } 106 NSK_DISPLAY1(" ... copied bytecode: %d bytes\n", (int)*size); 107 108 NSK_DISPLAY1("Release elements list: 0x%p\n", (void*)elements); 109 NSK_TRACE(NSK_CPP_STUB4(ReleaseByteArrayElements, jni, array, elements, JNI_ABORT)); 110 NSK_DISPLAY0(" ... released\n"); 111 112 return NSK_TRUE; 113 } 114 115 /* ============================================================================= */ 116 117 /** Agent algorithm. */ 118 static void JNICALL 119 agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) { 120 NSK_DISPLAY0("Wait for debuggee to become ready\n"); 121 if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout))) 122 return; 123 124 /* perform testing */ 125 { 126 NSK_DISPLAY0(">>> Obtain classloader and instrumented bytecode of tested class\n"); 127 { 128 jclass debugeeClass = NULL; 129 130 NSK_DISPLAY1("Find debugee class: %s\n", DEBUGEE_CLASS_NAME); 131 if (!NSK_JNI_VERIFY(jni, (debugeeClass = 132 NSK_CPP_STUB2(FindClass, jni, DEBUGEE_CLASS_NAME)) != NULL)) { 133 nsk_jvmti_setFailStatus(); 134 return; 135 } 136 NSK_DISPLAY1(" ... found class: 0x%p\n", (void*)debugeeClass); 137 138 if (!NSK_VERIFY(getBytecode(jvmti, jni, debugeeClass, 139 NEW_BYTECODE_FIELD_NAME, 140 BYTECODE_FIELD_SIG, 141 &newClassSize, &newClassBytes))) 142 return; 143 } 144 145 NSK_DISPLAY0(">>> Testcase #1: Load tested class and replace bytecode in CLASS_FILE_LOAD_HOOK event\n"); 146 { 147 jvmtiEvent event = JVMTI_EVENT_CLASS_FILE_LOAD_HOOK; 148 149 NSK_DISPLAY1("Enable event: %s\n", "CLASS_FILE_LOAD_HOOK"); 150 if (!NSK_VERIFY(nsk_jvmti_enableEvents(JVMTI_ENABLE, 1, &event, NULL))) 151 return; 152 NSK_DISPLAY0(" ... event enabled\n"); 153 154 NSK_DISPLAY0("Let debugee to load tested class\n"); 155 if (!NSK_VERIFY(nsk_jvmti_resumeSync())) 156 return; 157 NSK_DISPLAY0("Wait for tested class to be loaded\n"); 158 if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout))) 159 return; 160 161 NSK_DISPLAY1("Disable event: %s\n", "CLASS_FILE_LOAD_HOOK"); 162 if (NSK_VERIFY(nsk_jvmti_enableEvents(JVMTI_DISABLE, 1, &event, NULL))) { 163 NSK_DISPLAY0(" ... event disabled\n"); 164 } 165 166 NSK_DISPLAY1("Check if event was received: %s\n", "CLASS_FILE_LOAD_HOOK"); 167 if (eventsCount != 1) { 168 NSK_COMPLAIN3("Unexpected number of %s events for tested class:\n" 169 "# got events: %d\n" 170 "# expected: %d\n", 171 "CLASS_FILE_LOAD_HOOK", 172 eventsCount, 1); 173 nsk_jvmti_setFailStatus(); 174 } else { 175 NSK_DISPLAY1(" ... received: %d events\n", eventsCount); 176 } 177 } 178 179 NSK_DISPLAY0(">>> Clean used data\n"); 180 { 181 } 182 } 183 184 NSK_DISPLAY0("Let debugee to finish\n"); 185 if (!NSK_VERIFY(nsk_jvmti_resumeSync())) 186 return; 187 } 188 189 /* ============================================================================= */ 190 191 /** Callback for CLASS_FILE_LOAD_HOOK event **/ 192 static void JNICALL 193 callbackClassFileLoadHook(jvmtiEnv *jvmti, JNIEnv *jni, 194 jclass class_being_redefined, 195 jobject loader, const char* name, jobject protection_domain, 196 jint class_data_len, const unsigned char* class_data, 197 jint *new_class_data_len, unsigned char** new_class_data) { 198 199 NSK_DISPLAY5(" <CLASS_FILE_LOAD_HOOK>: name: %s, loader: 0x%p, redefined: 0x%p, bytecode: 0x%p:%d\n", 200 nsk_null_string(name), (void*)loader, (void*)class_being_redefined, 201 (void*)class_data, (int)class_data_len); 202 203 if (name != NULL && (strcmp(name, TESTED_CLASS_NAME) == 0)) { 204 NSK_DISPLAY1("SUCCESS! CLASS_FILE_LOAD_HOOK for tested class: %s\n", TESTED_CLASS_NAME); 205 eventsCount++; 206 207 NSK_DISPLAY2("Received bytecode of loaded class: 0x%p:%d\n", 208 (void*)class_data, (int)class_data_len); 209 if (nsk_getVerboseMode()) { 210 nsk_printHexBytes(" ", 16, class_data_len, class_data); 211 } 212 213 NSK_DISPLAY1("Check pointer to new_class_data_len: 0x%p\n", (void*)new_class_data_len); 214 if (new_class_data_len == NULL) { 215 NSK_COMPLAIN1("NULL new_class_data_len pointer passed to CLASS_FILE_LOAD_HOOK: 0x%p\n", 216 (void*)new_class_data_len); 217 nsk_jvmti_setFailStatus(); 218 } 219 220 NSK_DISPLAY1("Check pointer to new_class_data: 0x%p\n", (void*)new_class_data); 221 if (new_class_data == NULL) { 222 NSK_COMPLAIN1("NULL new_class_data pointer passed to CLASS_FILE_LOAD_HOOK: 0x%p\n", 223 (void*)new_class_data); 224 nsk_jvmti_setFailStatus(); 225 } 226 227 if (new_class_data_len != NULL && new_class_data != NULL) { 228 NSK_DISPLAY2("Replace with new bytecode: 0x%p:%d\n", 229 (void*)newClassBytes, (int)newClassSize); 230 if (nsk_getVerboseMode()) { 231 nsk_printHexBytes(" ", 16, newClassSize, newClassBytes); 232 } 233 234 *new_class_data_len = newClassSize; 235 *new_class_data = newClassBytes; 236 } 237 } 238 } 239 240 /* ============================================================================= */ 241 242 /** Agent library initialization. */ 243 #ifdef STATIC_BUILD 244 JNIEXPORT jint JNICALL Agent_OnLoad_classfloadhk004(JavaVM *jvm, char *options, void *reserved) { 245 return Agent_Initialize(jvm, options, reserved); 246 } 247 JNIEXPORT jint JNICALL Agent_OnAttach_classfloadhk004(JavaVM *jvm, char *options, void *reserved) { 248 return Agent_Initialize(jvm, options, reserved); 249 } 250 JNIEXPORT jint JNI_OnLoad_classfloadhk004(JavaVM *jvm, char *options, void *reserved) { 251 return JNI_VERSION_1_8; 252 } 253 #endif 254 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 255 jvmtiEnv* jvmti = NULL; 256 257 /* init framework and parse options */ 258 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) 259 return JNI_ERR; 260 261 timeout = nsk_jvmti_getWaitTime() * 60 * 1000; 262 263 /* create JVMTI environment */ 264 if (!NSK_VERIFY((jvmti = 265 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) 266 return JNI_ERR; 267 268 NSK_DISPLAY1("Add required capability: %s\n", "can_generate_eraly_class_hook_events"); 269 { 270 jvmtiCapabilities caps; 271 272 memset(&caps, 0, sizeof(caps)); 273 caps.can_generate_all_class_hook_events = 1; 274 if (!NSK_JVMTI_VERIFY( 275 NSK_CPP_STUB2(AddCapabilities, jvmti, &caps))) { 276 return JNI_ERR; 277 } 278 } 279 NSK_DISPLAY0(" ... added\n"); 280 281 NSK_DISPLAY1("Set callback for event: %s\n", "CLASS_FILE_LOAD_HOOK"); 282 { 283 jvmtiEventCallbacks callbacks; 284 jint size = (jint)sizeof(callbacks); 285 286 memset(&callbacks, 0, sizeof(callbacks)); 287 callbacks.ClassFileLoadHook = callbackClassFileLoadHook; 288 if (!NSK_JVMTI_VERIFY( 289 NSK_CPP_STUB3(SetEventCallbacks, jvmti, &callbacks, size))) { 290 return JNI_ERR; 291 } 292 } 293 NSK_DISPLAY0(" ... set\n"); 294 295 /* register agent proc and arg */ 296 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) 297 return JNI_ERR; 298 299 return JNI_OK; 300 } 301 302 /* ============================================================================= */ 303 304 }