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 jlong timeout = 0; 37 static jvmtiEnv *jvmti = NULL; 38 static jrawMonitorID syncLock = NULL; 39 40 /* constant names */ 41 #define JVMTI_EVENT_COUNT (int)(JVMTI_MAX_EVENT_TYPE_VAL - JVMTI_MIN_EVENT_TYPE_VAL + 1) 42 #define EXPECTED_COUNT 0 43 44 static int eventCount[JVMTI_EVENT_COUNT]; 45 46 /* ============================================================================= */ 47 48 void showEventStatistics() { 49 int i; 50 const char* str; 51 52 NSK_DISPLAY0("\n"); 53 NSK_DISPLAY0("Event statistics\n"); 54 NSK_DISPLAY0("----------------\n"); 55 for (i = 0; i < JVMTI_EVENT_COUNT; i++) { 56 if (eventCount[i] > 0) { 57 str = TranslateEvent((jvmtiEvent)(i+JVMTI_MIN_EVENT_TYPE_VAL)); 58 NSK_DISPLAY2("%-40s %7d\n", str, eventCount[i]); 59 } 60 } 61 } 62 63 /* ========================================================================== */ 64 65 void changeCount(jvmtiEvent event) { 66 67 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(RawMonitorEnter, jvmti, syncLock))) 68 nsk_jvmti_setFailStatus(); 69 70 eventCount[event - JVMTI_MIN_EVENT_TYPE_VAL]++; 71 72 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(RawMonitorExit, jvmti, syncLock))) 73 nsk_jvmti_setFailStatus(); 74 75 } 76 77 /* ============================================================================= */ 78 79 /* callbacks */ 80 JNIEXPORT void JNICALL 81 cbVMInit(jvmtiEnv* jvmti, JNIEnv* jni_env, jthread thread) { 82 changeCount(JVMTI_EVENT_VM_INIT); 83 NSK_DISPLAY0("--->VMINit is received\n"); 84 } 85 86 JNIEXPORT void JNICALL 87 cbVMDeath(jvmtiEnv* jvmti, JNIEnv* jni_env) { 88 changeCount(JVMTI_EVENT_VM_DEATH); 89 90 if (!NSK_JVMTI_VERIFY( 91 NSK_CPP_STUB2(DestroyRawMonitor, jvmti, syncLock))) 92 nsk_jvmti_setFailStatus(); 93 94 } 95 96 void JNICALL 97 cbException(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, 98 jmethodID method, jlocation location, jobject exception, 99 jmethodID catch_method, jlocation catch_location) { 100 changeCount(JVMTI_EVENT_EXCEPTION); 101 } 102 103 void JNICALL 104 cbExceptionCatch(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, 105 jmethodID method, jlocation location, jobject exception) { 106 changeCount(JVMTI_EVENT_EXCEPTION_CATCH); 107 } 108 109 void JNICALL 110 cbSingleStep(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, 111 jmethodID method, jlocation location) { 112 changeCount(JVMTI_EVENT_SINGLE_STEP); 113 } 114 115 void JNICALL 116 cbFramePop(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, 117 jmethodID method, jboolean was_popped_by_exception) { 118 changeCount(JVMTI_EVENT_FRAME_POP); 119 } 120 121 void JNICALL 122 cbBreakpoint(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, 123 jmethodID method, jlocation location) { 124 changeCount(JVMTI_EVENT_BREAKPOINT); 125 } 126 127 void JNICALL 128 cbFieldAccess(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, 129 jmethodID method, jlocation location, jclass field_klass, 130 jobject object, jfieldID field) { 131 changeCount(JVMTI_EVENT_FIELD_ACCESS); 132 } 133 134 void JNICALL 135 cbFieldModification(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, 136 jmethodID method, jlocation location, jclass field_klass, 137 jobject object, jfieldID field, char signature_type, 138 jvalue new_value) { 139 changeCount(JVMTI_EVENT_FIELD_MODIFICATION); 140 } 141 142 void JNICALL 143 cbMethodEntry(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, 144 jmethodID method) { 145 changeCount(JVMTI_EVENT_METHOD_ENTRY); 146 } 147 148 void JNICALL 149 cbMethodExit(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, 150 jmethodID method, jboolean was_popped_by_exception, 151 jvalue return_value) { 152 changeCount(JVMTI_EVENT_METHOD_EXIT); 153 } 154 155 void JNICALL 156 cbNativeMethodBind(jvmtiEnv *jvmti_env, JNIEnv* jni_env,jthread thread, 157 jmethodID method, void* address, void** new_address_ptr) { 158 changeCount(JVMTI_EVENT_NATIVE_METHOD_BIND); 159 } 160 161 void JNICALL 162 cbCompiledMethodLoad(jvmtiEnv *jvmti_env, jmethodID method, jint code_size, 163 const void* code_addr, jint map_length, 164 const jvmtiAddrLocationMap* map, const void* compile_info) { 165 changeCount(JVMTI_EVENT_COMPILED_METHOD_LOAD); 166 } 167 168 void JNICALL 169 cbCompiledMethodUnload(jvmtiEnv *jvmti_env, jmethodID method, 170 const void* code_addr) { 171 changeCount(JVMTI_EVENT_COMPILED_METHOD_UNLOAD); 172 } 173 174 void JNICALL 175 cbMonitorWait(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, 176 jobject object, jlong tout) { 177 178 changeCount(JVMTI_EVENT_MONITOR_WAIT); 179 } 180 181 void JNICALL 182 cbMonitorWaited(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, 183 jobject object, jboolean timed_out) { 184 185 changeCount(JVMTI_EVENT_MONITOR_WAITED); 186 } 187 188 JNIEXPORT void JNICALL 189 cbMonitorContendedEnter(jvmtiEnv* jvmti, JNIEnv* jni_env, jthread thread, 190 jobject object) { 191 192 changeCount(JVMTI_EVENT_MONITOR_CONTENDED_ENTER); 193 } 194 195 void JNICALL 196 cbMonitorContendedEntered(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, 197 jobject object) { 198 199 changeCount(JVMTI_EVENT_MONITOR_CONTENDED_ENTERED); 200 } 201 202 void JNICALL 203 cbGarbageCollectionStart(jvmtiEnv *jvmti_env) { 204 changeCount(JVMTI_EVENT_GARBAGE_COLLECTION_START); 205 } 206 207 void JNICALL 208 cbGarbageCollectionFinish(jvmtiEnv *jvmti_env) { 209 changeCount(JVMTI_EVENT_GARBAGE_COLLECTION_FINISH); 210 } 211 212 void JNICALL 213 cbObjectFree(jvmtiEnv *jvmti_env, jlong tag) { 214 changeCount(JVMTI_EVENT_OBJECT_FREE); 215 } 216 217 void JNICALL 218 cbVMObjectAlloc(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, 219 jobject object, jclass object_klass, jlong size) { 220 221 changeCount(JVMTI_EVENT_VM_OBJECT_ALLOC); 222 } 223 224 /* ============================================================================= */ 225 226 int enableOptionalEvents(jvmtiEnv *jvmti) { 227 int i; 228 int result = NSK_TRUE; 229 230 NSK_DISPLAY0("Enable events\n"); 231 232 /* enabling optional events */ 233 for (i = 0; i < JVMTI_EVENT_COUNT; i++) { 234 jvmtiEvent event = (jvmtiEvent)(i + JVMTI_MIN_EVENT_TYPE_VAL); 235 if (nsk_jvmti_isOptionalEvent(event)) 236 if (!NSK_JVMTI_VERIFY_CODE(JVMTI_ERROR_MUST_POSSESS_CAPABILITY, 237 NSK_CPP_STUB4(SetEventNotificationMode, jvmti, 238 JVMTI_ENABLE, event, NULL))) { 239 NSK_COMPLAIN1("Unexpected error enabling %s\n", 240 TranslateEvent(event)); 241 result = NSK_FALSE; 242 } 243 } 244 245 return result; 246 } 247 248 /* ============================================================================= */ 249 250 /** 251 * Testcase: check tested events. 252 * - check if expected events received for each method 253 * 254 * Returns NSK_TRUE if test may continue; or NSK_FALSE for test break. 255 */ 256 int checkEvents() { 257 int i; 258 jvmtiEvent event; 259 int result = NSK_TRUE; 260 261 for (i = 0; i < JVMTI_EVENT_COUNT; i++) { 262 263 event = (jvmtiEvent) (i + JVMTI_MIN_EVENT_TYPE_VAL); 264 265 if (nsk_jvmti_isOptionalEvent(event) && eventCount[i] > EXPECTED_COUNT) { 266 nsk_jvmti_setFailStatus(); 267 NSK_COMPLAIN3("Unexpected number of %s events:\n\treceived: %7d\n\texpected: %7d\n", 268 TranslateEvent(event), 269 eventCount[i], 270 EXPECTED_COUNT); 271 result = NSK_FALSE; 272 } 273 } 274 275 return result; 276 } 277 278 /* ============================================================================= */ 279 280 static int setCallBacks(jvmtiEnv *jvmti) { 281 int i; 282 283 jvmtiEventCallbacks eventCallbacks; 284 memset(&eventCallbacks, 0, sizeof(eventCallbacks)); 285 286 for (i = 0; i < JVMTI_EVENT_COUNT; i++) { 287 eventCount[i] = 0; 288 } 289 290 eventCallbacks.VMInit = cbVMInit; 291 eventCallbacks.VMDeath = cbVMDeath; 292 eventCallbacks.Exception = cbException; 293 eventCallbacks.ExceptionCatch = cbExceptionCatch; 294 eventCallbacks.SingleStep = cbSingleStep; 295 eventCallbacks.FramePop = cbFramePop; 296 eventCallbacks.Breakpoint = cbBreakpoint; 297 eventCallbacks.FieldAccess = cbFieldAccess; 298 eventCallbacks.FieldModification = cbFieldModification; 299 eventCallbacks.MethodEntry = cbMethodEntry; 300 eventCallbacks.MethodExit = cbMethodExit; 301 eventCallbacks.NativeMethodBind = cbNativeMethodBind; 302 eventCallbacks.CompiledMethodLoad = cbCompiledMethodLoad; 303 eventCallbacks.MonitorWait = cbMonitorWait; 304 eventCallbacks.MonitorWaited = cbMonitorWaited; 305 eventCallbacks.MonitorContendedEnter = cbMonitorContendedEnter; 306 eventCallbacks.MonitorContendedEntered = cbMonitorContendedEntered; 307 eventCallbacks.GarbageCollectionStart = cbGarbageCollectionStart; 308 eventCallbacks.GarbageCollectionFinish = cbGarbageCollectionFinish; 309 eventCallbacks.ObjectFree = cbObjectFree; 310 eventCallbacks.VMObjectAlloc = cbVMObjectAlloc; 311 312 if (!NSK_JVMTI_VERIFY( 313 NSK_CPP_STUB3(SetEventCallbacks, jvmti, 314 &eventCallbacks, 315 sizeof(eventCallbacks)))) 316 return NSK_FALSE; 317 318 return NSK_TRUE; 319 } 320 321 /* ============================================================================= */ 322 323 /** Agent algorithm. */ 324 static void JNICALL 325 agentProc(jvmtiEnv* jvmti, JNIEnv* agentJNI, void* arg) { 326 327 NSK_DISPLAY0("Wait for debuggee to become ready\n"); 328 if (!nsk_jvmti_waitForSync(timeout)) 329 return; 330 331 if (!checkEvents()) { 332 nsk_jvmti_setFailStatus(); 333 } 334 showEventStatistics(); 335 336 NSK_DISPLAY0("Let debuggee to finish\n"); 337 if (!nsk_jvmti_resumeSync()) 338 return; 339 340 } 341 342 /* ============================================================================= */ 343 344 /** Agent library initialization. */ 345 #ifdef STATIC_BUILD 346 JNIEXPORT jint JNICALL Agent_OnLoad_em07t001(JavaVM *jvm, char *options, void *reserved) { 347 return Agent_Initialize(jvm, options, reserved); 348 } 349 JNIEXPORT jint JNICALL Agent_OnAttach_em07t001(JavaVM *jvm, char *options, void *reserved) { 350 return Agent_Initialize(jvm, options, reserved); 351 } 352 JNIEXPORT jint JNI_OnLoad_em07t001(JavaVM *jvm, char *options, void *reserved) { 353 return JNI_VERSION_1_8; 354 } 355 #endif 356 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 357 358 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) 359 return JNI_ERR; 360 361 timeout = nsk_jvmti_getWaitTime() * 60 * 1000; 362 363 if (!NSK_VERIFY((jvmti = nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) 364 return JNI_ERR; 365 366 if (!NSK_JVMTI_VERIFY( 367 NSK_CPP_STUB3(CreateRawMonitor, jvmti, "_syncLock", &syncLock))) { 368 nsk_jvmti_setFailStatus(); 369 return JNI_ERR; 370 } 371 372 if (!setCallBacks(jvmti)) { 373 return JNI_ERR; 374 } 375 376 nsk_jvmti_showPossessedCapabilities(jvmti); 377 378 if (!enableOptionalEvents(jvmti)) { 379 return JNI_ERR; 380 } 381 382 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) 383 return JNI_ERR; 384 385 return JNI_OK; 386 } 387 388 /* ============================================================================= */ 389 390 391 }