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