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