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 "agent_common.h" 28 #include "jvmti_tools.h" 29 30 #define PASSED 0 31 #define STATUS_FAILED 2 32 33 extern "C" { 34 35 /* ========================================================================== */ 36 37 /* scaffold objects */ 38 static jlong timeout = 0; 39 40 /* test objects */ 41 static jthread thread = NULL; 42 static jmethodID midCheckPoint = NULL; 43 static int MethodEntryEventsCount = 0; 44 static int FramePopEventsCount = 0; 45 46 /* ========================================================================== */ 47 48 /** callback functions **/ 49 50 static void JNICALL 51 MethodEntry(jvmtiEnv *jvmti_env, JNIEnv *jni_env, 52 jthread thread, jmethodID method) { 53 char *name = NULL; 54 char *signature = NULL; 55 56 if (method != midCheckPoint) 57 return; 58 59 MethodEntryEventsCount++; 60 if (!NSK_JVMTI_VERIFY(jvmti_env->GetMethodName(method, &name, &signature, NULL))) { 61 nsk_jvmti_setFailStatus(); 62 return; 63 } 64 65 NSK_DISPLAY2("MethodEntry event: %s%s\n", name, signature); 66 67 if (name != NULL) 68 jvmti_env->Deallocate((unsigned char*)name); 69 if (signature != NULL) 70 jvmti_env->Deallocate((unsigned char*)signature); 71 72 switch(MethodEntryEventsCount) { 73 case 1: 74 NSK_DISPLAY0("Testcase #1: FramePop in both agents\n"); 75 if (!NSK_JVMTI_VERIFY(jvmti_env->NotifyFramePop(thread, 0))) 76 nsk_jvmti_setFailStatus(); 77 break; 78 79 case 2: 80 NSK_DISPLAY0("Testcase #2: w/o NotifyFramePop in 2nd agent\n"); 81 break; 82 83 case 3: 84 NSK_DISPLAY0("Testcase #3: FramePop disabled in 2nd agent\n"); 85 if (!NSK_JVMTI_VERIFY(jvmti_env->SetEventNotificationMode(JVMTI_DISABLE, JVMTI_EVENT_FRAME_POP, NULL))) 86 nsk_jvmti_setFailStatus(); 87 if (!NSK_JVMTI_VERIFY(jvmti_env->NotifyFramePop(thread, 0))) 88 nsk_jvmti_setFailStatus(); 89 break; 90 91 default: 92 NSK_COMPLAIN0("Should no reach here"); 93 nsk_jvmti_setFailStatus(); 94 break; 95 } 96 } 97 98 static void JNICALL 99 FramePop(jvmtiEnv *jvmti_env, JNIEnv *jni_env, 100 jthread thread, jmethodID method, 101 jboolean wasPopedByException) { 102 char *name = NULL; 103 char *signature = NULL; 104 105 FramePopEventsCount++; 106 if (!NSK_JVMTI_VERIFY(jvmti_env->GetMethodName(method, &name, &signature, NULL))) { 107 nsk_jvmti_setFailStatus(); 108 return; 109 } 110 111 NSK_DISPLAY2("FramePop event: %s%s\n", name, signature); 112 113 if (name != NULL) 114 jvmti_env->Deallocate((unsigned char*)name); 115 if (signature != NULL) 116 jvmti_env->Deallocate((unsigned char*)signature); 117 118 switch(MethodEntryEventsCount) { 119 case 1: 120 /* It's ok */ 121 break; 122 123 case 2: 124 NSK_COMPLAIN0("FramePop w/o NotifyFramePop in 2nd agent\n"); 125 nsk_jvmti_setFailStatus(); 126 break; 127 128 case 3: 129 NSK_COMPLAIN0("FramePop been disabled in 2nd agent\n"); 130 nsk_jvmti_setFailStatus(); 131 break; 132 133 default: 134 NSK_COMPLAIN0("Should no reach here"); 135 nsk_jvmti_setFailStatus(); 136 break; 137 } 138 } 139 140 /* ========================================================================== */ 141 142 static int prepare(jvmtiEnv* jvmti, JNIEnv* jni) { 143 const char* THREAD_NAME = "Debuggee Thread"; 144 jvmtiThreadInfo info; 145 jthread *threads = NULL; 146 jclass klass = NULL; 147 jint threads_count = 0; 148 int i; 149 150 NSK_DISPLAY0("Prepare: find tested thread\n"); 151 152 /* get all live threads */ 153 if (!NSK_JVMTI_VERIFY(jvmti->GetAllThreads(&threads_count, &threads))) 154 return NSK_FALSE; 155 156 if (!NSK_VERIFY(threads_count > 0 && threads != NULL)) 157 return NSK_FALSE; 158 159 /* find tested thread */ 160 for (i = 0; i < threads_count; i++) { 161 if (!NSK_VERIFY(threads[i] != NULL)) 162 return NSK_FALSE; 163 164 /* get thread information */ 165 if (!NSK_JVMTI_VERIFY(jvmti->GetThreadInfo(threads[i], &info))) 166 return NSK_FALSE; 167 168 NSK_DISPLAY3(" thread #%d (%s): %p\n", i, info.name, threads[i]); 169 170 /* find by name */ 171 if (info.name != NULL && (strcmp(info.name, THREAD_NAME) == 0)) { 172 thread = threads[i]; 173 } 174 175 if (info.name != NULL) { 176 if (!NSK_JVMTI_VERIFY(jvmti->Deallocate((unsigned char*)info.name))) 177 return NSK_FALSE; 178 } 179 } 180 181 /* deallocate threads list */ 182 if (!NSK_JVMTI_VERIFY(jvmti->Deallocate((unsigned char*)threads))) 183 return NSK_FALSE; 184 185 if (thread == NULL) { 186 NSK_COMPLAIN0("Debuggee thread not found"); 187 return NSK_FALSE; 188 } 189 190 if (!NSK_JNI_VERIFY(jni, (thread = jni->NewGlobalRef(thread)) != NULL)) 191 return NSK_FALSE; 192 193 /* get tested thread class */ 194 if (!NSK_JNI_VERIFY(jni, (klass = jni->GetObjectClass(thread)) != NULL)) 195 return NSK_FALSE; 196 197 /* get tested thread method 'checkPoint' */ 198 if (!NSK_JNI_VERIFY(jni, (midCheckPoint = jni->GetMethodID(klass, "checkPoint", "()V")) != NULL)) 199 return NSK_FALSE; 200 201 /* enable events */ 202 if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_METHOD_ENTRY, NULL))) 203 return NSK_FALSE; 204 if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_FRAME_POP, NULL))) 205 return NSK_FALSE; 206 207 return NSK_TRUE; 208 } 209 210 /* ========================================================================== */ 211 212 /** Agent algorithm. */ 213 static void JNICALL 214 agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) { 215 216 if (!nsk_jvmti_waitForSync(timeout)) 217 return; 218 219 if (!prepare(jvmti, jni)) { 220 nsk_jvmti_setFailStatus(); 221 return; 222 } 223 224 /* resume debugee and wait for sync */ 225 if (!nsk_jvmti_resumeSync()) 226 return; 227 if (!nsk_jvmti_waitForSync(timeout)) 228 return; 229 230 if (FramePopEventsCount == 0) { 231 NSK_COMPLAIN0("No FramePop events\n"); 232 nsk_jvmti_setFailStatus(); 233 } 234 235 NSK_TRACE(jni->DeleteGlobalRef(thread)); 236 if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(JVMTI_DISABLE, JVMTI_EVENT_METHOD_ENTRY, NULL))) 237 nsk_jvmti_setFailStatus(); 238 239 if (!nsk_jvmti_resumeSync()) 240 return; 241 } 242 243 /* ========================================================================== */ 244 245 /** Agent library initialization. */ 246 #ifdef STATIC_BUILD 247 JNIEXPORT jint JNICALL Agent_OnLoad_ma05t001a(JavaVM *jvm, char *options, void *reserved) { 248 return Agent_Initialize(jvm, options, reserved); 249 } 250 JNIEXPORT jint JNICALL Agent_OnAttach_ma05t001a(JavaVM *jvm, char *options, void *reserved) { 251 return Agent_Initialize(jvm, options, reserved); 252 } 253 JNIEXPORT jint JNI_OnLoad_ma05t001a(JavaVM *jvm, char *options, void *reserved) { 254 return JNI_VERSION_1_8; 255 } 256 #endif 257 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 258 jvmtiEnv* jvmti = NULL; 259 jvmtiEventCallbacks callbacks; 260 jvmtiCapabilities caps; 261 262 NSK_DISPLAY0("Agent_OnLoad\n"); 263 264 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) 265 return JNI_ERR; 266 267 timeout = nsk_jvmti_getWaitTime() * 60 * 1000; 268 269 if (!NSK_VERIFY((jvmti = 270 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) 271 return JNI_ERR; 272 273 memset(&caps, 0, sizeof(caps)); 274 caps.can_generate_method_entry_events = 1; 275 caps.can_generate_frame_pop_events = 1; 276 if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps))) 277 return JNI_ERR; 278 279 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) 280 return JNI_ERR; 281 282 memset(&callbacks, 0, sizeof(callbacks)); 283 callbacks.MethodEntry = &MethodEntry; 284 callbacks.FramePop = &FramePop; 285 if (!NSK_VERIFY(nsk_jvmti_init_MA(&callbacks))) 286 return JNI_ERR; 287 288 return JNI_OK; 289 } 290 291 /* ========================================================================== */ 292 293 }