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 "jvmti_tools.h" 28 #include "Injector.h" 29 #include "agent_common.h" 30 31 #define PASSED 0 32 33 extern "C" { 34 35 /* ========================================================================== */ 36 37 #define DEFAULT_MAX_NUMBER_OF_CLASSES 100 38 #define DEFAULT_NUMBER_OF_SAMPLES 10 39 #define DEFAULT_SAMPLING_INTERVAL 100 40 #define DEFAULT_PACKAGE_NAME "nsk/jvmti/scenarios/hotswap" 41 #define PROFILE_CLASS_NAME "nsk/share/jvmti/ProfileCollector" 42 43 enum { 44 VM_MODE_COMPILED = 0, 45 VM_MODE_INTERPRETED = 1, 46 VM_MODE_MIXED = 2 47 }; 48 49 /* scaffold objects */ 50 static jlong timeout = 0; 51 52 /* test options */ 53 static int number_of_samples; 54 static jlong sampling_interval; 55 static const char* package_name; 56 static size_t package_name_length; 57 static int vm_mode = VM_MODE_COMPILED; 58 static int bci_mode = BCI_MODE_EMCP; 59 static int sync_freq = 0; 60 61 static jclass profile_klass = NULL; 62 static jfieldID count_field = NULL; 63 64 /* test objects */ 65 static int max_classes; 66 static char** names = NULL; 67 static jvmtiClassDefinition* old_class_def = NULL; 68 static jvmtiClassDefinition* new_class_def = NULL; 69 static int classCount = 0; 70 static int newFlag = NSK_FALSE; 71 72 /* ========================================================================== */ 73 74 static int redefine(jvmtiEnv* jvmti, jvmtiClassDefinition* class_def) { 75 76 if (!NSK_VERIFY(classCount != 0)) 77 return NSK_FALSE; 78 79 NSK_DISPLAY1("Redefining %d classes...\n", classCount); 80 81 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(RedefineClasses, 82 jvmti, classCount, class_def))) 83 return NSK_FALSE; 84 85 return NSK_TRUE; 86 } 87 88 /* ========================================================================== */ 89 90 /** callback functions **/ 91 92 static void JNICALL 93 ClassFileLoadHook(jvmtiEnv *jvmti_env, JNIEnv *jni_env, 94 jclass class_being_redefined, jobject loader, 95 const char* name, jobject protection_domain, 96 jint class_data_len, const unsigned char* class_data, 97 jint *new_class_data_len, unsigned char** new_class_data) { 98 jint name_len; 99 100 if (name != NULL && classCount < max_classes && 101 class_being_redefined == NULL && 102 (strcmp(name, PROFILE_CLASS_NAME) != 0) && 103 (strncmp(name, package_name, package_name_length) == 0)) { 104 NSK_DISPLAY1("ClassFileLoadHook: %s\n", name); 105 name_len = (jint) strlen(name) + 1; 106 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(Allocate, jvmti_env, 107 name_len, (unsigned char**) &names[classCount]))) { 108 nsk_jvmti_setFailStatus(); 109 return; 110 } 111 memcpy(names[classCount], name, name_len); 112 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(Allocate, 113 jvmti_env, class_data_len, (unsigned char**) 114 &old_class_def[classCount].class_bytes))) { 115 nsk_jvmti_setFailStatus(); 116 return; 117 } 118 memcpy((unsigned char*) old_class_def[classCount].class_bytes, 119 class_data, class_data_len); 120 old_class_def[classCount].class_byte_count = class_data_len; 121 classCount++; 122 } 123 } 124 125 static int CompiledMethodLoadEventsCount = 0; 126 127 static void JNICALL 128 CompiledMethodLoad(jvmtiEnv *jvmti_env, jmethodID method, 129 jint code_size, const void* code_addr, jint map_length, 130 const jvmtiAddrLocationMap* map, const void* compile_info) { 131 char *name = NULL; 132 char *signature = NULL; 133 134 CompiledMethodLoadEventsCount++; 135 136 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB5(GetMethodName, 137 jvmti_env, method, &name, &signature, NULL))) { 138 nsk_jvmti_setFailStatus(); 139 return; 140 } 141 NSK_DISPLAY3("CompiledMethodLoad event: %s%s (0x%p)\n", 142 name, signature, code_addr); 143 if (name != NULL) 144 NSK_CPP_STUB2(Deallocate, jvmti_env, (unsigned char*)name); 145 if (signature != NULL) 146 NSK_CPP_STUB2(Deallocate, jvmti_env, (unsigned char*)signature); 147 } 148 149 static int SingleStepEventsCount = 0; 150 151 static void JNICALL 152 SingleStep(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, 153 jmethodID method, jlocation location) { 154 155 SingleStepEventsCount++; 156 } 157 158 static int ExceptionEventsCount = 0; 159 160 static void JNICALL 161 Exception(jvmtiEnv *jvmti_env, JNIEnv *jni_env, jthread thread, 162 jmethodID method, jlocation location, jobject exception, 163 jmethodID catch_method, jlocation catch_location) { 164 165 if (sync_freq && ((ExceptionEventsCount % sync_freq) == 0)) { 166 167 if (nsk_getVerboseMode()) { 168 jclass klass = NULL; 169 char *signature = NULL; 170 171 if (!NSK_JNI_VERIFY(jni_env, (klass = 172 NSK_CPP_STUB2(GetObjectClass, jni_env, exception)) != NULL)) { 173 nsk_jvmti_setFailStatus(); 174 return; 175 } 176 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(GetClassSignature, jvmti_env, 177 klass, &signature, NULL))) { 178 nsk_jvmti_setFailStatus(); 179 return; 180 } 181 NSK_DISPLAY2("Exception event %d: %s\n", 182 ExceptionEventsCount, signature); 183 if (signature != NULL) 184 NSK_CPP_STUB2(Deallocate, jvmti_env, (unsigned char*)signature); 185 } 186 187 if (!redefine(jvmti_env, (bci_mode != BCI_MODE_EMCP && newFlag) ? 188 new_class_def : old_class_def)) 189 nsk_jvmti_setFailStatus(); 190 191 NSK_DISPLAY1("SingleStepEventsCount: %d\n", SingleStepEventsCount); 192 if (vm_mode == VM_MODE_MIXED) { 193 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode, 194 jvmti_env, ((newFlag) ? JVMTI_DISABLE : JVMTI_ENABLE), 195 JVMTI_EVENT_SINGLE_STEP, NULL))) 196 nsk_jvmti_setFailStatus(); 197 } 198 199 if (nsk_getVerboseMode() && bci_mode != BCI_MODE_EMCP) { 200 jint profileCount = NSK_CPP_STUB3(GetStaticIntField, jni_env, 201 profile_klass, count_field); 202 NSK_DISPLAY1("profileCount: %d\n", profileCount); 203 } 204 205 newFlag = (newFlag) ? NSK_FALSE : NSK_TRUE; 206 } 207 208 ExceptionEventsCount++; 209 } 210 211 /* ========================================================================== */ 212 213 static jrawMonitorID waitLock = NULL; 214 215 static int prepare(jvmtiEnv* jvmti, JNIEnv* jni) { 216 int i; 217 218 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode, 219 jvmti, JVMTI_DISABLE, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, NULL))) 220 return NSK_FALSE; 221 222 if (vm_mode != VM_MODE_COMPILED) { 223 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode, 224 jvmti, JVMTI_ENABLE, JVMTI_EVENT_SINGLE_STEP, NULL))) 225 return NSK_FALSE; 226 } 227 228 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(CreateRawMonitor, 229 jvmti, "waitLock", &waitLock))) 230 return NSK_FALSE; 231 232 for (i = 0; i < classCount; i++) { 233 NSK_DISPLAY1("Find class: %s\n", names[i]); 234 if (!NSK_JNI_VERIFY(jni, (old_class_def[i].klass = 235 NSK_CPP_STUB2(FindClass, jni, names[i])) != NULL)) 236 return NSK_FALSE; 237 238 if (!NSK_JNI_VERIFY(jni, (old_class_def[i].klass = (jclass) 239 NSK_CPP_STUB2(NewGlobalRef, jni, 240 old_class_def[i].klass)) != NULL)) 241 return NSK_FALSE; 242 } 243 244 if (bci_mode != BCI_MODE_EMCP) { 245 NSK_DISPLAY1("Find class: %s\n", PROFILE_CLASS_NAME); 246 if (!NSK_JNI_VERIFY(jni, (profile_klass = 247 NSK_CPP_STUB2(FindClass, jni, PROFILE_CLASS_NAME)) != NULL)) 248 return NSK_FALSE; 249 250 if (!NSK_JNI_VERIFY(jni, (profile_klass = (jclass) 251 NSK_CPP_STUB2(NewGlobalRef, jni, profile_klass)) != NULL)) 252 return NSK_FALSE; 253 254 if (!NSK_JNI_VERIFY(jni, (count_field = 255 NSK_CPP_STUB4(GetStaticFieldID, jni, profile_klass, 256 (bci_mode == BCI_MODE_CALL) ? "callCount" : "allocCount", 257 "I")) != NULL)) 258 return NSK_FALSE; 259 260 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(Allocate, jvmti, 261 classCount * sizeof(jvmtiClassDefinition), 262 (unsigned char**) &new_class_def))) 263 return NSK_FALSE; 264 265 for (i = 0; i < classCount; i++) { 266 new_class_def[i].klass = old_class_def[i].klass; 267 if (!Inject(old_class_def[i].class_bytes, 268 old_class_def[i].class_byte_count, 269 (unsigned char**) &new_class_def[i].class_bytes, 270 &new_class_def[i].class_byte_count, bci_mode)) 271 return NSK_FALSE; 272 } 273 } 274 275 if (sync_freq) { 276 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode, 277 jvmti, JVMTI_ENABLE, JVMTI_EVENT_EXCEPTION, NULL))) 278 return NSK_FALSE; 279 } 280 281 return NSK_TRUE; 282 } 283 284 /* ========================================================================== */ 285 286 static int wait_for(jvmtiEnv* jvmti, jlong millis) { 287 288 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(RawMonitorEnter, jvmti, waitLock))) 289 return NSK_FALSE; 290 291 if (!NSK_JVMTI_VERIFY( 292 NSK_CPP_STUB3(RawMonitorWait, jvmti, waitLock, millis))) 293 nsk_jvmti_setFailStatus(); 294 295 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(RawMonitorExit, jvmti, waitLock))) 296 return NSK_FALSE; 297 298 return NSK_TRUE; 299 } 300 301 /* ========================================================================== */ 302 303 /** Agent algorithm. */ 304 static void JNICALL 305 agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) { 306 int i; 307 308 if (!nsk_jvmti_waitForSync(timeout)) 309 return; 310 311 if (!prepare(jvmti, jni)) { 312 nsk_jvmti_setFailStatus(); 313 return; 314 } 315 316 /* resume debugee and wait for sync */ 317 if (!nsk_jvmti_resumeSync()) 318 return; 319 if (!nsk_jvmti_waitForSync(timeout)) 320 return; 321 322 if (sync_freq) { 323 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode, 324 jvmti, JVMTI_DISABLE, JVMTI_EVENT_EXCEPTION, NULL))) 325 nsk_jvmti_setFailStatus(); 326 } else { 327 328 for (i = 0; i < number_of_samples && !nsk_jvmti_isFailStatus(); i++) { 329 wait_for(jvmti, sampling_interval); 330 331 if (!redefine(jvmti, (bci_mode != BCI_MODE_EMCP && newFlag) ? 332 new_class_def : old_class_def)) 333 nsk_jvmti_setFailStatus(); 334 335 NSK_DISPLAY1("SingleStepEventsCount: %d\n", SingleStepEventsCount); 336 if (vm_mode == VM_MODE_MIXED) { 337 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode, 338 jvmti, (((i % 2)==0) ? JVMTI_DISABLE : JVMTI_ENABLE), 339 JVMTI_EVENT_SINGLE_STEP, NULL))) 340 nsk_jvmti_setFailStatus(); 341 } 342 343 if (nsk_getVerboseMode() && bci_mode != BCI_MODE_EMCP) { 344 jint profileCount = NSK_CPP_STUB3(GetStaticIntField, jni, 345 profile_klass, count_field); 346 NSK_DISPLAY1("profileCount: %d\n", profileCount); 347 } 348 349 newFlag = (newFlag) ? NSK_FALSE : NSK_TRUE; 350 } 351 352 } 353 354 if (vm_mode != VM_MODE_COMPILED) { 355 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode, 356 jvmti, JVMTI_DISABLE, JVMTI_EVENT_SINGLE_STEP, NULL))) 357 nsk_jvmti_setFailStatus(); 358 } 359 360 if (!nsk_jvmti_resumeSync()) 361 return; 362 } 363 364 /* ========================================================================== */ 365 366 /** Agent library initialization. */ 367 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 368 jvmtiEnv* jvmti = NULL; 369 jvmtiCapabilities caps; 370 jvmtiEventCallbacks callbacks; 371 const char* optValue; 372 373 NSK_DISPLAY0("Agent_OnLoad\n"); 374 375 /* init framework and parse options */ 376 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) 377 return JNI_ERR; 378 379 timeout = nsk_jvmti_getWaitTime() * 60 * 1000; 380 381 /* get options */ 382 number_of_samples = nsk_jvmti_findOptionIntValue("samples", 383 DEFAULT_NUMBER_OF_SAMPLES); 384 if (!NSK_VERIFY(number_of_samples > 0)) 385 return JNI_ERR; 386 NSK_DISPLAY1("samples: %d\n", number_of_samples); 387 388 sampling_interval = nsk_jvmti_findOptionIntValue("interval", 389 DEFAULT_SAMPLING_INTERVAL); 390 if (!NSK_VERIFY(sampling_interval > 0)) 391 return JNI_ERR; 392 NSK_DISPLAY1("interval: %d\n", sampling_interval); 393 394 package_name = nsk_jvmti_findOptionStringValue("package", 395 DEFAULT_PACKAGE_NAME); 396 if (!NSK_VERIFY(package_name != NULL)) 397 return JNI_ERR; 398 NSK_DISPLAY1("package: %s\n", package_name); 399 400 package_name_length = strlen(package_name); 401 if (!NSK_VERIFY(package_name_length > 0)) 402 return JNI_ERR; 403 404 max_classes = nsk_jvmti_findOptionIntValue("classes", 405 DEFAULT_MAX_NUMBER_OF_CLASSES); 406 if (!NSK_VERIFY(max_classes > 0)) 407 return JNI_ERR; 408 NSK_DISPLAY1("classes: %d\n", max_classes); 409 410 optValue = nsk_jvmti_findOptionValue("mode"); 411 if (optValue != NULL) { 412 if (strcmp(optValue, "compiled") == 0) 413 vm_mode = VM_MODE_COMPILED; 414 else if (strcmp(optValue, "interpreted") == 0) 415 vm_mode = VM_MODE_INTERPRETED; 416 else if (strcmp(optValue, "mixed") == 0) 417 vm_mode = VM_MODE_MIXED; 418 else { 419 NSK_COMPLAIN1("Unknown option value: mode=%s\n", optValue); 420 return JNI_ERR; 421 } 422 } 423 424 optValue = nsk_jvmti_findOptionValue("bci"); 425 if (optValue != NULL) { 426 if (strcmp(optValue, "emcp") == 0) 427 bci_mode = BCI_MODE_EMCP; 428 else if (strcmp(optValue, "call") == 0) 429 bci_mode = BCI_MODE_CALL; 430 else if (strcmp(optValue, "alloc") == 0) 431 bci_mode = BCI_MODE_ALLOC; 432 else { 433 NSK_COMPLAIN1("Unknown option value: bci=%s\n", optValue); 434 return JNI_ERR; 435 } 436 } 437 438 sync_freq = nsk_jvmti_findOptionIntValue("sync", 0); 439 if (!NSK_VERIFY(sync_freq >= 0)) 440 return JNI_ERR; 441 NSK_DISPLAY1("sync: %d\n", sync_freq); 442 443 /* create JVMTI environment */ 444 if (!NSK_VERIFY((jvmti = 445 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) 446 return JNI_ERR; 447 448 /* allocate tables for classes */ 449 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(Allocate, jvmti, 450 max_classes * sizeof(char*), (unsigned char**) &names))) 451 return JNI_ERR; 452 453 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(Allocate, jvmti, 454 max_classes * sizeof(jvmtiClassDefinition), 455 (unsigned char**) &old_class_def))) 456 return JNI_ERR; 457 458 /* add capabilities */ 459 memset(&caps, 0, sizeof(caps)); 460 caps.can_redefine_classes = 1; 461 caps.can_generate_compiled_method_load_events = 1; 462 if (vm_mode != VM_MODE_COMPILED) { 463 caps.can_generate_single_step_events = 1; 464 } 465 if (sync_freq) { 466 caps.can_generate_exception_events = 1; 467 } 468 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(AddCapabilities, jvmti, &caps))) 469 return JNI_ERR; 470 471 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) 472 return JNI_ERR; 473 474 /* set event callbacks */ 475 memset(&callbacks, 0, sizeof(callbacks)); 476 callbacks.ClassFileLoadHook = &ClassFileLoadHook; 477 callbacks.CompiledMethodLoad = &CompiledMethodLoad; 478 if (vm_mode != VM_MODE_COMPILED) { 479 callbacks.SingleStep = &SingleStep; 480 } 481 if (sync_freq) { 482 callbacks.Exception = &Exception; 483 } 484 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(SetEventCallbacks, 485 jvmti, &callbacks, sizeof(callbacks)))) 486 return JNI_ERR; 487 488 /* enable events */ 489 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode, 490 jvmti, JVMTI_ENABLE, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, NULL))) 491 return JNI_ERR; 492 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode, 493 jvmti, JVMTI_ENABLE, JVMTI_EVENT_COMPILED_METHOD_LOAD, NULL))) 494 return JNI_ERR; 495 496 return JNI_OK; 497 } 498 499 /* ========================================================================== */ 500 501 }