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