1 /* 2 * Copyright (c) 2003, 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 <stdio.h> 25 #include <string.h> 26 #include <jvmti.h> 27 #include "agent_common.h" 28 29 #include "nsk_tools.h" 30 #include "JVMTITools.h" 31 #include "jvmti_tools.h" 32 #include "jni_tools.h" 33 34 extern "C" { 35 36 #define STATUS_FAILED 2 37 #define PASSED 0 38 39 /* tested methods */ 40 #define METH_NUM 4 41 static const char *METHODS[][2] = { 42 {"bpMethod", "()V"}, 43 {"nativeMethod", "()V"}, 44 {"anotherNativeMethod", "(I)V"}, 45 {"runThis", "([Ljava/lang/String;Ljava/io/PrintStream;)I"} 46 }; 47 48 /* event counters for the tested methods and expected numbers 49 of the events */ 50 static volatile long stepEv[][2] = { 51 {0, 1}, 52 {0, 0}, 53 {0, 0}, 54 {0, 1} 55 }; 56 57 static const char *CLASS_SIG = 58 "Lnsk/jvmti/SingleStep/singlestep003;"; 59 60 static volatile jint result = PASSED; 61 static jvmtiEnv *jvmti = NULL; 62 static jvmtiEventCallbacks callbacks; 63 64 static void setBP(jvmtiEnv *jvmti_env, JNIEnv *env, jclass klass) { 65 jmethodID mid; 66 67 if (!NSK_JNI_VERIFY(env, (mid = NSK_CPP_STUB4(GetMethodID, 68 env, klass, METHODS[0][0], METHODS[0][1])) != NULL)) 69 NSK_CPP_STUB2(FatalError, env, 70 "failed to get ID for the java method\n"); 71 72 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(SetBreakpoint, 73 jvmti_env, mid, 0))) 74 NSK_CPP_STUB2(FatalError, env, 75 "failed to set breakpoint\n"); 76 } 77 78 /** callback functions **/ 79 void JNICALL 80 ClassLoad(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thread, jclass klass) { 81 char *sig, *generic; 82 83 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(GetClassSignature, 84 jvmti_env, klass, &sig, &generic))) 85 NSK_CPP_STUB2(FatalError, env, 86 "failed to obtain a class signature\n"); 87 88 if (sig != NULL && (strcmp(sig, CLASS_SIG) == 0)) { 89 NSK_DISPLAY1( 90 "ClassLoad event received for the class \"%s\"\n" 91 "\tsetting breakpoint ...\n", 92 sig); 93 setBP(jvmti_env, env, klass); 94 } 95 } 96 97 void JNICALL 98 Breakpoint(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thr, jmethodID method, 99 jlocation loc) { 100 jclass klass; 101 char *sig, *generic; 102 103 NSK_DISPLAY0("Breakpoint event received\n"); 104 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(GetMethodDeclaringClass, 105 jvmti_env, method, &klass))) 106 NSK_COMPLAIN0("TEST FAILURE: unable to get method declaring class\n\n"); 107 108 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(GetClassSignature, 109 jvmti_env, klass, &sig, &generic))) 110 NSK_CPP_STUB2(FatalError, env, 111 "Breakpoint: failed to obtain a class signature\n"); 112 113 if (sig != NULL && (strcmp(sig, CLASS_SIG) == 0)) { 114 NSK_DISPLAY1("method declaring class \"%s\"\n\tenabling SingleStep events ...\n", 115 sig); 116 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode, 117 jvmti_env, JVMTI_ENABLE, JVMTI_EVENT_SINGLE_STEP, thr))) { 118 result = STATUS_FAILED; 119 NSK_COMPLAIN0("TEST FAILURE: cannot enable SingleStep events\n\n"); 120 } 121 } else { 122 result = STATUS_FAILED; 123 NSK_COMPLAIN1("TEST FAILURE: unexpected breakpoint event in method of class \"%s\"\n\n", 124 sig); 125 } 126 } 127 128 void JNICALL 129 SingleStep(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, 130 jmethodID method, jlocation location) { 131 jclass klass; 132 char *sig, *generic, *methNam, *methSig; 133 int i; 134 135 if (result == STATUS_FAILED) { 136 return; 137 } 138 139 NSK_DISPLAY0(">>>> SingleStep event received\n"); 140 141 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB5(GetMethodName, 142 jvmti_env, method, &methNam, &methSig, NULL))) { 143 result = STATUS_FAILED; 144 NSK_COMPLAIN0("TEST FAILED: unable to get method name during SingleStep callback\n\n"); 145 return; 146 } 147 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(GetMethodDeclaringClass, 148 jvmti_env, method, &klass))) { 149 result = STATUS_FAILED; 150 NSK_COMPLAIN0("TEST FAILED: unable to get method declaring class during SingleStep callback\n\n"); 151 return; 152 } 153 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(GetClassSignature, 154 jvmti_env, klass, &sig, &generic))) { 155 result = STATUS_FAILED; 156 NSK_COMPLAIN0("TEST FAILED: unable to obtain a class signature during SingleStep callback\n\n"); 157 return; 158 } 159 160 if (sig != NULL) { 161 if (stepEv[METH_NUM-1][0] == 1) { 162 result = STATUS_FAILED; 163 NSK_COMPLAIN0("TEST FAILED: SingleStep event received after disabling the event generation\n\n"); 164 return; 165 } 166 167 for (i=0; i<METH_NUM; i++) { 168 if ((strcmp(methNam,METHODS[i][0]) == 0) && 169 (strcmp(methSig,METHODS[i][1]) == 0) && 170 (strcmp(sig,CLASS_SIG) == 0)) { 171 stepEv[i][0]++; 172 173 if (stepEv[i][1] == 1) { 174 NSK_DISPLAY3( 175 "CHECK PASSED: SingleStep event received for the method:\n" 176 "\t \"%s %s\" of class \"%s\"\n" 177 "\tas expected\n", 178 methNam, methSig, sig); 179 } else { 180 result = STATUS_FAILED; 181 NSK_COMPLAIN3( 182 "TEST FAILED: SingleStep event received for the method:\n" 183 "\t \"%s %s\" of class \"%s\"\n", 184 methNam, methSig, sig); 185 } 186 187 if (i == (METH_NUM-1)) { 188 NSK_DISPLAY0("Disabling the single step event generation\n"); 189 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode, 190 jvmti_env, JVMTI_DISABLE, JVMTI_EVENT_SINGLE_STEP, thread))) { 191 result = STATUS_FAILED; 192 NSK_COMPLAIN0("TEST FAILED: cannot disable SingleStep events\n\n"); 193 } 194 } 195 } 196 } 197 } 198 199 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(Deallocate, 200 jvmti_env, (unsigned char*) methNam))) { 201 result = STATUS_FAILED; 202 NSK_COMPLAIN0("TEST FAILED: unable to deallocate memory pointed to method name\n\n"); 203 } 204 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(Deallocate, 205 jvmti_env, (unsigned char*) methSig))) { 206 result = STATUS_FAILED; 207 NSK_COMPLAIN0("TEST FAILED: unable to deallocate memory pointed to method signature\n\n"); 208 } 209 210 NSK_DISPLAY0("<<<<\n\n"); 211 } 212 /************************/ 213 214 /* dummy method used only to provoke SingleStep events */ 215 JNIEXPORT void JNICALL 216 Java_nsk_jvmti_SingleStep_singlestep003_anotherNativeMethod( 217 JNIEnv *env, jobject obj, jint i) { 218 NSK_DISPLAY0("inside the anotherNativeMethod()\n\n"); 219 } 220 221 /* dummy method used only to provoke SingleStep events */ 222 JNIEXPORT void JNICALL 223 Java_nsk_jvmti_SingleStep_singlestep003_nativeMethod( 224 JNIEnv *env, jobject obj) { 225 jint i = 0; 226 227 NSK_DISPLAY0("inside the nativeMethod()\n\n"); 228 i++; 229 230 Java_nsk_jvmti_SingleStep_singlestep003_anotherNativeMethod(env, obj, i); 231 } 232 233 JNIEXPORT jint JNICALL 234 Java_nsk_jvmti_SingleStep_singlestep003_check( 235 JNIEnv *env, jobject obj) { 236 int i; 237 238 for (i=0; i<METH_NUM; i++) 239 if (stepEv[i][0] == 0) { 240 if (stepEv[i][1] == 0) { 241 NSK_DISPLAY1("CHECK PASSED: no SingleStep events for the method \"%s\" as expected\n\n", 242 METHODS[i][0]); 243 } 244 else { 245 result = STATUS_FAILED; 246 NSK_COMPLAIN1("TEST FAILED: no SingleStep events for the method \"%s\"\n\n", 247 METHODS[i][0]); 248 } 249 } 250 251 return result; 252 } 253 254 #ifdef STATIC_BUILD 255 JNIEXPORT jint JNICALL Agent_OnLoad_singlestep003(JavaVM *jvm, char *options, void *reserved) { 256 return Agent_Initialize(jvm, options, reserved); 257 } 258 JNIEXPORT jint JNICALL Agent_OnAttach_singlestep003(JavaVM *jvm, char *options, void *reserved) { 259 return Agent_Initialize(jvm, options, reserved); 260 } 261 JNIEXPORT jint JNI_OnLoad_singlestep003(JavaVM *jvm, char *options, void *reserved) { 262 return JNI_VERSION_1_8; 263 } 264 #endif 265 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 266 jvmtiCapabilities caps; 267 268 /* init framework and parse options */ 269 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) 270 return JNI_ERR; 271 272 /* create JVMTI environment */ 273 if (!NSK_VERIFY((jvmti = 274 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) 275 return JNI_ERR; 276 277 /* add capability to generate compiled method events */ 278 memset(&caps, 0, sizeof(jvmtiCapabilities)); 279 caps.can_generate_breakpoint_events = 1; 280 caps.can_generate_single_step_events = 1; 281 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(AddCapabilities, 282 jvmti, &caps))) 283 return JNI_ERR; 284 285 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(GetCapabilities, 286 jvmti, &caps))) 287 return JNI_ERR; 288 if (!caps.can_generate_single_step_events) 289 NSK_DISPLAY0("Warning: generation of single step events is not implemented\n"); 290 291 /* set event callback */ 292 NSK_DISPLAY0("setting event callbacks ...\n"); 293 (void) memset(&callbacks, 0, sizeof(callbacks)); 294 callbacks.ClassLoad = &ClassLoad; 295 callbacks.Breakpoint = &Breakpoint; 296 callbacks.SingleStep = &SingleStep; 297 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(SetEventCallbacks, 298 jvmti, &callbacks, sizeof(callbacks)))) 299 return JNI_ERR; 300 301 NSK_DISPLAY0("setting event callbacks done\nenabling JVMTI events ...\n"); 302 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode, 303 jvmti, JVMTI_ENABLE, JVMTI_EVENT_CLASS_LOAD, NULL))) 304 return JNI_ERR; 305 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode, 306 jvmti, JVMTI_ENABLE, JVMTI_EVENT_BREAKPOINT, NULL))) 307 return JNI_ERR; 308 NSK_DISPLAY0("enabling the events done\n\n"); 309 310 return JNI_OK; 311 } 312 313 }