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