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