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 <string.h>
  25 #include "jvmti.h"
  26 #include "agent_common.h"
  27 #include "jni_tools.h"
  28 #include "jvmti_tools.h"
  29 #include "JVMTITools.h"
  30 
  31 extern "C" {
  32 
  33 /* ============================================================================= */
  34 
  35 /* scaffold objects */
  36 static jvmtiEnv *jvmti = NULL;
  37 static jlong timeout = 0;
  38 static jrawMonitorID syncLock = NULL;
  39 
  40 /* constant names */
  41 #define STEP_NUMBER 3
  42 #define CLASS_NAME "nsk/jvmti/scenarios/events/EM02/em02t010"
  43 #define FIELD_ACC_NAME "testedField_acc"
  44 #define FIELD_MOD_NAME "testedField_mod"
  45 #define JVMTI_EVENT_COUNT   (int)(JVMTI_MAX_EVENT_TYPE_VAL - JVMTI_MIN_EVENT_TYPE_VAL + 1)
  46 #define NUMBER_OF_INVOCATIONS 1000
  47 
  48 static int eventCount[JVMTI_EVENT_COUNT];
  49 static int newEventCount[JVMTI_EVENT_COUNT];
  50 
  51 /* ============================================================================= */
  52 
  53 static void
  54 showEventStatistics(int step) {
  55     int i;
  56     const char* str;
  57     int *currentCounts = (step == 1) ? &eventCount[0] : &newEventCount[0];
  58 
  59     NSK_DISPLAY0("\n");
  60     NSK_DISPLAY1("Event statistics for %d step:\n", step);
  61     NSK_DISPLAY0("-----------------------------\n");
  62     for (i = 0; i < JVMTI_EVENT_COUNT; i++) {
  63         if (currentCounts[i] > 0) {
  64             str = TranslateEvent((jvmtiEvent)(i+JVMTI_MIN_EVENT_TYPE_VAL));
  65             NSK_DISPLAY2("%-40s %7d\n", str, currentCounts[i]);
  66         }
  67     }
  68 }
  69 
  70 /* ========================================================================== */
  71 
  72 int checkEvents(int step) {
  73     int i;
  74     jvmtiEvent curr;
  75     int result = NSK_TRUE;
  76     int *currentCounts;
  77     int isExpected = 0;
  78 
  79     switch (step) {
  80         case 1:
  81             currentCounts = &eventCount[0];
  82             break;
  83 
  84         case 2:
  85         case 3:
  86             currentCounts = &newEventCount[0];
  87             break;
  88 
  89         default:
  90             NSK_COMPLAIN1("Unexpected step no: %d\n", step);
  91             return NSK_FALSE;
  92     }
  93 
  94     for (i = 0; i < JVMTI_EVENT_COUNT; i++) {
  95 
  96         curr = (jvmtiEvent) (i + JVMTI_MIN_EVENT_TYPE_VAL);
  97 
  98         switch (step) {
  99             case 1:
 100                 isExpected = ((curr == JVMTI_EVENT_VM_INIT)
 101                                 || (curr == JVMTI_EVENT_FIELD_MODIFICATION)
 102                                 || (curr == JVMTI_EVENT_FIELD_ACCESS));
 103                 break;
 104 
 105             case 2:
 106                 isExpected = ((curr == JVMTI_EVENT_FIELD_MODIFICATION)
 107                                 || (curr == JVMTI_EVENT_FIELD_ACCESS));
 108                 break;
 109 
 110             case 3:
 111                 isExpected = (curr == JVMTI_EVENT_VM_DEATH);
 112                 break;
 113         }
 114 
 115         if (isExpected) {
 116             if (curr == JVMTI_EVENT_FIELD_MODIFICATION ||
 117                                 curr == JVMTI_EVENT_FIELD_ACCESS) {
 118                 if (currentCounts[i] != NUMBER_OF_INVOCATIONS) {
 119                     NSK_COMPLAIN3("Unexpected number of %s events %d, expected value is %d\n",
 120                                         TranslateEvent(curr),
 121                                         currentCounts[i],
 122                                         NUMBER_OF_INVOCATIONS);
 123                     result = NSK_FALSE;
 124                 }
 125             } else {
 126                 if (currentCounts[i] < 1) {
 127                         NSK_COMPLAIN2("Unexpected events number %7d for %s\n\texpected value must be greater than 1\n",
 128                                             currentCounts[i],
 129                                             TranslateEvent(curr));
 130                     result = NSK_FALSE;
 131                 }
 132             }
 133 
 134         } else {
 135 
 136             if (currentCounts[i] > 0) {
 137                 NSK_COMPLAIN2("Unexpected event %s was sent %d times\n",
 138                                     TranslateEvent(curr),
 139                                     currentCounts[i]);
 140                 result = NSK_FALSE;
 141             }
 142         }
 143     }
 144 
 145     return result;
 146 }
 147 
 148 static void
 149 changeCount(jvmtiEvent event, int *currentCounts) {
 150 
 151     if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorEnter(syncLock)))
 152         nsk_jvmti_setFailStatus();
 153 
 154     currentCounts[event - JVMTI_MIN_EVENT_TYPE_VAL]++;
 155 
 156     if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorExit(syncLock)))
 157         nsk_jvmti_setFailStatus();
 158 
 159 }
 160 
 161 /* ============================================================================= */
 162 
 163 /* callbacks */
 164 JNIEXPORT void JNICALL
 165 cbVMInit(jvmtiEnv* jvmti, JNIEnv* jni_env, jthread thread) {
 166     changeCount(JVMTI_EVENT_VM_INIT, &eventCount[0]);
 167 }
 168 
 169 JNIEXPORT void JNICALL
 170 cbVMDeath(jvmtiEnv* jvmti, JNIEnv* jni_env) {
 171     changeCount(JVMTI_EVENT_VM_DEATH, &newEventCount[0]);
 172     showEventStatistics(STEP_NUMBER);
 173     if (!checkEvents(STEP_NUMBER))
 174         nsk_jvmti_setFailStatus();
 175 
 176     if (!NSK_JVMTI_VERIFY(jvmti->DestroyRawMonitor(syncLock)))
 177         nsk_jvmti_setFailStatus();
 178 
 179 }
 180 
 181 void JNICALL
 182 cbException(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
 183                 jmethodID method, jlocation location, jobject exception,
 184                 jmethodID catch_method, jlocation catch_location) {
 185 
 186     changeCount(JVMTI_EVENT_EXCEPTION, &eventCount[0]);
 187 }
 188 
 189 void JNICALL
 190 cbExceptionCatch(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
 191                 jmethodID method, jlocation location, jobject exception) {
 192 
 193     changeCount(JVMTI_EVENT_EXCEPTION_CATCH, &eventCount[0]);
 194 }
 195 
 196 void JNICALL
 197 cbSingleStep(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
 198                 jmethodID method, jlocation location) {
 199 
 200     changeCount(JVMTI_EVENT_SINGLE_STEP, &eventCount[0]);
 201 }
 202 
 203 void JNICALL
 204 cbFramePop(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
 205                 jmethodID method, jboolean was_popped_by_exception) {
 206     changeCount(JVMTI_EVENT_FRAME_POP, &eventCount[0]);
 207 }
 208 
 209 void JNICALL
 210 cbBreakpoint(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
 211                 jmethodID method, jlocation location) {
 212     changeCount(JVMTI_EVENT_BREAKPOINT, &eventCount[0]);
 213 }
 214 
 215 void JNICALL
 216 cbFieldAccess(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
 217                 jmethodID method, jlocation location, jclass field_klass,
 218                 jobject object, jfieldID field) {
 219 
 220     changeCount(JVMTI_EVENT_FIELD_ACCESS, &eventCount[0]);
 221 }
 222 
 223 void JNICALL
 224 cbFieldModification(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
 225                 jmethodID method, jlocation location, jclass field_klass,
 226                 jobject object, jfieldID field, char signature_type,
 227                 jvalue new_value) {
 228 
 229     changeCount(JVMTI_EVENT_FIELD_MODIFICATION, &eventCount[0]);
 230 }
 231 
 232 void JNICALL
 233 cbNewFieldAccess(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
 234                 jmethodID method, jlocation location, jclass field_klass,
 235                 jobject object, jfieldID field) {
 236 
 237     changeCount(JVMTI_EVENT_FIELD_ACCESS, &newEventCount[0]);
 238 }
 239 
 240 void JNICALL
 241 cbNewFieldModification(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
 242                 jmethodID method, jlocation location, jclass field_klass,
 243                 jobject object, jfieldID field, char signature_type,
 244                 jvalue new_value) {
 245 
 246     changeCount(JVMTI_EVENT_FIELD_MODIFICATION, &newEventCount[0]);
 247 }
 248 
 249 void JNICALL
 250 cbMethodEntry(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
 251                 jmethodID method) {
 252 
 253     changeCount(JVMTI_EVENT_METHOD_ENTRY, &eventCount[0]);
 254 }
 255 
 256 void JNICALL
 257 cbMethodExit(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
 258                 jmethodID method, jboolean was_popped_by_exception,
 259                 jvalue return_value) {
 260 
 261     changeCount(JVMTI_EVENT_METHOD_EXIT, &eventCount[0]);
 262 }
 263 
 264 void JNICALL
 265 cbNativeMethodBind(jvmtiEnv *jvmti_env, JNIEnv* jni_env,jthread thread,
 266                 jmethodID method, void* address, void** new_address_ptr) {
 267     changeCount(JVMTI_EVENT_NATIVE_METHOD_BIND, &eventCount[0]);
 268 }
 269 
 270 void JNICALL
 271 cbMonitorWait(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
 272                     jobject object, jlong tout) {
 273 
 274     changeCount(JVMTI_EVENT_MONITOR_WAIT, &eventCount[0]);
 275 }
 276 
 277 void JNICALL
 278 cbMonitorWaited(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
 279                     jobject object, jboolean timed_out) {
 280 
 281     changeCount(JVMTI_EVENT_MONITOR_WAITED, &eventCount[0]);
 282 }
 283 
 284 JNIEXPORT void JNICALL
 285 cbMonitorContendedEnter(jvmtiEnv* jvmti, JNIEnv* jni_env, jthread thread,
 286                             jobject object) {
 287 
 288     changeCount(JVMTI_EVENT_MONITOR_CONTENDED_ENTER, &eventCount[0]);
 289 }
 290 
 291 void JNICALL
 292 cbMonitorContendedEntered(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
 293                             jobject object) {
 294 
 295     changeCount(JVMTI_EVENT_MONITOR_CONTENDED_ENTERED, &eventCount[0]);
 296 }
 297 
 298 void JNICALL
 299 cbCompiledMethodLoad(jvmtiEnv *jvmti_env, jmethodID method, jint code_size,
 300                 const void* code_addr, jint map_length,
 301                 const jvmtiAddrLocationMap* map, const void* compile_info) {
 302     changeCount(JVMTI_EVENT_COMPILED_METHOD_LOAD, &eventCount[0]);
 303 }
 304 
 305 void JNICALL
 306 cbCompiledMethodUnload(jvmtiEnv *jvmti_env, jmethodID method,
 307                 const void* code_addr) {
 308     changeCount(JVMTI_EVENT_COMPILED_METHOD_UNLOAD, &eventCount[0]);
 309 }
 310 
 311 void JNICALL
 312 cbGarbageCollectionStart(jvmtiEnv *jvmti_env) {
 313     changeCount(JVMTI_EVENT_GARBAGE_COLLECTION_START, &eventCount[0]);
 314 }
 315 
 316 void JNICALL
 317 cbGarbageCollectionFinish(jvmtiEnv *jvmti_env) {
 318     changeCount(JVMTI_EVENT_GARBAGE_COLLECTION_FINISH, &eventCount[0]);
 319 }
 320 
 321 void JNICALL
 322 cbObjectFree(jvmtiEnv *jvmti_env, jlong tag) {
 323 
 324     changeCount(JVMTI_EVENT_OBJECT_FREE, &eventCount[0]);
 325 }
 326 
 327 void JNICALL
 328 cbVMObjectAlloc(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
 329                     jobject object, jclass object_klass, jlong size) {
 330 
 331     changeCount(JVMTI_EVENT_VM_OBJECT_ALLOC, &eventCount[0]);
 332 }
 333 
 334 /* ============================================================================= */
 335 
 336 static int enableEvent(jvmtiEvent event) {
 337 
 338     if (nsk_jvmti_isOptionalEvent(event)
 339             && (event != JVMTI_EVENT_FIELD_MODIFICATION)
 340             && (event != JVMTI_EVENT_FIELD_ACCESS)) {
 341         if (!NSK_JVMTI_VERIFY_CODE(JVMTI_ERROR_MUST_POSSESS_CAPABILITY,
 342                 jvmti->SetEventNotificationMode(JVMTI_ENABLE, event, NULL))) {
 343             NSK_COMPLAIN1("Unexpected error enabling %s\n",
 344                 TranslateEvent(event));
 345             return NSK_FALSE;
 346         }
 347     } else {
 348         if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(JVMTI_ENABLE, event, NULL))) {
 349             NSK_COMPLAIN1("Unexpected error enabling %s\n",
 350                 TranslateEvent(event));
 351             return NSK_FALSE;
 352         }
 353     }
 354 
 355     return NSK_TRUE;
 356 }
 357 
 358 /**
 359  * Enable or disable tested events.
 360  */
 361 static int enableEventList() {
 362 
 363     int i, result;
 364 
 365     result = enableEvent(JVMTI_EVENT_VM_INIT);
 366 
 367     result = result && enableEvent(JVMTI_EVENT_VM_DEATH);
 368 
 369     /* enabling optional events */
 370     for (i = 0; i < JVMTI_EVENT_COUNT; i++) {
 371         jvmtiEvent event = (jvmtiEvent)(i+JVMTI_MIN_EVENT_TYPE_VAL);
 372 
 373         if (nsk_jvmti_isOptionalEvent(event))
 374             result = result && enableEvent(event);
 375     }
 376 
 377     if (result == NSK_FALSE) {
 378         nsk_jvmti_setFailStatus();
 379         return NSK_FALSE;
 380     }
 381 
 382     return NSK_TRUE;
 383 }
 384 
 385 /* ============================================================================= */
 386 
 387 static int
 388 setCallBacks(int step) {
 389 
 390     int i;
 391 
 392     jvmtiEventCallbacks eventCallbacks;
 393     memset(&eventCallbacks, 0, sizeof(eventCallbacks));
 394 
 395     switch (step) {
 396         case 1:
 397             for (i = 0; i < JVMTI_EVENT_COUNT; i++) {
 398                 eventCount[i] = 0;
 399             }
 400 
 401             eventCallbacks.VMInit                    = cbVMInit;
 402             eventCallbacks.Exception                 = cbException;
 403             eventCallbacks.ExceptionCatch            = cbExceptionCatch;
 404             eventCallbacks.SingleStep                = cbSingleStep;
 405             eventCallbacks.FramePop                  = cbFramePop;
 406             eventCallbacks.Breakpoint                = cbBreakpoint;
 407             eventCallbacks.FieldAccess               = cbFieldAccess;
 408             eventCallbacks.FieldModification         = cbFieldModification;
 409             eventCallbacks.MethodEntry               = cbMethodEntry;
 410             eventCallbacks.MethodExit                = cbMethodExit;
 411             eventCallbacks.NativeMethodBind          = cbNativeMethodBind;
 412             eventCallbacks.CompiledMethodLoad        = cbCompiledMethodLoad;
 413             eventCallbacks.CompiledMethodUnload      = cbCompiledMethodUnload;
 414             eventCallbacks.MonitorWait               = cbMonitorWait;
 415             eventCallbacks.MonitorWaited             = cbMonitorWaited;
 416             eventCallbacks.MonitorContendedEnter     = cbMonitorContendedEnter;
 417             eventCallbacks.MonitorContendedEntered   = cbMonitorContendedEntered;
 418             eventCallbacks.GarbageCollectionStart    = cbGarbageCollectionStart;
 419             eventCallbacks.GarbageCollectionFinish   = cbGarbageCollectionFinish;
 420             eventCallbacks.ObjectFree                = cbObjectFree;
 421             eventCallbacks.VMObjectAlloc             = cbVMObjectAlloc;
 422             break;
 423 
 424         case 2:
 425             for (i = 0; i < JVMTI_EVENT_COUNT; i++) {
 426                 newEventCount[i] = 0;
 427             }
 428 
 429             eventCallbacks.FieldAccess               = cbNewFieldAccess;
 430             eventCallbacks.FieldModification         = cbNewFieldModification;
 431             break;
 432 
 433         case 3:
 434             for (i = 0; i < JVMTI_EVENT_COUNT; i++) {
 435                 newEventCount[i] = 0;
 436             }
 437 
 438             eventCallbacks.VMDeath                   = cbVMDeath;
 439             break;
 440 
 441     }
 442     if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&eventCallbacks, sizeof(eventCallbacks))))
 443         return NSK_FALSE;
 444 
 445     return NSK_TRUE;
 446 }
 447 
 448 /* ============================================================================= */
 449 
 450 /** Agent algorithm. */
 451 static void JNICALL
 452 agentProc(jvmtiEnv* jvmti, JNIEnv* agentJNI, void* arg) {
 453 
 454     int i;
 455     jfieldID field_accID, field_modID;
 456     jclass cls;
 457 
 458 
 459     if (!nsk_jvmti_waitForSync(timeout))
 460         return;
 461 
 462     if (!NSK_JNI_VERIFY(agentJNI, (cls = agentJNI->FindClass(CLASS_NAME)) != NULL))
 463         return;
 464 
 465     if (!NSK_JNI_VERIFY(agentJNI, (field_accID =
 466             agentJNI->GetStaticFieldID(cls, FIELD_ACC_NAME, "I")) != NULL))
 467         return;
 468 
 469     if (!NSK_JNI_VERIFY(agentJNI, (field_modID =
 470             agentJNI->GetStaticFieldID(cls, FIELD_MOD_NAME, "I")) != NULL))
 471         return;
 472 
 473     if (!NSK_JVMTI_VERIFY(jvmti->SetFieldModificationWatch(cls, field_modID)))
 474         return;
 475 
 476     if (!NSK_JVMTI_VERIFY(jvmti->SetFieldAccessWatch(cls, field_accID)))
 477         return;
 478 
 479     if (!nsk_jvmti_resumeSync())
 480         return;
 481 
 482     for (i = 1; i <= STEP_NUMBER; i++) {
 483 
 484         if (!nsk_jvmti_waitForSync(timeout))
 485             return;
 486 
 487         if (i < STEP_NUMBER) {
 488             showEventStatistics(i);
 489             if (!checkEvents(i))
 490                 nsk_jvmti_setFailStatus();
 491 
 492             if (!setCallBacks(i + 1)) {
 493                 return;
 494             }
 495         }
 496 
 497         if (!nsk_jvmti_resumeSync())
 498             return;
 499     }
 500 
 501 }
 502 
 503 /* ============================================================================= */
 504 
 505 /** Agent library initialization. */
 506 #ifdef STATIC_BUILD
 507 JNIEXPORT jint JNICALL Agent_OnLoad_em02t010(JavaVM *jvm, char *options, void *reserved) {
 508     return Agent_Initialize(jvm, options, reserved);
 509 }
 510 JNIEXPORT jint JNICALL Agent_OnAttach_em02t010(JavaVM *jvm, char *options, void *reserved) {
 511     return Agent_Initialize(jvm, options, reserved);
 512 }
 513 JNIEXPORT jint JNI_OnLoad_em02t010(JavaVM *jvm, char *options, void *reserved) {
 514     return JNI_VERSION_1_8;
 515 }
 516 #endif
 517 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
 518 
 519     if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))
 520         return JNI_ERR;
 521 
 522     timeout = nsk_jvmti_getWaitTime() * 60 * 1000;
 523 
 524     if (!NSK_VERIFY((jvmti = nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL))
 525         return JNI_ERR;
 526 
 527     if (!NSK_JVMTI_VERIFY(jvmti->CreateRawMonitor("_syncLock", &syncLock))) {
 528         nsk_jvmti_setFailStatus();
 529         return JNI_ERR;
 530     }
 531 
 532     {
 533         jvmtiCapabilities caps;
 534         memset(&caps, 0, sizeof(caps));
 535 
 536         caps.can_generate_field_modification_events = 1;
 537         caps.can_generate_field_access_events = 1;
 538         if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps)))
 539             return JNI_ERR;
 540     }
 541 
 542     if (!setCallBacks(1)) {
 543         return JNI_ERR;
 544     }
 545 
 546     if (!enableEventList()) {
 547         return JNI_ERR;
 548     }
 549 
 550     if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL)))
 551         return JNI_ERR;
 552 
 553     return JNI_OK;
 554 }
 555 
 556 /* ============================================================================= */
 557 
 558 
 559 }