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