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