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